Initial commit
Bin2CPP / Sonarqube (push) Successful in 5m3s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 4m45s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 5m13s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 4m50s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 4m48s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 4m56s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 4m55s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 5m6s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 5m4s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 4m53s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 4m52s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 5m2s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 5m0s
Bin2CPP / Clang Format Checks (push) Successful in 6s
Conan Packaging / Package Bin2CPP/1.0.0 (push) Successful in 4m56s
Bin2CPP / Sonarqube (push) Successful in 5m3s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 4m45s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 5m13s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 4m50s
Bin2CPP / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 4m48s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 4m56s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 4m55s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 5m6s
Bin2CPP / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 5m4s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 4m53s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 4m52s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 5m2s
Bin2CPP / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 5m0s
Bin2CPP / Clang Format Checks (push) Successful in 6s
Conan Packaging / Package Bin2CPP/1.0.0 (push) Successful in 4m56s
This commit is contained in:
+122
@@ -0,0 +1,122 @@
|
||||
---
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AccessModifierOffset: -2
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
PadOperators: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
PadOperators: true
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCaseColons: true
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 2
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: Empty
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BitFieldColonSpacing: After
|
||||
BreakBeforeBraces: Custom
|
||||
BracedInitializerIndentWidth: 2
|
||||
BreakAfterAttributes: Always
|
||||
BreakArrays: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
CompactNamespaces: false
|
||||
Cpp11BracedListStyle: true
|
||||
EmptyLineBeforeAccessModifier: Always
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
InsertBraces: true
|
||||
InsertNewlineAtEOF: true
|
||||
IntegerLiteralSeparator:
|
||||
Binary: -1
|
||||
Decimal: 3
|
||||
DecimalMinDigits: 5
|
||||
Hex: -1
|
||||
LambdaBodyIndentation: Signature
|
||||
Language: Cpp
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Left
|
||||
UseTab: Never
|
||||
Standard: Auto
|
||||
BraceWrapping:
|
||||
AfterNamespace: true
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: true
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
ColumnLimit: 120
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SortIncludes: CaseSensitive
|
||||
PenaltyReturnTypeOnItsOwnLine: 500
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCtorInitializerColon: false
|
||||
SpaceBeforeInheritanceColon: false
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpacesBeforeTrailingComments: 3
|
||||
PackConstructorInitializers: Never
|
||||
SeparateDefinitionBlocks: Always
|
||||
MaxEmptyLinesToKeep: 1
|
||||
BreakBeforeBinaryOperators: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
PadOperators: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceInEmptyBlock: true
|
||||
PenaltyBreakAssignment: 200
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# .clang-tidy
|
||||
---
|
||||
Checks: >
|
||||
-*,
|
||||
bugprone-*,
|
||||
clang-analyzer-*,
|
||||
cppcoreguidelines-*,
|
||||
modernize-*,
|
||||
performance-*,
|
||||
readability-*,
|
||||
portability-*,
|
||||
|
||||
-modernize-use-trailing-return-type,
|
||||
-readability-avoid-const-params-in-decls,
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-avoid-do-while
|
||||
|
||||
ExcludeHeaderFilterRegex: '_generated.*'
|
||||
|
||||
CheckOptions:
|
||||
- key: readability-implicit-bool-conversion.AllowPointerConditions
|
||||
value: true
|
||||
@@ -0,0 +1,3 @@
|
||||
* text=auto eol=lf
|
||||
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Bin2CPP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:main
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: ["Debug", "RelWithDebInfo", "Release"]
|
||||
unity_build: ["ON", "OFF"]
|
||||
conan_profile: ["./ConanProfiles/clang", "./ConanProfiles/clang_asan"]
|
||||
name: "Build & Test ${{ matrix.build_type }} with ${{ matrix.conan_profile }} (Unity Build: ${{ matrix.unity_build }})"
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
run: apt-get update && apt-get install -y nodejs
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
conan install . --remote=bigfootpackages -pr:h=${{ matrix.conan_profile }} -pr:b=./ConanProfiles/Tools/clang --build=* -s:h build_type=${{ matrix.build_type }}
|
||||
. ./build/${{ matrix.build_type }}/generators/conanbuild.sh
|
||||
cmake -S . -B ./build/${{ matrix.build_type }} --toolchain ./build/${{ matrix.build_type }}/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_UNITY_BUILD=${{ matrix.unity_build }} -G "Ninja"
|
||||
cmake --build build/${{ matrix.build_type }} --parallel $(nproc)
|
||||
. ./build/${{ matrix.build_type }}/generators/deactivate_conanbuild.sh
|
||||
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
cd ./build/${{ matrix.build_type }}
|
||||
ctest . --output-on-failure
|
||||
|
||||
clang-format:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:main
|
||||
name: "Clang Format Checks"
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
run: apt-get update && apt-get install -y nodejs
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Clang Format Checks
|
||||
run: chmod +x format.sh && ./format.sh --check Bin2CPP
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Conan Packaging
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
conan-packages:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:main
|
||||
env:
|
||||
ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }}
|
||||
ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
name: "Package Bin2CPP/1.0.0"
|
||||
steps:
|
||||
- name: Set BRANCH_NAME
|
||||
run: echo "BRANCH_NAME=$(echo $GITHUB_REF_NAME | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Node.js
|
||||
run: apt-get update && apt-get install -y nodejs
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Run Conan packaging
|
||||
run: |
|
||||
echo "Building Bin2CPP@$1.0.0"
|
||||
CONAN_LOGIN_USERNAME=${ARTIFACTORY_USER} \
|
||||
CONAN_PASSWORD=${ARTIFACTORY_PASSWORD} \
|
||||
conan create . \
|
||||
--version=1.0.0 \
|
||||
--user=bigfootdev \
|
||||
--channel=${{ env.BRANCH_NAME }} \
|
||||
-pr:b=./ConanProfiles/Tools/clang -pr:h=./ConanProfiles/clang \
|
||||
--build=* --remote=bigfootpackages
|
||||
|
||||
CONAN_LOGIN_USERNAME=${ARTIFACTORY_USER} \
|
||||
CONAN_PASSWORD=${ARTIFACTORY_PASSWORD} \
|
||||
conan upload bin2cpp/1.0.0@bigfootdev/${{ env.BRANCH_NAME }} \
|
||||
--only-recipe --remote=bigfootpackages
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Bin2CPP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- Development
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:main
|
||||
name: "Sonarqube"
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
run: apt-get update && apt-get install -y nodejs
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Generate
|
||||
run: |
|
||||
conan profile detect
|
||||
conan install . --remote=bigfootpackages -pr:h=./ConanProfiles/clang_coverage -pr:b=./ConanProfiles/Tools/clang --build=* -s:h build_type=Debug
|
||||
. ./build/Debug/generators/conanbuild.sh
|
||||
cmake -S . -B ./build/Debug --toolchain ./build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G "Ninja"
|
||||
cmake --build build/Debug --parallel $(nproc)
|
||||
. ./build/Debug/generators/deactivate_conanbuild.sh
|
||||
|
||||
- name: Clang-Tidy
|
||||
run: run-clang-tidy -p ./build/Debug/ >> tidy_result.txt
|
||||
|
||||
- name: Infer
|
||||
run: infer run --compilation-database build/Debug/compile_commands.json
|
||||
|
||||
- name: SonarQube Scan
|
||||
if: github.head_ref == 'main' || github.ref_name == 'main'
|
||||
uses: SonarSource/sonarqube-scan-action@v7.0.0
|
||||
with:
|
||||
args: >
|
||||
-Dsonar.cxx.jsonCompilationDatabase=./build/Debug/compile_commands.json
|
||||
-Dsonar.verbose=true
|
||||
env:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST }}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
[Bb]uild*
|
||||
Environment/output
|
||||
*.generated.h
|
||||
|
||||
.scannerwork
|
||||
|
||||
SonarqubeResult
|
||||
*.profraw
|
||||
|
||||
conan_imports_manifest.txt
|
||||
CMakeUserPresets.json
|
||||
conan.lock
|
||||
conanbuildinfo.txt
|
||||
conaninfo.txt
|
||||
graph_info.json
|
||||
|
||||
.idea
|
||||
|
||||
test_package/Vendor
|
||||
|
||||
graphviz
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName})
|
||||
|
||||
add_executable(${PROJECT_NAME})
|
||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPEXE_SOURCES
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPEXE_HEADERS
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
|
||||
)
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${BIN2CPPEXE_SOURCES}
|
||||
PRIVATE
|
||||
FILE_SET HEADERS
|
||||
BASE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Include
|
||||
FILES
|
||||
${BIN2CPPEXE_HEADERS}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
Bin2CPPCompileAndLinkFlags
|
||||
Bin2CPPLib
|
||||
CLI11::CLI11
|
||||
${CMAKE_DL_LIBS})
|
||||
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX Src FILES ${BIN2CPPEXE_SOURCES} ${BIN2CPPEXE_HEADERS})
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Bin2CPP/${ParentFolder})
|
||||
|
||||
##################ASAN SETUP###################
|
||||
|
||||
if(${ASAN})
|
||||
if(MSVC)
|
||||
get_filename_component(MSVC_BIN_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY)
|
||||
set(ASAN_DLL "${MSVC_BIN_DIR}/clang_rt.asan_dynamic-x86_64.dll")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-asan.timestamp"
|
||||
DEPENDS "${ASAN_DLL}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ASAN_DLL}" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-asan.timestamp"
|
||||
COMMENT "Copying ASan DLL for ${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
add_custom_target(${PROJECT_NAME}Asan
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-asan.timestamp"
|
||||
)
|
||||
|
||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}Asan)
|
||||
set_target_properties(${PROJECT_NAME}Asan PROPERTIES FOLDER UtilityTargets/Bin2CPP/${ParentFolder})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
########INSTALL
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <Generator.hpp>
|
||||
#include <Log.hpp>
|
||||
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CLI::App app {"Bin2CPP allows you to generate a C++ header containing the binary content of an input file"};
|
||||
argv = app.ensure_utf8(argv);
|
||||
|
||||
std::string input;
|
||||
app.add_option("-f,--input", input, "The input file")->required();
|
||||
std::string output;
|
||||
app.add_option("-o,--output", output, "The output file")->required();
|
||||
std::optional<std::string> arrayType;
|
||||
app.add_option("--arrayType", arrayType, "The type of the array");
|
||||
std::optional<std::string> arrayInclude;
|
||||
app.add_option("--arrayInclude", arrayInclude, "Include for the array type");
|
||||
std::optional<std::string> arrayName;
|
||||
app.add_option("--arrayName", arrayName, "The array name");
|
||||
std::optional<std::string> customNamespace;
|
||||
app.add_option("--namespace", customNamespace, "The namespace");
|
||||
bool verbose = false;
|
||||
app.add_option("--verbose", verbose, "Activate logging");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
std::unique_ptr<Bin2CPP::Singleton<Bin2CPP::Log>::Lifetime> loggerLifetime =
|
||||
verbose ? std::make_unique<Bin2CPP::Singleton<Bin2CPP::Log>::Lifetime>() : nullptr;
|
||||
|
||||
Bin2CPP::Generator generator(input);
|
||||
if (arrayType)
|
||||
{
|
||||
generator.SetMapping(Bin2CPP::MappingKey::ARRAY_TYPE, arrayType.value());
|
||||
}
|
||||
if (arrayInclude)
|
||||
{
|
||||
generator.SetMapping(Bin2CPP::MappingKey::ARRAY_TYPE_INCLUDE, arrayInclude.value());
|
||||
}
|
||||
if (arrayName)
|
||||
{
|
||||
generator.SetMapping(Bin2CPP::MappingKey::ARRAY_NAME, arrayName.value());
|
||||
}
|
||||
if (customNamespace)
|
||||
{
|
||||
generator.SetMapping(Bin2CPP::MappingKey::NAMESPACE, customNamespace.value());
|
||||
}
|
||||
|
||||
if (!generator.Generate())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to generate '{}'", input);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ofstream out(output);
|
||||
if (!out)
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to open '{}'", output);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out << generator.Get();
|
||||
out.close();
|
||||
|
||||
BIN2CPP_LOG_INFO("'{}' Generated !", output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName})
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC)
|
||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPLIB_SOURCES
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPLIB_HEADERS
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPLIB_OTHERS
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp.in
|
||||
)
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${BIN2CPPLIB_SOURCES}
|
||||
PUBLIC
|
||||
FILE_SET HEADERS
|
||||
BASE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Include
|
||||
FILES
|
||||
${BIN2CPPLIB_HEADERS}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
Bin2CPPCompileAndLinkFlags
|
||||
PUBLIC
|
||||
quill::quill
|
||||
magic_enum::magic_enum)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
QUILL_DISABLE_NON_PREFIXED_MACROS)
|
||||
|
||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/MimallocImpl.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX Src FILES ${BIN2CPPLIB_SOURCES} ${BIN2CPPLIB_HEADERS} ${BIN2CPPLIB_OTHERS})
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Bin2CPP/${ParentFolder})
|
||||
@@ -0,0 +1,280 @@
|
||||
/*********************************************************************
|
||||
* \file Generator.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#include <Generator.hpp>
|
||||
|
||||
#include <Assert.hpp>
|
||||
#include <GeneratedTemplate.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
Generator::Generator(const std::string_view p_inputFile):
|
||||
m_inputFile(p_inputFile)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Generator::SetMapping(const MappingKey p_key, const std::string_view p_value)
|
||||
{
|
||||
const std::optional<std::size_t> index = magic_enum::enum_index(p_key);
|
||||
BIN2CPP_CRITICAL_ASSERT(index.has_value(), "Incorrect mapping key! Got {}", magic_enum::enum_integer(p_key));
|
||||
|
||||
m_mappingTable[index.value()] = p_value;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::Generate()
|
||||
{
|
||||
if (!ComputeMappings())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Invalid mappings! Can't generate file!");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_result = g_generatedTemplate;
|
||||
|
||||
for (std::uint32_t i = 0; i < m_mappingTable.size(); ++i)
|
||||
{
|
||||
const std::string KEY = magic_enum::enum_name(magic_enum::enum_value<MappingKey>(i)).data();
|
||||
const std::string& VALUE = m_mappingTable[i];
|
||||
|
||||
const std::string pattern = "\\{\\{" + KEY + "\\}\\}";
|
||||
std::regex placeholderRegex(pattern);
|
||||
m_result = std::regex_replace(m_result, placeholderRegex, VALUE);
|
||||
}
|
||||
|
||||
return Validate();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::string_view Generator::Get() const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeMappings()
|
||||
{
|
||||
std::filesystem::path file {m_inputFile.data()};
|
||||
if (!std::filesystem::exists(file))
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("File '{}' does not exists!", m_inputFile);
|
||||
return false;
|
||||
}
|
||||
if (std::filesystem::is_directory(file))
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("'{}' is not a file!", m_inputFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputeFilename())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute filename");
|
||||
return false;
|
||||
}
|
||||
if (!ComputeGuardName())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute GuardName");
|
||||
return false;
|
||||
}
|
||||
if (!ComputeArrayTypeInclude())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute ArrayTypeInclude");
|
||||
return false;
|
||||
}
|
||||
if (!ComputeArrayType())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute ArrayType");
|
||||
return false;
|
||||
}
|
||||
if (!ComputeArrayName())
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute ArrayName");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ifstream in {m_inputFile.data(), std::ios::binary};
|
||||
if (!in)
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to open '{}'", m_inputFile);
|
||||
return false;
|
||||
}
|
||||
in.seekg(0, std::ios::end);
|
||||
const size_t fileSize = static_cast<size_t>(in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<std::byte> data(fileSize);
|
||||
in.read(std::bit_cast<char*>(data.data()), fileSize);
|
||||
|
||||
if (!ComputeArraySize(data))
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute ArraySize");
|
||||
return false;
|
||||
}
|
||||
if (!ComputeData(data))
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Failed to compute Data");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeFilename()
|
||||
{
|
||||
std::filesystem::path file {m_inputFile.data()};
|
||||
m_mappingTable[magic_enum::enum_index(MappingKey::FILENAME).value()] = file.filename().string();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeGuardName()
|
||||
{
|
||||
std::filesystem::path file {m_inputFile.data()};
|
||||
std::string guardName = file.filename().string();
|
||||
|
||||
std::transform(guardName.begin(),
|
||||
guardName.end(),
|
||||
guardName.begin(),
|
||||
[](const char c)
|
||||
{
|
||||
if (!std::isalnum(c))
|
||||
{
|
||||
return static_cast<int>('_');
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::toupper(c);
|
||||
}
|
||||
});
|
||||
m_mappingTable[magic_enum::enum_index(MappingKey::GUARD_NAME).value()] = std::format("{}_HPP", guardName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeArrayTypeInclude()
|
||||
{
|
||||
std::string& value = m_mappingTable[magic_enum::enum_index(MappingKey::ARRAY_TYPE_INCLUDE).value()];
|
||||
if (value.empty())
|
||||
{
|
||||
value = "<array>";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeArrayType()
|
||||
{
|
||||
std::string& value = m_mappingTable[magic_enum::enum_index(MappingKey::ARRAY_TYPE).value()];
|
||||
if (value.empty())
|
||||
{
|
||||
value = "std::array";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeArrayName()
|
||||
{
|
||||
std::string& value = m_mappingTable[magic_enum::enum_index(MappingKey::ARRAY_NAME).value()];
|
||||
if (value.empty())
|
||||
{
|
||||
std::filesystem::path file {m_inputFile.data()};
|
||||
value = std::format("g_{}", file.filename().string());
|
||||
|
||||
std::transform(value.begin(),
|
||||
value.end(),
|
||||
value.begin(),
|
||||
[](const char c)
|
||||
{
|
||||
if (!std::isalnum(c))
|
||||
{
|
||||
return static_cast<int>('_');
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<int>(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeArraySize(const std::span<std::byte> p_data)
|
||||
{
|
||||
m_mappingTable[magic_enum::enum_index(MappingKey::ARRAY_SIZE).value()] = std::to_string(p_data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::ComputeData(const std::span<std::byte> p_data)
|
||||
{
|
||||
std::string& value = m_mappingTable[magic_enum::enum_index(MappingKey::DATA).value()];
|
||||
value.clear();
|
||||
|
||||
constexpr std::size_t bytesPerLine = 16;
|
||||
constexpr std::string_view linePrefix = "\n ";
|
||||
|
||||
for (std::size_t i = 0; i < p_data.size(); ++i)
|
||||
{
|
||||
if (i > 0 && i % bytesPerLine == 0)
|
||||
{
|
||||
value.append(linePrefix.data(), linePrefix.size());
|
||||
}
|
||||
|
||||
const std::string element = std::format("std::byte{{0x{:02X}}}", std::to_integer<std::uint8_t>(p_data[i]));
|
||||
value.append(element.data(), element.size());
|
||||
|
||||
if (i + 1 < p_data.size())
|
||||
{
|
||||
value.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool Generator::Validate()
|
||||
{
|
||||
std::regex unreplacedRegex(R"(\{\{[A-Z_]+\}\})");
|
||||
std::smatch match;
|
||||
|
||||
if (std::regex_search(m_result, match, unreplacedRegex))
|
||||
{
|
||||
BIN2CPP_LOG_ERROR("Warning: Unreplaced placeholder found: {}", match.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Bin2CPP
|
||||
@@ -0,0 +1,121 @@
|
||||
/*********************************************************************
|
||||
* \file Assert.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIN2CPP_ASSERT_HPP
|
||||
#define BIN2CPP_ASSERT_HPP
|
||||
#include <Log.hpp>
|
||||
|
||||
#if defined BIN2CPP_NOT_OPTIMIZED
|
||||
|
||||
#include <source_location>
|
||||
#include <string>
|
||||
|
||||
#if defined BIN2CPP_LINUX
|
||||
#include <csignal>
|
||||
#endif
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
class AssertHandler
|
||||
{
|
||||
public:
|
||||
AssertHandler() = delete;
|
||||
|
||||
AssertHandler(const AssertHandler& p_handler) = delete;
|
||||
AssertHandler(AssertHandler&& p_handler) = delete;
|
||||
|
||||
~AssertHandler() = delete;
|
||||
|
||||
/**
|
||||
* Handle an assertion.
|
||||
*
|
||||
* \param p_location Location of the assertion.
|
||||
* \param p_format Format string for the assertion message.
|
||||
* \param p_args Arguments for the format string.
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
static void Handle(const std::source_location& p_location, std::format_string<ARGS...> p_format, ARGS&&... p_args)
|
||||
{
|
||||
BIN2CPP_LOG_FATAL("Assert: {} (File:{}, Line:{}, Function:{})",
|
||||
std::format(p_format, std::forward<ARGS>(p_args)...),
|
||||
p_location.file_name(),
|
||||
p_location.line(),
|
||||
p_location.function_name());
|
||||
}
|
||||
|
||||
AssertHandler& operator=(const AssertHandler& p_handler) = delete;
|
||||
AssertHandler& operator=(AssertHandler&& p_handler) = delete;
|
||||
};
|
||||
} // namespace Bin2CPP
|
||||
|
||||
#if defined BIN2CPP_WINDOWS
|
||||
#define BIN2CPP_BREAK \
|
||||
do \
|
||||
{ \
|
||||
__debugbreak(); \
|
||||
} while (false)
|
||||
#elif defined BIN2CPP_LINUX
|
||||
#define BIN2CPP_BREAK \
|
||||
do \
|
||||
{ \
|
||||
std::raise(SIGTRAP); \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
#define BIN2CPP_ASSERT(p_assert, p_message, ...) \
|
||||
do \
|
||||
{ \
|
||||
constexpr std::source_location location = std::source_location::current(); \
|
||||
if (!(p_assert)) [[unlikely]] \
|
||||
{ \
|
||||
Bin2CPP::AssertHandler::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
Bin2CPP::Singleton<Bin2CPP::Log>::Instance().Flush(); \
|
||||
} \
|
||||
BIN2CPP_BREAK; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define BIN2CPP_SOFT_ASSERT(p_assert, p_message, ...) \
|
||||
do \
|
||||
{ \
|
||||
constexpr std::source_location location = std::source_location::current(); \
|
||||
if (!(p_assert)) [[unlikely]] \
|
||||
{ \
|
||||
Bin2CPP::AssertHandler::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
Bin2CPP::Singleton<Bin2CPP::Log>::Instance().Flush(); \
|
||||
} \
|
||||
BIN2CPP_BREAK; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define BIN2CPP_CRITICAL_ASSERT(p_assert, p_message, ...) \
|
||||
do \
|
||||
{ \
|
||||
constexpr std::source_location location = std::source_location::current(); \
|
||||
if (!(p_assert)) [[unlikely]] \
|
||||
{ \
|
||||
Bin2CPP::AssertHandler::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
Bin2CPP::Singleton<Bin2CPP::Log>::Instance().Flush(); \
|
||||
} \
|
||||
BIN2CPP_BREAK; \
|
||||
std::abort(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
#define BIN2CPP_ASSERT(p_assert, p_message, ...)
|
||||
|
||||
#define BIN2CPP_SOFT_ASSERT(p_assert, p_message, ...)
|
||||
|
||||
#define BIN2CPP_CRITICAL_ASSERT(p_assert, p_message, ...)
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*********************************************************************
|
||||
* \file GeneratedTemplate.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date March 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIN2CPP_GENERATED_TEMPLATE_HPP
|
||||
#define BIN2CPP_GENERATED_TEMPLATE_HPP
|
||||
#include <string_view>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
constexpr std::string_view g_generatedTemplate = R"(/**
|
||||
* Auto-generated header from: {{FILENAME}}
|
||||
* Generated by Bin2CPP
|
||||
*
|
||||
* DO NOT TOUCH
|
||||
*/
|
||||
#ifndef {{GUARD_NAME}}
|
||||
#define {{GUARD_NAME}}
|
||||
#include {{ARRAY_TYPE_INCLUDE}}
|
||||
#include <cstddef>
|
||||
|
||||
namespace {{NAMESPACE}}
|
||||
{
|
||||
inline constexpr {{ARRAY_TYPE}}<std::byte, {{ARRAY_SIZE}}> {{ARRAY_NAME}} = {
|
||||
{{DATA}}
|
||||
};
|
||||
|
||||
} // namespace {{NAMESPACE}}
|
||||
|
||||
#endif // {{GUARD_NAME}}
|
||||
)";
|
||||
} // namespace Bin2CPP
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,157 @@
|
||||
/*********************************************************************
|
||||
* \file Generator.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIN2CPP_GENERATOR_HPP
|
||||
#define BIN2CPP_GENERATOR_HPP
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
enum class MappingKey
|
||||
{
|
||||
FILENAME,
|
||||
GUARD_NAME,
|
||||
NAMESPACE,
|
||||
ARRAY_TYPE_INCLUDE,
|
||||
ARRAY_TYPE,
|
||||
ARRAY_SIZE,
|
||||
ARRAY_NAME,
|
||||
DATA
|
||||
};
|
||||
|
||||
class Generator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param p_inputFile the Input file
|
||||
*/
|
||||
Generator(const std::string_view p_inputFile);
|
||||
|
||||
Generator(const Generator& p_generator) = default;
|
||||
Generator(Generator&& p_generator) = default;
|
||||
|
||||
/**
|
||||
* Set a mapping
|
||||
*
|
||||
*/
|
||||
void SetMapping(const MappingKey p_key, const std::string_view p_value);
|
||||
|
||||
/**
|
||||
* Generate
|
||||
*
|
||||
* \return True if successful, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool Generate();
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::string_view Get() const;
|
||||
|
||||
~Generator() = default;
|
||||
|
||||
Generator& operator=(const Generator& p_generator) = default;
|
||||
Generator& operator=(Generator&& p_generator) = default;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute the mappings
|
||||
*
|
||||
* \return True if all mappings have valid values, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeMappings();
|
||||
|
||||
/**
|
||||
* Compute the filename mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeFilename();
|
||||
|
||||
/**
|
||||
* Compute the guardName mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeGuardName();
|
||||
|
||||
/**
|
||||
* Compute the arrayTypeInclude mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeArrayTypeInclude();
|
||||
|
||||
/**
|
||||
* Compute the arrayType mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeArrayType();
|
||||
|
||||
/**
|
||||
* Compute the arrayName mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeArrayName();
|
||||
|
||||
/**
|
||||
* Compute the arraySize mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeArraySize(const std::span<std::byte> p_data);
|
||||
|
||||
/**
|
||||
* Compute the data mapping
|
||||
*
|
||||
* \return True if success, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool ComputeData(const std::span<std::byte> p_data);
|
||||
|
||||
/**
|
||||
* Validate generated is correct (no remaining tags)
|
||||
*
|
||||
* \return True if valid, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool Validate();
|
||||
|
||||
/**
|
||||
* The mapping table
|
||||
*/
|
||||
std::array<std::string, magic_enum::enum_count<MappingKey>()> m_mappingTable;
|
||||
|
||||
/**
|
||||
* The input file
|
||||
*/
|
||||
std::string m_inputFile;
|
||||
|
||||
/**
|
||||
* The result
|
||||
*/
|
||||
std::string m_result;
|
||||
};
|
||||
} // namespace Bin2CPP
|
||||
#endif
|
||||
@@ -0,0 +1,133 @@
|
||||
/*********************************************************************
|
||||
* \file Log.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIN2CPP_LOG_HPP
|
||||
#define BIN2CPP_LOG_HPP
|
||||
#include <Singleton.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
#ifdef BIN2CPP_WINDOWS
|
||||
#pragma warning(disable: 4702)
|
||||
#endif
|
||||
#include <quill/Backend.h>
|
||||
#include <quill/Frontend.h>
|
||||
#include <quill/LogMacros.h>
|
||||
#include <quill/Logger.h>
|
||||
#include <quill/sinks/ConsoleSink.h>
|
||||
#if defined BIN2CPP_WINDOWS
|
||||
#pragma warning(default: 4702)
|
||||
#endif
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
Log();
|
||||
|
||||
Log(const Log& p_logger) = delete;
|
||||
Log(Log&& p_logger) = delete;
|
||||
|
||||
/**
|
||||
* Register a logger.
|
||||
*
|
||||
* \return The logger, nullptr if it does not exist
|
||||
*/
|
||||
[[nodiscard]]
|
||||
quill::Logger* GetLogger();
|
||||
|
||||
/*
|
||||
* Flush all the loggers
|
||||
*
|
||||
*/
|
||||
void Flush();
|
||||
|
||||
~Log();
|
||||
|
||||
Log& operator=(const Log& p_logger) = delete;
|
||||
Log& operator=(Log&& p_logger) = delete;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The sinks
|
||||
*/
|
||||
std::array<std::shared_ptr<quill::Sink>, 1> m_sinks;
|
||||
};
|
||||
} // namespace Bin2CPP
|
||||
|
||||
#define BIN2CPP_LOG_DEBUG(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
|
||||
{ \
|
||||
QUILL_LOG_DEBUG(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BIN2CPP_LOG_TRACE(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
|
||||
{ \
|
||||
QUILL_LOG_TRACE_L3(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BIN2CPP_LOG_INFO(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
|
||||
{ \
|
||||
QUILL_LOG_INFO(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BIN2CPP_LOG_WARN(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
|
||||
{ \
|
||||
QUILL_LOG_WARNING(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BIN2CPP_LOG_ERROR(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
|
||||
{ \
|
||||
QUILL_LOG_ERROR(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define BIN2CPP_LOG_FATAL(fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
|
||||
{ \
|
||||
QUILL_LOG_CRITICAL(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
@@ -0,0 +1,104 @@
|
||||
/*********************************************************************
|
||||
* \file Singleton.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIN2CPP_SINGLETON_HPP
|
||||
#define BIN2CPP_SINGLETON_HPP
|
||||
#include <optional>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
template<class TYPE>
|
||||
class Singleton
|
||||
{
|
||||
public:
|
||||
Singleton() = delete;
|
||||
|
||||
Singleton(const Singleton& p_singleton) = delete;
|
||||
Singleton(Singleton&& p_singleton) = delete;
|
||||
|
||||
~Singleton() = delete;
|
||||
|
||||
/**
|
||||
* Get the instance.
|
||||
*
|
||||
* \return The instance
|
||||
*/
|
||||
static TYPE& Instance()
|
||||
{
|
||||
return ms_instance.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the instance initialized
|
||||
*
|
||||
* \return True if initialized, false otherwise
|
||||
*/
|
||||
static bool HasInstance()
|
||||
{
|
||||
return ms_instance.has_value();
|
||||
}
|
||||
|
||||
class Lifetime
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* \param p_args Arguments for the singleton
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
explicit Lifetime(ARGS&&... p_args)
|
||||
{
|
||||
Initialize(std::forward<ARGS>(p_args)...);
|
||||
}
|
||||
|
||||
Lifetime(const Lifetime& p_lifetime) = delete;
|
||||
Lifetime(Lifetime&& p_lifetime) = delete;
|
||||
|
||||
~Lifetime()
|
||||
{
|
||||
Finalize();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
Lifetime& operator=(const Lifetime& p_lifetime) = delete;
|
||||
[[nodiscard]]
|
||||
Lifetime& operator=(Lifetime&& p_lifetime) = delete;
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
Singleton& operator=(const Singleton& p_singleton) = delete;
|
||||
[[nodiscard]]
|
||||
Singleton& operator=(Singleton&& p_singleton) = delete;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize the singleton.
|
||||
*
|
||||
* \param p_args Arguments for the singleton
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
static void Initialize(ARGS&&... p_args)
|
||||
{
|
||||
ms_instance.emplace(std::forward<ARGS>(p_args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize the singleton.
|
||||
*
|
||||
*/
|
||||
static void Finalize()
|
||||
{
|
||||
ms_instance.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* The singleton.
|
||||
*/
|
||||
inline static std::optional<TYPE> ms_instance;
|
||||
};
|
||||
} // namespace Bin2CPP
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*******************************************************************
|
||||
* \file Log.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#include <Log.hpp>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
Log::Log()
|
||||
{
|
||||
quill::Backend::start();
|
||||
|
||||
m_sinks[0] = quill::Frontend::create_or_get_sink<quill::ConsoleSink>("ConsoleSink");
|
||||
|
||||
quill::Logger* logger = quill::Frontend::create_or_get_logger("Bin2CPP", m_sinks[0]);
|
||||
logger->set_log_level(quill::LogLevel::TraceL3);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
quill::Logger* Log::GetLogger()
|
||||
{
|
||||
return quill::Frontend::get_logger("Bin2CPP");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Log::Flush()
|
||||
{
|
||||
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
|
||||
{
|
||||
logger->flush_log();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
Flush();
|
||||
|
||||
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
|
||||
{
|
||||
quill::Frontend::remove_logger(logger);
|
||||
}
|
||||
|
||||
quill::Backend::stop();
|
||||
}
|
||||
} // namespace Bin2CPP
|
||||
@@ -0,0 +1,2 @@
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bin2CPPLib)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bin2CPP)
|
||||
@@ -0,0 +1,90 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName}Tests)
|
||||
|
||||
add_executable(${PROJECT_NAME})
|
||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPLIBTESTS_SOURCES
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE BIN2CPPLIBTESTS_HEADERS
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
|
||||
)
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${BIN2CPPLIBTESTS_SOURCES}
|
||||
PRIVATE
|
||||
FILE_SET HEADERS
|
||||
BASE_DIRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Include
|
||||
FILES
|
||||
${BIN2CPPLIBTESTS_HEADERS}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
Bin2CPPCompileAndLinkFlags
|
||||
Bin2CPPLib
|
||||
gtest::gtest)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(${PROJECT_NAME} XML_OUTPUT_DIR ${CMAKE_BINARY_DIR}/TestResults/)
|
||||
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX Src/ FILES ${BIN2CPPLIBTESTS_SOURCES} ${BIN2CPPLIBTESTS_HEADERS})
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Tests/Bin2CPP/${ParentFolder})
|
||||
|
||||
##################ASAN SETUP###################
|
||||
|
||||
if(${ASAN})
|
||||
if(MSVC)
|
||||
get_filename_component(MSVC_BIN_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY)
|
||||
set(ASAN_DLL "${MSVC_BIN_DIR}/clang_rt.asan_dynamic-x86_64.dll")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-asan.timestamp"
|
||||
DEPENDS "${ASAN_DLL}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ASAN_DLL}" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-asan.timestamp"
|
||||
COMMENT "Copying ASan DLL for ${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
add_custom_target(${PROJECT_NAME}Asan
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-asan.timestamp"
|
||||
)
|
||||
|
||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}Asan)
|
||||
set_target_properties(${PROJECT_NAME}Asan PROPERTIES FOLDER UtilityTargets/Tests/Bin2CPP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
##################COPY FIXTURE FOLDER###################
|
||||
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Fixture)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Fixture)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE FIXTURE_FILES
|
||||
CONFIGURE_DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Fixture/*
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-fixture.timestamp"
|
||||
DEPENDS ${FIXTURE_FILES}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory $<TARGET_FILE_DIR:${PROJECT_NAME}>/Fixture
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/Fixture $<TARGET_FILE_DIR:${PROJECT_NAME}>/Fixture
|
||||
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-fixture.timestamp"
|
||||
COMMENT "Copying Fixture folder for ${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
add_custom_target(${PROJECT_NAME}Fixture
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-fixture.timestamp"
|
||||
)
|
||||
|
||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}Fixture)
|
||||
set_target_properties(${PROJECT_NAME}Fixture PROPERTIES FOLDER UtilityTargets/Tests/Bin2CPP)
|
||||
@@ -0,0 +1 @@
|
||||
Hello World
|
||||
@@ -0,0 +1,133 @@
|
||||
/*********************************************************************
|
||||
* \file Generator.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#include <Generator.hpp>
|
||||
|
||||
#include <Log.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
class GeneratorFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
Singleton<Log>::Lifetime m_lifetime;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(GeneratorFixture, GenerateDefault)
|
||||
{
|
||||
Generator generator("Fixture/toto.txt");
|
||||
EXPECT_TRUE(generator.Generate());
|
||||
|
||||
constexpr std::string_view expectedResult = R"(/**
|
||||
* Auto-generated header from: toto.txt
|
||||
* Generated by Bin2CPP
|
||||
*
|
||||
* DO NOT TOUCH
|
||||
*/
|
||||
#ifndef TOTO_TXT_HPP
|
||||
#define TOTO_TXT_HPP
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline constexpr std::array<std::byte, 11> g_toto_txt = {
|
||||
std::byte{0x48}, std::byte{0x65}, std::byte{0x6C}, std::byte{0x6C}, std::byte{0x6F}, std::byte{0x20}, std::byte{0x57}, std::byte{0x6F}, std::byte{0x72}, std::byte{0x6C}, std::byte{0x64}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // TOTO_TXT_HPP
|
||||
)";
|
||||
EXPECT_STREQ(expectedResult.data(), generator.Get().data());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(GeneratorFixture, GenerateNamespace)
|
||||
{
|
||||
Generator generator("Fixture/toto.txt");
|
||||
generator.SetMapping(MappingKey::NAMESPACE, "Test");
|
||||
EXPECT_TRUE(generator.Generate());
|
||||
|
||||
constexpr std::string_view expectedResult = R"(/**
|
||||
* Auto-generated header from: toto.txt
|
||||
* Generated by Bin2CPP
|
||||
*
|
||||
* DO NOT TOUCH
|
||||
*/
|
||||
#ifndef TOTO_TXT_HPP
|
||||
#define TOTO_TXT_HPP
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
namespace Test
|
||||
{
|
||||
inline constexpr std::array<std::byte, 11> g_toto_txt = {
|
||||
std::byte{0x48}, std::byte{0x65}, std::byte{0x6C}, std::byte{0x6C}, std::byte{0x6F}, std::byte{0x20}, std::byte{0x57}, std::byte{0x6F}, std::byte{0x72}, std::byte{0x6C}, std::byte{0x64}
|
||||
};
|
||||
|
||||
} // namespace Test
|
||||
|
||||
#endif // TOTO_TXT_HPP
|
||||
)";
|
||||
EXPECT_STREQ(expectedResult.data(), generator.Get().data());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(GeneratorFixture, GenerateCustomArray)
|
||||
{
|
||||
Generator generator("Fixture/toto.txt");
|
||||
generator.SetMapping(MappingKey::ARRAY_TYPE, "eastl::array");
|
||||
generator.SetMapping(MappingKey::ARRAY_TYPE_INCLUDE, "<EASTL/array.h>");
|
||||
generator.SetMapping(MappingKey::ARRAY_NAME, "g_myArray");
|
||||
EXPECT_TRUE(generator.Generate());
|
||||
|
||||
constexpr std::string_view expectedResult = R"(/**
|
||||
* Auto-generated header from: toto.txt
|
||||
* Generated by Bin2CPP
|
||||
*
|
||||
* DO NOT TOUCH
|
||||
*/
|
||||
#ifndef TOTO_TXT_HPP
|
||||
#define TOTO_TXT_HPP
|
||||
#include <EASTL/array.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline constexpr eastl::array<std::byte, 11> g_myArray = {
|
||||
std::byte{0x48}, std::byte{0x65}, std::byte{0x6C}, std::byte{0x6C}, std::byte{0x6F}, std::byte{0x20}, std::byte{0x57}, std::byte{0x6F}, std::byte{0x72}, std::byte{0x6C}, std::byte{0x64}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // TOTO_TXT_HPP
|
||||
)";
|
||||
EXPECT_STREQ(expectedResult.data(), generator.Get().data());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(GeneratorFixture, NonExistentFile)
|
||||
{
|
||||
Generator generator("Fixture/tata.txt");
|
||||
EXPECT_FALSE(generator.Generate());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(GeneratorFixture, Directory)
|
||||
{
|
||||
Generator generator("Fixture/");
|
||||
EXPECT_FALSE(generator.Generate());
|
||||
}
|
||||
} // namespace Bin2CPP
|
||||
@@ -0,0 +1,76 @@
|
||||
/*********************************************************************
|
||||
* \file Log.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#include <Log.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Assert.hpp>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
class LogFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
Log m_log;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, GetLogger_ShouldReturnTheLogger)
|
||||
{
|
||||
EXPECT_TRUE(m_log.GetLogger());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, LogDebug)
|
||||
{
|
||||
Singleton<Log>::Lifetime singletonLifetime;
|
||||
BIN2CPP_LOG_DEBUG("Hello");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, LogTrace)
|
||||
{
|
||||
Singleton<Log>::Lifetime singletonLifetime;
|
||||
|
||||
BIN2CPP_LOG_TRACE("Hello");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, LogInfo)
|
||||
{
|
||||
Singleton<Log>::Lifetime singletonLifetime;
|
||||
BIN2CPP_LOG_INFO("Hello");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, LogWarn)
|
||||
{
|
||||
Singleton<Log>::Lifetime singletonLifetime;
|
||||
BIN2CPP_LOG_WARN("Hello");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, LogError)
|
||||
{
|
||||
Singleton<Log>::Lifetime singletonLifetime;
|
||||
BIN2CPP_LOG_ERROR("Hello");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(LogFixture, LogFatal)
|
||||
{
|
||||
Singleton<Log>::Lifetime singletonLifetime;
|
||||
BIN2CPP_LOG_FATAL("Hello");
|
||||
}
|
||||
} // namespace Bin2CPP
|
||||
@@ -0,0 +1,39 @@
|
||||
/*********************************************************************
|
||||
* \file Singleton.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#include <Singleton.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bin2CPP
|
||||
{
|
||||
class SingletonFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
Singleton<std::uint8_t>::Lifetime m_lifetime {8};
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SingletonFixture, HasInstance_ShouldReturnTrueIfSingletonIsInitialized)
|
||||
{
|
||||
EXPECT_TRUE(Singleton<std::uint8_t>::HasInstance());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SingletonFixture, HasInstance_ShouldReturnFaleIfSingletonIsNotInitialized)
|
||||
{
|
||||
EXPECT_FALSE(Singleton<std::uint32_t>::HasInstance());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SingletonFixture, Instance_ShouldReturnTheInstance)
|
||||
{
|
||||
EXPECT_EQ(Singleton<std::uint8_t>::Instance(), 8);
|
||||
}
|
||||
} // namespace Bin2CPP
|
||||
@@ -0,0 +1 @@
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bin2CPPLib)
|
||||
@@ -0,0 +1,23 @@
|
||||
if(NOT TARGET Bin2CPP)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
find_program(BIN2CPP_EXECUTABLE
|
||||
NAMES Bin2CPP
|
||||
PATHS ENV PATH
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
else()
|
||||
find_program(BIN2CPP_EXECUTABLE
|
||||
NAMES Bin2CPP
|
||||
PATHS "${CMAKE_CURRENT_LIST_DIR}"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BIN2CPP_EXECUTABLE)
|
||||
get_filename_component(BIN2CPP_EXECUTABLE "${BIN2CPP_EXECUTABLE}" ABSOLUTE)
|
||||
add_executable(Bin2CPP IMPORTED)
|
||||
set_property(TARGET Bin2CPP PROPERTY IMPORTED_LOCATION ${BIN2CPP_EXECUTABLE})
|
||||
else()
|
||||
message(WARNING "Bin2CPP executable not found in ${CMAKE_CURRENT_LIST_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,19 @@
|
||||
add_library(Bin2CPPCompileAndLinkFlags INTERFACE)
|
||||
|
||||
target_compile_options(Bin2CPPCompileAndLinkFlags INTERFACE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
|
||||
$<$<CXX_COMPILER_ID:Clang,GNU>:-Wall -Wextra -Wpedantic -Werror>
|
||||
$<$<AND:$<BOOL:${COVERAGE}>,$<CXX_COMPILER_ID:Clang>>:-fprofile-instr-generate -fcoverage-mapping>
|
||||
)
|
||||
|
||||
target_link_options(Bin2CPPCompileAndLinkFlags INTERFACE
|
||||
$<$<AND:$<BOOL:${COVERAGE}>,$<CXX_COMPILER_ID:Clang>>:-fprofile-instr-generate>
|
||||
)
|
||||
|
||||
target_compile_definitions(Bin2CPPCompileAndLinkFlags INTERFACE
|
||||
$<$<CONFIG:Release>:BIN2CPP_OPTIMIZED>
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:BIN2CPP_NOT_OPTIMIZED>
|
||||
$<$<PLATFORM_ID:Windows>:BIN2CPP_WINDOWS>
|
||||
$<$<PLATFORM_ID:Linux>:BIN2CPP_LINUX>
|
||||
$<$<PLATFORM_ID:Windows>:NOMINMAX>
|
||||
$<$<PLATFORM_ID:Windows>:WIN32_LEAN_AND_MEAN>)
|
||||
@@ -0,0 +1,14 @@
|
||||
find_package(Python3 COMPONENTS Interpreter Development)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(magic_enum REQUIRED)
|
||||
find_package(CLI11 REQUIRED)
|
||||
find_package(quill REQUIRED)
|
||||
|
||||
if(BUILD_TESTS)
|
||||
find_package(GTest REQUIRED)
|
||||
endif()
|
||||
@@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 3.26)
|
||||
|
||||
project(Bin2CPP VERSION 1.0.0
|
||||
DESCRIPTION "Bin2CPP"
|
||||
LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/CMake/CustomTargets.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/CMake/FindDependencies.cmake)
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "" FORCE)
|
||||
|
||||
option(BUILD_TESTS OFF)
|
||||
option(ASAN OFF)
|
||||
option(COVERAGE OFF)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_OPTIMIZE_DEPENDENCIES 1)
|
||||
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
SET(CMAKE_INSTALL_RPATH "\${ORIGIN}")
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bin2CPP/Sources)
|
||||
if(${BUILD_TESTS})
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Bin2CPP/Tests)
|
||||
endif()
|
||||
@@ -0,0 +1,5 @@
|
||||
include_guard()
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
||||
@@ -0,0 +1,2 @@
|
||||
[built-in options]
|
||||
b_lto = true
|
||||
@@ -0,0 +1,9 @@
|
||||
include_guard()
|
||||
|
||||
find_program(MOLD_PROGRAM mold)
|
||||
if (MOLD_PROGRAM)
|
||||
set(CMAKE_LINKER_TYPE MOLD)
|
||||
message(STATUS "mold linker found: ${MOLD_PROGRAM}")
|
||||
else ()
|
||||
message(WARNING "mold linker not found")
|
||||
endif ()
|
||||
@@ -0,0 +1,19 @@
|
||||
[settings]
|
||||
os=Linux
|
||||
arch=x86_64
|
||||
compiler=clang
|
||||
compiler.version=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Release
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/../Toolchains/ipo.cmake
|
||||
tools.meson.mesontoolchain:extra_machine_files+={{profile_dir}}/../Toolchains/ipo.ini
|
||||
|
||||
tools.system.package_manager:mode=install
|
||||
tools.system.package_manager:sudo=True
|
||||
|
||||
tools.build:compiler_executables={"c": "clang", "cpp": "clang++"}
|
||||
@@ -0,0 +1,18 @@
|
||||
[settings]
|
||||
os=Windows
|
||||
arch=x86_64
|
||||
compiler=msvc
|
||||
compiler.version=195
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Release
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/../Toolchains/ipo.cmake
|
||||
tools.meson.mesontoolchain:extra_machine_files+={{profile_dir}}/../Toolchains/ipo.ini
|
||||
|
||||
tools.build:cflags=["/Zc:preprocessor", "/Zc:__STDC__", "/D_CRT_DECLARE_NONSTDC_NAMES=1"]
|
||||
tools.build:cxxflags=["/Zc:preprocessor", "/permissive-", "/Zc:__cplusplus", "/Zc:enumTypes", "/Zc:templateScope"]
|
||||
|
||||
tools.env.virtualenv:powershell=powershell.exe
|
||||
@@ -0,0 +1,30 @@
|
||||
[settings]
|
||||
os=Linux
|
||||
arch=x86_64
|
||||
compiler=clang
|
||||
compiler.version=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Release
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/Toolchains/mold.cmake
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/Toolchains/ipo.cmake
|
||||
tools.meson.mesontoolchain:extra_machine_files+={{profile_dir}}/Toolchains/ipo.ini
|
||||
|
||||
tools.system.package_manager:mode=install
|
||||
tools.system.package_manager:sudo=True
|
||||
|
||||
tools.build:compiler_executables={"c": "clang", "cpp": "clang++"}
|
||||
|
||||
tools.cmake.cmaketoolchain:generator=Ninja
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/4.3.2
|
||||
!mold/*: mold/2.41.0@bigfootdev/main
|
||||
!ninja/*: ninja/1.13.2
|
||||
|
||||
[options]
|
||||
bin2cpp/*:build_tests=True
|
||||
@@ -0,0 +1,35 @@
|
||||
[settings]
|
||||
os=Linux
|
||||
arch=x86_64
|
||||
compiler=clang
|
||||
compiler.version=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Debug
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/Toolchains/mold.cmake
|
||||
|
||||
tools.system.package_manager:mode=install
|
||||
tools.system.package_manager:sudo=True
|
||||
|
||||
tools.build:exelinkflags=["-fsanitize=address,undefined,leak"]
|
||||
tools.build:sharedlinkflags=["-fsanitize=address,undefined,leak"]
|
||||
|
||||
tools.build:cflags=["-fsanitize=address,undefined,leak", "-fno-sanitize-recover=all"]
|
||||
tools.build:cxxflags=["-fsanitize=address,undefined,leak", "-fno-sanitize-recover=all"]
|
||||
|
||||
tools.cmake.cmaketoolchain:generator=Ninja
|
||||
|
||||
tools.build:compiler_executables={"c": "clang", "cpp": "clang++"}
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/4.3.2
|
||||
!mold/*: mold/2.41.0@bigfootdev/main
|
||||
!ninja/*: ninja/1.13.2
|
||||
|
||||
[options]
|
||||
bin2cpp/*:asan=True
|
||||
bin2cpp/*:build_tests=True
|
||||
@@ -0,0 +1,29 @@
|
||||
[settings]
|
||||
os=Linux
|
||||
arch=x86_64
|
||||
compiler=clang
|
||||
compiler.version=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Debug
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/Toolchains/mold.cmake
|
||||
|
||||
tools.system.package_manager:mode=install
|
||||
tools.system.package_manager:sudo=True
|
||||
|
||||
tools.cmake.cmaketoolchain:generator=Ninja
|
||||
|
||||
tools.build:compiler_executables={"c": "clang", "cpp": "clang++"}
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/4.3.2
|
||||
!mold/*: mold/2.41.0@bigfootdev/main
|
||||
!ninja/*: ninja/1.13.2
|
||||
|
||||
[options]
|
||||
bin2cpp/*:build_tests=True
|
||||
bin2cpp/*:coverage=True
|
||||
@@ -0,0 +1,24 @@
|
||||
[settings]
|
||||
os=Windows
|
||||
arch=x86_64
|
||||
compiler=msvc
|
||||
compiler.version=195
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Release
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/Toolchains/ipo.cmake
|
||||
tools.meson.mesontoolchain:extra_machine_files+={{profile_dir}}/Toolchains/ipo.ini
|
||||
|
||||
tools.build:cflags=["/Zc:preprocessor", "/Zc:__STDC__", "/D_CRT_DECLARE_NONSTDC_NAMES=1"]
|
||||
tools.build:cxxflags=["/Zc:preprocessor", "/permissive-", "/Zc:__cplusplus", "/Zc:enumTypes", "/Zc:templateScope", "/Zc:throwingNew"]
|
||||
|
||||
tools.env.virtualenv:powershell=powershell.exe
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/4.3.2
|
||||
|
||||
[options]
|
||||
bin2cpp/*:build_tests=True
|
||||
@@ -0,0 +1,22 @@
|
||||
[settings]
|
||||
os=Windows
|
||||
arch=x86_64
|
||||
compiler=msvc
|
||||
compiler.version=195
|
||||
compiler.cppstd=20
|
||||
compiler.cstd=17
|
||||
compiler.runtime=static
|
||||
build_type=Debug
|
||||
|
||||
[conf]
|
||||
tools.build:cflags=["/Zc:preprocessor", "/Zc:__STDC__", "/D_CRT_DECLARE_NONSTDC_NAMES=1", "/fsanitize=address"]
|
||||
tools.build:cxxflags=["/Zc:preprocessor", "/permissive-", "/Zc:__cplusplus", "/Zc:enumTypes", "/Zc:templateScope", "/Zc:throwingNew", "/fsanitize=address"]
|
||||
|
||||
tools.env.virtualenv:powershell=powershell.exe
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/4.3.2
|
||||
|
||||
[options]
|
||||
bin2cpp/*:asan=True
|
||||
bin2cpp/*:build_tests=True
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022-2026 Romain BOULLARD
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,84 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
|
||||
from conan.tools.files import copy
|
||||
import os
|
||||
|
||||
required_conan_version = ">=1.33.0"
|
||||
|
||||
class Bin2CPP(ConanFile):
|
||||
name = "bin2cpp"
|
||||
homepage = "https://git.romainboullard.com/rboullard/Bin2CPP"
|
||||
description = "A utility that converts files to CPP headers"
|
||||
topics = ("utility")
|
||||
license = "MIT"
|
||||
version = "1.0.0"
|
||||
package_type = "application"
|
||||
|
||||
# Binary configuration
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
options = {
|
||||
"shared": [True, False],
|
||||
"fPIC": [True, False],
|
||||
"build_tests": [True, False],
|
||||
"asan": [True, False],
|
||||
"coverage": [True, False]
|
||||
}
|
||||
default_options = {
|
||||
"shared": False,
|
||||
"fPIC": True,
|
||||
"build_tests": False,
|
||||
"asan": False,
|
||||
"coverage": False
|
||||
}
|
||||
|
||||
generators = "CMakeDeps"
|
||||
|
||||
def export_sources(self):
|
||||
copy(self, "CMakeLists.txt", self.recipe_folder, self.export_sources_folder)
|
||||
copy(self, os.path.join("Bin2CPP", "*"), self.recipe_folder, self.export_sources_folder)
|
||||
copy(self, os.path.join("CMake", "*"), self.recipe_folder, self.export_sources_folder)
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def configure(self):
|
||||
if self.settings.os == "Windows":
|
||||
del self.options.fPIC
|
||||
|
||||
def requirements(self):
|
||||
self.requires("quill/11.0.2", transitive_headers=True)
|
||||
self.requires("magic_enum/0.9.7", transitive_headers=True)
|
||||
self.requires("cli11/2.6.1@bigfootdev/main")
|
||||
|
||||
if(self.options.build_tests):
|
||||
self.test_requires("gtest/1.17.0")
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
|
||||
tc.variables["BUILD_TESTS"] = self.options.build_tests
|
||||
tc.variables["ASAN"] = self.options.asan
|
||||
tc.variables["COVERAGE"] = self.options.coverage
|
||||
|
||||
tc.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def package(self):
|
||||
copy(self, pattern="LICENSE", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
|
||||
copy(self, "Bin2CPPTargets.cmake",
|
||||
src=os.path.join(self.source_folder, "CMake"),
|
||||
dst=os.path.join(self.package_folder, "bin"))
|
||||
|
||||
@property
|
||||
def _module_path(self):
|
||||
return os.path.join("bin", "Bin2CPPTargets.cmake")
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.set_property("cmake_build_modules", [self._module_path])
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
@echo off
|
||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||
|
||||
REM =========================
|
||||
REM Variables
|
||||
REM =========================
|
||||
SET FMT=clang-format
|
||||
SET MODE=
|
||||
SET EXIT_CODE=0
|
||||
|
||||
REM =========================
|
||||
REM Parse arguments
|
||||
REM =========================
|
||||
:parse_args
|
||||
IF "%~1"=="" GOTO end_parse_args
|
||||
IF "%~1"=="--check" (
|
||||
SET MODE=check
|
||||
) ELSE IF "%~1"=="--fix" (
|
||||
SET MODE=fix
|
||||
) ELSE (
|
||||
REM Accumulate directories
|
||||
SET DIRS=!DIRS! "%~1"
|
||||
)
|
||||
SHIFT
|
||||
GOTO parse_args
|
||||
:end_parse_args
|
||||
|
||||
IF "%MODE%"=="" (
|
||||
ECHO Usage: %~nx0 --check|--fix <directory> [<directory> ...]
|
||||
EXIT /B 1
|
||||
)
|
||||
|
||||
IF "%DIRS%"=="" (
|
||||
ECHO Please provide at least one directory.
|
||||
EXIT /B 1
|
||||
)
|
||||
|
||||
REM =========================
|
||||
REM Iterate over directories
|
||||
REM =========================
|
||||
FOR %%D IN (%DIRS%) DO (
|
||||
IF NOT EXIST "%%~D" (
|
||||
ECHO %%~D is not a valid directory.
|
||||
SET EXIT_CODE=1
|
||||
GOTO :continue_dirs
|
||||
)
|
||||
|
||||
REM Recursively find source files
|
||||
FOR /R "%%~D" %%F IN (*.h *.hpp *.c *.cpp *.m *.mm) DO (
|
||||
SET FILE=%%F
|
||||
REM Skip *_generated* files
|
||||
ECHO !FILE! | FINDSTR /I "_generated" >nul
|
||||
IF ERRORLEVEL 1 (
|
||||
IF "%MODE%"=="fix" (
|
||||
ECHO Formatting !FILE!
|
||||
%FMT% -i "!FILE!"
|
||||
) ELSE (
|
||||
ECHO Checking !FILE!
|
||||
%FMT% --dry-run --Werror "!FILE!" 2>nul
|
||||
IF ERRORLEVEL 1 (
|
||||
REM clang-format will already print diagnostics
|
||||
SET EXIT_CODE=1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:continue_dirs
|
||||
)
|
||||
|
||||
EXIT /B %EXIT_CODE%
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
FMT="clang-format"
|
||||
MODE=""
|
||||
DIRS=()
|
||||
EXIT_CODE=0
|
||||
|
||||
# =========================
|
||||
# Parse arguments
|
||||
# =========================
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--check)
|
||||
MODE="check"
|
||||
;;
|
||||
--fix)
|
||||
MODE="fix"
|
||||
;;
|
||||
*)
|
||||
DIRS+=("$arg")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Ensure mode is set
|
||||
if [[ -z "$MODE" ]]; then
|
||||
echo "Usage: $0 --check|--fix <directory> [<directory> ...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure at least one directory
|
||||
if [[ ${#DIRS[@]} -eq 0 ]]; then
|
||||
echo "Please provide at least one directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# =========================
|
||||
# Process directories
|
||||
# =========================
|
||||
for DIR in "${DIRS[@]}"; do
|
||||
if [[ ! -d "$DIR" ]]; then
|
||||
echo "$DIR is not a valid directory."
|
||||
EXIT_CODE=1
|
||||
continue
|
||||
fi
|
||||
|
||||
# Find all source files safely (null-separated)
|
||||
while IFS= read -r -d '' FILE; do
|
||||
[[ "$FILE" == *_generated* ]] && continue
|
||||
|
||||
if [[ "$MODE" == "fix" ]]; then
|
||||
echo "Formatting $FILE"
|
||||
"$FMT" -i "$FILE"
|
||||
else
|
||||
echo "Checking $FILE"
|
||||
# Check mode: clang-format diagnostic only
|
||||
if ! "$FMT" --dry-run --Werror "$FILE"; then
|
||||
# clang-format prints: file:line:col: error ...
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
fi
|
||||
done < <(
|
||||
find "$DIR" \( -name '*.h' -o -name '*.hpp' -o -name '*.c' -o -name '*.cpp' -o -name '*.m' -o -name '*.mm' \) -print0
|
||||
)
|
||||
done
|
||||
|
||||
exit $EXIT_CODE
|
||||
@@ -0,0 +1,60 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
REM ─── Validate argument ───────────────────────────────────────────────────────
|
||||
if "%~1"=="force" set "build_option=--build=*" & goto :start
|
||||
if "%~1"=="missing" set "build_option=--build=missing" & goto :start
|
||||
|
||||
echo Usage: %~n0 [force^|missing]
|
||||
echo force - Rebuild all packages from source
|
||||
echo missing - Only build packages not already cached
|
||||
exit /b 1
|
||||
|
||||
:start
|
||||
REM ─── Register remote (skip if already registered) ────────────────────────────
|
||||
conan remote list | findstr /i "bigfootpackages" >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo Adding Conan remote: bigfootpackages
|
||||
conan remote add bigfootpackages https://conan.romainboullard.com/artifactory/api/conan/BigfootPackages
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Failed to add Conan remote.
|
||||
exit /b 1
|
||||
)
|
||||
) else (
|
||||
echo Conan remote 'bigfootpackages' already registered, skipping.
|
||||
)
|
||||
|
||||
REM ─── Shared flags ────────────────────────────────────────────────────────────
|
||||
set "conan_common=--remote=bigfootpackages -pr:h=./ConanProfiles/msvc -pr:b=./ConanProfiles/Tools/msvc -of build"
|
||||
|
||||
REM ─── Install dependencies for each build type ────────────────────────────────
|
||||
for %%C in (Release RelWithDebInfo Debug) do (
|
||||
echo.
|
||||
echo [%%C] Installing dependencies...
|
||||
conan install . %conan_common% %build_option% -s:h build_type=%%C
|
||||
if errorlevel 1 (
|
||||
echo ERROR: conan install failed for build type %%C
|
||||
exit /b 1
|
||||
)
|
||||
echo [%%C] Done.
|
||||
)
|
||||
|
||||
echo.
|
||||
echo All build types installed successfully.
|
||||
|
||||
REM ─── Activate build environment and run CMake ────────────────────────────────
|
||||
echo.
|
||||
echo Activating build environment and configuring CMake...
|
||||
mkdir graphviz 2>nul
|
||||
|
||||
powershell -ExecutionPolicy Bypass -Command "& 'build/build/generators/conanbuild.ps1'; cmake -S . -B build --toolchain build/build/generators/conan_toolchain.cmake --graphviz=graphviz/graph.dot; if ($LASTEXITCODE -ne 0) { Write-Host 'ERROR: CMake configuration failed'; exit 1 }"
|
||||
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Build environment or CMake step failed.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo CMake configuration successful.
|
||||
|
||||
endlocal
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ─── Validate arguments ───────────────────────────────────────────────────────
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: $(basename "$0") [force|missing] [Release|RelWithDebInfo|Debug]"
|
||||
echo " force - Rebuild all packages from source"
|
||||
echo " missing - Only build packages not already cached"
|
||||
echo " build_type (optional) - One of: Release, RelWithDebInfo, Debug"
|
||||
echo " If omitted, all build types are processed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "${1:-}" in
|
||||
force) build_option="--build=*" ;;
|
||||
missing) build_option="--build=missing" ;;
|
||||
*)
|
||||
echo "Usage: $(basename "$0") [force|missing] [Release|RelWithDebInfo|Debug]"
|
||||
echo " force - Rebuild all packages from source"
|
||||
echo " missing - Only build packages not already cached"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# ─── Validate optional build_type argument ────────────────────────────────────
|
||||
all_build_types=(Release RelWithDebInfo Debug)
|
||||
|
||||
if [[ -n "${2:-}" ]]; then
|
||||
case "${2}" in
|
||||
Release|RelWithDebInfo|Debug)
|
||||
build_types=("${2}")
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Invalid build type '${2}'. Must be one of: Release, RelWithDebInfo, Debug"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
build_types=("${all_build_types[@]}")
|
||||
fi
|
||||
|
||||
# ─── Register remote (skip if already registered) ─────────────────────────────
|
||||
if conan remote list 2>/dev/null | grep -qi "bigfootpackages"; then
|
||||
echo "Conan remote 'bigfootpackages' already registered, skipping."
|
||||
else
|
||||
echo "Adding Conan remote: bigfootpackages"
|
||||
if ! conan remote add bigfootpackages https://conan.romainboullard.com/artifactory/api/conan/BigfootPackages; then
|
||||
echo "ERROR: Failed to add Conan remote."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─── Shared flags ─────────────────────────────────────────────────────────────
|
||||
conan_common=(
|
||||
--remote=bigfootpackages
|
||||
-pr:h=./ConanProfiles/clang
|
||||
-pr:b=./ConanProfiles/Tools/clang
|
||||
-of build
|
||||
)
|
||||
|
||||
# ─── Install dependencies for each build type ─────────────────────────────────
|
||||
for build_type in "${build_types[@]}"; do
|
||||
echo
|
||||
echo "[${build_type}] Installing dependencies..."
|
||||
if ! conan install . "${conan_common[@]}" ${build_option} -s:h "build_type=${build_type}"; then
|
||||
echo "ERROR: conan install failed for build type ${build_type}"
|
||||
exit 1
|
||||
fi
|
||||
echo "[${build_type}] Done."
|
||||
done
|
||||
|
||||
echo
|
||||
echo "All selected build types installed successfully."
|
||||
|
||||
# ─── Configure CMake for each build type ─────────────────────────────────────
|
||||
echo
|
||||
echo "Configuring CMake for each build type..."
|
||||
|
||||
for build_type in "${build_types[@]}"; do
|
||||
echo
|
||||
echo "[${build_type}] Activating build environment..."
|
||||
# shellcheck disable=SC1090
|
||||
source "build/build/${build_type}/generators/conanbuild.sh"
|
||||
|
||||
mkdir -p "graphviz/${build_type}"
|
||||
|
||||
echo "[${build_type}] Running CMake..."
|
||||
if ! cmake -S . -B "build/${build_type}" \
|
||||
--toolchain "build/build/${build_type}/generators/conan_toolchain.cmake" \
|
||||
-DCMAKE_BUILD_TYPE="${build_type}" \
|
||||
-G "Ninja" \
|
||||
--graphviz="graphviz/${build_type}/graph.dot"; then
|
||||
echo "ERROR: CMake configuration failed for build type ${build_type}."
|
||||
exit 1
|
||||
fi
|
||||
echo "[${build_type}] Done."
|
||||
done
|
||||
|
||||
echo
|
||||
echo "CMake configuration successful."
|
||||
@@ -0,0 +1,14 @@
|
||||
sonar.projectKey=Bin2CPP
|
||||
|
||||
sonar.projectVersion=1.0.0
|
||||
|
||||
sonar.sourceEncoding=UTF-8
|
||||
|
||||
sonar.sources=Bin2CPP/Sources
|
||||
sonar.tests=Bin2CPP/Tests
|
||||
|
||||
sonar.cxx.file.suffixes=.hpp,.cpp,.h
|
||||
sonar.cxx.clangtidy.reportPaths=tidy_result.txt
|
||||
sonar.cxx.infer.reportPaths=infer-out/report.json
|
||||
|
||||
sonar.cxx.jsonCompilationDatabase.analyzeOnlyContainedFiles=True
|
||||
@@ -0,0 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(test_package LANGUAGES C)
|
||||
|
||||
find_package(Bin2CPP REQUIRED CONFIG)
|
||||
|
||||
find_program(BIN2CPP_EXECUTABLE NAMES Bin2CPP)
|
||||
execute_process(COMMAND ${BIN2CPP_EXECUTABLE} -h)
|
||||
@@ -0,0 +1,18 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.build import can_run
|
||||
from conan.tools.cmake import CMake, cmake_layout
|
||||
import os
|
||||
|
||||
|
||||
class TestPackageConan(ConanFile):
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def requirements(self):
|
||||
self.requires(self.tested_reference_str)
|
||||
|
||||
def test(self):
|
||||
self.run("Bin2CPP --help", env="conanrun")
|
||||
Reference in New Issue
Block a user