add single-header version

This commit is contained in:
BlackMATov
2022-09-21 17:26:27 +07:00
parent cbc38caf0d
commit 24c1457ca9
7 changed files with 8616 additions and 37 deletions

114
.ci/build_singles.py Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
import sys
#
#
#
EMPTY_MATCHER = re.compile(r'^\s*$')
C_COMMENT_MATCHER = re.compile(r'^/\*.*\*/', re.S)
USER_INCLUDE_MATCHER = re.compile(r'#\s*include\s*\"(.*)\"')
SYSTEM_INCLUDE_MATCHER = re.compile(r'#\s*include\s*<(.*)>')
PRAGMA_ONCE_MATCHER = re.compile(r'#\s*pragma\s+once')
#
#
#
def CollectLicenseComment(headerPath):
with open(headerPath, "r") as headerStream:
headerContent = headerStream.read().strip()
commentMatch = re.match(C_COMMENT_MATCHER, headerContent)
return commentMatch.group() if commentMatch else ""
def CollectSystemIncludes(headerPath, parsedHeaders = set()):
with open(headerPath, "r") as headerStream:
headerContent = headerStream.read().strip()
if PRAGMA_ONCE_MATCHER.search(headerContent) and headerPath in parsedHeaders:
return set()
headerIncludes = set()
parsedHeaders.add(headerPath)
headerLines = headerContent.split('\n')
for headerLine in headerLines:
includeMatch = USER_INCLUDE_MATCHER.findall(headerLine)
if includeMatch:
internalHeaderPath = os.path.abspath(os.path.join(os.path.dirname(headerPath), includeMatch[0]))
headerIncludes = headerIncludes.union(CollectSystemIncludes(internalHeaderPath, parsedHeaders))
includeMatch = SYSTEM_INCLUDE_MATCHER.findall(headerLine)
if includeMatch:
headerIncludes.add(includeMatch[0])
return headerIncludes
def ParseHeader(headerPath, parsedHeaders = set()):
with open(headerPath, "r") as headerStream:
headerContent = headerStream.read().strip()
headerContent = re.sub(C_COMMENT_MATCHER, '', headerContent)
if PRAGMA_ONCE_MATCHER.search(headerContent) and headerPath in parsedHeaders:
return ""
parsedHeaders.add(headerPath)
headerLines = headerContent.split('\n')
outputContent = ""
shouldSkipNextEmptyLines = True
for headerLine in headerLines:
if EMPTY_MATCHER.match(headerLine) and shouldSkipNextEmptyLines:
continue
if PRAGMA_ONCE_MATCHER.match(headerLine):
shouldSkipNextEmptyLines = True
continue
includeMatch = USER_INCLUDE_MATCHER.findall(headerLine)
if includeMatch:
internalHeaderPath = os.path.abspath(os.path.join(os.path.dirname(headerPath), includeMatch[0]))
internalHeaderContent = ParseHeader(internalHeaderPath, parsedHeaders)
outputContent += internalHeaderContent
shouldSkipNextEmptyLines = True
continue
includeMatch = SYSTEM_INCLUDE_MATCHER.findall(headerLine)
if includeMatch:
shouldSkipNextEmptyLines = True
continue
shouldSkipNextEmptyLines = False
outputContent += "{}\n".format(headerLine)
return "{}\n".format(outputContent)
#
#
#
inputHeaderPath = os.path.abspath(sys.argv[1])
outputHeaderPath = os.path.abspath(sys.argv[2])
os.makedirs(os.path.dirname(outputHeaderPath), exist_ok=True)
with open(outputHeaderPath, "w") as outputHeaderStream:
licenseComment = CollectLicenseComment(inputHeaderPath)
systemIncludes = CollectSystemIncludes(inputHeaderPath)
outputHeaderStream.write("{}\n".format(licenseComment))
outputHeaderStream.write("\n")
for systemInclude in sorted(systemIncludes):
outputHeaderStream.write("#include <{}>\n".format(systemInclude))
outputHeaderStream.write("\n")
outputHeaderStream.write(ParseHeader(inputHeaderPath).strip())
outputHeaderStream.write("\n")

View File

@@ -4,6 +4,8 @@ Checks: '-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
-bugprone-forwarding-reference-overload,
-bugprone-lambda-function-name,
-bugprone-macro-parentheses,
clang-analyzer-*,
@@ -11,6 +13,7 @@ Checks: '-*,
cppcoreguidelines-*,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
modernize-*,
@@ -22,7 +25,9 @@ Checks: '-*,
readability-*,
-readability-identifier-length,
-readability-named-parameter,
-readability-redundant-access-specifiers,
-readability-simplify-boolean-expr,
-readability-use-anyofallof,
'
...

View File

