├── .clang-format ├── .dockerignore ├── .github └── workflows │ ├── amd64_docker_cmake.yml │ ├── amd64_linux_cmake.yml │ ├── amd64_macos_cmake.yml │ ├── amd64_windows_cmake.yml │ ├── arm64_docker_cmake.yml │ ├── arm64_macos_cmake.yml │ └── riscv64_docker_cmake.yml ├── .gitignore ├── AUTHORS ├── Bar ├── CMakeLists.txt ├── include │ └── bar │ │ └── Bar.hpp ├── src │ └── Bar.cpp └── tests │ ├── CMakeLists.txt │ └── bar_test.cpp ├── CMakeLists.txt ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── Foo ├── CMakeLists.txt ├── include │ └── foo │ │ └── Foo.hpp ├── src │ └── Foo.cpp └── tests │ ├── CMakeLists.txt │ └── foo_test.cpp ├── FooApp ├── CMakeLists.txt ├── msg.proto └── src │ └── main.cpp ├── LICENSE ├── README.md ├── ci ├── Makefile ├── README.md ├── docker │ ├── almalinux │ │ └── Dockerfile │ ├── alpine │ │ └── Dockerfile │ ├── archlinux │ │ └── Dockerfile │ ├── debian │ │ └── Dockerfile │ ├── fedora │ │ └── Dockerfile │ ├── opensuse │ │ └── Dockerfile │ ├── rockylinux │ │ └── Dockerfile │ └── ubuntu │ │ └── Dockerfile ├── docs │ ├── docker.dot │ ├── docker.svg │ └── generate_image.sh ├── samples │ ├── CMakeLists.txt │ └── main.cpp └── vagrant │ ├── freebsd │ └── Vagrantfile │ ├── netbsd │ └── Vagrantfile │ └── openbsd │ └── Vagrantfile ├── cmake ├── CMakeExternalConfig.cmake.in ├── check_deps.cmake ├── cpp.cmake ├── dependencies │ └── CMakeLists.txt ├── host.CMakeLists.txt ├── host.cmake └── system_deps.cmake ├── examples ├── CMakeLists.txt └── example.cpp └── patches ├── ZLIB-v1.3.1.patch ├── abseil-cpp-20240722.0.patch ├── googletest-v1.15.2.patch ├── protobuf-v29.3.patch └── re2-2024-04-01.patch /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | Standard: Cpp11 4 | Cpp11BracedListStyle: true 5 | UseTab: ForIndentation 6 | TabWidth: 2 7 | IndentWidth: 2 8 | ContinuationIndentWidth: 2 9 | ConstructorInitializerIndentWidth: 2 10 | AccessModifierOffset: 0 11 | AlignAfterOpenBracket: true 12 | AlignConsecutiveAssignments: true 13 | AlignConsecutiveDeclarations: false 14 | AlignEscapedNewlinesLeft: true 15 | AlignOperands: true 16 | AlignTrailingComments: true 17 | AllowAllParametersOfDeclarationOnNextLine: false 18 | AllowShortBlocksOnASingleLine: false 19 | AllowShortCaseLabelsOnASingleLine: false 20 | AllowShortFunctionsOnASingleLine: Inline 21 | AllowShortIfStatementsOnASingleLine: true 22 | AllowShortLoopsOnASingleLine: false 23 | AlwaysBreakAfterDefinitionReturnType: TopLevel 24 | AlwaysBreakAfterReturnType: TopLevelDefinitions 25 | AlwaysBreakBeforeMultilineStrings: true 26 | AlwaysBreakTemplateDeclarations: true 27 | BinPackParameters: false 28 | BinPackArguments: false 29 | BreakBeforeBinaryOperators: None 30 | BreakBeforeBraces: Attach 31 | BreakBeforeTernaryOperators: false 32 | BreakConstructorInitializersBeforeComma: true 33 | ColumnLimit: 88 34 | CommentPragmas: '^ IWYU pragma:' 35 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 36 | DerivePointerAlignment: false 37 | DisableFormat: false 38 | ExperimentalAutoDetectBinPacking: false 39 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 40 | IndentCaseLabels: true 41 | IndentFunctionDeclarationAfterType: false 42 | IndentWrappedFunctionNames: false 43 | KeepEmptyLinesAtTheStartOfBlocks: false 44 | MaxEmptyLinesToKeep: 1 45 | NamespaceIndentation: Inner 46 | ObjCBlockIndentWidth: 2 47 | ObjCSpaceAfterProperty: false 48 | ObjCSpaceBeforeProtocolList: false 49 | PenaltyBreakBeforeFirstCallParameter: 1 50 | PenaltyBreakComment: 300 51 | PenaltyBreakFirstLessLess: 120 52 | PenaltyBreakString: 1000 53 | PenaltyExcessCharacter: 1000000 54 | PenaltyReturnTypeOnItsOwnLine: 200 55 | PointerAlignment: Left 56 | SortIncludes: true 57 | SpaceAfterCStyleCast: false 58 | SpaceBeforeAssignmentOperators: true 59 | SpaceBeforeParens: ControlStatements 60 | SpaceInEmptyParentheses: false 61 | SpacesBeforeTrailingComments: 1 62 | SpacesInAngles: false 63 | SpacesInCStyleCastParentheses: false 64 | SpacesInContainerLiterals: false 65 | SpacesInParentheses: false 66 | SpacesInSquareBrackets: false 67 | ... 68 | 69 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Project Files unneeded by docker 2 | .dockerignore 3 | 4 | .git 5 | .gitignore 6 | .github 7 | .clang-format 8 | 9 | # CMake 10 | cmake/docs 11 | cmake/README.md 12 | 13 | ci/docker 14 | ci/docs 15 | ci/cache 16 | ci/Makefile 17 | 18 | AUTHORS 19 | CONTRIBUTORS 20 | LICENSE 21 | README.md 22 | CONTRIBUTING.md 23 | 24 | # Native cmake build 25 | build/ 26 | build*/ 27 | 28 | # Editor directories and files 29 | *.user 30 | *.swp 31 | -------------------------------------------------------------------------------- /.github/workflows/amd64_docker_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/docker-library/official-images 2 | name: amd64 Docker CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | jobs: 11 | docker: 12 | strategy: 13 | matrix: 14 | distro: [ 15 | almalinux, 16 | alpine, 17 | archlinux, 18 | debian, 19 | fedora, 20 | opensuse, 21 | rockylinux, 22 | ubuntu 23 | ] 24 | fail-fast: false 25 | name: amd64•${{matrix.distro}}•CMake 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v4 29 | - name: Check docker 30 | run: | 31 | docker info 32 | docker buildx ls 33 | - name: Build env image 34 | run: make --directory=ci amd64_${{matrix.distro}}_env 35 | - name: Build devel image 36 | run: make --directory=ci amd64_${{matrix.distro}}_devel 37 | - name: Build project 38 | run: make --directory=ci amd64_${{matrix.distro}}_build 39 | - name: Test project 40 | run: make --directory=ci amd64_${{matrix.distro}}_test 41 | 42 | - name: Build install env image 43 | run: make --directory=ci amd64_${{matrix.distro}}_install_env 44 | - name: Build install devel image 45 | run: make --directory=ci amd64_${{matrix.distro}}_install_devel 46 | - name: Build install project 47 | run: make --directory=ci amd64_${{matrix.distro}}_install_build 48 | - name: Test install project 49 | run: make --directory=ci amd64_${{matrix.distro}}_install_test 50 | 51 | amd64_docker_cmake: 52 | runs-on: ubuntu-latest 53 | needs: docker 54 | steps: 55 | - uses: actions/checkout@v4 56 | -------------------------------------------------------------------------------- /.github/workflows/amd64_linux_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/actions/runner-images 2 | name: amd64 Linux CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | # Building using the github runner environement directly. 11 | jobs: 12 | native: 13 | strategy: 14 | matrix: 15 | cmake: [ 16 | {name: "Make", generator: "Unix Makefiles", config: "Release"}, 17 | {name: "Ninja", generator: "Ninja", config: "Release"}, 18 | {name: "Ninja Multi", generator: "Ninja Multi-Config", config: "Release"}, 19 | ] 20 | fail-fast: false 21 | name: amd64•Linux•CMake(${{matrix.cmake.name}}) 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: Install Ninja 26 | run: | 27 | sudo apt-get update 28 | sudo apt-get install ninja-build 29 | - name: Check CMake 30 | run: cmake --version 31 | - name: Configure 32 | run: > 33 | cmake -S. -Bbuild 34 | -G "${{matrix.cmake.generator}}" 35 | -DCMAKE_BUILD_TYPE=${{matrix.cmake.config}} 36 | -DCMAKE_INSTALL_PREFIX=install 37 | - name: Build 38 | run: > 39 | cmake --build build 40 | --config ${{matrix.cmake.config}} 41 | --target all 42 | -v -j2 43 | - name: Test 44 | run: > 45 | CTEST_OUTPUT_ON_FAILURE=1 46 | cmake --build build 47 | --config ${{matrix.cmake.config}} 48 | --target test 49 | -v 50 | - name: Install 51 | run: > 52 | cmake --build build 53 | --config ${{matrix.cmake.config}} 54 | --target install 55 | -v 56 | 57 | amd64_linux_cmake: 58 | runs-on: ubuntu-latest 59 | needs: native 60 | steps: 61 | - uses: actions/checkout@v4 62 | -------------------------------------------------------------------------------- /.github/workflows/amd64_macos_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/actions/runner-images 2 | name: amd64 MacOS CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | # Building using the github runner environement directly. 11 | jobs: 12 | native: 13 | strategy: 14 | matrix: 15 | cmake: [ 16 | {name: "Xcode", generator: "Xcode", config: Release, build_target: ALL_BUILD, test_target: RUN_TESTS, install_target: install}, 17 | {name: "Make", generator: "Unix Makefiles", config: Release, build_target: all, test_target: test, install_target: install}, 18 | ] 19 | fail-fast: false 20 | name: amd64•MacOS•CMake(${{matrix.cmake.name}}) 21 | runs-on: macos-13 # last macos intel based runner 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Check CMake 25 | run: cmake --version 26 | - name: Configure 27 | run: > 28 | cmake -S. -Bbuild 29 | -G "${{matrix.cmake.generator}}" 30 | -DCMAKE_BUILD_TYPE=${{matrix.cmake.config}} 31 | -DCMAKE_INSTALL_PREFIX=install 32 | - name: Build 33 | run: > 34 | cmake --build build 35 | --config ${{matrix.cmake.config}} 36 | --target ${{matrix.cmake.build_target}} 37 | -v -j2 38 | - name: Test 39 | run: > 40 | CTEST_OUTPUT_ON_FAILURE=1 41 | cmake --build build 42 | --config ${{matrix.cmake.config}} 43 | --target ${{matrix.cmake.test_target}} 44 | -v 45 | - name: Install 46 | run: > 47 | cmake --build build 48 | --config ${{matrix.cmake.config}} 49 | --target ${{matrix.cmake.install_target}} 50 | -v 51 | 52 | amd64_macos_cmake: 53 | runs-on: ubuntu-latest 54 | needs: native 55 | steps: 56 | - uses: actions/checkout@v4 57 | -------------------------------------------------------------------------------- /.github/workflows/amd64_windows_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/actions/runner-images 2 | name: amd64 Windows CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | # Building using the github runner environement directly. 11 | jobs: 12 | native: 13 | strategy: 14 | matrix: 15 | cmake: [ 16 | {name: "VS22", generator: "Visual Studio 17 2022", config: Release, build_target: ALL_BUILD, test_target: RUN_TESTS, install_target: INSTALL}, 17 | {name: "VS22", generator: "Visual Studio 17 2022", config: Debug, build_target: ALL_BUILD, test_target: RUN_TESTS, install_target: INSTALL}, 18 | ] 19 | fail-fast: false 20 | name: amd64•Windows•CMake(${{matrix.cmake.name}},${{matrix.cmake.config}}) 21 | runs-on: windows-latest 22 | env: 23 | CTEST_OUTPUT_ON_FAILURE: 1 24 | steps: 25 | - uses: actions/checkout@v4 26 | - name: Check CMake 27 | run: | 28 | cmake --version 29 | cmake -G || true 30 | - name: Configure 31 | run: > 32 | cmake -S. -Bbuild 33 | -G "${{matrix.cmake.generator}}" 34 | -DCMAKE_CONFIGURATION_TYPES=${{matrix.cmake.config}} 35 | -DCMAKE_INSTALL_PREFIX=install 36 | - name: Build 37 | run: > 38 | cmake --build build 39 | --config ${{matrix.cmake.config}} 40 | --target ${{matrix.cmake.build_target}} 41 | -v -j2 42 | - name: Test 43 | run: > 44 | cmake --build build 45 | --config ${{matrix.cmake.config}} 46 | --target ${{matrix.cmake.test_target}} 47 | -v 48 | - name: Install 49 | run: > 50 | cmake --build build 51 | --config ${{matrix.cmake.config}} 52 | --target ${{matrix.cmake.install_target}} 53 | -v 54 | 55 | amd64_windows_cmake: 56 | runs-on: ubuntu-latest 57 | needs: native 58 | steps: 59 | - uses: actions/checkout@v4 60 | -------------------------------------------------------------------------------- /.github/workflows/arm64_docker_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/docker-library/official-images 2 | name: arm64 Docker CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | jobs: 11 | docker: 12 | strategy: 13 | matrix: 14 | distro: [ 15 | almalinux, 16 | alpine, 17 | debian, 18 | #fedora, # timeout 19 | #opensuse, # timeout 20 | rockylinux, 21 | ubuntu 22 | ] 23 | fail-fast: false 24 | name: arm64•${{matrix.distro}}•CMake 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v4 28 | - name: Set up QEMU 29 | uses: docker/setup-qemu-action@v3 30 | - name: Check docker 31 | run: | 32 | docker info 33 | docker buildx ls 34 | - name: Build env image 35 | run: make --directory=ci arm64_${{matrix.distro}}_env 36 | - name: Build devel project 37 | run: make --directory=ci arm64_${{matrix.distro}}_devel 38 | - name: Build project 39 | run: make --directory=ci arm64_${{matrix.distro}}_build 40 | - name: Test project 41 | run: make --directory=ci arm64_${{matrix.distro}}_test 42 | 43 | - name: Build install env image 44 | run: make --directory=ci arm64_${{matrix.distro}}_install_env 45 | - name: Build install devel project 46 | run: make --directory=ci arm64_${{matrix.distro}}_install_devel 47 | - name: Build install project 48 | run: make --directory=ci arm64_${{matrix.distro}}_install_build 49 | - name: Test install project 50 | run: make --directory=ci arm64_${{matrix.distro}}_install_test 51 | 52 | arm64_docker_cmake: 53 | runs-on: ubuntu-latest 54 | needs: docker 55 | steps: 56 | - uses: actions/checkout@v4 57 | -------------------------------------------------------------------------------- /.github/workflows/arm64_macos_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/actions/runner-images 2 | name: arm64 MacOS CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | # Building using the github runner environement directly. 11 | jobs: 12 | native: 13 | strategy: 14 | matrix: 15 | cmake: [ 16 | {name: "Xcode", generator: "Xcode", config: Release, build_target: ALL_BUILD, test_target: RUN_TESTS, install_target: install}, 17 | {name: "Make", generator: "Unix Makefiles", config: Release, build_target: all, test_target: test, install_target: install}, 18 | ] 19 | fail-fast: false 20 | name: arm64•MacOS•CMake(${{matrix.cmake.name}}) 21 | runs-on: macos-latest # M1 based runner 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Check CMake 25 | run: cmake --version 26 | - name: Configure 27 | run: > 28 | cmake -S. -Bbuild 29 | -G "${{matrix.cmake.generator}}" 30 | -DCMAKE_BUILD_TYPE=${{matrix.cmake.config}} 31 | -DCMAKE_INSTALL_PREFIX=install 32 | - name: Build 33 | run: > 34 | cmake --build build 35 | --config ${{matrix.cmake.config}} 36 | --target ${{matrix.cmake.build_target}} 37 | -v -j2 38 | - name: Test 39 | run: > 40 | CTEST_OUTPUT_ON_FAILURE=1 41 | cmake --build build 42 | --config ${{matrix.cmake.config}} 43 | --target ${{matrix.cmake.test_target}} 44 | -v 45 | - name: Install 46 | run: > 47 | cmake --build build 48 | --config ${{matrix.cmake.config}} 49 | --target ${{matrix.cmake.install_target}} 50 | -v 51 | 52 | arm64_macos_cmake: 53 | runs-on: ubuntu-latest 54 | needs: native 55 | steps: 56 | - uses: actions/checkout@v4 57 | -------------------------------------------------------------------------------- /.github/workflows/riscv64_docker_cmake.yml: -------------------------------------------------------------------------------- 1 | # ref: https://github.com/docker-library/official-images 2 | name: riscv64 Docker CMake 3 | 4 | on: [push, pull_request, workflow_dispatch] 5 | 6 | concurrency: 7 | group: ${{github.workflow}}-${{github.ref}} 8 | cancel-in-progress: true 9 | 10 | jobs: 11 | docker: 12 | strategy: 13 | matrix: 14 | distro: [ 15 | # almalinux, 16 | alpine, 17 | debian, # currently only unstable not latest 18 | # fedora, 19 | # opensuse, 20 | # rockylinux, 21 | #ubuntu, 22 | ] 23 | fail-fast: false 24 | name: riscv64•${{matrix.distro}}•CMake 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/checkout@v4 28 | - name: Set up QEMU 29 | uses: docker/setup-qemu-action@v3 30 | - name: Check docker 31 | run: | 32 | docker info 33 | docker buildx ls 34 | - name: Build env image 35 | run: make --directory=ci riscv64_${{matrix.distro}}_env 36 | - name: Build devel project 37 | run: make --directory=ci riscv64_${{matrix.distro}}_devel 38 | - name: Build project 39 | run: make --directory=ci riscv64_${{matrix.distro}}_build 40 | - name: Test project 41 | run: make --directory=ci riscv64_${{matrix.distro}}_test 42 | 43 | - name: Build install env image 44 | run: make --directory=ci riscv64_${{matrix.distro}}_install_env 45 | - name: Build install devel project 46 | run: make --directory=ci riscv64_${{matrix.distro}}_install_devel 47 | - name: Build install project 48 | run: make --directory=ci riscv64_${{matrix.distro}}_install_build 49 | - name: Test install project 50 | run: make --directory=ci riscv64_${{matrix.distro}}_install_test 51 | 52 | riscv64_docker_cmake: 53 | runs-on: ubuntu-latest 54 | needs: docker 55 | steps: 56 | - uses: actions/checkout@v4 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | build*/ 3 | export/ 4 | cache/ 5 | 6 | .vagrant/ 7 | /msg.txt 8 | 9 | # IDE 10 | .vs/ 11 | .cache/ 12 | # Kdevelop 13 | .kdev4/ 14 | *.kdev4 15 | # vim 16 | compile_commands.json 17 | *.swp 18 | *.user 19 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as one of 6 | # Organization's name 7 | # Individual's name 8 | # Individual's name 9 | # See CONTRIBUTORS for the meaning of multiple email addresses. 10 | 11 | # Please keep the list sorted. 12 | Google LLC 13 | Mizux Seiha 14 | -------------------------------------------------------------------------------- /Bar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(Bar) 2 | target_sources(Bar 3 | PRIVATE 4 | include/bar/Bar.hpp 5 | src/Bar.cpp) 6 | target_include_directories(Bar 7 | PUBLIC 8 | $ 9 | $) 10 | target_compile_features(Bar PUBLIC cxx_std_20) 11 | set_target_properties(Bar PROPERTIES 12 | VERSION ${PROJECT_VERSION} 13 | POSITION_INDEPENDENT_CODE ON 14 | PUBLIC_HEADER include/bar/Bar.hpp) 15 | if(APPLE) 16 | set_target_properties(Bar PROPERTIES INSTALL_RPATH "@loader_path") 17 | elseif(UNIX) 18 | set_target_properties(Bar PROPERTIES INSTALL_RPATH "$ORIGIN") 19 | endif() 20 | target_link_libraries(Bar PRIVATE absl::log) 21 | add_library(${PROJECT_NAMESPACE}::Bar ALIAS Bar) 22 | 23 | add_subdirectory(tests) 24 | 25 | # Install 26 | include(GNUInstallDirs) 27 | install(TARGETS Bar 28 | EXPORT ${PROJECT_NAME}Targets 29 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/bar 30 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 31 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 32 | #RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 33 | ) 34 | -------------------------------------------------------------------------------- /Bar/include/bar/Bar.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //! @namespace bar The Bar namespace 8 | namespace bar { 9 | //! @defgroup StringVector Vector of String usage. 10 | //! @{ 11 | /*! @brief Test returning a vector of string. 12 | * @param level Scope level. 13 | * @return A vector of string.*/ 14 | std::vector stringVectorOutput(int level); 15 | /*! @brief Test using a vector of string passed by value. 16 | * @param data Input data. 17 | * @return The size of the data vector.*/ 18 | int stringVectorInput(std::vector data); 19 | /*! @brief Test using a vector of string passed by const ref. 20 | * @param data Input data. 21 | * @return The size of the data vector.*/ 22 | int stringVectorRefInput(const std::vector& data); 23 | //! @} 24 | 25 | //! @defgroup StringJaggedArray Vector of Vector of String usage. 26 | //! @{ 27 | /*! @brief Test returning a jagged array of string. 28 | * @param level Scope level. 29 | * @return A jagged array of string.*/ 30 | std::vector> stringJaggedArrayOutput(int level); 31 | /*! @brief Test using a jagged array of string passed by value. 32 | * @param data Input data. 33 | * @return The size of the data outer vector.*/ 34 | int stringJaggedArrayInput(std::vector> data); 35 | /*! @brief Test using a jagged array of string passed by const ref. 36 | * @param data Input data. 37 | * @return The size of the data outer vector.*/ 38 | int stringJaggedArrayRefInput(const std::vector>& data); 39 | //! @} 40 | 41 | //! @defgroup PairVector Vector of Pair usage. 42 | //! @{ 43 | /*! @brief Test returning a vector of pair. 44 | * @param level Scope level. 45 | * @return A vector of pair.*/ 46 | std::vector> pairVectorOutput(int level); 47 | /*! @brief Test using a vector of pair passed by value. 48 | * @param data Input data. 49 | * @return The size of the data vector.*/ 50 | int pairVectorInput(std::vector> data); 51 | /*! @brief Test using a vector of pair passed by const ref. 52 | * @param data Input data. 53 | * @return The size of the data vector.*/ 54 | int pairVectorRefInput(const std::vector>& data); 55 | //! @} 56 | 57 | //! @defgroup PairJaggedArray Jagged array of Pair usage. 58 | //! @{ 59 | /*! @brief Test returning a jagged array of pair. 60 | * @param level Scope level. 61 | * @return A jagged array of pair.*/ 62 | std::vector>> pairJaggedArrayOutput(int level); 63 | /*! @brief Test using a jagged array of pair passed by value. 64 | * @param data Input data. 65 | * @return The size of the data outer vector.*/ 66 | int pairJaggedArrayInput(std::vector>> data); 67 | /*! @brief Test using a jagged of pair passed by const ref. 68 | * @param data Input data. 69 | * @return The size of the data outer vector.*/ 70 | int pairJaggedArrayRefInput(const std::vector>>& data); 71 | //! @} 72 | 73 | //! @defgroup FreeFunction Free function usage. 74 | //! @{ 75 | /*! @brief Free function in bar namespace. 76 | * @param level Scope level.*/ 77 | void freeFunction(int level); 78 | /*! @brief Free function in bar namespace. 79 | * @param level Scope level.*/ 80 | void freeFunction(int64_t level); 81 | //! @} 82 | 83 | //! @brief Class Bar. 84 | class Bar { 85 | public: 86 | //! @defgroup StaticMembers Static members 87 | //! @{ 88 | 89 | /*! @brief Static method of Bar class. 90 | * @param[in] level Scope level.*/ 91 | static void staticFunction(int level); 92 | 93 | /*! @brief Static method of Bar class. 94 | * @param[in] level Scope level.*/ 95 | static void staticFunction(int64_t level); 96 | 97 | //! @} 98 | 99 | //! @defgroup IntegerMembers Integer members 100 | //! @{ 101 | 102 | /*! @brief Method (getter) of Bar class. 103 | * @return A member value.*/ 104 | int getInt() const; 105 | /*! @brief Method (setter) of Bar class. 106 | * @param[in] input A member value.*/ 107 | void setInt(int input); 108 | 109 | //! @} 110 | 111 | //! @defgroup Int64Members Long Integer members 112 | //! @{ 113 | 114 | /*! @brief Method (getter) of Bar class. 115 | * @return A member value.*/ 116 | int64_t getInt64() const; 117 | /*! @brief Method (setter) of Bar class. 118 | * @param[in] input A member value.*/ 119 | void setInt64(int64_t input); 120 | 121 | //! @} 122 | 123 | //! @brief Print object for debug. 124 | std::string operator()() const; 125 | 126 | private: 127 | int _intValue = 0; 128 | int64_t _int64Value = 0; 129 | }; 130 | } // namespace bar 131 | -------------------------------------------------------------------------------- /Bar/src/Bar.cpp: -------------------------------------------------------------------------------- 1 | #include "bar/Bar.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "absl/log/log.h" 8 | 9 | namespace bar { 10 | std::vector stringVectorOutput(int level) { 11 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 12 | std::vector result(level, std::to_string(level)); 13 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 14 | return result; 15 | } 16 | 17 | int stringVectorInput(std::vector data) { 18 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 19 | LOG(INFO) << "{"; 20 | for (const auto& item : data) { 21 | LOG(INFO) << item << ", "; 22 | } 23 | LOG(INFO) << "}" << std::endl; 24 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 25 | return data.size(); 26 | } 27 | 28 | int stringVectorRefInput(const std::vector& data) { 29 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 30 | LOG(INFO) << "{"; 31 | for (const auto& item : data) { 32 | LOG(INFO) << item << ", "; 33 | } 34 | LOG(INFO) << "}" << std::endl; 35 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 36 | return data.size(); 37 | } 38 | 39 | std::vector> stringJaggedArrayOutput(int level) { 40 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 41 | std::vector> result; 42 | result.reserve(level); 43 | for (int i = 1; i <= level; ++i) { 44 | result.emplace_back(std::vector(i, std::to_string(i))); 45 | } 46 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 47 | return result; 48 | } 49 | 50 | int stringJaggedArrayInput(std::vector> data) { 51 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 52 | LOG(INFO) << "{"; 53 | for (const auto& inner : data) { 54 | LOG(INFO) << "{"; 55 | for (const auto& item : inner) { 56 | LOG(INFO) << item << ", "; 57 | } 58 | LOG(INFO) << "}, "; 59 | } 60 | LOG(INFO) << "}" << std::endl; 61 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 62 | return data.size(); 63 | } 64 | 65 | int stringJaggedArrayRefInput(const std::vector>& data) { 66 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 67 | LOG(INFO) << "{"; 68 | for (const auto& inner : data) { 69 | LOG(INFO) << "{"; 70 | for (const auto& item : inner) { 71 | LOG(INFO) << item << ", "; 72 | } 73 | LOG(INFO) << "}, "; 74 | } 75 | LOG(INFO) << "}" << std::endl; 76 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 77 | return data.size(); 78 | } 79 | 80 | std::vector> pairVectorOutput(int level) { 81 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 82 | std::vector> result(level, std::make_pair(level, level)); 83 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 84 | return result; 85 | } 86 | 87 | int pairVectorInput(std::vector> data) { 88 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 89 | LOG(INFO) << "{"; 90 | for (const auto& item : data) { 91 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 92 | } 93 | LOG(INFO) << "}" << std::endl; 94 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 95 | return data.size(); 96 | } 97 | 98 | int pairVectorRefInput(const std::vector>& data) { 99 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 100 | LOG(INFO) << "{"; 101 | for (const auto& item : data) { 102 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 103 | } 104 | LOG(INFO) << "}" << std::endl; 105 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 106 | return data.size(); 107 | } 108 | 109 | std::vector>> pairJaggedArrayOutput(int level) { 110 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 111 | std::vector>> result; 112 | result.reserve(level); 113 | for (int i = 1; i <= level; ++i) { 114 | result.emplace_back(std::vector>(i, std::make_pair(i, i))); 115 | } 116 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 117 | return result; 118 | } 119 | 120 | int pairJaggedArrayInput(std::vector>> data) { 121 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 122 | LOG(INFO) << "{"; 123 | for (const auto& inner : data) { 124 | LOG(INFO) << "{"; 125 | for (const auto& item : inner) { 126 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 127 | } 128 | LOG(INFO) << "}, "; 129 | } 130 | LOG(INFO) << "}" << std::endl; 131 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 132 | return data.size(); 133 | } 134 | 135 | int pairJaggedArrayRefInput(const std::vector>>& data) { 136 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 137 | LOG(INFO) << "{"; 138 | for (const auto& inner : data) { 139 | LOG(INFO) << "{"; 140 | for (const auto& item : inner) { 141 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 142 | } 143 | LOG(INFO) << "}, "; 144 | } 145 | LOG(INFO) << "}" << std::endl; 146 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 147 | return data.size(); 148 | } 149 | 150 | void freeFunction(int level) { 151 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 152 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 153 | } 154 | 155 | void freeFunction(int64_t level) { 156 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" << std::endl; 157 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" << std::endl; 158 | } 159 | 160 | void Bar::staticFunction(int level) { 161 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 162 | freeFunction(level + 1); 163 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 164 | } 165 | 166 | void Bar::staticFunction(int64_t level) { 167 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" << std::endl; 168 | freeFunction(level + 1); 169 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" << std::endl; 170 | } 171 | 172 | int Bar::getInt() const { 173 | return _intValue; 174 | } 175 | 176 | void Bar::setInt(int input) { 177 | _intValue = input; 178 | } 179 | 180 | int64_t Bar::getInt64() const { 181 | return _int64Value; 182 | } 183 | 184 | void Bar::setInt64(int64_t input) { 185 | _int64Value = input; 186 | } 187 | 188 | std::string Bar::operator()() const { 189 | return std::string{"\"Bar\":{\"int\":"} + std::to_string(_intValue) + 190 | ",\"int64\":" + std::to_string(_int64Value) + "}"; 191 | } 192 | 193 | namespace { 194 | void* kVar = [] { 195 | std::cerr << "kBar" << std::endl; 196 | return nullptr; 197 | }(); 198 | } // namespace 199 | 200 | } // namespace bar 201 | -------------------------------------------------------------------------------- /Bar/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT BUILD_TESTING) 2 | return() 3 | endif() 4 | 5 | add_executable(bar_test) 6 | target_sources(bar_test PRIVATE bar_test.cpp) 7 | target_include_directories(bar_test PUBLIC 8 | $) 9 | target_compile_features(bar_test PRIVATE cxx_std_20) 10 | set_target_properties(bar_test PROPERTIES 11 | VERSION ${PROJECT_VERSION} 12 | POSITION_INDEPENDENT_CODE ON 13 | ) 14 | if(APPLE) 15 | set_target_properties(bar_test PROPERTIES 16 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") 17 | elseif(UNIX) 18 | set_target_properties(bar_test PROPERTIES 19 | INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN") 20 | endif() 21 | target_link_libraries(bar_test PRIVATE 22 | #GTest::gtest_main 23 | Catch2::Catch2WithMain 24 | ${PROJECT_NAMESPACE}::Bar) 25 | 26 | add_test(NAME bar_test COMMAND bar_test) 27 | -------------------------------------------------------------------------------- /Bar/tests/bar_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace bar { 9 | 10 | TEST_CASE("Bar free function", "[Bar]") { 11 | SECTION("Int Function") { REQUIRE_NOTHROW(freeFunction(42)); } 12 | SECTION("Int64_t Function") { REQUIRE_NOTHROW(freeFunction(int64_t{42})); } 13 | } 14 | 15 | TEST_CASE("String Vector usage", "[Bar]") { 16 | SECTION("Vector of String Output") { 17 | std::vector result; 18 | REQUIRE_NOTHROW(result = stringVectorOutput(8)); 19 | REQUIRE(result.size() == 8); 20 | for (const auto& it : result) { 21 | REQUIRE(it == std::to_string(8)); 22 | } 23 | } 24 | SECTION("Vector of String Input by value") { 25 | std::vector data{"1", "2", "3", "4", "5"}; 26 | int size = 0; 27 | REQUIRE_NOTHROW(size = stringVectorInput(data)); 28 | REQUIRE(size == 5); 29 | } 30 | SECTION("Vector of String Input by const ref") { 31 | std::vector data{"1", "2", "3", "4", "5"}; 32 | int size = 0; 33 | REQUIRE_NOTHROW(size = stringVectorRefInput(data)); 34 | REQUIRE(size == 5); 35 | } 36 | } 37 | 38 | TEST_CASE("String Jagged Array usage", "[Bar]") { 39 | SECTION("Jagged Array of String Output") { 40 | std::vector> result; 41 | REQUIRE_NOTHROW(result = stringJaggedArrayOutput(8)); 42 | REQUIRE(result.size() == 8); 43 | for (int i = 0; i < result.size(); ++i) { 44 | REQUIRE(i + 1 == result[i].size()); 45 | } 46 | for (int i = 1; i <= result.size(); ++i) { 47 | const auto& inner = result[i - 1]; 48 | for (const auto& it : inner) { 49 | REQUIRE(it == std::to_string(i)); 50 | } 51 | } 52 | } 53 | SECTION("Jagged Array of String Input by value") { 54 | std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 55 | int size = 0; 56 | REQUIRE_NOTHROW(size = stringJaggedArrayInput(data)); 57 | REQUIRE(size == 2); 58 | } 59 | SECTION("Jagged Array of String Input by const ref") { 60 | std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 61 | int size = 0; 62 | REQUIRE_NOTHROW(size = stringJaggedArrayRefInput(data)); 63 | REQUIRE(size == 2); 64 | } 65 | } 66 | 67 | TEST_CASE("Pair Vector usage", "[Bar]") { 68 | SECTION("Vector of Pair Output") { 69 | std::vector result; 70 | REQUIRE_NOTHROW(result = stringVectorOutput(8)); 71 | REQUIRE(result.size() == 8); 72 | for (const auto& it : result) { 73 | REQUIRE(it == std::to_string(8)); 74 | } 75 | } 76 | SECTION("Vector of Pair Input by value") { 77 | std::vector data{"1", "2", "3", "4", "5"}; 78 | int size = 0; 79 | REQUIRE_NOTHROW(size = stringVectorInput(data)); 80 | REQUIRE(size == 5); 81 | } 82 | SECTION("Vector of Pair Input by const ref") { 83 | std::vector data{"1", "2", "3", "4", "5"}; 84 | int size = 0; 85 | REQUIRE_NOTHROW(size = stringVectorRefInput(data)); 86 | REQUIRE(size == 5); 87 | } 88 | } 89 | 90 | TEST_CASE("Pair Jagged Array usage", "[Bar]") { 91 | SECTION("Jagged Array of Pair Output") { 92 | std::vector>> result; 93 | REQUIRE_NOTHROW(result = pairJaggedArrayOutput(8)); 94 | REQUIRE(result.size() == 8); 95 | for (int i = 0; i < result.size(); ++i) { 96 | REQUIRE(i + 1 == result[i].size()); 97 | } 98 | for (int i = 1; i <= result.size(); ++i) { 99 | const auto& inner = result[i - 1]; 100 | for (const auto& it : inner) { 101 | REQUIRE(it == std::make_pair(i, i)); 102 | } 103 | } 104 | } 105 | SECTION("Jagged Array of Pair Input by value") { 106 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, {{4, 4}, {5, 5}}}; 107 | int size = 0; 108 | REQUIRE_NOTHROW(size = pairJaggedArrayInput(data)); 109 | REQUIRE(size == 2); 110 | } 111 | SECTION("Jagged Array of Pair Input by const ref") { 112 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, {{4, 4}, {5, 5}}}; 113 | int size = 0; 114 | REQUIRE_NOTHROW(size = pairJaggedArrayRefInput(data)); 115 | REQUIRE(size == 2); 116 | } 117 | } 118 | 119 | TEST_CASE("Bar static method", "[Bar]") { 120 | SECTION("Int Method") { REQUIRE_NOTHROW(Bar::staticFunction(42)); } 121 | SECTION("Int64_t Method") { REQUIRE_NOTHROW(Bar::staticFunction(int64_t{42})); } 122 | } 123 | 124 | TEST_CASE("Bar::Ctor", "[Bar]") { 125 | SECTION("Default constructor") { 126 | Bar* b = new Bar(); 127 | REQUIRE(b != nullptr); 128 | } 129 | } 130 | 131 | SCENARIO("Bar Int", "[Bar]") { 132 | GIVEN("A Bar instance") { 133 | Bar bar; 134 | WHEN("Setting a value") { 135 | REQUIRE_NOTHROW(bar.setInt(42)); 136 | THEN("The value is updated") { REQUIRE(bar.getInt() == 42); } 137 | } 138 | } 139 | } 140 | 141 | SCENARIO("Bar Int64", "[Bar]") { 142 | GIVEN("A Bar instance") { 143 | Bar bar; 144 | WHEN("Setting a value") { 145 | REQUIRE_NOTHROW(bar.setInt64(31)); 146 | THEN("The value is updated") { REQUIRE(bar.getInt64() == 31); } 147 | } 148 | } 149 | } 150 | 151 | TEST_CASE("Bar::operator()", "[Bar]") { 152 | SECTION("Debug print") { INFO("Bar: " << Bar()()); } 153 | } 154 | 155 | } // namespace bar 156 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file is just an orchestration 2 | cmake_minimum_required(VERSION 3.16..3.31) 3 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 4 | 5 | # Enable output of compile commands during generation. 6 | option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compile command" ON) 7 | 8 | project(CMakeExternal VERSION 1.0.0 LANGUAGES CXX) 9 | set(PROJECT_NAMESPACE CMakeExternal) 10 | message(STATUS "${PROJECT_NAME} version: ${PROJECT_VERSION}") 11 | #message(STATUS "major: ${PROJECT_VERSION_MAJOR}") 12 | #message(STATUS "minor: ${PROJECT_VERSION_MINOR}") 13 | #message(STATUS "patch: ${PROJECT_VERSION_PATCH}") 14 | 15 | message(STATUS "system name: ${CMAKE_SYSTEM_NAME}") 16 | # Set max os target version. 17 | set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) 18 | 19 | set(CMAKE_CXX_STANDARD 17) 20 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 21 | set(CMAKE_CXX_EXTENSIONS OFF) 22 | 23 | # Default Build Type to be Release 24 | get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 25 | if(isMultiConfig) 26 | if(NOT CMAKE_CONFIGURATION_TYPES) 27 | set(CMAKE_CONFIGURATION_TYPES "Release;Debug" CACHE STRING 28 | "Choose the type of builds, options are: Debug Release RelWithDebInfo MinSizeRel. (default: Release;Debug)" 29 | FORCE) 30 | endif() 31 | message(STATUS "Configuration types: ${CMAKE_CONFIGURATION_TYPES}") 32 | else() 33 | if(NOT CMAKE_BUILD_TYPE) 34 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING 35 | "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel. (default: Release)" 36 | FORCE) 37 | endif() 38 | message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 39 | endif() 40 | 41 | # Layout build dir like install dir 42 | include(GNUInstallDirs) 43 | if(UNIX) 44 | option(BUILD_SHARED_LIBS "Build shared libraries (.so or .dylib)." ON) 45 | set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) 46 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 47 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 48 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 49 | # for multi-config build system (e.g. Xcode, Ninja Multi-Config) 50 | foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) 51 | string(TOUPPER ${OutputConfig} OUTPUTCONFIG) 52 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_LIBDIR}) 53 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_LIBDIR}) 54 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 55 | endforeach() 56 | else() 57 | # Currently Only support static build for windows 58 | option(BUILD_SHARED_LIBS "Build shared libraries (.dll)." OFF) 59 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 60 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 61 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 62 | # for multi-config builds (e.g. msvc) 63 | foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) 64 | string(TOUPPER ${OutputConfig} OUTPUTCONFIG) 65 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 66 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 67 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 68 | endforeach() 69 | endif() 70 | 71 | if(MSVC AND BUILD_SHARED_LIBS) 72 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 73 | endif() 74 | 75 | # Disable CTest targets 76 | set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1) 77 | include(CTest) 78 | 79 | option(BUILD_ZLIB "Build the ZLIB dependency Library" ON) 80 | message(STATUS "Build ZLIB: ${BUILD_ZLIB}") 81 | 82 | option(BUILD_absl "Build the abseil-cpp dependency Library" ON) 83 | message(STATUS "Build abseil-cpp: ${BUILD_absl}") 84 | 85 | option(BUILD_Protobuf "Build the Protobuf dependency Library" ON) 86 | message(STATUS "Build protobuf: ${BUILD_Protobuf}") 87 | 88 | option(BUILD_re2 "Build the re2 dependency Library" ON) 89 | message(STATUS "Build re2: ${BUILD_re2}") 90 | 91 | if(BUILD_TESTING) 92 | option(BUILD_Catch2 "Build Catch2" ON) 93 | message(STATUS "Build Catch2: ${BUILD_Catch2}") 94 | 95 | option(BUILD_googletest "Build googletest" ON) 96 | message(STATUS "Build googletest: ${BUILD_googletest}") 97 | 98 | option(BUILD_benchmark "Build benchmark" ON) 99 | message(STATUS "Build benchmark: ${BUILD_benchmark}") 100 | else() 101 | set(BUILD_Catch2 OFF) 102 | set(BUILD_re2 OFF) 103 | set(BUILD_googletest OFF) 104 | set(BUILD_benchmark OFF) 105 | endif() 106 | 107 | # Find system deps 108 | include(system_deps) 109 | 110 | # Build Needed dependencies 111 | add_subdirectory(cmake/dependencies dependencies) 112 | 113 | include(host) 114 | # verify deps 115 | include(check_deps) 116 | 117 | include(cpp) 118 | 119 | ## Examples 120 | option(BUILD_EXAMPLES "Build examples" ON) 121 | message(STATUS "Build examples: ${BUILD_EXAMPLES}") 122 | add_subdirectory(examples) 123 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This is the official list of people who can contribute 2 | # (and typically have contributed) code to this repository. 3 | # The AUTHORS file lists the copyright holders; this file 4 | # lists people. For example, Google employees are listed here 5 | # but not in AUTHORS, because Google holds the copyright. 6 | # 7 | # The submission process automatically checks to make sure 8 | # that people submitting code are listed in this file (by email address). 9 | # 10 | # Names should be added to this file only after verifying that 11 | # the individual or the individual's organization has agreed to 12 | # the appropriate Contributor License Agreement, found here: 13 | # 14 | # http://code.google.com/legal/individual-cla-v1.0.html 15 | # http://code.google.com/legal/corporate-cla-v1.0.html 16 | # 17 | # The agreement for individuals can be filled out on the web. 18 | # 19 | # When adding J Random Contributor's name to this file, 20 | # either J's name or J's organization's name should be 21 | # added to the AUTHORS file, depending on whether the 22 | # individual or corporate CLA was used. 23 | 24 | # Names should be added to this file like so: 25 | # Individual's name 26 | # Individual's name 27 | # 28 | # An entry with multiple email addresses specifies that the 29 | # first address should be used in the submit logs and 30 | # that the other addresses should be recognized as the 31 | # same person when interacting with Gerrit. 32 | 33 | # Please keep the list sorted. 34 | 35 | -------------------------------------------------------------------------------- /Foo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(Foo) 2 | target_sources(Foo 3 | PRIVATE 4 | include/foo/Foo.hpp 5 | src/Foo.cpp) 6 | target_include_directories(Foo 7 | PUBLIC 8 | $ 9 | $) 10 | target_compile_features(Foo PUBLIC cxx_std_20) 11 | set_target_properties(Foo PROPERTIES 12 | VERSION ${PROJECT_VERSION} 13 | POSITION_INDEPENDENT_CODE ON 14 | PUBLIC_HEADER include/foo/Foo.hpp) 15 | if(APPLE) 16 | set_target_properties(Foo PROPERTIES INSTALL_RPATH "@loader_path") 17 | elseif(UNIX) 18 | set_target_properties(Foo PROPERTIES INSTALL_RPATH "$ORIGIN") 19 | endif() 20 | target_link_libraries(Foo PRIVATE absl::log) 21 | add_library(${PROJECT_NAMESPACE}::Foo ALIAS Foo) 22 | 23 | add_subdirectory(tests) 24 | 25 | # Install 26 | include(GNUInstallDirs) 27 | install(TARGETS Foo 28 | EXPORT ${PROJECT_NAME}Targets 29 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/foo 30 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 31 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 32 | #RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 33 | ) 34 | -------------------------------------------------------------------------------- /Foo/include/foo/Foo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //! @namespace foo The Foo namespace 8 | namespace foo { 9 | //! @defgroup StringVector Vector of String usage. 10 | //! @{ 11 | /*! @brief Test returning a vector of string. 12 | * @param level Scope level. 13 | * @return A vector of string.*/ 14 | std::vector stringVectorOutput(int level); 15 | /*! @brief Test using a vector of string passed by value. 16 | * @param data Input data. 17 | * @return The size of the data vector.*/ 18 | int stringVectorInput(std::vector data); 19 | /*! @brief Test using a vector of string passed by const ref. 20 | * @param data Input data. 21 | * @return The size of the data vector.*/ 22 | int stringVectorRefInput(const std::vector& data); 23 | //! @} 24 | 25 | //! @defgroup StringJaggedArray Vector of Vector of String usage. 26 | //! @{ 27 | /*! @brief Test returning a jagged array of string. 28 | * @param level Scope level. 29 | * @return A jagged array of string.*/ 30 | std::vector> stringJaggedArrayOutput(int level); 31 | /*! @brief Test using a jagged array of string passed by value. 32 | * @param data Input data. 33 | * @return The size of the data outer vector.*/ 34 | int stringJaggedArrayInput(std::vector> data); 35 | /*! @brief Test using a jagged array of string passed by const ref. 36 | * @param data Input data. 37 | * @return The size of the data outer vector.*/ 38 | int stringJaggedArrayRefInput(const std::vector>& data); 39 | //! @} 40 | 41 | //! @defgroup PairVector Vector of Pair usage. 42 | //! @{ 43 | /*! @brief Test returning a vector of pair. 44 | * @param level Scope level. 45 | * @return A vector of pair.*/ 46 | std::vector> pairVectorOutput(int level); 47 | /*! @brief Test using a vector of pair passed by value. 48 | * @param data Input data. 49 | * @return The size of the data vector.*/ 50 | int pairVectorInput(std::vector> data); 51 | /*! @brief Test using a vector of pair passed by const ref. 52 | * @param data Input data. 53 | * @return The size of the data vector.*/ 54 | int pairVectorRefInput(const std::vector>& data); 55 | //! @} 56 | 57 | //! @defgroup PairJaggedArray Jagged array of Pair usage. 58 | //! @{ 59 | /*! @brief Test returning a jagged array of pair. 60 | * @param level Scope level. 61 | * @return A jagged array of pair.*/ 62 | std::vector>> pairJaggedArrayOutput(int level); 63 | /*! @brief Test using a jagged array of pair passed by value. 64 | * @param data Input data. 65 | * @return The size of the data outer vector.*/ 66 | int pairJaggedArrayInput(std::vector>> data); 67 | /*! @brief Test using a jagged of pair passed by const ref. 68 | * @param data Input data. 69 | * @return The size of the data outer vector.*/ 70 | int pairJaggedArrayRefInput(const std::vector>>& data); 71 | //! @} 72 | 73 | //! @defgroup FreeFunction Free function usage. 74 | //! @{ 75 | /*! @brief Free function in foo namespace. 76 | * @param level Scope level.*/ 77 | void freeFunction(int level); 78 | /*! @brief Free function in foo namespace. 79 | * @param level Scope level.*/ 80 | void freeFunction(int64_t level); 81 | //! @} 82 | 83 | //! @brief Class Foo. 84 | class Foo { 85 | public: 86 | //! @defgroup StaticMembers Static members 87 | //! @{ 88 | 89 | /*! @brief Static method of Foo class. 90 | * @param[in] level Scope level.*/ 91 | static void staticFunction(int level); 92 | 93 | /*! @brief Static method of Foo class. 94 | * @param[in] level Scope level.*/ 95 | static void staticFunction(int64_t level); 96 | 97 | //! @} 98 | 99 | //! @defgroup IntegerMembers Integer members 100 | //! @{ 101 | 102 | /*! @brief Method (getter) of Foo class. 103 | * @return A member value.*/ 104 | int getInt() const; 105 | /*! @brief Method (setter) of Foo class. 106 | * @param[in] input A member value.*/ 107 | void setInt(int input); 108 | 109 | //! @} 110 | 111 | //! @defgroup Int64Members Long Integer members 112 | //! @{ 113 | 114 | /*! @brief Method (getter) of Foo class. 115 | * @return A member value.*/ 116 | int64_t getInt64() const; 117 | /*! @brief Method (setter) of Foo class. 118 | * @param[in] input A member value.*/ 119 | void setInt64(int64_t input); 120 | 121 | //! @} 122 | 123 | //! @brief Print object for debug. 124 | std::string operator()() const; 125 | 126 | private: 127 | int _intValue = 0; 128 | int64_t _int64Value = 0; 129 | }; 130 | } // namespace foo 131 | -------------------------------------------------------------------------------- /Foo/src/Foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo/Foo.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace foo { 10 | std::vector stringVectorOutput(int level) { 11 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 12 | std::vector result(level, std::to_string(level)); 13 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 14 | return result; 15 | } 16 | 17 | int stringVectorInput(std::vector data) { 18 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 19 | LOG(INFO) << "{"; 20 | for (const auto& item : data) { 21 | LOG(INFO) << item << ", "; 22 | } 23 | LOG(INFO) << "}" << std::endl; 24 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 25 | return data.size(); 26 | } 27 | 28 | int stringVectorRefInput(const std::vector& data) { 29 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 30 | LOG(INFO) << "{"; 31 | for (const auto& item : data) { 32 | LOG(INFO) << item << ", "; 33 | } 34 | LOG(INFO) << "}" << std::endl; 35 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 36 | return data.size(); 37 | } 38 | 39 | std::vector> stringJaggedArrayOutput(int level) { 40 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 41 | std::vector> result; 42 | result.reserve(level); 43 | for (int i = 1; i <= level; ++i) { 44 | result.emplace_back(std::vector(i, std::to_string(i))); 45 | } 46 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 47 | return result; 48 | } 49 | 50 | int stringJaggedArrayInput(std::vector> data) { 51 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 52 | LOG(INFO) << "{"; 53 | for (const auto& inner : data) { 54 | LOG(INFO) << "{"; 55 | for (const auto& item : inner) { 56 | LOG(INFO) << item << ", "; 57 | } 58 | LOG(INFO) << "}, "; 59 | } 60 | LOG(INFO) << "}" << std::endl; 61 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 62 | return data.size(); 63 | } 64 | 65 | int stringJaggedArrayRefInput(const std::vector>& data) { 66 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 67 | LOG(INFO) << "{"; 68 | for (const auto& inner : data) { 69 | LOG(INFO) << "{"; 70 | for (const auto& item : inner) { 71 | LOG(INFO) << item << ", "; 72 | } 73 | LOG(INFO) << "}, "; 74 | } 75 | LOG(INFO) << "}" << std::endl; 76 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 77 | return data.size(); 78 | } 79 | 80 | std::vector> pairVectorOutput(int level) { 81 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 82 | std::vector> result(level, std::make_pair(level, level)); 83 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 84 | return result; 85 | } 86 | 87 | int pairVectorInput(std::vector> data) { 88 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 89 | LOG(INFO) << "{"; 90 | for (const auto& item : data) { 91 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 92 | } 93 | LOG(INFO) << "}" << std::endl; 94 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 95 | return data.size(); 96 | } 97 | 98 | int pairVectorRefInput(const std::vector>& data) { 99 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 100 | LOG(INFO) << "{"; 101 | for (const auto& item : data) { 102 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 103 | } 104 | LOG(INFO) << "}" << std::endl; 105 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 106 | return data.size(); 107 | } 108 | 109 | std::vector>> pairJaggedArrayOutput(int level) { 110 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 111 | std::vector>> result; 112 | result.reserve(level); 113 | for (int i = 1; i <= level; ++i) { 114 | result.emplace_back(std::vector>(i, std::make_pair(i, i))); 115 | } 116 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 117 | return result; 118 | } 119 | 120 | int pairJaggedArrayInput(std::vector>> data) { 121 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 122 | LOG(INFO) << "{"; 123 | for (const auto& inner : data) { 124 | LOG(INFO) << "{"; 125 | for (const auto& item : inner) { 126 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 127 | } 128 | LOG(INFO) << "}, "; 129 | } 130 | LOG(INFO) << "}" << std::endl; 131 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 132 | return data.size(); 133 | } 134 | 135 | int pairJaggedArrayRefInput(const std::vector>>& data) { 136 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 137 | LOG(INFO) << "{"; 138 | for (const auto& inner : data) { 139 | LOG(INFO) << "{"; 140 | for (const auto& item : inner) { 141 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 142 | } 143 | LOG(INFO) << "}, "; 144 | } 145 | LOG(INFO) << "}" << std::endl; 146 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 147 | return data.size(); 148 | } 149 | 150 | void freeFunction(int level) { 151 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 152 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 153 | } 154 | 155 | void freeFunction(int64_t level) { 156 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" << std::endl; 157 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" << std::endl; 158 | } 159 | 160 | void Foo::staticFunction(int level) { 161 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 162 | freeFunction(level + 1); 163 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 164 | } 165 | 166 | void Foo::staticFunction(int64_t level) { 167 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" << std::endl; 168 | freeFunction(level + 1); 169 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" << std::endl; 170 | } 171 | 172 | int Foo::getInt() const { 173 | return _intValue; 174 | } 175 | 176 | void Foo::setInt(int input) { 177 | _intValue = input; 178 | } 179 | 180 | int64_t Foo::getInt64() const { 181 | return _int64Value; 182 | } 183 | 184 | void Foo::setInt64(int64_t input) { 185 | _int64Value = input; 186 | } 187 | 188 | std::string Foo::operator()() const { 189 | return std::string{"\"Foo\":{\"int\":"} + std::to_string(_intValue) + 190 | ",\"int64\":" + std::to_string(_int64Value) + "}"; 191 | } 192 | 193 | namespace { 194 | void* kVar = [] { 195 | std::cerr << "kFoo" << std::endl; 196 | return nullptr; 197 | }(); 198 | } // namespace 199 | 200 | } // namespace foo 201 | -------------------------------------------------------------------------------- /Foo/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT BUILD_TESTING) 2 | return() 3 | endif() 4 | 5 | add_executable(foo_test) 6 | target_sources(foo_test PRIVATE foo_test.cpp) 7 | target_include_directories(foo_test PUBLIC 8 | $) 9 | target_compile_features(foo_test PRIVATE cxx_std_20) 10 | set_target_properties(foo_test PROPERTIES 11 | VERSION ${PROJECT_VERSION} 12 | POSITION_INDEPENDENT_CODE ON 13 | ) 14 | if(APPLE) 15 | set_target_properties(foo_test PROPERTIES 16 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") 17 | elseif(UNIX) 18 | set_target_properties(foo_test PROPERTIES 19 | INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN") 20 | endif() 21 | target_link_libraries(foo_test PRIVATE 22 | #GTest::gtest_main 23 | Catch2::Catch2WithMain 24 | ${PROJECT_NAMESPACE}::Foo) 25 | 26 | add_test(NAME foo_test COMMAND foo_test) 27 | -------------------------------------------------------------------------------- /Foo/tests/foo_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace foo { 9 | 10 | TEST_CASE("Foo free function", "[Foo]") { 11 | SECTION("Int Function") { REQUIRE_NOTHROW(freeFunction(42)); } 12 | SECTION("Int64_t Function") { REQUIRE_NOTHROW(freeFunction(int64_t{42})); } 13 | } 14 | 15 | TEST_CASE("String Vector usage", "[Foo]") { 16 | SECTION("Vector of String Output") { 17 | std::vector result; 18 | REQUIRE_NOTHROW(result = stringVectorOutput(8)); 19 | REQUIRE(result.size() == 8); 20 | for (const auto& it : result) { 21 | REQUIRE(it == std::to_string(8)); 22 | } 23 | } 24 | SECTION("Vector of String Input by value") { 25 | std::vector data{"1", "2", "3", "4", "5"}; 26 | int size = 0; 27 | REQUIRE_NOTHROW(size = stringVectorInput(data)); 28 | REQUIRE(size == 5); 29 | } 30 | SECTION("Vector of String Input by const ref") { 31 | std::vector data{"1", "2", "3", "4", "5"}; 32 | int size = 0; 33 | REQUIRE_NOTHROW(size = stringVectorRefInput(data)); 34 | REQUIRE(size == 5); 35 | } 36 | } 37 | 38 | TEST_CASE("String Jagged Array usage", "[Foo]") { 39 | SECTION("Jagged Array of String Output") { 40 | std::vector> result; 41 | REQUIRE_NOTHROW(result = stringJaggedArrayOutput(8)); 42 | REQUIRE(result.size() == 8); 43 | for (int i = 0; i < result.size(); ++i) { 44 | REQUIRE(i + 1 == result[i].size()); 45 | } 46 | for (int i = 1; i <= result.size(); ++i) { 47 | const auto& inner = result[i - 1]; 48 | for (const auto& it : inner) { 49 | REQUIRE(it == std::to_string(i)); 50 | } 51 | } 52 | } 53 | SECTION("Jagged Array of String Input by value") { 54 | std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 55 | int size = 0; 56 | REQUIRE_NOTHROW(size = stringJaggedArrayInput(data)); 57 | REQUIRE(size == 2); 58 | } 59 | SECTION("Jagged Array of String Input by const ref") { 60 | std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 61 | int size = 0; 62 | REQUIRE_NOTHROW(size = stringJaggedArrayRefInput(data)); 63 | REQUIRE(size == 2); 64 | } 65 | } 66 | 67 | TEST_CASE("Pair Vector usage", "[Foo]") { 68 | SECTION("Vector of Pair Output") { 69 | std::vector result; 70 | REQUIRE_NOTHROW(result = stringVectorOutput(8)); 71 | REQUIRE(result.size() == 8); 72 | for (const auto& it : result) { 73 | REQUIRE(it == std::to_string(8)); 74 | } 75 | } 76 | SECTION("Vector of Pair Input by value") { 77 | std::vector data{"1", "2", "3", "4", "5"}; 78 | int size = 0; 79 | REQUIRE_NOTHROW(size = stringVectorInput(data)); 80 | REQUIRE(size == 5); 81 | } 82 | SECTION("Vector of Pair Input by const ref") { 83 | std::vector data{"1", "2", "3", "4", "5"}; 84 | int size = 0; 85 | REQUIRE_NOTHROW(size = stringVectorRefInput(data)); 86 | REQUIRE(size == 5); 87 | } 88 | } 89 | 90 | TEST_CASE("Pair Jagged Array usage", "[Foo]") { 91 | SECTION("Jagged Array of Pair Output") { 92 | std::vector>> result; 93 | REQUIRE_NOTHROW(result = pairJaggedArrayOutput(8)); 94 | REQUIRE(result.size() == 8); 95 | for (int i = 0; i < result.size(); ++i) { 96 | REQUIRE(i + 1 == result[i].size()); 97 | } 98 | for (int i = 1; i <= result.size(); ++i) { 99 | const auto& inner = result[i - 1]; 100 | for (const auto& it : inner) { 101 | REQUIRE(it == std::make_pair(i, i)); 102 | } 103 | } 104 | } 105 | SECTION("Jagged Array of Pair Input by value") { 106 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, {{4, 4}, {5, 5}}}; 107 | int size = 0; 108 | REQUIRE_NOTHROW(size = pairJaggedArrayInput(data)); 109 | REQUIRE(size == 2); 110 | } 111 | SECTION("Jagged Array of Pair Input by const ref") { 112 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, {{4, 4}, {5, 5}}}; 113 | int size = 0; 114 | REQUIRE_NOTHROW(size = pairJaggedArrayRefInput(data)); 115 | REQUIRE(size == 2); 116 | } 117 | } 118 | 119 | TEST_CASE("Foo static method", "[Foo]") { 120 | SECTION("Int Method") { REQUIRE_NOTHROW(Foo::staticFunction(42)); } 121 | SECTION("Int64_t Method") { REQUIRE_NOTHROW(Foo::staticFunction(int64_t{42})); } 122 | } 123 | 124 | TEST_CASE("Foo::Ctor", "[Foo]") { 125 | SECTION("Default constructor") { 126 | Foo* b = new Foo(); 127 | REQUIRE(b != nullptr); 128 | } 129 | } 130 | 131 | SCENARIO("Foo Int", "[Foo]") { 132 | GIVEN("A Foo instance") { 133 | Foo foo; 134 | WHEN("Setting a value") { 135 | REQUIRE_NOTHROW(foo.setInt(42)); 136 | THEN("The value is updated") { REQUIRE(foo.getInt() == 42); } 137 | } 138 | } 139 | } 140 | 141 | SCENARIO("Foo Int64", "[Foo]") { 142 | GIVEN("A Foo instance") { 143 | Foo foo; 144 | WHEN("Setting a value") { 145 | REQUIRE_NOTHROW(foo.setInt64(31)); 146 | THEN("The value is updated") { REQUIRE(foo.getInt64() == 31); } 147 | } 148 | } 149 | } 150 | 151 | TEST_CASE("Foo::operator()", "[Foo]") { 152 | SECTION("Debug print") { INFO("Foo: " << Foo()()); } 153 | } 154 | 155 | } // namespace foo 156 | -------------------------------------------------------------------------------- /FooApp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(FooApp) 2 | get_cpp_proto(PROTO_HDRS PROTO_SRCS) 3 | target_sources(FooApp PRIVATE 4 | src/main.cpp 5 | ${PROTO_HDRS} ${PROTO_SRCS}) 6 | target_include_directories(FooApp PRIVATE 7 | $ 8 | $ 9 | $ 10 | ) 11 | target_compile_features(FooApp PRIVATE cxx_std_17) 12 | set_target_properties(FooApp PROPERTIES 13 | VERSION ${PROJECT_VERSION}) 14 | # note: macOS is APPLE and also UNIX ! 15 | if(APPLE) 16 | set_target_properties(FooApp PROPERTIES 17 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") 18 | elseif(UNIX) 19 | set_target_properties(FooApp PROPERTIES 20 | INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") 21 | endif() 22 | target_link_libraries(FooApp PRIVATE 23 | ZLIB::ZLIB 24 | absl::flags_parse 25 | absl::log 26 | absl::log_globals 27 | absl::log_initialize 28 | absl::log_severity 29 | absl::strings 30 | protobuf::libprotobuf 31 | CMakeExternal::Foo 32 | CMakeExternal::Bar 33 | ) 34 | 35 | add_executable(${PROJECT_NAMESPACE}::FooApp ALIAS FooApp) 36 | 37 | if(BUILD_TESTING) 38 | add_test(NAME cpp_FooApp_test COMMAND FooApp) 39 | endif() 40 | 41 | # Install 42 | include(GNUInstallDirs) 43 | install(TARGETS FooApp 44 | EXPORT ${PROJECT_NAME}Targets 45 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 46 | ) 47 | -------------------------------------------------------------------------------- /FooApp/msg.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package msg; 3 | 4 | // Msg represents a tuple {key, value}. 5 | message Msg { 6 | string key = 1; 7 | int32 value = 2; 8 | } 9 | 10 | // MsgList represents a list of msg. 11 | message MsgList { 12 | repeated Msg msgs = 1; 13 | } 14 | -------------------------------------------------------------------------------- /FooApp/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "bar/Bar.hpp" 16 | #include "foo/Foo.hpp" 17 | 18 | #include 19 | #include "msg.pb.h" 20 | 21 | void AddMsg(msg::Msg* msgPtr, const std::string& key, std::int32_t value); 22 | 23 | int main(int argc, char* argv[]) { 24 | absl::InitializeLog(); 25 | absl::SetProgramUsageMessage("FooBarApp"); 26 | absl::EnableLogPrefix(false); 27 | absl::SetStderrThreshold(absl::LogSeverity::kInfo); 28 | absl::ParseCommandLine(argc, argv); 29 | { 30 | const std::vector v = {"foo","bar","baz"}; 31 | std::string s = absl::StrJoin(v, "-"); 32 | LOG(INFO) << "Joined string: " << s << "\n"; 33 | } 34 | 35 | foo::Foo::staticFunction(int{0}); 36 | bar::Bar::staticFunction(int{1}); 37 | 38 | GOOGLE_PROTOBUF_VERIFY_VERSION; 39 | // Write a Message 40 | { 41 | msg::MsgList msgList; 42 | AddMsg(msgList.add_msgs(), "bar", 3); 43 | AddMsg(msgList.add_msgs(), "baz", 5); 44 | AddMsg(msgList.add_msgs(), "bop", 7); 45 | // Write the new address book back to disk. 46 | std::fstream out("msg.txt", std::ios::out | std::ios::trunc | std::ios::binary); 47 | if (!msgList.SerializeToOstream(&out)) { 48 | std::cerr << "Failed to write /tmp/msg.txt." << std::endl; 49 | return -1; 50 | } 51 | } 52 | 53 | // Read a Message 54 | { 55 | msg::MsgList msgList; 56 | std::fstream in("msg.txt", std::ios::in | std::ios::binary); 57 | if (!msgList.ParseFromIstream(&in) || msgList.msgs_size() != 3) { 58 | std::cerr << "Failed to read /tmp/msg.txt." << std::endl; 59 | return -2; 60 | } 61 | 62 | for (std::size_t i=0; i < 3; ++i) { 63 | std::cout << "hello " << msgList.msgs(i).key() 64 | << ":" << msgList.msgs(i).value() << std::endl; 65 | } 66 | } 67 | 68 | // Optional: Delete all global objects allocated by libprotobuf. 69 | google::protobuf::ShutdownProtobufLibrary(); 70 | 71 | return 0; 72 | } 73 | 74 | void AddMsg(msg::Msg* msgPtr, const std::string& key, std::int32_t value) { 75 | msgPtr->set_key(key.c_str()); 76 | msgPtr->set_value(value); 77 | } 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Github-CI:
2 | [![Build Status][amd64_linux_status]][amd64_linux_link] 3 | [![Build Status][amd64_macos_status]][amd64_macos_link] 4 | [![Build Status][arm64_macos_status]][arm64_macos_link] 5 | [![Build Status][amd64_windows_status]][amd64_windows_link]
6 | 7 | [![Build Status][amd64_docker_status]][amd64_docker_link] 8 | [![Build Status][arm64_docker_status]][arm64_docker_link] 9 | [![Build Status][riscv64_docker_status]][riscv64_docker_link]
10 | 11 | [amd64_linux_status]: ./../../actions/workflows/amd64_linux_cmake.yml/badge.svg 12 | [amd64_linux_link]: ./../../actions/workflows/amd64_linux_cmake.yml 13 | [amd64_macos_status]: ./../../actions/workflows/amd64_macos_cmake.yml/badge.svg 14 | [amd64_macos_link]: ./../../actions/workflows/amd64_macos_cmake.yml 15 | [arm64_macos_status]: ./../../actions/workflows/arm64_macos_cmake.yml/badge.svg 16 | [arm64_macos_link]: ./../../actions/workflows/arm64_macos_cmake.yml 17 | [amd64_windows_status]: ./../../actions/workflows/amd64_windows_cmake.yml/badge.svg 18 | [amd64_windows_link]: ./../../actions/workflows/amd64_windows_cmake.yml 19 | 20 | [amd64_docker_status]: ./../../actions/workflows/amd64_docker_cmake.yml/badge.svg 21 | [amd64_docker_link]: ./../../actions/workflows/amd64_docker_cmake.yml 22 | [arm64_docker_status]: ./../../actions/workflows/arm64_docker_cmake.yml/badge.svg 23 | [arm64_docker_link]: ./../../actions/workflows/arm64_docker_cmake.yml 24 | [riscv64_docker_status]: ./../../actions/workflows/riscv64_docker_cmake.yml/badge.svg 25 | [riscv64_docker_link]: ./../../actions/workflows/riscv64_docker_cmake.yml 26 | 27 | # Introduction 28 | 29 | 39 | 40 | This is an example of how to create a Modern [CMake](https://cmake.org/) C++ Project using 41 | [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module to include dependency(ies) as subproject(s). 42 | 43 | This project should run on GNU/Linux, MacOS and Windows. 44 | 45 | ## Requirement 46 | 47 | You'll need: 48 | 49 | * "CMake >= 3.16". 50 | 51 | ## Codemap 52 | 53 | The project layout is as follow: 54 | 55 | * [CMakeLists.txt](CMakeLists.txt) Top-level for [CMake](https://cmake.org/cmake/help/latest/) based build. 56 | * [cmake](cmake) Subsidiary CMake files. 57 | 58 | * [ci](ci) Root directory for continuous integration. 59 | 60 | * [Foo](Foo) Root directory for `Foo` library. 61 | * [CMakeLists.txt](Foo/CMakeLists.txt) for `Foo`. 62 | * [include](Foo/include) public folder. 63 | * [foo](Foo/include/foo) 64 | * [Foo.hpp](Foo/include/foo/Foo.hpp) 65 | * [src](Foo/src) private folder. 66 | * [src/Foo.cpp](Foo/src/Foo.cpp) 67 | * [Bar](Bar) Root directory for `Bar` library. 68 | * [CMakeLists.txt](Bar/CMakeLists.txt) for `Bar`. 69 | * [include](Bar/include) public folder. 70 | * [bar](Bar/include/bar) 71 | * [Bar.hpp](Bar/include/bar/Bar.hpp) 72 | * [src](Bar/src) private folder. 73 | * [src/Bar.cpp](Bar/src/Bar.cpp) 74 | * [FooApp](FooApp) Root directory for `FooApp` executable. 75 | * [CMakeLists.txt](FooApp/CMakeLists.txt) for `FooApp`. 76 | * [src](FooApp/src) private folder. 77 | * [src/main.cpp](FooApp/src/main.cpp) 78 | 79 | ## Dependencies 80 | 81 | To complexify a little, the CMake project is composed of three libraries (Foo, Bar and FooBar) 82 | with the following dependencies: 83 | 84 | ```sh 85 | Foo: 86 | Bar: 87 | FooApp: PUBLIC Foo PRIVATE Bar 88 | ``` 89 | 90 | note: Since `Foo` is a public dependency of `FooBar`, then `FooBarApp` will 91 | *see* `Foo` inlude directories 92 | 93 | ## Build 94 | 95 | To build the C++ project, as usual: 96 | 97 | ```sh 98 | cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 99 | cmake --build build --config Release 100 | CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test 101 | ``` 102 | ## Build directory layout 103 | Since we want to use the [CMAKE_BINARY_DIR](https://cmake.org/cmake/help/latest/variable/CMAKE_BINARY_DIR.html) to generate the binary package. 104 | We want this layout (tree build --prune -P "*.so|FooApp"): 105 | 106 | ``` 107 | build 108 | ├── bin 109 | │   └── FooApp 110 | └── lib 111 |    └── lib*.so 112 | ``` 113 | 114 | ## Appendices 115 | 116 | Few links on the subject... 117 | 118 | ### Resources 119 | 120 | Project layout: 121 | * [The Pitchfork Layout Revision 1 (cxx-pflR1)](https://github.com/vector-of-bool/pitchfork) 122 | 123 | CMake: 124 | * https://llvm.org/docs/CMakePrimer.html 125 | * https://cliutils.gitlab.io/modern-cmake/ 126 | * https://cgold.readthedocs.io/en/latest/ 127 | 128 | # Contributing 129 | 130 | The [CONTRIBUTING.md](./CONTRIBUTING.md) file contains instructions on how to 131 | file the Contributor License Agreement before sending any pull requests (PRs). 132 | Of course, if you're new to the project, it's usually best to discuss any 133 | proposals and reach consensus before sending your first PR. 134 | 135 | ## License 136 | 137 | Apache 2. See the LICENSE file for details. 138 | 139 | ## Disclaimer 140 | 141 | This is not an official Google product, it is just code that happens to be 142 | owned by Google. 143 | 144 | -------------------------------------------------------------------------------- /ci/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT := cmake-external 2 | BRANCH := $(shell git rev-parse --abbrev-ref HEAD) 3 | SHA1 := $(shell git rev-parse --verify HEAD) 4 | 5 | # General commands 6 | .PHONY: help 7 | BOLD:=\e[1m 8 | RESET:=\e[0m 9 | 10 | help: 11 | @echo -e "${BOLD}SYNOPSIS${RESET}" 12 | @echo -e "\tmake [NOCACHE=1] [VERBOSE=1]" 13 | @echo 14 | @echo -e "${BOLD}DESCRIPTION${RESET}" 15 | @echo -e "\ttest build inside docker container to have a reproductible build." 16 | @echo 17 | @echo -e "${BOLD}MAKE TARGETS${RESET}" 18 | @echo -e "\t${BOLD}help${RESET}: display this help and exit." 19 | @echo 20 | @echo -e "\tBuild using docker and the host platform." 21 | @echo -e "\t${BOLD}_${RESET}: build a docker image for a specific distro." 22 | @echo -e "\t${BOLD}save__${RESET}: Save a docker image for a specific distro." 23 | @echo -e "\t${BOLD}sh__${RESET}: run a container using the docker image specified (debug purpose)." 24 | @echo -e "\t${BOLD}clean__${RESET}: Remove a docker image for a specific distro." 25 | @echo -e "\t${BOLD}clean_all${RESET}: Remove ALL caches and docker images." 26 | @echo 27 | @echo -e "\tWith ${BOLD}${RESET}:" 28 | @echo -e "\t\t${BOLD}almalinux${RESET} (latest)" 29 | @echo -e "\t\t${BOLD}alpine${RESET} (edge)" 30 | @echo -e "\t\t${BOLD}archlinux${RESET} (latest)" 31 | @echo -e "\t\t${BOLD}debian${RESET} (latest)" 32 | @echo -e "\t\t${BOLD}fedora${RESET} (latest)" 33 | @echo -e "\t\t${BOLD}opensuse${RESET} (tumbleweed)" 34 | @echo -e "\t\t${BOLD}rockylinux${RESET} (9)" 35 | @echo -e "\t\t${BOLD}ubuntu${RESET} (rolling)" 36 | @echo -e "\t\t${BOLD}all${RESET}: trigger ALL DISTROS." 37 | @echo 38 | @echo -e "\tWith ${BOLD}${RESET}:" 39 | @echo -e "\t\t${BOLD}env${RESET}" 40 | @echo -e "\t\t${BOLD}devel${RESET}" 41 | @echo -e "\t\t${BOLD}build${RESET}" 42 | @echo -e "\t\t${BOLD}test${RESET}" 43 | @echo -e "\t\t${BOLD}install_env${RESET}" 44 | @echo -e "\t\t${BOLD}install_devel${RESET}" 45 | @echo -e "\t\t${BOLD}install_build${RESET}" 46 | @echo -e "\t\t${BOLD}install_test${RESET}" 47 | @echo -e "\te.g. 'make ubuntu_test'" 48 | @echo 49 | @echo -e "\tBuild using docker buildx with a platform specified." 50 | @echo -e "\t${BOLD}_${RESET}: build docker images for ALL DISTROS." 51 | @echo -e "\t${BOLD}__${RESET}: build docker image for a specific distro." 52 | @echo -e "\t${BOLD}save__${RESET}: Save docker images for ALL DISTROS." 53 | @echo -e "\t${BOLD}save___${RESET}: Save the docker image for a specific distro." 54 | @echo -e "\t${BOLD}sh___${RESET}: run a container using the docker image specified (debug purpose)." 55 | @echo -e "\t${BOLD}clean___${RESET}: Remove cache and docker image." 56 | @echo -e "\t${BOLD}clean_platforms${RESET}: Remove ALL cache and docker image." 57 | @echo 58 | @echo -e "\tWith ${BOLD}${RESET}:" 59 | @echo -e "\t\t${BOLD}amd64${RESET}: linux/amd64 (x86_64)" 60 | @echo -e "\t\t${BOLD}386${RESET}: linux/386 (x86)" 61 | @echo -e "\t\t${BOLD}arm${RESET}: linux/arm (armv7)" 62 | @echo -e "\t\t${BOLD}arm64${RESET}: linux/arm64 (aarch64, arm64v8)" 63 | @echo -e "\t\t${BOLD}mips${RESET}: linux/mips (mips 32bits)" 64 | @echo -e "\t\t${BOLD}mipsle${RESET}: linux/mipsle (mips 32bits Little Endian)" 65 | @echo -e "\t\t${BOLD}mips64${RESET}: linux/mips64 (mips 64bits)" 66 | @echo -e "\t\t${BOLD}mips64le${RESET}: linux/mips64le (mips 64bits Little Endian)" 67 | @echo -e "\t\t${BOLD}ppc64${RESET}: linux/ppc64 (PowerPC 64Bits)" 68 | @echo -e "\t\t${BOLD}ppc64le${RESET}: linux/ppc64le (PowerPC 64Bits Little Endian)" 69 | @echo -e "\t\t${BOLD}riscv64${RESET}: linux/riscv64 (RISC-V 64bits)" 70 | @echo -e "\t\t${BOLD}s390x${RESET}: linux/s390x (IBM System/390x)" 71 | @echo -e "\te.g. 'make amd64_ubuntu_test'" 72 | @echo -e "\tDocker image unavailable: arm64_archlinux" 73 | @echo 74 | @echo -e "\tBuild using a vagrant machine." 75 | @echo -e "\t${BOLD}_${RESET}: build the vagrant virtual machine." 76 | @echo -e "\t${BOLD}sh__${RESET}: ssh to the vagrant machine specified (debug purpose)." 77 | @echo -e "\t${BOLD}clean_${RESET}: Remove virtual machine for the specified vm." 78 | @echo -e "\t${BOLD}clean_vms${RESET}: Remove ALL vagrant box." 79 | @echo 80 | @echo -e "\tWith ${BOLD}${RESET}:" 81 | @echo -e "\t\t${BOLD}freebsd${RESET} (FreeBSD 14)" 82 | @echo -e "\t\t${BOLD}netbsd${RESET} (NetBSD 9)" 83 | @echo -e "\t\t${BOLD}openbsd${RESET} (OpenBSD 7)" 84 | @echo 85 | @echo -e "\tWith ${BOLD}${RESET}:" 86 | @echo -e "\t\t${BOLD}build${RESET}" 87 | @echo -e "\te.g. 'make freebsd_build'" 88 | @echo 89 | @echo -e "\tGlobal targets." 90 | @echo -e "\t${BOLD}clean${RESET}: Remove ALL caches and docker images." 91 | @echo -e "\t${BOLD}distclean${RESET}: Remove everything." 92 | @echo 93 | @echo -e "\t${BOLD}NOCACHE=1${RESET}: use 'docker build --no-cache' when building container (default use cache)." 94 | @echo -e "\t${BOLD}VERBOSE=1${RESET}: use 'docker build --progress=plain' when building container." 95 | @echo 96 | @echo -e "branch: $(BRANCH)" 97 | @echo -e "sha1: $(SHA1)" 98 | 99 | # Need to add cmd_distro to PHONY otherwise target are ignored since they do not 100 | # contain recipe (using FORCE do not work here) 101 | .PHONY: all 102 | all: all_test 103 | 104 | # Delete all implicit rules to speed up makefile 105 | MAKEFLAGS += --no-builtin-rules 106 | .SUFFIXES: 107 | # Remove some rules from gmake that .SUFFIXES does not remove. 108 | SUFFIXES := 109 | # Keep all intermediate files 110 | # ToDo: try to remove it later 111 | .SECONDARY: 112 | 113 | # Docker image name prefix. 114 | IMAGE := ${PROJECT} 115 | 116 | DOCKER_BUILD_CMD := docker build 117 | DOCKER_BUILDX_CMD := docker buildx build 118 | ifdef NOCACHE 119 | DOCKER_BUILD_CMD := ${DOCKER_BUILD_CMD} --no-cache 120 | DOCKER_BUILDX_CMD := ${DOCKER_BUILDX_CMD} --no-cache 121 | endif 122 | ifdef VERBOSE 123 | DOCKER_BUILD_CMD := ${DOCKER_BUILD_CMD} --progress=plain 124 | DOCKER_BUILDX_CMD := ${DOCKER_BUILDX_CMD} --progress=plain 125 | endif 126 | DOCKER_RUN_CMD := docker run --rm --init --net=host 127 | 128 | # Currently supported distro 129 | DISTROS := \ 130 | almalinux \ 131 | alpine \ 132 | archlinux \ 133 | debian \ 134 | fedora \ 135 | opensuse \ 136 | rockylinux \ 137 | ubuntu 138 | 139 | # $* stem 140 | # $< first prerequist 141 | # $@ target name 142 | 143 | ############ 144 | ## STAGES ## 145 | ############ 146 | STAGES := env devel build test install_env install_devel install_build install_test 147 | 148 | define make-stage-target = 149 | #$$(info STAGE: $1) 150 | #$$(info Create targets: all_$1 $(addsuffix _$1, $(DISTROS)).) 151 | targets_$1 := $(addsuffix _$1, $(DISTROS)) 152 | .PHONY: all_$1 $$(targets_$1) 153 | all_$1: $$(targets_$1) 154 | $$(targets_$1): %_$1: docker/%/Dockerfile 155 | #@docker image rm -f ${IMAGE}:$$*_$1 2>/dev/null 156 | ${DOCKER_BUILD_CMD} --target=$1 --tag ${IMAGE}:$$*_$1 -f $$< .. 157 | 158 | #$$(info Create targets: save_all_$1 $(addprefix save_, $(addsuffix _$1, $(DISTROS))) (debug).) 159 | save_targets_$1 := $(addprefix save_, $(addsuffix _$1, $(DISTROS))) 160 | .PHONY: save_all_$1 $$(save_targets_$1) 161 | save_all_$1: $$(save_targets_$1) 162 | $$(save_targets_$1): save_%_$1: cache/%/docker_$1.tar 163 | cache/%/docker_$1.tar: %_$1 164 | @rm -f $$@ 165 | mkdir -p cache/$$* 166 | docker save ${IMAGE}:$$*_$1 -o $$@ 167 | 168 | #$$(info Create targets: $(addprefix sh_, $(addsuffix _$1, $(DISTROS))) (debug).) 169 | sh_targets_$1 := $(addprefix sh_, $(addsuffix _$1, $(DISTROS))) 170 | .PHONY: $$(sh_targets_$1) 171 | $$(sh_targets_$1): sh_%_$1: %_$1 172 | ${DOCKER_RUN_CMD} -it --name ${PROJECT}_$$*_$1 ${IMAGE}:$$*_$1 173 | 174 | #$$(info Create targets: clean_all_$1 $(addprefix clean_, $(addsuffix _$1, $(DISTROS))).) 175 | clean_targets_$1 := $(addprefix clean_, $(addsuffix _$1, $(DISTROS))) 176 | .PHONY: clean_all_$1 $$(clean_targets_$1) 177 | clean_all_$1: $$(clean_targets_$1) 178 | $$(clean_targets_$1): clean_%_$1: 179 | docker image rm -f ${IMAGE}:$$*_$1 2>/dev/null 180 | rm -f cache/$$*/docker_$1.tar 181 | endef 182 | 183 | $(foreach stage,$(STAGES),$(eval $(call make-stage-target,$(stage)))) 184 | 185 | ## MERGE ## 186 | .PHONY: clean_all 187 | clean_all: $(addprefix clean_all_, $(STAGES)) 188 | rm -f $(addprefix cache/, $(DISTROS)) 189 | 190 | ############## 191 | ## PLATFORM ## 192 | ############## 193 | # ref: https://go.dev/doc/install/source#environment 194 | # ref: https://github.com/containerd/containerd/blob/269548fa27e0089a8b8278fc4fc781d7f65a939b/platforms/platforms.go#L80-L94 195 | PLATFORMS := \ 196 | 386 amd64 \ 197 | arm arm64 \ 198 | mips mipsle mips64 mips64le \ 199 | ppc64 ppc64le \ 200 | riscv64 \ 201 | s390x 202 | 203 | define make-platform-stage-target = 204 | #$$(info PLATFORM: '$1' STAGE: '$2') 205 | #$$(info Create targets: $1_all_$2 $(addprefix $1_, $(addsuffix _$2, $(DISTROS))).) 206 | targets_$1_$2 := $(addprefix $1_, $(addsuffix _$2, $(DISTROS))) 207 | .PHONY: $1_all_$2 $$(targets_$1_$2) 208 | $1_all_$2: $$(targets_$1_$2) 209 | $$(targets_$1_$2): $1_%_$2: docker/%/Dockerfile 210 | #@docker image rm -f ${IMAGE}:$1_$$*_$2 2>/dev/null 211 | ${DOCKER_BUILDX_CMD} --platform linux/$1 --target=$2 --tag ${IMAGE}:$1_$$*_$2 -f $$< .. 212 | 213 | #$$(info Create save targets: save_$1_all_$2 $(addprefix save_$1_, $(addsuffix _$2, $(DISTROS))) (debug).) 214 | save_targets_$1_$2 := $(addprefix save_$1_, $(addsuffix _$2, $(DISTROS))) 215 | .PHONY: save_$1_all_$2 $$(save_targets_$1_$2) 216 | save_$1_all_$2: $$(save_targets_$1_$2) 217 | $$(save_targets_$1_$2): save_$1_%_$2: cache/$1/%/docker_$2.tar 218 | cache/$1/%/docker_$2.tar: $1_%_$2 219 | @rm -f $$@ 220 | mkdir -p cache/$1/$$* 221 | docker save ${IMAGE}:$1_$$*_$2 -o $$@ 222 | 223 | #$$(info Create sh targets: $(addprefix sh_$1_, $(addsuffix _$2, $(DISTROS))) (debug).) 224 | sh_targets_$1_$2 := $(addprefix sh_$1_, $(addsuffix _$2, $(DISTROS))) 225 | .PHONY: $$(sh_targets_$1_$2) 226 | $$(sh_targets_$1_$2): sh_$1_%_$2: $1_%_$2 227 | ${DOCKER_RUN_CMD} --platform linux/$1 -it --name ${IMAGE}_$1_$$*_$2 ${IMAGE}:$1_$$*_$2 228 | 229 | #$$(info Create targets: clean_$1_all_$2 $(addprefix clean_$1_, $(addsuffix _$2, $(DISTROS))).) 230 | clean_targets_$1_$2 := $(addprefix clean_$1_, $(addsuffix _$2, $(DISTROS))) 231 | .PHONY: clean_$1_all_$2 $$(clean_targets_$1_$2) 232 | clean_$1_all_$2: $$(clean_targets_$1_$2) 233 | $$(clean_targets_$1_$2): clean_$1_%_$2: 234 | docker image rm -f ${IMAGE}:$1_$$*_$2 2>/dev/null 235 | rm -f cache/$1/$$*/docker_$2.tar 236 | endef 237 | 238 | define make-platform-target = 239 | #$$(info PLATFORM: $1) 240 | $(foreach stage,$(STAGES),$(eval $(call make-platform-stage-target,$1,$(stage)))) 241 | 242 | # merge 243 | .PHONY: clean_$1 244 | clean_$1: $(addprefix clean_$1_all_, $(STAGES)) 245 | -rmdir $(addprefix cache/$1/, $(DISTROS)) 246 | -rmdir cache/$1 247 | endef 248 | 249 | $(foreach platform,$(PLATFORMS),$(eval $(call make-platform-target,$(platform)))) 250 | 251 | ## MERGE ## 252 | .PHONY: clean_platforms 253 | clean_platforms: $(addprefix clean_, $(PLATFORMS)) 254 | 255 | ############# 256 | ## VAGRANT ## 257 | ############# 258 | VAGRANT_VMS := \ 259 | freebsd \ 260 | netbsd \ 261 | openbsd 262 | 263 | vms_targets := $(addsuffix _build, $(VAGRANT_VMS)) 264 | .PHONY: vms_build $(vms_targets) 265 | vms_build: $(vms_targets) 266 | $(vms_targets): %_build: vagrant/%/Vagrantfile 267 | @cd vagrant/$* && vagrant destroy -f 268 | cd vagrant/$* && vagrant up 269 | 270 | sh_vms_targets := $(addprefix sh_,$(addsuffix _build, $(VAGRANT_VMS))) 271 | .PHONY: $(sh_vms_targets) 272 | $(sh_vms_targets): sh_%_build: vagrant/%/Vagrantfile 273 | cd vagrant/$* && vagrant up 274 | cd vagrant/$* && vagrant ssh 275 | 276 | clean_vms_targets := $(addprefix clean_, $(VAGRANT_VMS)) 277 | .PHONY: clean_vms $(clean_vms_targets) 278 | clean_vms: $(clean_vms_targets) 279 | $(clean_vms_targets): clean_%: vagrant/%/Vagrantfile 280 | cd vagrant/$* && vagrant destroy -f 281 | -rm -rf vagrant/$*/.vagrant 282 | 283 | ########### 284 | ## CLEAN ## 285 | ########### 286 | .PHONY: clean 287 | clean: clean_all clean_platforms clean_vms 288 | docker container prune -f 289 | docker image prune -f 290 | -rmdir cache 291 | 292 | .PHONY: distclean 293 | distclean: clean 294 | -docker container rm -f $$(docker container ls -aq) 295 | -docker image rm -f $$(docker image ls -aq) 296 | -vagrant box remove -f generic/freebsd14 297 | -------------------------------------------------------------------------------- /ci/README.md: -------------------------------------------------------------------------------- 1 | # CI: Makefile/Docker testing 2 | 3 | To test the build on various distro, I'm using docker containers and a Makefile for orchestration. 4 | 5 | pros: 6 | * You are independent of third party CI runner VM images (e.g. [github actions/virtual-environments](https://github.com/actions/virtual-environments)). 7 | * You can run it locally on any host having a linux docker image support. 8 | * Most CI provide runner with docker and Makefile installed. 9 | 10 | cons: 11 | * Only GNU/Linux distro supported. 12 | * Could take few GiB (~30 GiB for all distro and all languages) 13 | * ~500MiB OS + C++/CMake tools, 14 | 15 | ## Usage 16 | 17 | To get the help simply type: 18 | ```sh 19 | make 20 | ``` 21 | 22 | note: you can also use from top directory 23 | ```sh 24 | make --directory=ci 25 | ``` 26 | 27 | ### Example 28 | 29 | For example to test inside an `Alpine` container: 30 | ```sh 31 | make alpine_test 32 | ``` 33 | 34 | ## Docker layers 35 | 36 | Dockerfile is splitted in several stages. 37 | 38 | ![docker](docs/docker.svg) 39 | 40 | ### Run arm64v8 image on amd64 machine 41 | 42 | You can build and run `arm64v8` (i.e. `aarch64`) docker container on a `amd64` host (`x86_64`) by enabling qemu support: 43 | ```sh 44 | docker run --pull always --rm --privileged multiarch/qemu-user-static --reset -p yes 45 | ``` 46 | ref: https://github.com/multiarch/qemu-user-static#getting-started 47 | 48 | Then you should be able to run them, e.g.: 49 | ```sh 50 | docker run --rm -it arm64v8/ubuntu 51 | ``` 52 | ref: https://github.com/docker-library/official-images#architectures-other-than-amd64 53 | 54 | ### Docker buildx 55 | 56 | ref: https://docs.docker.com/buildx/working-with-buildx/ 57 | 58 | On you enable qemu support (see above), you can list available platform using: 59 | ```sh 60 | docker buildx ls 61 | ``` 62 | Then you can build a docker image using one of the available platform 63 | ```sh 64 | docker buildx build --platform linux/arm64 ... 65 | ``` 66 | 67 | ## Custom CMake install 68 | 69 | To control the version of CMake, instead of using the 70 | [version provided by the distro package manager](https://repology.org/project/cmake/badges), you can: 71 | * Install the prebuilt binaries (recommanded) 72 | * Build it from source (slower) 73 | * Install it using the [pypi package cmake](https://pypi.org/project/cmake/) (need a python stack) 74 | 75 | ### Install prebuilt 76 | 77 | The recommended and faster way is to use the prebuilt version: 78 | ```Dockerfile 79 | # Install CMake 3.25.2 80 | RUN wget "https://cmake.org/files/v3.25/cmake-3.25.2-linux-x86_64.sh" \ 81 | && chmod a+x cmake-3.25.2-linux-x86_64.sh \ 82 | && ./cmake-3.25.2-linux-x86_64.sh --prefix=/usr/local/ --skip-license \ 83 | && rm cmake-3.25.2-linux-x86_64.sh 84 | ``` 85 | 86 | **warning**: Since [CMake 3.20](https://cmake.org/files/v3.20/) Kitware use a lowercase `linux` instead of `Linux` (e.g. [CMake 3.19](https://cmake.org/files/v3.19/)). 87 | 88 | ### Build from source 89 | 90 | To build from source you can use the following snippet: 91 | ```Dockerfile 92 | # Install CMake 3.25.2 93 | RUN wget "https://cmake.org/files/v3.25/cmake-3.25.2.tar.gz" \ 94 | && tar xzf cmake-3.25.2.tar.gz \ 95 | && rm cmake-3.25.2.tar.gz \ 96 | && cd cmake-3.25.2 \ 97 | && ./bootstrap --prefix=/usr/local/ \ 98 | && make \ 99 | && make install \ 100 | && cd .. \ 101 | && rm -rf cmake-3.25.2 102 | ``` 103 | 104 | -------------------------------------------------------------------------------- /ci/docker/almalinux/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/almalinux 3 | FROM almalinux:latest AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN dnf -y update \ 8 | && dnf -y install git wget openssl-devel cmake \ 9 | && dnf -y groupinstall "Development Tools" \ 10 | && dnf clean all \ 11 | && rm -rf /var/cache/dnf 12 | CMD [ "/usr/bin/bash" ] 13 | 14 | # Add the library src to our build env 15 | FROM env AS devel 16 | WORKDIR /home/project 17 | COPY . . 18 | 19 | FROM devel AS build 20 | RUN cmake --version 21 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 22 | RUN cmake --build build --target all -v 23 | RUN cmake --build build --target install -v 24 | 25 | FROM build AS test 26 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 27 | 28 | # Test install rules 29 | FROM env AS install_env 30 | COPY --from=build /usr/local /usr/local/ 31 | 32 | FROM install_env AS install_devel 33 | WORKDIR /home/samples 34 | COPY ci/samples . 35 | 36 | FROM install_devel AS install_build 37 | RUN cmake -S. -Bbuild 38 | RUN cmake --build build --target all -v 39 | 40 | FROM install_build AS install_test 41 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 42 | -------------------------------------------------------------------------------- /ci/docker/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/alpine 3 | FROM alpine:edge AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN apk add --no-cache git build-base linux-headers cmake 8 | 9 | # Add the library src to our build env 10 | FROM env AS devel 11 | WORKDIR /home/project 12 | COPY . . 13 | 14 | FROM devel AS build 15 | RUN cmake --version 16 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 17 | RUN cmake --build build --target all -v 18 | RUN cmake --build build --target install -v 19 | 20 | FROM build AS test 21 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 22 | 23 | # Test install rules 24 | FROM env AS install_env 25 | COPY --from=build /usr/local /usr/local/ 26 | 27 | FROM install_env AS install_devel 28 | WORKDIR /home/samples 29 | COPY ci/samples . 30 | 31 | FROM install_devel AS install_build 32 | RUN cmake -S. -Bbuild 33 | RUN cmake --build build --target all -v 34 | 35 | FROM install_build AS install_test 36 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 37 | -------------------------------------------------------------------------------- /ci/docker/archlinux/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/archlinux/ 3 | FROM archlinux:latest AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN pacman -Syu --noconfirm git base-devel cmake 8 | 9 | # Add the library src to our build env 10 | FROM env AS devel 11 | WORKDIR /home/project 12 | COPY . . 13 | 14 | FROM devel AS build 15 | RUN cmake --version 16 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 17 | RUN cmake --build build --target all -v 18 | RUN cmake --build build --target install -v 19 | 20 | FROM build AS test 21 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 22 | 23 | # Test install rules 24 | FROM env AS install_env 25 | COPY --from=build /usr/local /usr/local/ 26 | 27 | FROM install_env AS install_devel 28 | WORKDIR /home/samples 29 | COPY ci/samples . 30 | 31 | FROM install_devel AS install_build 32 | RUN cmake -S. -Bbuild 33 | RUN cmake --build build --target all -v 34 | 35 | FROM install_build AS install_test 36 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 37 | -------------------------------------------------------------------------------- /ci/docker/debian/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/debian 3 | FROM debian:unstable AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN apt-get update -qq \ 8 | && apt-get install -yq git wget libssl-dev build-essential cmake \ 9 | && apt-get clean \ 10 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 11 | 12 | # Add the library src to our build env 13 | FROM env AS devel 14 | WORKDIR /home/project 15 | COPY . . 16 | 17 | FROM devel AS build 18 | RUN cmake --version 19 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 20 | RUN cmake --build build --target all -v 21 | RUN cmake --build build --target install -v 22 | 23 | FROM build AS test 24 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 25 | 26 | # Test install rules 27 | FROM env AS install_env 28 | COPY --from=build /usr/local /usr/local/ 29 | 30 | FROM install_env AS install_devel 31 | WORKDIR /home/samples 32 | COPY ci/samples . 33 | 34 | FROM install_devel AS install_build 35 | RUN cmake -S. -Bbuild 36 | RUN cmake --build build --target all -v 37 | 38 | FROM install_build AS install_test 39 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 40 | -------------------------------------------------------------------------------- /ci/docker/fedora/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/fedora 3 | FROM fedora:latest AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN dnf -y update \ 8 | && dnf -y install git wget \ 9 | && dnf -y install @development-tools \ 10 | && dnf -y install gcc-c++ cmake \ 11 | && dnf clean all 12 | 13 | # Add the library src to our build env 14 | FROM env AS devel 15 | WORKDIR /home/project 16 | COPY . . 17 | 18 | FROM devel AS build 19 | RUN cmake --version 20 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 21 | RUN cmake --build build --target all -v 22 | RUN cmake --build build --target install -v 23 | 24 | FROM build AS test 25 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 26 | 27 | # Test install rules 28 | FROM env AS install_env 29 | COPY --from=build /usr/local /usr/local/ 30 | 31 | FROM install_env AS install_devel 32 | WORKDIR /home/samples 33 | COPY ci/samples . 34 | 35 | FROM install_devel AS install_build 36 | RUN cmake -S. -Bbuild 37 | RUN cmake --build build --target all -v 38 | 39 | FROM install_build AS install_test 40 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 41 | -------------------------------------------------------------------------------- /ci/docker/opensuse/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/r/opensuse/tumbleweed 3 | FROM opensuse/tumbleweed AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN zypper update -y \ 8 | && zypper install -y git patch gcc gcc-c++ cmake \ 9 | && zypper clean -a 10 | ENV CC=gcc CXX=g++ 11 | 12 | # Add the library src to our build env 13 | FROM env AS devel 14 | WORKDIR /home/project 15 | COPY . . 16 | 17 | FROM devel AS build 18 | RUN cmake --version 19 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 20 | RUN cmake --build build --target all -v 21 | RUN cmake --build build --target install -v 22 | 23 | FROM build AS test 24 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 25 | 26 | # Test install rules 27 | FROM env AS install_env 28 | COPY --from=build /usr/local /usr/local/ 29 | 30 | FROM install_env AS install_devel 31 | WORKDIR /home/samples 32 | COPY ci/samples . 33 | 34 | FROM install_devel AS install_build 35 | RUN cmake -S. -Bbuild 36 | RUN cmake --build build --target all -v 37 | 38 | FROM install_build AS install_test 39 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 40 | -------------------------------------------------------------------------------- /ci/docker/rockylinux/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/rockylinux 3 | FROM rockylinux:9 AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN dnf -y update \ 8 | && dnf -y install git wget openssl-devel cmake \ 9 | && dnf -y groupinstall "Development Tools" \ 10 | && dnf clean all \ 11 | && rm -rf /var/cache/dnf 12 | CMD [ "/usr/bin/bash" ] 13 | 14 | # Add the library src to our build env 15 | FROM env AS devel 16 | WORKDIR /home/project 17 | COPY . . 18 | 19 | FROM devel AS build 20 | RUN cmake --version 21 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 22 | RUN cmake --build build --target all -v 23 | RUN cmake --build build --target install -v 24 | 25 | FROM build AS test 26 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 27 | 28 | # Test install rules 29 | FROM env AS install_env 30 | COPY --from=build /usr/local /usr/local/ 31 | 32 | FROM install_env AS install_devel 33 | WORKDIR /home/samples 34 | COPY ci/samples . 35 | 36 | FROM install_devel AS install_build 37 | RUN cmake -S. -Bbuild 38 | RUN cmake --build build --target all -v 39 | 40 | FROM install_build AS install_test 41 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 42 | -------------------------------------------------------------------------------- /ci/docker/ubuntu/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/_/ubuntu 3 | FROM ubuntu:latest AS env 4 | 5 | # Install system build dependencies 6 | ENV PATH=/usr/local/bin:$PATH 7 | RUN apt update -q \ 8 | && DEBIAN_FRONTEND=noninteractive apt install -yq \ 9 | git wget libssl-dev \ 10 | build-essential cmake \ 11 | && apt-get clean \ 12 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 13 | 14 | FROM env AS devel 15 | WORKDIR /home/project 16 | COPY . . 17 | 18 | FROM devel AS build 19 | RUN cmake --version 20 | RUN cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release 21 | RUN cmake --build build --target all -v 22 | RUN cmake --build build --target install -v 23 | 24 | FROM build AS test 25 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 26 | 27 | # Test install rules 28 | FROM env AS install_env 29 | COPY --from=build /usr/local /usr/local/ 30 | 31 | FROM install_env AS install_devel 32 | WORKDIR /home/samples 33 | COPY ci/samples . 34 | 35 | FROM install_devel AS install_build 36 | RUN cmake -S. -Bbuild 37 | RUN cmake --build build --target all -v 38 | 39 | FROM install_build AS install_test 40 | RUN CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test -v 41 | -------------------------------------------------------------------------------- /ci/docs/docker.dot: -------------------------------------------------------------------------------- 1 | @startdot 2 | digraph DockerDeps { 3 | //rankdir=BT; 4 | rankdir=TD; 5 | node [shape=cylinder, style="rounded,filled", color=black, fillcolor=royalblue]; 6 | DISTRO_IMG [label=":latest"]; 7 | PKG [label="packages\ne.g. cmake, g++", shape=box3d]; 8 | SRC [label="git repo", shape=folder]; 9 | SPL [label="samples", shape=folder]; 10 | 11 | subgraph clusterDockerfile { 12 | ENV_IMG [label="cmake-external:_env\nenv"]; 13 | DEVEL_IMG [label="cmake-external:_devel\ndevel"]; 14 | BUILD_IMG [label="cmake-external:_build\nbuild"]; 15 | TEST_IMG [label="cmake-external:_test\ntest"]; 16 | INSTALL_ENV_IMG [label="cmake-external:_install_env\ninstall_env"]; 17 | INSTALL_DEVEL_IMG [label="cmake-external:_install_devel\ninstall_devel"]; 18 | INSTALL_BUILD_IMG [label="cmake-external:_install_build\ninstall_build"]; 19 | INSTALL_TEST_IMG [label="cmake-external:_install_test\ninstall_test"]; 20 | 21 | ENV_IMG -> DEVEL_IMG; 22 | DEVEL_IMG -> BUILD_IMG; 23 | BUILD_IMG -> TEST_IMG; 24 | 25 | ENV_IMG -> INSTALL_ENV_IMG; 26 | BUILD_IMG -> INSTALL_ENV_IMG [label="copy install", style="dashed"]; 27 | INSTALL_ENV_IMG -> INSTALL_DEVEL_IMG; 28 | SPL -> INSTALL_DEVEL_IMG [label="copy", style="dashed"]; 29 | INSTALL_DEVEL_IMG -> INSTALL_BUILD_IMG; 30 | INSTALL_BUILD_IMG -> INSTALL_TEST_IMG; 31 | 32 | color=royalblue; 33 | label = "docker//Dockerfile"; 34 | } 35 | DISTRO_IMG -> ENV_IMG; 36 | PKG -> ENV_IMG [label="install", style="dashed"]; 37 | SRC -> DEVEL_IMG [label="copy", style="dashed"]; 38 | 39 | subgraph clusterCache { 40 | node [shape=note, style="rounded,filled", color=black, fillcolor=royalblue]; 41 | ENV_TAR [label="docker_env.tar"]; 42 | DEVEL_TAR [label="docker_devel.tar"]; 43 | BUILD_TAR [label="docker_build.tar"]; 44 | TEST_TAR [label="docker_test.tar"]; 45 | INSTALL_ENV_TAR [label="docker_install_env.tar"]; 46 | INSTALL_DEVEL_TAR [label="docker_install_devel.tar"]; 47 | INSTALL_BUILD_TAR [label="docker_install_build.tar"]; 48 | INSTALL_TEST_TAR [label="docker_install_test.tar"]; 49 | 50 | edge [color=red]; 51 | ENV_IMG -> ENV_TAR [label="make save__env"]; 52 | DEVEL_IMG -> DEVEL_TAR [label="make save__devel"]; 53 | BUILD_IMG -> BUILD_TAR [label="make save__build"]; 54 | TEST_IMG -> TEST_TAR [label="make save__test"]; 55 | INSTALL_ENV_IMG -> INSTALL_ENV_TAR [label="make save__install_env"]; 56 | INSTALL_DEVEL_IMG -> INSTALL_DEVEL_TAR [label="make save__install_devel"]; 57 | INSTALL_BUILD_IMG -> INSTALL_BUILD_TAR [label="make save__install_build"]; 58 | INSTALL_TEST_IMG -> INSTALL_TEST_TAR [label="make save__install_test"]; 59 | 60 | color=royalblue; 61 | label = "cache//"; 62 | } 63 | } 64 | @enddot 65 | -------------------------------------------------------------------------------- /ci/docs/docker.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | DockerDeps 11 | 12 | 13 | clusterDockerfile 14 | 15 | docker/<distro>/Dockerfile 16 | 17 | 18 | clusterCache 19 | 20 | cache/<distro>/ 21 | 22 | 23 | 24 | DISTRO_IMG 25 | 26 | 27 | <distro>:latest 28 | 29 | 30 | 31 | ENV_IMG 32 | 33 | 34 | cmake-external:<distro>_env 35 | env 36 | 37 | 38 | 39 | DISTRO_IMG->ENV_IMG 40 | 41 | 42 | 43 | 44 | 45 | PKG 46 | 47 | 48 | 49 | 50 | packages 51 | e.g. cmake, g++ 52 | 53 | 54 | 55 | PKG->ENV_IMG 56 | 57 | 58 | install 59 | 60 | 61 | 62 | SRC 63 | 64 | git repo 65 | 66 | 67 | 68 | DEVEL_IMG 69 | 70 | 71 | cmake-external:<distro>_devel 72 | devel 73 | 74 | 75 | 76 | SRC->DEVEL_IMG 77 | 78 | 79 | copy 80 | 81 | 82 | 83 | SPL 84 | 85 | samples 86 | 87 | 88 | 89 | INSTALL_DEVEL_IMG 90 | 91 | 92 | cmake-external:<distro>_install_devel 93 | install_devel 94 | 95 | 96 | 97 | SPL->INSTALL_DEVEL_IMG 98 | 99 | 100 | copy 101 | 102 | 103 | 104 | ENV_IMG->DEVEL_IMG 105 | 106 | 107 | 108 | 109 | 110 | INSTALL_ENV_IMG 111 | 112 | 113 | cmake-external:<distro>_install_env 114 | install_env 115 | 116 | 117 | 118 | ENV_IMG->INSTALL_ENV_IMG 119 | 120 | 121 | 122 | 123 | 124 | ENV_TAR 125 | 126 | 127 | 128 | docker_env.tar 129 | 130 | 131 | 132 | ENV_IMG->ENV_TAR 133 | 134 | 135 | make save_<distro>_env 136 | 137 | 138 | 139 | BUILD_IMG 140 | 141 | 142 | cmake-external:<distro>_build 143 | build 144 | 145 | 146 | 147 | DEVEL_IMG->BUILD_IMG 148 | 149 | 150 | 151 | 152 | 153 | DEVEL_TAR 154 | 155 | 156 | 157 | docker_devel.tar 158 | 159 | 160 | 161 | DEVEL_IMG->DEVEL_TAR 162 | 163 | 164 | make save_<distro>_devel 165 | 166 | 167 | 168 | TEST_IMG 169 | 170 | 171 | cmake-external:<distro>_test 172 | test 173 | 174 | 175 | 176 | BUILD_IMG->TEST_IMG 177 | 178 | 179 | 180 | 181 | 182 | BUILD_IMG->INSTALL_ENV_IMG 183 | 184 | 185 | copy install 186 | 187 | 188 | 189 | BUILD_TAR 190 | 191 | 192 | 193 | docker_build.tar 194 | 195 | 196 | 197 | BUILD_IMG->BUILD_TAR 198 | 199 | 200 | make save_<distro>_build 201 | 202 | 203 | 204 | TEST_TAR 205 | 206 | 207 | 208 | docker_test.tar 209 | 210 | 211 | 212 | TEST_IMG->TEST_TAR 213 | 214 | 215 | make save_<distro>_test 216 | 217 | 218 | 219 | INSTALL_ENV_IMG->INSTALL_DEVEL_IMG 220 | 221 | 222 | 223 | 224 | 225 | INSTALL_ENV_TAR 226 | 227 | 228 | 229 | docker_install_env.tar 230 | 231 | 232 | 233 | INSTALL_ENV_IMG->INSTALL_ENV_TAR 234 | 235 | 236 | make save_<distro>_install_env 237 | 238 | 239 | 240 | INSTALL_BUILD_IMG 241 | 242 | 243 | cmake-external:<distro>_install_build 244 | install_build 245 | 246 | 247 | 248 | INSTALL_DEVEL_IMG->INSTALL_BUILD_IMG 249 | 250 | 251 | 252 | 253 | 254 | INSTALL_DEVEL_TAR 255 | 256 | 257 | 258 | docker_install_devel.tar 259 | 260 | 261 | 262 | INSTALL_DEVEL_IMG->INSTALL_DEVEL_TAR 263 | 264 | 265 | make save_<distro>_install_devel 266 | 267 | 268 | 269 | INSTALL_TEST_IMG 270 | 271 | 272 | cmake-external:<distro>_install_test 273 | install_test 274 | 275 | 276 | 277 | INSTALL_BUILD_IMG->INSTALL_TEST_IMG 278 | 279 | 280 | 281 | 282 | 283 | INSTALL_BUILD_TAR 284 | 285 | 286 | 287 | docker_install_build.tar 288 | 289 | 290 | 291 | INSTALL_BUILD_IMG->INSTALL_BUILD_TAR 292 | 293 | 294 | make save_<distro>_install_build 295 | 296 | 297 | 298 | INSTALL_TEST_TAR 299 | 300 | 301 | 302 | docker_install_test.tar 303 | 304 | 305 | 306 | INSTALL_TEST_IMG->INSTALL_TEST_TAR 307 | 308 | 309 | make save_<distro>_install_test 310 | 311 | 312 | 313 | -------------------------------------------------------------------------------- /ci/docs/generate_image.sh: -------------------------------------------------------------------------------- 1 | #/usr/bin/env bash 2 | set -ex 3 | 4 | rm -f *.svg *.png 5 | for i in *.dot; do 6 | #plantuml -Tpng "$i"; 7 | plantuml -Tsvg "$i"; 8 | done 9 | -------------------------------------------------------------------------------- /ci/samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(Sample VERSION 1.0.0 LANGUAGES CXX) 3 | 4 | include(CTest) 5 | find_package(CMakeExternal CONFIG REQUIRED) 6 | 7 | add_executable(sample) 8 | target_sources(sample PRIVATE 9 | main.cpp) 10 | target_compile_features(sample PUBLIC cxx_std_17) 11 | set_target_properties(sample PROPERTIES 12 | VERSION ${PROJECT_VERSION}) 13 | target_link_libraries(sample PRIVATE 14 | absl::flags_parse 15 | absl::log 16 | absl::log_initialize 17 | absl::strings 18 | CMakeExternal::Foo 19 | CMakeExternal::Bar 20 | ) 21 | 22 | if(BUILD_TESTING) 23 | add_test(NAME sample_UT COMMAND sample) 24 | endif() 25 | 26 | # Install 27 | include(GNUInstallDirs) 28 | install(TARGETS sample 29 | EXPORT SampleTargets 30 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 31 | ) 32 | -------------------------------------------------------------------------------- /ci/samples/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | int main(int argc, char* argv[]) { 17 | absl::InitializeLog(); 18 | absl::SetProgramUsageMessage("FooBarApp"); 19 | absl::EnableLogPrefix(false); 20 | absl::SetStderrThreshold(absl::LogSeverity::kInfo); 21 | absl::ParseCommandLine(argc, argv); 22 | { 23 | const std::vector v = {"foo","bar","baz"}; 24 | std::string s = absl::StrJoin(v, "-"); 25 | LOG(INFO) << "Joined string: " << s << "\n"; 26 | } 27 | 28 | foo::freeFunction(0); 29 | bar::freeFunction(1); 30 | std::cout << std::endl; 31 | 32 | foo::Foo::staticFunction(int{0}); 33 | bar::Bar::staticFunction(int{1}); 34 | std::cout << std::endl; 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /ci/vagrant/freebsd/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure("2") do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://vagrantcloud.com/search. 15 | config.vm.guest = :freebsd 16 | config.vm.box = "generic/freebsd14" 17 | config.vm.provider "virtualbox" do |v| 18 | v.name = "ci_freebsd" 19 | end 20 | config.ssh.shell = "sh" 21 | 22 | # Disable automatic box update checking. If you disable this, then 23 | # boxes will only be checked for updates when the user runs 24 | # `vagrant box outdated`. This is not recommended. 25 | # config.vm.box_check_update = false 26 | 27 | # Create a forwarded port mapping which allows access to a specific port 28 | # within the machine from a port on the host machine. In the example below, 29 | # accessing "localhost:8080" will access port 80 on the guest machine. 30 | # NOTE: This will enable public access to the opened port 31 | # config.vm.network "forwarded_port", guest: 80, host: 8080 32 | 33 | # Create a forwarded port mapping which allows access to a specific port 34 | # within the machine from a port on the host machine and only allow access 35 | # via 127.0.0.1 to disable public access 36 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 37 | 38 | # Create a private network, which allows host-only access to the machine 39 | # using a specific IP. 40 | # config.vm.network "private_network", ip: "192.168.33.10" 41 | 42 | # Create a public network, which generally matched to bridged network. 43 | # Bridged networks make the machine appear as another physical device on 44 | # your network. 45 | # config.vm.network "public_network" 46 | 47 | # Share an additional folder to the guest VM. The first argument is 48 | # the path on the host to the actual folder. The second argument is 49 | # the path on the guest to mount the folder. And the optional third 50 | # argument is a set of non-required options. 51 | #config.vm.synced_folder "../../..", "/home/vagrant/project" 52 | config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true 53 | 54 | 55 | # Provider-specific configuration so you can fine-tune various 56 | # backing providers for Vagrant. These expose provider-specific options. 57 | # Example for VirtualBox: 58 | # 59 | # config.vm.provider "virtualbox" do |vb| 60 | # # Display the VirtualBox GUI when booting the machine 61 | # vb.gui = true 62 | # 63 | # # Customize the amount of memory on the VM: 64 | # vb.memory = "1024" 65 | # end 66 | # 67 | # View the documentation for the provider you are using for more 68 | # information on available options. 69 | 70 | # Enable provisioning with a shell script. Additional provisioners such as 71 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 72 | # documentation for more information about their specific syntax and use. 73 | # note: clang installed by default 74 | config.vm.provision "env", type: "shell", inline:<<-SHELL 75 | set -x 76 | pkg update -f 77 | pkg install -y git cmake 78 | SHELL 79 | 80 | config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/" 81 | config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/" 82 | config.vm.provision "file", source: "../../../Foo", destination: "$HOME/project/" 83 | config.vm.provision "file", source: "../../../Bar", destination: "$HOME/project/" 84 | config.vm.provision "file", source: "../../../FooBar", destination: "$HOME/project/" 85 | config.vm.provision "file", source: "../../../FooBarApp", destination: "$HOME/project/" 86 | config.vm.provision "file", source: "../../../examples", destination: "$HOME/project/" 87 | 88 | config.vm.provision "devel", type: "shell", inline:<<-SHELL 89 | set -x 90 | cd project 91 | ls 92 | SHELL 93 | 94 | config.vm.provision "configure", type: "shell", inline:<<-SHELL 95 | set -x 96 | cd project 97 | cmake -S. -Bbuild 98 | SHELL 99 | 100 | config.vm.provision "build", type: "shell", inline:<<-SHELL 101 | set -x 102 | cd project 103 | cmake --build build -v 104 | SHELL 105 | 106 | config.vm.provision "test", type: "shell", inline:<<-SHELL 107 | set -x 108 | cd project 109 | cmake --build build --target test -v 110 | SHELL 111 | end 112 | -------------------------------------------------------------------------------- /ci/vagrant/netbsd/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure("2") do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://vagrantcloud.com/search. 15 | config.vm.guest = :netbsd 16 | config.vm.box = "generic/netbsd9" 17 | config.vm.provider "virtualbox" do |v| 18 | v.name = "ci_netbsd" 19 | end 20 | config.ssh.shell = "sh" 21 | 22 | # Disable automatic box update checking. If you disable this, then 23 | # boxes will only be checked for updates when the user runs 24 | # `vagrant box outdated`. This is not recommended. 25 | # config.vm.box_check_update = false 26 | 27 | # Create a forwarded port mapping which allows access to a specific port 28 | # within the machine from a port on the host machine. In the example below, 29 | # accessing "localhost:8080" will access port 80 on the guest machine. 30 | # NOTE: This will enable public access to the opened port 31 | # config.vm.network "forwarded_port", guest: 80, host: 8080 32 | 33 | # Create a forwarded port mapping which allows access to a specific port 34 | # within the machine from a port on the host machine and only allow access 35 | # via 127.0.0.1 to disable public access 36 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 37 | 38 | # Create a private network, which allows host-only access to the machine 39 | # using a specific IP. 40 | # config.vm.network "private_network", ip: "192.168.33.10" 41 | 42 | # Create a public network, which generally matched to bridged network. 43 | # Bridged networks make the machine appear as another physical device on 44 | # your network. 45 | # config.vm.network "public_network" 46 | 47 | # Share an additional folder to the guest VM. The first argument is 48 | # the path on the host to the actual folder. The second argument is 49 | # the path on the guest to mount the folder. And the optional third 50 | # argument is a set of non-required options. 51 | #config.vm.synced_folder "../../..", "/home/vagrant/project" 52 | config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true 53 | 54 | 55 | # Provider-specific configuration so you can fine-tune various 56 | # backing providers for Vagrant. These expose provider-specific options. 57 | # Example for VirtualBox: 58 | # 59 | # config.vm.provider "virtualbox" do |vb| 60 | # # Display the VirtualBox GUI when booting the machine 61 | # vb.gui = true 62 | # 63 | # # Customize the amount of memory on the VM: 64 | # vb.memory = "1024" 65 | # end 66 | # 67 | # View the documentation for the provider you are using for more 68 | # information on available options. 69 | 70 | # Enable provisioning with a shell script. Additional provisioners such as 71 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 72 | # documentation for more information about their specific syntax and use. 73 | # note: clang installed by default 74 | config.vm.provision "env", type: "shell", inline:<<-SHELL 75 | set -x 76 | pkg update -f 77 | pkg install -y git cmake 78 | SHELL 79 | 80 | config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/" 81 | config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/" 82 | config.vm.provision "file", source: "../../../Foo", destination: "$HOME/project/" 83 | config.vm.provision "file", source: "../../../Bar", destination: "$HOME/project/" 84 | config.vm.provision "file", source: "../../../FooBar", destination: "$HOME/project/" 85 | config.vm.provision "file", source: "../../../FooBarApp", destination: "$HOME/project/" 86 | config.vm.provision "file", source: "../../../examples", destination: "$HOME/project/" 87 | 88 | config.vm.provision "devel", type: "shell", inline:<<-SHELL 89 | set -x 90 | cd project 91 | ls 92 | SHELL 93 | 94 | config.vm.provision "configure", type: "shell", inline:<<-SHELL 95 | set -x 96 | cd project 97 | cmake -S. -Bbuild 98 | SHELL 99 | 100 | config.vm.provision "build", type: "shell", inline:<<-SHELL 101 | set -x 102 | cd project 103 | cmake --build build -v 104 | SHELL 105 | 106 | config.vm.provision "test", type: "shell", inline:<<-SHELL 107 | set -x 108 | cd project 109 | cmake --build build --target test -v 110 | SHELL 111 | end 112 | -------------------------------------------------------------------------------- /ci/vagrant/openbsd/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure("2") do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://vagrantcloud.com/search. 15 | config.vm.guest = :openbsd 16 | config.vm.box = "generic/openbsd7" 17 | config.vm.provider "virtualbox" do |v| 18 | v.name = "ci_openbsd" 19 | end 20 | config.ssh.shell = "sh" 21 | 22 | # Disable automatic box update checking. If you disable this, then 23 | # boxes will only be checked for updates when the user runs 24 | # `vagrant box outdated`. This is not recommended. 25 | # config.vm.box_check_update = false 26 | 27 | # Create a forwarded port mapping which allows access to a specific port 28 | # within the machine from a port on the host machine. In the example below, 29 | # accessing "localhost:8080" will access port 80 on the guest machine. 30 | # NOTE: This will enable public access to the opened port 31 | # config.vm.network "forwarded_port", guest: 80, host: 8080 32 | 33 | # Create a forwarded port mapping which allows access to a specific port 34 | # within the machine from a port on the host machine and only allow access 35 | # via 127.0.0.1 to disable public access 36 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 37 | 38 | # Create a private network, which allows host-only access to the machine 39 | # using a specific IP. 40 | # config.vm.network "private_network", ip: "192.168.33.10" 41 | 42 | # Create a public network, which generally matched to bridged network. 43 | # Bridged networks make the machine appear as another physical device on 44 | # your network. 45 | # config.vm.network "public_network" 46 | 47 | # Share an additional folder to the guest VM. The first argument is 48 | # the path on the host to the actual folder. The second argument is 49 | # the path on the guest to mount the folder. And the optional third 50 | # argument is a set of non-required options. 51 | #config.vm.synced_folder "../../..", "/home/vagrant/project" 52 | config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true 53 | 54 | 55 | # Provider-specific configuration so you can fine-tune various 56 | # backing providers for Vagrant. These expose provider-specific options. 57 | # Example for VirtualBox: 58 | # 59 | # config.vm.provider "virtualbox" do |vb| 60 | # # Display the VirtualBox GUI when booting the machine 61 | # vb.gui = true 62 | # 63 | # # Customize the amount of memory on the VM: 64 | # vb.memory = "1024" 65 | # end 66 | # 67 | # View the documentation for the provider you are using for more 68 | # information on available options. 69 | 70 | # Enable provisioning with a shell script. Additional provisioners such as 71 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 72 | # documentation for more information about their specific syntax and use. 73 | # note: clang installed by default 74 | config.vm.provision "env", type: "shell", inline:<<-SHELL 75 | set -x 76 | pkg update -f 77 | pkg install -y git cmake 78 | SHELL 79 | 80 | config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/" 81 | config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/" 82 | config.vm.provision "file", source: "../../../Foo", destination: "$HOME/project/" 83 | config.vm.provision "file", source: "../../../Bar", destination: "$HOME/project/" 84 | config.vm.provision "file", source: "../../../FooBar", destination: "$HOME/project/" 85 | config.vm.provision "file", source: "../../../FooBarApp", destination: "$HOME/project/" 86 | config.vm.provision "file", source: "../../../examples", destination: "$HOME/project/" 87 | 88 | config.vm.provision "devel", type: "shell", inline:<<-SHELL 89 | set -x 90 | cd project 91 | ls 92 | SHELL 93 | 94 | config.vm.provision "configure", type: "shell", inline:<<-SHELL 95 | set -x 96 | cd project 97 | cmake -S. -Bbuild 98 | SHELL 99 | 100 | config.vm.provision "build", type: "shell", inline:<<-SHELL 101 | set -x 102 | cd project 103 | cmake --build build -v 104 | SHELL 105 | 106 | config.vm.provision "test", type: "shell", inline:<<-SHELL 107 | set -x 108 | cd project 109 | cmake --build build --target test -v 110 | SHELL 111 | end 112 | -------------------------------------------------------------------------------- /cmake/CMakeExternalConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # CMakeExternal CMake configuration file 2 | 3 | include(CMakeFindDependencyMacro) 4 | find_dependency(ZLIB REQUIRED NO_MODULE) 5 | find_dependency(absl REQUIRED NO_MODULE) 6 | find_dependency(Protobuf REQUIRED NO_MODULE) 7 | 8 | include("${CMAKE_CURRENT_LIST_DIR}/CMakeExternalTargets.cmake") 9 | -------------------------------------------------------------------------------- /cmake/check_deps.cmake: -------------------------------------------------------------------------------- 1 | # Check dependencies 2 | if(NOT TARGET ZLIB::ZLIB) 3 | message(FATAL_ERROR "Target ZLIB::ZLIB not available.") 4 | endif() 5 | 6 | if(NOT TARGET absl::base) 7 | message(FATAL_ERROR "Target absl::base not available.") 8 | endif() 9 | set(ABSL_DEPS 10 | absl::base 11 | absl::core_headers 12 | absl::absl_check 13 | absl::absl_log 14 | absl::check 15 | absl::die_if_null 16 | absl::flags 17 | absl::flags_commandlineflag 18 | absl::flags_marshalling 19 | absl::flags_parse 20 | absl::flags_reflection 21 | absl::flags_usage 22 | absl::log 23 | absl::log_flags 24 | absl::log_globals 25 | absl::log_initialize 26 | absl::log_internal_message 27 | absl::cord 28 | absl::random_random 29 | absl::raw_hash_set 30 | absl::hash 31 | absl::leak_check 32 | absl::memory 33 | absl::meta 34 | absl::stacktrace 35 | absl::status 36 | absl::statusor 37 | absl::str_format 38 | absl::strings 39 | absl::synchronization 40 | absl::time 41 | absl::any 42 | ) 43 | 44 | if(NOT TARGET protobuf::libprotobuf) 45 | message(FATAL_ERROR "Target protobuf::libprotobuf not available.") 46 | endif() 47 | 48 | # CXX Test 49 | if(BUILD_TESTING) 50 | if(NOT TARGET Catch2::Catch2) 51 | message(FATAL_ERROR "Target Catch2::Catch2 not available.") 52 | endif() 53 | 54 | if(NOT TARGET re2::re2) 55 | message(FATAL_ERROR "Target re2::re2 not available.") 56 | endif() 57 | 58 | if(NOT TARGET GTest::gtest_main) 59 | message(FATAL_ERROR "Target GTest::gtest_main not available.") 60 | endif() 61 | endif() 62 | -------------------------------------------------------------------------------- /cmake/cpp.cmake: -------------------------------------------------------------------------------- 1 | # Check primitive types 2 | option(CHECK_TYPE "Check primitive type size" OFF) 3 | if(CHECK_TYPE) 4 | include(CMakePushCheckState) 5 | cmake_push_check_state(RESET) 6 | set(CMAKE_EXTRA_INCLUDE_FILES "cstdint") 7 | include(CheckTypeSize) 8 | check_type_size("long" SIZEOF_LONG LANGUAGE CXX) 9 | message(STATUS "Found long size: ${SIZEOF_LONG}") 10 | check_type_size("long long" SIZEOF_LONG_LONG LANGUAGE CXX) 11 | message(STATUS "Found long long size: ${SIZEOF_LONG_LONG}") 12 | check_type_size("int64_t" SIZEOF_INT64_T LANGUAGE CXX) 13 | message(STATUS "Found int64_t size: ${SIZEOF_INT64_T}") 14 | 15 | check_type_size("unsigned long" SIZEOF_ULONG LANGUAGE CXX) 16 | message(STATUS "Found unsigned long size: ${SIZEOF_ULONG}") 17 | check_type_size("unsigned long long" SIZEOF_ULONG_LONG LANGUAGE CXX) 18 | message(STATUS "Found unsigned long long size: ${SIZEOF_ULONG_LONG}") 19 | check_type_size("uint64_t" SIZEOF_UINT64_T LANGUAGE CXX) 20 | message(STATUS "Found uint64_t size: ${SIZEOF_UINT64_T}") 21 | 22 | check_type_size("int *" SIZEOF_INT_P LANGUAGE CXX) 23 | message(STATUS "Found int * size: ${SIZEOF_INT_P}") 24 | check_type_size("intptr_t" SIZEOF_INTPTR_T LANGUAGE CXX) 25 | message(STATUS "Found intptr_t size: ${SIZEOF_INTPTR_T}") 26 | check_type_size("uintptr_t" SIZEOF_UINTPTR_T LANGUAGE CXX) 27 | message(STATUS "Found uintptr_t size: ${SIZEOF_UINTPTR_T}") 28 | cmake_pop_check_state() 29 | endif() 30 | 31 | include(GNUInstallDirs) 32 | 33 | # get_cpp_proto() 34 | # CMake macro to generate Protobuf cpp sources 35 | # Parameters: 36 | # the proto c++ headers list 37 | # the proto c++ sources list 38 | # e.g.: 39 | # get_cpp_proto(PROTO_HDRS PROTO_SRCS) 40 | macro(get_cpp_proto PROTO_HDRS PROTO_SRCS) 41 | file(GLOB_RECURSE PROTO_FILES RELATIVE ${PROJECT_SOURCE_DIR} "*.proto") 42 | ## Get Protobuf include dir 43 | get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES) 44 | foreach(dir IN LISTS protobuf_dirs) 45 | if (NOT "${dir}" MATCHES "INSTALL_INTERFACE|-NOTFOUND") 46 | message(STATUS "protoc(cc) Adding proto path: ${dir}") 47 | list(APPEND PROTO_DIRS "--proto_path=${dir}") 48 | endif() 49 | endforeach() 50 | 51 | foreach(PROTO_FILE IN LISTS PROTO_FILES) 52 | message(STATUS "protoc(cc) .proto: ${PROTO_FILE}") 53 | get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY) 54 | get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE) 55 | set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h) 56 | set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc) 57 | message(STATUS "protoc(cc) hdr: ${PROTO_HDR}") 58 | message(STATUS "protoc(cc) src: ${PROTO_SRC}") 59 | add_custom_command( 60 | OUTPUT ${PROTO_SRC} ${PROTO_HDR} 61 | COMMAND ${PROTOC_PRG} 62 | "--proto_path=${PROJECT_SOURCE_DIR}" 63 | ${PROTO_DIRS} 64 | "--cpp_out=${PROJECT_BINARY_DIR}" 65 | ${PROTO_FILE} 66 | DEPENDS ${PROTO_NAME}.proto ${PROTOC_PRG} 67 | COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}" 68 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 69 | VERBATIM) 70 | list(APPEND ${PROTO_HDRS} ${PROTO_HDR}) 71 | list(APPEND ${PROTO_SRCS} ${PROTO_SRC}) 72 | endforeach() 73 | endmacro() 74 | 75 | 76 | add_subdirectory(Foo) 77 | add_subdirectory(Bar) 78 | 79 | add_subdirectory(FooApp) 80 | 81 | # Install 82 | install(EXPORT ${PROJECT_NAME}Targets 83 | NAMESPACE ${PROJECT_NAMESPACE}:: 84 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} 85 | COMPONENT Devel) 86 | include(CMakePackageConfigHelpers) 87 | configure_package_config_file(cmake/${PROJECT_NAME}Config.cmake.in 88 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 89 | INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 90 | NO_SET_AND_CHECK_MACRO 91 | NO_CHECK_REQUIRED_COMPONENTS_MACRO) 92 | write_basic_package_version_file( 93 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 94 | COMPATIBILITY SameMajorVersion) 95 | install( 96 | FILES 97 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 98 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 99 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 100 | COMPONENT Devel) 101 | -------------------------------------------------------------------------------- /cmake/dependencies/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | set(FETCHCONTENT_QUIET OFF) 3 | set(FETCHCONTENT_UPDATES_DISCONNECTED ON) 4 | set(BUILD_SHARED_LIBS ON) 5 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 6 | set(BUILD_TESTING OFF) 7 | set(CMAKE_Fortran_COMPILER OFF) 8 | 9 | # ############################################################################## 10 | # ZLIB 11 | # ############################################################################## 12 | if(BUILD_ZLIB) 13 | message(CHECK_START "Fetching ZLIB") 14 | list(APPEND CMAKE_MESSAGE_INDENT " ") 15 | FetchContent_Declare( 16 | ZLIB 17 | GIT_REPOSITORY "https://github.com/madler/ZLIB.git" 18 | GIT_TAG "v1.3.1" 19 | GIT_SHALLOW TRUE 20 | PATCH_COMMAND git apply --ignore-whitespace 21 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/ZLIB-v1.3.1.patch") 22 | set(ZLIB_BUILD_EXAMPLES OFF) 23 | FetchContent_MakeAvailable(ZLIB) 24 | list(POP_BACK CMAKE_MESSAGE_INDENT) 25 | message(CHECK_PASS "fetched") 26 | endif() 27 | 28 | # ############################################################################## 29 | # ABSEIL-CPP 30 | # ############################################################################## 31 | if(BUILD_absl) 32 | message(CHECK_START "Fetching Abseil-cpp") 33 | list(APPEND CMAKE_MESSAGE_INDENT " ") 34 | FetchContent_Declare( 35 | absl 36 | GIT_REPOSITORY "https://github.com/abseil/abseil-cpp.git" 37 | GIT_TAG "20240722.0" 38 | GIT_SHALLOW TRUE 39 | PATCH_COMMAND git apply --ignore-whitespace 40 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/abseil-cpp-20240722.0.patch" 41 | OVERRIDE_FIND_PACKAGE) 42 | set(ABSL_USE_SYSTEM_INCLUDES ON) 43 | # We want Abseil to declare what C++ standard it was compiled with. 44 | set(ABSL_PROPAGATE_CXX_STD ON) 45 | # We want Abseil to keep the INSTALL rules enabled, even though it is a 46 | # subproject. Otherwise the install rules in this project break. 47 | set(ABSL_ENABLE_INSTALL ON) 48 | set(ABSL_BUILD_TESTING OFF) 49 | FetchContent_MakeAvailable(absl) 50 | list(POP_BACK CMAKE_MESSAGE_INDENT) 51 | message(CHECK_PASS "fetched") 52 | endif() 53 | 54 | # ############################################################################## 55 | # Protobuf 56 | # ############################################################################## 57 | if(BUILD_Protobuf) 58 | message(CHECK_START "Fetching Protobuf") 59 | list(APPEND CMAKE_MESSAGE_INDENT " ") 60 | FetchContent_Declare( 61 | Protobuf 62 | GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git" 63 | GIT_TAG "v29.3" 64 | GIT_SHALLOW TRUE 65 | GIT_SUBMODULES "" 66 | PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/protobuf-v29.3.patch" 67 | ) 68 | set(protobuf_BUILD_TESTS OFF) 69 | set(protobuf_BUILD_SHARED_LIBS ON) 70 | set(protobuf_BUILD_EXPORT OFF) 71 | set(protobuf_MSVC_STATIC_RUNTIME OFF) 72 | #set(protobuf_BUILD_LIBUPB ON) 73 | FetchContent_MakeAvailable(Protobuf) 74 | list(POP_BACK CMAKE_MESSAGE_INDENT) 75 | message(CHECK_PASS "fetched") 76 | endif() 77 | 78 | # ############################################################################## 79 | # RE2 80 | # ############################################################################## 81 | if(BUILD_re2) 82 | message(CHECK_START "Fetching re2") 83 | list(APPEND CMAKE_MESSAGE_INDENT " ") 84 | FetchContent_Declare( 85 | re2 86 | GIT_REPOSITORY "https://github.com/google/re2.git" 87 | GIT_TAG "2024-04-01" 88 | GIT_SHALLOW TRUE 89 | PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/re2-2024-04-01.patch" 90 | ) 91 | set(RE2_BUILD_TESTING OFF) 92 | FetchContent_MakeAvailable(re2) 93 | list(POP_BACK CMAKE_MESSAGE_INDENT) 94 | message(CHECK_PASS "fetched") 95 | endif() 96 | ############### 97 | ## TESTING ## 98 | ############### 99 | if(BUILD_Catch2) 100 | message(CHECK_START "Fetching Catch2") 101 | list(APPEND CMAKE_MESSAGE_INDENT " ") 102 | FetchContent_Declare( 103 | Catch2 104 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git 105 | GIT_TAG devel 106 | GIT_SHALLOW TRUE 107 | FIND_PACKAGE_ARGS) 108 | FetchContent_MakeAvailable(Catch2) 109 | list(POP_BACK CMAKE_MESSAGE_INDENT) 110 | message(CHECK_PASS "fetched") 111 | endif() 112 | 113 | if(BUILD_googletest) 114 | message(CHECK_START "Fetching googletest") 115 | list(APPEND CMAKE_MESSAGE_INDENT " ") 116 | FetchContent_Declare( 117 | googletest 118 | GIT_REPOSITORY https://github.com/google/googletest.git 119 | GIT_TAG v1.15.2 120 | GIT_SHALLOW TRUE 121 | PATCH_COMMAND git apply --ignore-whitespace 122 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/googletest-v1.15.2.patch" 123 | #FIND_PACKAGE_ARGS NAMES GTest GMock 124 | ) 125 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 126 | set(INSTALL_GTEST OFF) 127 | set(GTEST_HAS_ABSL ON) 128 | FetchContent_MakeAvailable(googletest) 129 | list(POP_BACK CMAKE_MESSAGE_INDENT) 130 | message(CHECK_PASS "fetched") 131 | endif() 132 | 133 | if(BUILD_benchmark) 134 | message(CHECK_START "Fetching benchmark") 135 | list(APPEND CMAKE_MESSAGE_INDENT " ") 136 | FetchContent_Declare( 137 | benchmark 138 | GIT_REPOSITORY https://github.com/google/benchmark.git 139 | GIT_TAG v1.9.1 140 | GIT_SHALLOW TRUE 141 | #PATCH_COMMAND git apply --ignore-whitespace "" 142 | ) 143 | set(BENCHMARK_ENABLE_TESTING OFF) 144 | set(BENCHMARK_ENABLE_WERROR OFF) 145 | set(BENCHMARK_ENABLE_INSTALL OFF) 146 | FetchContent_MakeAvailable(benchmark) 147 | list(POP_BACK CMAKE_MESSAGE_INDENT) 148 | message(CHECK_PASS "fetched") 149 | endif() 150 | -------------------------------------------------------------------------------- /cmake/host.CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | # fetch_git_dependency() 4 | # 5 | # CMake function to download, build and install (in staging area) a dependency at configure 6 | # time. 7 | # 8 | # Parameters: 9 | # NAME: name of the dependency 10 | # REPOSITORY: git url of the dependency 11 | # TAG: tag of the dependency 12 | # PATCH_COMMAND: apply patch 13 | # SOURCE_SUBDIR: Path to source CMakeLists.txt relative to root dir 14 | # CMAKE_ARGS: List of specific CMake args to add 15 | # 16 | # e.g.: 17 | # fetch_git_dependency( 18 | # NAME 19 | # abseil-cpp 20 | # URL 21 | # https://github.com/abseil/abseil-cpp.git 22 | # TAG 23 | # main 24 | # PATCH_COMMAND 25 | # "git apply ${CMAKE_SOURCE_DIR}/patches/abseil-cpp.patch" 26 | # ) 27 | function(fetch_git_dependency) 28 | set(options "") 29 | set(oneValueArgs NAME REPOSITORY TAG PATCH_COMMAND SOURCE_SUBDIR) 30 | set(multiValueArgs CMAKE_ARGS) 31 | cmake_parse_arguments(GIT_DEP 32 | "${options}" 33 | "${oneValueArgs}" 34 | "${multiValueArgs}" 35 | ${ARGN} 36 | ) 37 | message(STATUS "Building ${GIT_DEP_NAME}: ...") 38 | string(TOLOWER ${GIT_DEP_NAME} NAME_LOWER) 39 | 40 | if(GIT_DEP_PATCH_COMMAND) 41 | set(PATCH_CMD "${GIT_DEP_PATCH_COMMAND}") 42 | else() 43 | set(PATCH_CMD "") 44 | endif() 45 | configure_file( 46 | ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in 47 | ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-subbuild/CMakeLists.txt @ONLY) 48 | 49 | execute_process( 50 | COMMAND ${CMAKE_COMMAND} -S. -Bproject_build -G "${CMAKE_GENERATOR}" 51 | RESULT_VARIABLE result 52 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-subbuild) 53 | if(result) 54 | message(FATAL_ERROR "CMake step for ${GIT_DEP_NAME} failed: ${result}") 55 | endif() 56 | 57 | execute_process( 58 | COMMAND ${CMAKE_COMMAND} --build project_build --config ${CMAKE_BUILD_TYPE} 59 | RESULT_VARIABLE result 60 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-subbuild) 61 | if(result) 62 | message(FATAL_ERROR "Build step for ${GIT_DEP_NAME} failed: ${result}") 63 | endif() 64 | 65 | if(GIT_DEP_SOURCE_SUBDIR) 66 | add_subdirectory( 67 | ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-src/${GIT_DEP_SOURCE_SUBDIR} 68 | ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-build) 69 | else() 70 | add_subdirectory( 71 | ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-src 72 | ${CMAKE_BINARY_DIR}/_deps/${NAME_LOWER}-build) 73 | endif() 74 | 75 | message(STATUS "Building ${GIT_DEP_NAME}: ...DONE") 76 | endfunction() 77 | 78 | project(host-meta CXX) 79 | 80 | include(FetchContent) 81 | set(FETCHCONTENT_QUIET OFF) 82 | set(FETCHCONTENT_UPDATES_DISCONNECTED ON) 83 | set(BUILD_SHARED_LIBS OFF) 84 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 85 | set(BUILD_TESTING OFF) 86 | 87 | message(CHECK_START "Fetching Abseil-cpp") 88 | list(APPEND CMAKE_MESSAGE_INDENT " ") 89 | set(ABSL_ENABLE_INSTALL ON) 90 | set(ABSL_USE_SYSTEM_INCLUDES ON) 91 | set(ABSL_PROPAGATE_CXX_STD ON) 92 | FetchContent_Declare( 93 | absl 94 | GIT_REPOSITORY "https://github.com/abseil/abseil-cpp.git" 95 | GIT_TAG "20240722.0" 96 | PATCH_COMMAND git apply "${CMAKE_CURRENT_LIST_DIR}/@PATCHES_PATH@/abseil-cpp-20240722.0.patch") 97 | FetchContent_MakeAvailable(absl) 98 | list(POP_BACK CMAKE_MESSAGE_INDENT) 99 | message(CHECK_PASS "fetched") 100 | 101 | message(CHECK_START "Fetching Protobuf") 102 | list(APPEND CMAKE_MESSAGE_INDENT " ") 103 | set(protobuf_BUILD_TESTS OFF) 104 | set(protobuf_BUILD_SHARED_LIBS ON) 105 | set(protobuf_BUILD_EXPORT OFF) 106 | set(protobuf_MSVC_STATIC_RUNTIME OFF) 107 | set(protobuf_WITH_ZLIB OFF) 108 | FetchContent_Declare( 109 | protobuf 110 | GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git" 111 | GIT_TAG "v27.3" 112 | GIT_SUBMODULES "" 113 | PATCH_COMMAND git apply "${CMAKE_CURRENT_LIST_DIR}/@PATCHES_PATH@/protobuf-v27.3.patch") 114 | FetchContent_MakeAvailable(protobuf) 115 | list(POP_BACK CMAKE_MESSAGE_INDENT) 116 | message(CHECK_PASS "fetched") 117 | -------------------------------------------------------------------------------- /cmake/host.cmake: -------------------------------------------------------------------------------- 1 | if(NOT CMAKE_CROSSCOMPILING) 2 | set(PROTOC_PRG protobuf::protoc) 3 | return() 4 | endif() 5 | 6 | message(STATUS "Subproject: HostTools...") 7 | 8 | file(RELATIVE_PATH 9 | PATCHES_PATH 10 | ${CMAKE_CURRENT_BINARY_DIR}/host_tools 11 | ${CMAKE_CURRENT_SOURCE_DIR}/patches) 12 | 13 | configure_file( 14 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/host.CMakeLists.txt 15 | ${CMAKE_CURRENT_BINARY_DIR}/host_tools/CMakeLists.txt 16 | @ONLY) 17 | 18 | add_custom_command( 19 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/host_tools 20 | COMMAND ${CMAKE_COMMAND} -E remove_directory build 21 | COMMAND ${CMAKE_COMMAND} -S. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${CMAKE_CURRENT_BINARY_DIR}/host_tools/bin 22 | COMMAND ${CMAKE_COMMAND} --build build --config Release -v 23 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools 24 | ) 25 | 26 | add_custom_target(host_tools 27 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/host_tools 28 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 29 | 30 | add_executable(host_protoc IMPORTED GLOBAL) 31 | set_target_properties(host_protoc PROPERTIES 32 | IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/host_tools/bin/protoc) 33 | 34 | add_dependencies(host_protoc host_tools) 35 | set(PROTOC_PRG host_protoc) 36 | 37 | message(STATUS "Subproject: HostTools...DONE") 38 | -------------------------------------------------------------------------------- /cmake/system_deps.cmake: -------------------------------------------------------------------------------- 1 | # Check dependencies 2 | set(CMAKE_THREAD_PREFER_PTHREAD TRUE) 3 | set(THREAD_PREFER_PTHREAD_FLAG TRUE) 4 | find_package(Threads REQUIRED) 5 | 6 | # Tell find_package() to try “Config” mode before “Module” mode if no mode was specified. 7 | # This should avoid find_package() to first find our FindXXX.cmake modules if 8 | # distro package already provide a CMake config file... 9 | set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) 10 | 11 | # libprotobuf force us to depends on ZLIB::ZLIB target 12 | if(NOT BUILD_ZLIB) 13 | find_package(ZLIB REQUIRED) 14 | endif() 15 | 16 | if(NOT BUILD_absl) 17 | find_package(absl REQUIRED) 18 | endif() 19 | 20 | if(NOT BUILD_Protobuf) 21 | find_package(Protobuf REQUIRED) 22 | endif() 23 | 24 | # CXX Test 25 | if(BUILD_TESTING) 26 | if(NOT BUILD_Catch2) 27 | find_package(Catch2 REQUIRED) 28 | endif() 29 | 30 | if(NOT BUILD_re2) 31 | find_package(re2 REQUIRED) 32 | endif() 33 | 34 | if(NOT BUILD_googletest) 35 | find_package(GTest REQUIRED) 36 | endif() 37 | endif() 38 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT BUILD_EXAMPLES) 2 | return() 3 | endif() 4 | 5 | add_executable(example) 6 | target_sources(example PRIVATE example.cpp) 7 | target_include_directories(example PUBLIC 8 | $) 9 | target_compile_features(example PRIVATE cxx_std_20) 10 | set_target_properties(example PROPERTIES 11 | VERSION ${PROJECT_VERSION} 12 | POSITION_INDEPENDENT_CODE ON 13 | ) 14 | if(APPLE) 15 | set_target_properties(example PROPERTIES 16 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") 17 | elseif(UNIX) 18 | set_target_properties(example PROPERTIES 19 | INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN") 20 | endif() 21 | target_link_libraries(example PRIVATE 22 | #GTest::gtest_main 23 | Catch2::Catch2WithMain 24 | ${PROJECT_NAMESPACE}::Foo 25 | ${PROJECT_NAMESPACE}::Bar 26 | ) 27 | 28 | add_test(NAME example COMMAND example) 29 | -------------------------------------------------------------------------------- /examples/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | int main(int /*argc*/, char** /*argv*/) { 7 | foo::freeFunction(0); 8 | bar::freeFunction(1); 9 | std::cout << std::endl; 10 | 11 | foo::Foo::staticFunction(int{0}); 12 | bar::Bar::staticFunction(int{1}); 13 | std::cout << std::endl; 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /patches/ZLIB-v1.3.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 15ceebe..03825a2 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -1,23 +1,21 @@ 6 | -cmake_minimum_required(VERSION 2.4.4...3.15.0) 7 | -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) 8 | +cmake_minimum_required(VERSION 3.15) 9 | 10 | -project(zlib C) 11 | - 12 | -set(VERSION "1.3.1") 13 | +project(zlib VERSION 1.3.1 LANGUAGES C) 14 | 15 | option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON) 16 | 17 | -set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") 18 | -set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") 19 | -set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") 20 | -set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") 21 | -set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") 22 | +include(GNUInstallDirs) 23 | +set(INSTALL_BIN_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH "Installation directory for executables") 24 | +set(INSTALL_LIB_DIR "${CMAKE_INSTALL_LIBDIR}" CACHE PATH "Installation directory for libraries") 25 | +set(INSTALL_INC_DIR "${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH "Installation directory for headers") 26 | +set(INSTALL_MAN_DIR "${CMAKE_INSTALL_MANDIR}" CACHE PATH "Installation directory for manual pages") 27 | +set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_DATADIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") 28 | 29 | include(CheckTypeSize) 30 | include(CheckFunctionExists) 31 | include(CheckIncludeFile) 32 | include(CheckCSourceCompiles) 33 | -enable_testing() 34 | +include(CTest) 35 | 36 | check_include_file(sys/types.h HAVE_SYS_TYPES_H) 37 | check_include_file(stdint.h HAVE_STDINT_H) 38 | @@ -149,12 +147,21 @@ if(MINGW) 39 | set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) 40 | endif(MINGW) 41 | 42 | -add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) 43 | -target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) 44 | -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) 45 | -target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) 46 | -set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) 47 | -set_target_properties(zlib PROPERTIES SOVERSION 1) 48 | +if(BUILD_SHARED_LIBS) 49 | + add_library(ZLIB SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) 50 | + set_target_properties(ZLIB PROPERTIES DEFINE_SYMBOL ZLIB_DLL) 51 | + set_target_properties(ZLIB PROPERTIES SOVERSION 1) 52 | +else() 53 | + add_library(ZLIB STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) 54 | +endif() 55 | + 56 | +target_include_directories(ZLIB PUBLIC 57 | + $ 58 | + $ 59 | + $) 60 | + 61 | +add_library(ZLIB::ZLIB ALIAS ZLIB) 62 | + 63 | 64 | if(NOT CYGWIN) 65 | # This property causes shared libraries on Linux to have the full version 66 | @@ -164,26 +171,45 @@ if(NOT CYGWIN) 67 | # 68 | # This has no effect with MSVC, on that platform the version info for 69 | # the DLL comes from the resource file win32/zlib1.rc 70 | - set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) 71 | + set_target_properties(ZLIB PROPERTIES VERSION ${ZLIB_FULL_VERSION}) 72 | endif() 73 | 74 | if(UNIX) 75 | # On unix-like platforms the library is almost always called libz 76 | - set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) 77 | - if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX)) 78 | - set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") 79 | + set_target_properties(ZLIB PROPERTIES OUTPUT_NAME z) 80 | + if(NOT APPLE AND NOT(CMAKE_SYSTEM_NAME STREQUAL AIX) AND BUILD_SHARED_LIBS) 81 | + set_target_properties(ZLIB PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") 82 | endif() 83 | elseif(BUILD_SHARED_LIBS AND WIN32) 84 | # Creates zlib1.dll when building shared library version 85 | - set_target_properties(zlib PROPERTIES SUFFIX "1.dll") 86 | + set_target_properties(ZLIB PROPERTIES SUFFIX "1.dll") 87 | +endif() 88 | + 89 | +if(NOT UNIX) 90 | + set_target_properties(ZLIB PROPERTIES OUTPUT_NAME zlib) 91 | endif() 92 | 93 | -if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) 94 | - install(TARGETS zlib zlibstatic 95 | - RUNTIME DESTINATION "${INSTALL_BIN_DIR}" 96 | - ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" 97 | - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) 98 | +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) 99 | + install(TARGETS ZLIB 100 | + EXPORT ZLIBTargets 101 | + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" 102 | + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" 103 | + LIBRARY DESTINATION "${INSTALL_LIB_DIR}") 104 | + install(EXPORT ZLIBTargets 105 | + NAMESPACE ZLIB:: 106 | + DESTINATION lib/cmake/ZLIB) 107 | + include(CMakePackageConfigHelpers) 108 | + write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/ZLIBConfigVersion.cmake" 109 | + VERSION ${PROJECT_VERSION} 110 | + COMPATIBILITY SameMajorVersion) 111 | + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ZLIBConfig.cmake" 112 | + "include(\"\${CMAKE_CURRENT_LIST_DIR}/ZLIBTargets.cmake\")" 113 | + ) 114 | + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ZLIBConfig.cmake" 115 | + "${CMAKE_CURRENT_BINARY_DIR}/ZLIBConfigVersion.cmake" 116 | + DESTINATION lib/cmake/ZLIB) 117 | endif() 118 | + 119 | if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) 120 | install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") 121 | endif() 122 | @@ -199,20 +225,20 @@ endif() 123 | #============================================================================ 124 | if(ZLIB_BUILD_EXAMPLES) 125 | add_executable(example test/example.c) 126 | - target_link_libraries(example zlib) 127 | + target_link_libraries(example ZLIB) 128 | add_test(example example) 129 | 130 | add_executable(minigzip test/minigzip.c) 131 | - target_link_libraries(minigzip zlib) 132 | + target_link_libraries(minigzip ZLIB) 133 | 134 | if(HAVE_OFF64_T) 135 | add_executable(example64 test/example.c) 136 | - target_link_libraries(example64 zlib) 137 | + target_link_libraries(example64 ZLIB) 138 | set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 139 | add_test(example64 example64) 140 | 141 | add_executable(minigzip64 test/minigzip.c) 142 | - target_link_libraries(minigzip64 zlib) 143 | + target_link_libraries(minigzip64 ZLIB) 144 | set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 145 | endif() 146 | endif() 147 | -------------------------------------------------------------------------------- /patches/abseil-cpp-20240722.0.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake 2 | index 32cc28f..e51d6df 100644 3 | --- a/CMake/AbseilDll.cmake 4 | +++ b/CMake/AbseilDll.cmake 5 | @@ -699,31 +699,44 @@ set(ABSL_INTERNAL_TEST_DLL_TARGETS 6 | 7 | include(CheckCXXSourceCompiles) 8 | 9 | -check_cxx_source_compiles( 10 | - [==[ 11 | -#ifdef _MSC_VER 12 | -# if _MSVC_LANG < 201703L 13 | -# error "The compiler defaults or is configured for C++ < 17" 14 | -# endif 15 | -#elif __cplusplus < 201703L 16 | -# error "The compiler defaults or is configured for C++ < 17" 17 | -#endif 18 | -int main() { return 0; } 19 | -]==] 20 | +message(WARNING "ABSL_CXX_STANDARD: ${ABSL_CXX_STANDARD}") 21 | +message(WARNING "CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}") 22 | +message(WARNING "CMAKE_CXX_STANDARD_REQUIRED: ${CMAKE_CXX_STANDARD_REQUIRED}") 23 | +message(WARNING "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") 24 | + 25 | +if(CMAKE_CXX_STANDARD GREATER_EQUAL 17) 26 | + set(ABSL_INTERNAL_AT_LEAST_CXX17 TRUE) 27 | +else() 28 | + check_cxx_source_compiles( 29 | + [==[ 30 | + #ifdef _MSC_VER 31 | + # if _MSVC_LANG < 201703L 32 | + # error "The compiler defaults or is configured for C++ < 17" 33 | + # endif 34 | + #elif __cplusplus < 201703L 35 | + # error "The compiler defaults or is configured for C++ < 17" 36 | + #endif 37 | + int main() { return 0; } 38 | + ]==] 39 | ABSL_INTERNAL_AT_LEAST_CXX17) 40 | +endif() 41 | 42 | -check_cxx_source_compiles( 43 | - [==[ 44 | -#ifdef _MSC_VER 45 | -# if _MSVC_LANG < 202002L 46 | -# error "The compiler defaults or is configured for C++ < 20" 47 | -# endif 48 | -#elif __cplusplus < 202002L 49 | -# error "The compiler defaults or is configured for C++ < 20" 50 | -#endif 51 | -int main() { return 0; } 52 | -]==] 53 | +if(CMAKE_CXX_STANDARD GREATER_EQUAL 20) 54 | + set(ABSL_INTERNAL_AT_LEAST_CXX20 TRUE) 55 | +else() 56 | + check_cxx_source_compiles( 57 | + [==[ 58 | + #ifdef _MSC_VER 59 | + # if _MSVC_LANG < 202002L 60 | + # error "The compiler defaults or is configured for C++ < 20" 61 | + # endif 62 | + #elif __cplusplus < 202002L 63 | + # error "The compiler defaults or is configured for C++ < 20" 64 | + #endif 65 | + int main() { return 0; } 66 | + ]==] 67 | ABSL_INTERNAL_AT_LEAST_CXX20) 68 | +endif() 69 | 70 | if(ABSL_INTERNAL_AT_LEAST_CXX20) 71 | set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20) 72 | @@ -731,6 +744,7 @@ elseif(ABSL_INTERNAL_AT_LEAST_CXX17) 73 | set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17) 74 | else() 75 | set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_14) 76 | + message(FATAL_ERROR "Should not pass here !!!") 77 | endif() 78 | 79 | function(absl_internal_dll_contains) 80 | diff --git a/absl/flags/declare.h b/absl/flags/declare.h 81 | index 8d2a856..a154046 100644 82 | --- a/absl/flags/declare.h 83 | +++ b/absl/flags/declare.h 84 | @@ -59,10 +59,15 @@ ABSL_NAMESPACE_END 85 | 86 | // Internal implementation of ABSL_DECLARE_FLAG to allow macro expansion of its 87 | // arguments. Clients must use ABSL_DECLARE_FLAG instead. 88 | +#if defined(_MSC_VER) 89 | +#define ABSL_DECLARE_FLAG_INTERNAL(type, name) \ 90 | + extern absl::Flag FLAGS_##name 91 | +#else 92 | #define ABSL_DECLARE_FLAG_INTERNAL(type, name) \ 93 | extern absl::Flag FLAGS_##name; \ 94 | namespace absl /* block flags in namespaces */ {} \ 95 | /* second redeclaration is to allow applying attributes */ \ 96 | extern absl::Flag FLAGS_##name 97 | +#endif // _MSC_VER 98 | 99 | #endif // ABSL_FLAGS_DECLARE_H_ 100 | -------------------------------------------------------------------------------- /patches/googletest-v1.15.2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/googlemock/include/gmock/internal/gmock-port.h b/googlemock/include/gmock/internal/gmock-port.h 2 | index e9d9e32..ca55646 100644 3 | --- a/googlemock/include/gmock/internal/gmock-port.h 4 | +++ b/googlemock/include/gmock/internal/gmock-port.h 5 | @@ -85,11 +85,11 @@ 6 | 7 | // Macros for declaring flags. 8 | #define GMOCK_DECLARE_bool_(name) \ 9 | - ABSL_DECLARE_FLAG(bool, GMOCK_FLAG_NAME_(name)) 10 | + GTEST_API_ ABSL_DECLARE_FLAG(bool, GMOCK_FLAG_NAME_(name)) 11 | #define GMOCK_DECLARE_int32_(name) \ 12 | - ABSL_DECLARE_FLAG(int32_t, GMOCK_FLAG_NAME_(name)) 13 | + GTEST_API_ ABSL_DECLARE_FLAG(int32_t, GMOCK_FLAG_NAME_(name)) 14 | #define GMOCK_DECLARE_string_(name) \ 15 | - ABSL_DECLARE_FLAG(std::string, GMOCK_FLAG_NAME_(name)) 16 | + GTEST_API_ ABSL_DECLARE_FLAG(std::string, GMOCK_FLAG_NAME_(name)) 17 | 18 | #define GMOCK_FLAG_GET(name) ::absl::GetFlag(GMOCK_FLAG(name)) 19 | #define GMOCK_FLAG_SET(name, value) \ 20 | diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake 21 | index 580ac1c..b338398 100644 22 | --- a/googletest/cmake/internal_utils.cmake 23 | +++ b/googletest/cmake/internal_utils.cmake 24 | @@ -11,6 +11,7 @@ 25 | # - The functions/macros defined in this file may depend on Google 26 | # Test and Google Mock's option() definitions, and thus must be 27 | # called *after* the options have been defined. 28 | +include(GNUInstallDirs) 29 | 30 | # Tweaks CMake's default compiler/linker settings to suit Google Test's needs. 31 | # 32 | @@ -170,11 +171,11 @@ function(cxx_library_with_type name type cxx_flags) 33 | # Set the output directory for build artifacts. 34 | set_target_properties(${name} 35 | PROPERTIES 36 | - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" 37 | - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" 38 | - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" 39 | - PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" 40 | - COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") 41 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" 42 | + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" 43 | + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" 44 | + PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" 45 | + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") 46 | # Make PDBs match library name. 47 | get_target_property(pdb_debug_postfix ${name} DEBUG_POSTFIX) 48 | set_target_properties(${name} 49 | @@ -185,11 +186,19 @@ function(cxx_library_with_type name type cxx_flags) 50 | COMPILE_PDB_NAME_DEBUG "${name}${pdb_debug_postfix}") 51 | 52 | if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED") 53 | - set_target_properties(${name} 54 | - PROPERTIES 55 | - COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1") 56 | + target_compile_definitions(${name} PRIVATE 57 | + "GTEST_CREATE_SHARED_LIBRARY=1") 58 | target_compile_definitions(${name} INTERFACE 59 | - $) 60 | + $ 61 | + $ 62 | + ) 63 | + if(APPLE) 64 | + set_target_properties(${name} PROPERTIES 65 | + INSTALL_RPATH "@loader_path") 66 | + elseif(UNIX) 67 | + set_target_properties(${name} PROPERTIES 68 | + INSTALL_RPATH "$ORIGIN") 69 | + endif() 70 | endif() 71 | if (DEFINED GTEST_HAS_PTHREAD) 72 | target_link_libraries(${name} PUBLIC Threads::Threads) 73 | @@ -226,9 +235,8 @@ function(cxx_executable_with_flags name cxx_flags libs) 74 | COMPILE_FLAGS "${cxx_flags}") 75 | endif() 76 | if (BUILD_SHARED_LIBS) 77 | - set_target_properties(${name} 78 | - PROPERTIES 79 | - COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1") 80 | + target_compile_definitions(${name} PRIVATE 81 | + "GTEST_LINKED_AS_SHARED_LIBRARY=1") 82 | endif() 83 | # To support mixing linking in static and dynamic libraries, link each 84 | # library in with an extra call to target_link_libraries. 85 | diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h 86 | index 8d27c2c..890c953 100644 87 | --- a/googletest/include/gtest/internal/gtest-port.h 88 | +++ b/googletest/include/gtest/internal/gtest-port.h 89 | @@ -867,10 +867,10 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; 90 | #ifndef GTEST_API_ 91 | 92 | #ifdef _MSC_VER 93 | -#if defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY 94 | -#define GTEST_API_ __declspec(dllimport) 95 | -#elif defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY 96 | +#if defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY 97 | #define GTEST_API_ __declspec(dllexport) 98 | +#elif defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY 99 | +#define GTEST_API_ __declspec(dllimport) 100 | #endif 101 | #elif GTEST_HAVE_ATTRIBUTE_(visibility) 102 | #define GTEST_API_ __attribute__((visibility("default"))) 103 | @@ -2287,11 +2287,11 @@ using TimeInMillis = int64_t; // Represents time in milliseconds. 104 | 105 | // Macros for declaring flags. 106 | #define GTEST_DECLARE_bool_(name) \ 107 | - ABSL_DECLARE_FLAG(bool, GTEST_FLAG_NAME_(name)) 108 | + GTEST_API_ ABSL_DECLARE_FLAG(bool, GTEST_FLAG_NAME_(name)) 109 | #define GTEST_DECLARE_int32_(name) \ 110 | - ABSL_DECLARE_FLAG(int32_t, GTEST_FLAG_NAME_(name)) 111 | + GTEST_API_ ABSL_DECLARE_FLAG(int32_t, GTEST_FLAG_NAME_(name)) 112 | #define GTEST_DECLARE_string_(name) \ 113 | - ABSL_DECLARE_FLAG(std::string, GTEST_FLAG_NAME_(name)) 114 | + GTEST_API_ ABSL_DECLARE_FLAG(std::string, GTEST_FLAG_NAME_(name)) 115 | 116 | #define GTEST_FLAG_SAVER_ ::absl::FlagSaver 117 | 118 | -------------------------------------------------------------------------------- /patches/protobuf-v29.3.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 807ef014..8937d5eb 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -42,7 +42,7 @@ else (BUILD_SHARED_LIBS) 6 | endif (BUILD_SHARED_LIBS) 7 | option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" ${protobuf_BUILD_SHARED_LIBS_DEFAULT}) 8 | include(CMakeDependentOption) 9 | -cmake_dependent_option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON 10 | +cmake_dependent_option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" OFF 11 | "NOT protobuf_BUILD_SHARED_LIBS" OFF) 12 | set(protobuf_WITH_ZLIB_DEFAULT ON) 13 | option(protobuf_WITH_ZLIB "Build with zlib support" ${protobuf_WITH_ZLIB_DEFAULT}) 14 | @@ -160,24 +160,16 @@ endif() 15 | 16 | set(_protobuf_FIND_ZLIB) 17 | if (protobuf_WITH_ZLIB) 18 | - find_package(ZLIB) 19 | - if (ZLIB_FOUND) 20 | - set(HAVE_ZLIB 1) 21 | - # FindZLIB module define ZLIB_INCLUDE_DIRS variable 22 | - # Set ZLIB_INCLUDE_DIRECTORIES for compatible 23 | - set(ZLIB_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIRECTORIES} ${ZLIB_INCLUDE_DIRS}) 24 | - # Using imported target if exists 25 | - if (TARGET ZLIB::ZLIB) 26 | - set(ZLIB_LIBRARIES ZLIB::ZLIB) 27 | - set(_protobuf_FIND_ZLIB "if(NOT ZLIB_FOUND)\n find_package(ZLIB)\nendif()") 28 | - endif (TARGET ZLIB::ZLIB) 29 | - else (ZLIB_FOUND) 30 | - set(HAVE_ZLIB 0) 31 | - # Explicitly set these to empty (override NOT_FOUND) so cmake doesn't 32 | - # complain when we use them later. 33 | - set(ZLIB_INCLUDE_DIRECTORIES) 34 | - set(ZLIB_LIBRARIES) 35 | - endif (ZLIB_FOUND) 36 | + if (NOT TARGET ZLIB::ZLIB) 37 | + find_package(ZLIB REQUIRED) 38 | + endif() 39 | + set(HAVE_ZLIB 1) 40 | + # FindZLIB module define ZLIB_INCLUDE_DIRS variable 41 | + # Set ZLIB_INCLUDE_DIRECTORIES for compatible 42 | + set(ZLIB_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIRECTORIES} ${ZLIB_INCLUDE_DIRS}) 43 | + # Using imported target if exists 44 | + set(ZLIB_LIBRARIES ZLIB::ZLIB) 45 | + set(_protobuf_FIND_ZLIB "if(NOT ZLIB_FOUND AND NOT TARGET ZLIB::ZLIB)\n find_package(ZLIB REQUIRED)\nendif()") 46 | endif (protobuf_WITH_ZLIB) 47 | 48 | # We need to link with libatomic on systems that do not have builtin atomics, or 49 | @@ -279,7 +271,6 @@ else (MSVC) 50 | endif (MSVC) 51 | 52 | include_directories( 53 | - ${ZLIB_INCLUDE_DIRECTORIES} 54 | ${protobuf_BINARY_DIR} 55 | # Support #include-ing other top-level directories, i.e. upb_generator. 56 | ${protobuf_SOURCE_DIR} 57 | -------------------------------------------------------------------------------- /patches/re2-2024-04-01.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index bdac5af..cedaf6e 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -131,6 +131,13 @@ set(RE2_HEADERS 6 | 7 | add_library(re2 ${RE2_SOURCES}) 8 | target_compile_features(re2 PUBLIC cxx_std_14) 9 | +if(APPLE) 10 | + set_target_properties(re2 PROPERTIES 11 | + INSTALL_RPATH "@loader_path") 12 | +elseif(UNIX) 13 | + set_target_properties(re2 PROPERTIES 14 | + INSTALL_RPATH "$ORIGIN") 15 | +endif() 16 | target_include_directories(re2 PUBLIC $) 17 | # CMake gives "set_target_properties called with incorrect number of arguments." 18 | # errors if we don't quote ${RE2_HEADERS}, so quote it despite prevailing style. 19 | --------------------------------------------------------------------------------