@@ -10,8 +10,6 @@ endif()
project(meta.hpp)
add_library(${PROJECT_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)
target_include_directories(${PROJECT_NAME} INTERFACE headers)
@@ -39,5 +37,6 @@ include(EnableGCov)
include(EnableUBSan)
add_subdirectory(manuals)
add_subdirectory(singles)
add_subdirectory(vendors)
add_subdirectory(untests)

View File

@@ -37,19 +37,19 @@ namespace meta_hpp::detail
swap(flags_, other.flags_);
}
constexpr explicit operator bool() const noexcept {
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return !!flags_;
}
constexpr underlying_type as_raw() const noexcept {
[[nodiscard]] constexpr underlying_type as_raw() const noexcept {
return flags_;
}
constexpr enum_type as_enum() const noexcept {
[[nodiscard]] constexpr enum_type as_enum() const noexcept {
return static_cast<enum_type>(flags_);
}
constexpr bool has(bitflags flags) const noexcept {
[[nodiscard]] constexpr bool has(bitflags flags) const noexcept {
return flags.flags_ == (flags_ & flags.flags_);
}

30
singles/CMakeLists.txt Normal file
View File

@@ -0,0 +1,30 @@
project(meta.hpp.singles)
#
# generate
#
find_package(PythonInterp REQUIRED)
set(META_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(META_SINGLES_INPUT "${META_ROOT_DIR}/headers/meta.hpp/meta_all.hpp")
set(META_SINGLES_OUTPUT "${META_ROOT_DIR}/singles/headers/meta.hpp/meta_all.hpp")
file(GLOB_RECURSE META_SINGLES_DEPENDS "${META_ROOT_DIR}/headers/*.hpp")
add_custom_command(OUTPUT "${META_SINGLES_OUTPUT}"
COMMAND "${PYTHON_EXECUTABLE}" ".ci/build_singles.py" "${META_SINGLES_INPUT}" "${META_SINGLES_OUTPUT}"
DEPENDS ${META_SINGLES_DEPENDS}
WORKING_DIRECTORY "${META_ROOT_DIR}")
add_custom_target(${PROJECT_NAME}.generate
DEPENDS "${META_SINGLES_OUTPUT}")
#
# library
#
add_library(${PROJECT_NAME} INTERFACE)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}.generate)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)
target_include_directories(${PROJECT_NAME} INTERFACE headers)
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads)

File diff suppressed because it is too large Load Diff

View File

@@ -4,40 +4,77 @@ file(GLOB_RECURSE UNTESTS_SOURCES "*.cpp" "*.hpp")
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${UNTESTS_SOURCES})
add_executable(${PROJECT_NAME} ${UNTESTS_SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE meta.hpp doctest_with_main)
target_link_libraries(${PROJECT_NAME} PRIVATE meta.hpp)
if(${BUILD_WITH_COVERAGE})
target_link_libraries(${PROJECT_NAME} PRIVATE enable_gcov)
endif()
add_executable(${PROJECT_NAME}.singles ${UNTESTS_SOURCES})
target_link_libraries(${PROJECT_NAME}.singles PRIVATE meta.hpp.singles)
if(${BUILD_WITH_SANITIZERS})
target_link_libraries(${PROJECT_NAME} PRIVATE enable_asan enable_ubsan)
endif()
#
# setup defines
#
target_compile_options(${PROJECT_NAME}
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:
/WX /W4>
PRIVATE
$<$<CXX_COMPILER_ID:GNU>:
-Werror -Wall -Wextra -Wpedantic>
PRIVATE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Werror -Weverything -Wconversion
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-exit-time-destructors
-Wno-global-constructors
-Wno-padded
-Wno-unknown-warning-option
-Wno-unneeded-internal-declaration
-Wno-unneeded-member-function
-Wno-unused-macros
-Wno-weak-vtables
>)
function(setup_defines_for_target TARGET)
target_compile_definitions(${TARGET} PRIVATE
DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
DOCTEST_CONFIG_USE_STD_HEADERS)
endfunction()
target_compile_definitions(${PROJECT_NAME} PRIVATE
DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
DOCTEST_CONFIG_USE_STD_HEADERS)
setup_defines_for_target(${PROJECT_NAME})
setup_defines_for_target(${PROJECT_NAME}.singles)
#
# setup libraries
#
function(setup_libraries_for_target TARGET)
target_link_libraries(${TARGET} PRIVATE doctest_with_main)
if(${BUILD_WITH_COVERAGE})
target_link_libraries(${TARGET} PRIVATE enable_gcov)
endif()
if(${BUILD_WITH_SANITIZERS})
target_link_libraries(${TARGET} PRIVATE enable_asan enable_ubsan)
endif()
endfunction()
setup_libraries_for_target(${PROJECT_NAME})
setup_libraries_for_target(${PROJECT_NAME}.singles)
#
# setup warnings
#
function(setup_warnings_for_target TARGET)
target_compile_options(${TARGET}
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:
/WX /W4>
PRIVATE
$<$<CXX_COMPILER_ID:GNU>:
-Werror -Wall -Wextra -Wpedantic>
PRIVATE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Werror -Weverything -Wconversion
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-exit-time-destructors
-Wno-global-constructors
-Wno-padded
-Wno-unknown-warning-option
-Wno-unneeded-internal-declaration
-Wno-unneeded-member-function
-Wno-unused-macros
-Wno-weak-vtables
>)
endfunction()
setup_warnings_for_target(${PROJECT_NAME})
setup_warnings_for_target(${PROJECT_NAME}.singles)
#
# add tests
#
add_test(${PROJECT_NAME} ${PROJECT_NAME})
add_test(${PROJECT_NAME} ${PROJECT_NAME}.singles)