├── examples ├── CMakeLists.txt └── example.cpp ├── .gitignore ├── Bar ├── CMakeLists.txt ├── tests │ ├── CMakeLists.txt │ └── bar_test.cpp ├── include │ └── bar │ │ └── Bar.hpp └── src │ └── Bar.cpp ├── Foo ├── CMakeLists.txt ├── tests │ ├── CMakeLists.txt │ └── foo_test.cpp ├── include │ └── foo │ │ └── Foo.hpp └── src │ └── Foo.cpp ├── ci ├── docs │ ├── generate_image.sh │ ├── docker.dot │ └── docker.svg ├── samples │ ├── CMakeLists.txt │ └── main.cpp ├── docker │ ├── alpine │ │ └── Dockerfile │ ├── archlinux │ │ └── Dockerfile │ ├── opensuse │ │ └── Dockerfile │ ├── fedora │ │ └── Dockerfile │ ├── ubuntu │ │ └── Dockerfile │ ├── debian │ │ └── Dockerfile │ ├── almalinux │ │ └── Dockerfile │ └── rockylinux │ │ └── Dockerfile ├── README.md ├── vagrant │ ├── freebsd │ │ └── Vagrantfile │ ├── openbsd │ │ └── Vagrantfile │ └── netbsd │ │ └── Vagrantfile └── Makefile ├── FooApp ├── msg.proto ├── CMakeLists.txt └── src │ └── main.cpp ├── cmake ├── CMakeExternalConfig.cmake.in ├── system_deps.cmake ├── host.cmake ├── check_deps.cmake ├── ccache.cmake ├── host.CMakeLists.txt ├── dependencies │ └── CMakeLists.txt └── cpp.cmake ├── AUTHORS ├── .dockerignore ├── .github ├── dependabot.yml └── workflows │ ├── arm64_docker_cmake.yml │ ├── riscv64_docker_cmake.yml │ ├── amd64_docker_cmake.yml │ ├── amd64_windows_cmake.yml │ ├── amd64_linux_cmake.yml │ ├── amd64_macos_cmake.yml │ └── arm64_macos_cmake.yml ├── patches ├── re2-2025-08-12.patch ├── abseil-cpp-20250814.1.patch ├── protobuf-v33.0.patch ├── googletest-v1.17.0.patch └── ZLIB-v1.3.1.patch ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── CMakeLists.txt ├── README.md ├── .clang-format └── LICENSE /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_cxx_example( 2 | NAME 3 | example 4 | SOURCES 5 | example.cpp 6 | LINK_LIBRARIES 7 | ${PROJECT_NAMESPACE}::Foo 8 | ${PROJECT_NAMESPACE}::Bar 9 | ) 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Native build 2 | .cache/ 3 | .vagrant/ 4 | build/ 5 | build*/ 6 | cache/ 7 | compile_commands.json 8 | export/ 9 | 10 | # Editors 11 | .kdev4/ 12 | *.kdev4 13 | *.swp 14 | *.user 15 | .vs/ 16 | .vscode/ 17 | -------------------------------------------------------------------------------- /Bar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_cxx_library( 2 | NAME 3 | Bar 4 | HEADERS 5 | include/bar/Bar.hpp 6 | SOURCES 7 | src/Bar.cpp 8 | LINK_LIBRARIES 9 | absl::log 10 | INSTALL_DIR 11 | bar 12 | ) 13 | 14 | add_subdirectory(tests) 15 | -------------------------------------------------------------------------------- /Foo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_cxx_library( 2 | NAME 3 | Foo 4 | HEADERS 5 | include/foo/Foo.hpp 6 | SOURCES 7 | src/Foo.cpp 8 | LINK_LIBRARIES 9 | absl::log 10 | INSTALL_DIR 11 | foo 12 | ) 13 | 14 | add_subdirectory(tests) 15 | -------------------------------------------------------------------------------- /ci/docs/generate_image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eux 3 | 4 | # Check plantuml is in PATH 5 | command -v plantuml 6 | 7 | #rm -f "*.png" 8 | rm -f "*.svg" 9 | for i in *.dot; do 10 | #plantuml -Tpng "$i"; 11 | plantuml -Tsvg "$i"; 12 | done 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int /*argc*/, char** /*argv*/) { 6 | foo::freeFunction(0); 7 | bar::freeFunction(1); 8 | std::cout << std::endl; 9 | 10 | foo::Foo::staticFunction(int{0}); 11 | bar::Bar::staticFunction(int{1}); 12 | std::cout << std::endl; 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Bar/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT BUILD_TESTING) 2 | return() 3 | endif() 4 | 5 | file(GLOB CPP_SRCS "*.cpp") 6 | foreach(_TEST_FILE IN LISTS CPP_SRCS) 7 | get_filename_component(_NAME ${_TEST_FILE} NAME_WE) 8 | get_filename_component(_FILE_NAME ${_TEST_FILE} NAME) 9 | add_cxx_test( 10 | NAME 11 | ${_NAME} 12 | SOURCES 13 | ${_FILE_NAME} 14 | LINK_LIBRARIES 15 | ${PROJECT_NAMESPACE}::Bar 16 | ) 17 | endforeach() 18 | -------------------------------------------------------------------------------- /Foo/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT BUILD_TESTING) 2 | return() 3 | endif() 4 | 5 | file(GLOB CPP_SRCS "*.cpp") 6 | foreach(_TEST_FILE IN LISTS CPP_SRCS) 7 | get_filename_component(_NAME ${_TEST_FILE} NAME_WE) 8 | get_filename_component(_FILE_NAME ${_TEST_FILE} NAME) 9 | add_cxx_test( 10 | NAME 11 | ${_NAME} 12 | SOURCES 13 | ${_FILE_NAME} 14 | LINK_LIBRARIES 15 | ${PROJECT_NAMESPACE}::Foo 16 | ) 17 | endforeach() 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Project Files unneeded by docker 2 | .dockerignore 3 | 4 | .git 5 | .gitignore 6 | .github 7 | .clang-format 8 | 9 | AUTHORS 10 | CONTRIBUTING.md 11 | CONTRIBUTORS 12 | LICENSE 13 | README.md 14 | docs 15 | 16 | # CMake 17 | cmake/docs 18 | cmake/README.md 19 | 20 | # CI 21 | ci/Makefile 22 | ci/docker 23 | ci/docs 24 | ci/cache 25 | 26 | # Native build 27 | .cache/ 28 | .vagrant/ 29 | build/ 30 | build*/ 31 | cache/ 32 | compile_commands.json 33 | export/ 34 | 35 | # Editors 36 | .kdev4/ 37 | *.kdev4 38 | *.swp 39 | *.user 40 | .vs/ 41 | .vscode/ 42 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Keep GitHub Actions up to date with GitHub's Dependabot... 2 | # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot 3 | # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem 4 | version: 2 5 | updates: 6 | - package-ecosystem: github-actions 7 | directory: / 8 | groups: 9 | github-actions: 10 | patterns: 11 | - "*" # Group all Actions updates into a single larger pull request 12 | schedule: 13 | interval: weekly 14 | -------------------------------------------------------------------------------- /patches/re2-2025-08-12.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 81b4af2..b1ffaac 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -140,6 +140,13 @@ set(RE2_HEADERS 6 | 7 | add_library(re2 ${RE2_SOURCES}) 8 | target_compile_features(re2 PUBLIC ${RE2_CXX_VERSION}) 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 | -------------------------------------------------------------------------------- /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 main.cpp) 9 | target_compile_features(sample PUBLIC cxx_std_20) 10 | set_target_properties(sample PROPERTIES 11 | CXX_STANDARD 20 12 | CXX_STANDARD_REQUIRED ON 13 | VERSION ${PROJECT_VERSION}) 14 | target_link_libraries(sample PRIVATE 15 | absl::flags_parse 16 | absl::log 17 | absl::log_initialize 18 | absl::strings 19 | CMakeExternal::Foo 20 | CMakeExternal::Bar 21 | ) 22 | 23 | if(BUILD_TESTING) 24 | add_test(NAME sample_UT COMMAND sample) 25 | endif() 26 | 27 | # Install 28 | include(GNUInstallDirs) 29 | install(TARGETS sample 30 | EXPORT SampleTargets 31 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ci/samples/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char* argv[]) { 16 | absl::InitializeLog(); 17 | absl::SetProgramUsageMessage("FooBarApp"); 18 | absl::EnableLogPrefix(false); 19 | absl::SetStderrThreshold(absl::LogSeverity::kInfo); 20 | absl::ParseCommandLine(argc, argv); 21 | { 22 | const std::vector v = {"foo", "bar", "baz"}; 23 | std::string s = absl::StrJoin(v, "-"); 24 | LOG(INFO) << "Joined string: " << s << "\n"; 25 | } 26 | 27 | foo::freeFunction(0); 28 | bar::freeFunction(1); 29 | std::cout << std::endl; 30 | 31 | foo::Foo::staticFunction(int{0}); 32 | bar::Bar::staticFunction(int{1}); 33 | std::cout << std::endl; 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /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/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 refresh \ 8 | && zypper install -y git 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 | -------------------------------------------------------------------------------- /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 AND NOT TARGET ZLIB::ZLIB) 13 | find_package(ZLIB REQUIRED) 14 | endif() 15 | 16 | if(NOT BUILD_absl AND NOT TARGET absl::base) 17 | find_package(absl REQUIRED) 18 | endif() 19 | 20 | if(NOT BUILD_re2 AND NOT TARGET re2::re2) 21 | find_package(re2 REQUIRED) 22 | endif() 23 | 24 | if(NOT BUILD_Protobuf AND NOT TARGET protobuf::libprotobuf) 25 | find_package(Protobuf REQUIRED) 26 | endif() 27 | 28 | # CXX Test 29 | if(BUILD_TESTING) 30 | if(NOT BUILD_googletest AND NOT TARGET GTest::gtest_main) 31 | find_package(GTest REQUIRED) 32 | endif() 33 | 34 | if(NOT BUILD_benchmark AND NOT TARGET benchmark::benchmark) 35 | find_package(benchmark REQUIRED) 36 | endif() 37 | endif() 38 | -------------------------------------------------------------------------------- /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/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 build-essential cmake \ 10 | && apt-get clean \ 11 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 12 | 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/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 \ 9 | git wget libssl-dev build-essential cmake \ 10 | && apt-get clean \ 11 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 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/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 group install "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/rockylinux/Dockerfile: -------------------------------------------------------------------------------- 1 | # Create a virtual environment with all tools installed 2 | # ref: https://hub.docker.com/rockylinux/rockylinux 3 | FROM rockylinux/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 group install "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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 re2::re2) 45 | message(FATAL_ERROR "Target re2::re2 not available.") 46 | endif() 47 | set(RE2_DEPS re2::re2) 48 | 49 | if(NOT TARGET protobuf::libprotobuf) 50 | message(FATAL_ERROR "Target protobuf::libprotobuf not available.") 51 | endif() 52 | 53 | # CXX Test 54 | if(BUILD_TESTING) 55 | if(NOT TARGET GTest::gtest) 56 | message(FATAL_ERROR "Target GTest::gtest not available.") 57 | endif() 58 | if(NOT TARGET GTest::gtest_main) 59 | message(FATAL_ERROR "Target GTest::gtest_main not available.") 60 | endif() 61 | if(NOT TARGET benchmark::benchmark) 62 | message(FATAL_ERROR "Target benchmark::benchmark not available.") 63 | endif() 64 | endif() 65 | -------------------------------------------------------------------------------- /FooApp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(FooApp) 2 | get_cpp_proto(PROTO_HDRS PROTO_SRCS) 3 | target_sources(FooApp 4 | PRIVATE 5 | src/main.cpp 6 | ${PROTO_HDRS} ${PROTO_SRCS}) 7 | target_include_directories(FooApp 8 | PRIVATE 9 | $ 10 | $ 11 | $ 12 | ) 13 | target_compile_features(FooApp PRIVATE cxx_std_17) 14 | if(MSVC AND BUILD_SHARED_LIBS) 15 | target_compile_definitions(FooApp INTERFACE "PROTO_DLL=__declspec(dllimport)") 16 | target_compile_definitions(FooApp PRIVATE "PROTO_DLL=__declspec(dllexport)") 17 | else() 18 | target_compile_definitions(FooApp PUBLIC "PROTO_DLL=") 19 | endif() 20 | # note: macOS is APPLE and also UNIX ! 21 | if(APPLE) 22 | set_target_properties(FooApp PROPERTIES 23 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") 24 | elseif(UNIX) 25 | set_target_properties(FooApp PROPERTIES 26 | INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") 27 | endif() 28 | set_target_properties(FooApp PROPERTIES 29 | VERSION ${PROJECT_VERSION}) 30 | target_link_libraries(FooApp PRIVATE 31 | ZLIB::ZLIB 32 | absl::flags_parse 33 | absl::log 34 | absl::log_globals 35 | absl::log_initialize 36 | absl::log_severity 37 | absl::strings 38 | protobuf::libprotobuf 39 | CMakeExternal::Foo 40 | CMakeExternal::Bar 41 | ) 42 | add_executable(${PROJECT_NAMESPACE}::FooApp ALIAS FooApp) 43 | 44 | # Test 45 | if(BUILD_TESTING) 46 | add_test(NAME cpp_FooApp_test COMMAND FooApp) 47 | endif() 48 | 49 | # Install 50 | include(GNUInstallDirs) 51 | install(TARGETS FooApp 52 | EXPORT ${PROJECT_NAME}Targets 53 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 54 | ) 55 | -------------------------------------------------------------------------------- /.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-24.04-arm 26 | steps: 27 | - uses: actions/checkout@v6 28 | - name: Check docker 29 | run: | 30 | docker info 31 | docker buildx ls 32 | - name: Build env image 33 | run: make --directory=ci arm64_${{matrix.distro}}_env 34 | - name: Build devel project 35 | run: make --directory=ci arm64_${{matrix.distro}}_devel 36 | - name: Build project 37 | run: make --directory=ci arm64_${{matrix.distro}}_build 38 | - name: Test project 39 | run: make --directory=ci arm64_${{matrix.distro}}_test 40 | 41 | - name: Build install env image 42 | run: make --directory=ci arm64_${{matrix.distro}}_install_env 43 | - name: Build install devel project 44 | run: make --directory=ci arm64_${{matrix.distro}}_install_devel 45 | - name: Build install project 46 | run: make --directory=ci arm64_${{matrix.distro}}_install_build 47 | - name: Test install project 48 | run: make --directory=ci arm64_${{matrix.distro}}_install_test 49 | 50 | arm64_docker_cmake: 51 | runs-on: ubuntu-latest 52 | needs: docker 53 | steps: 54 | - uses: actions/checkout@v6 55 | -------------------------------------------------------------------------------- /.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@v6 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@v6 57 | -------------------------------------------------------------------------------- /.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 | platform: [amd64] # arm64 riscv64 15 | distro: [ 16 | almalinux, 17 | alpine, 18 | archlinux, 19 | debian, 20 | fedora, 21 | opensuse, 22 | rockylinux, 23 | ubuntu 24 | ] 25 | fail-fast: false 26 | name: ${{matrix.platform}}•${{matrix.distro}}•CMake 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v6 30 | - name: Check docker 31 | run: | 32 | docker info 33 | docker buildx ls 34 | - name: Build env image 35 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_env 36 | - name: Build devel image 37 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_devel 38 | - name: Build project 39 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_build 40 | - name: Test project 41 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_test 42 | 43 | - name: Build install env image 44 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_install_env 45 | - name: Build install devel image 46 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_install_devel 47 | - name: Build install project 48 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_install_build 49 | - name: Test install project 50 | run: make --directory=ci ${{matrix.platform}}_${{matrix.distro}}_install_test 51 | 52 | amd64_docker_cmake: 53 | runs-on: ubuntu-latest 54 | needs: docker 55 | steps: 56 | - uses: actions/checkout@v6 57 | -------------------------------------------------------------------------------- /cmake/ccache.cmake: -------------------------------------------------------------------------------- 1 | if(NOT UNIX) 2 | return() 3 | endif() 4 | 5 | find_program(CCACHE_PROGRAM ccache) 6 | if(CCACHE_PROGRAM) 7 | # Set up wrapper scripts 8 | set(C_LAUNCHER "${CCACHE_PROGRAM}") 9 | set(CXX_LAUNCHER "${CCACHE_PROGRAM}") 10 | 11 | file(WRITE "${CMAKE_BINARY_DIR}/launch-c" 12 | "#!/usr/bin/env sh\n" 13 | "# Xcode generator doesn't include the compiler as the\n" 14 | "# first argument, Ninja and Makefiles do. Handle both cases.\n" 15 | "if [ \"$1\" = \"${CMAKE_C_COMPILER}\" ]; then\n" 16 | " shift\n" 17 | "fi\n" 18 | "export CCACHE_CPP2=true\n" 19 | "exec \"${C_LAUNCHER}\" \"${CMAKE_C_COMPILER}\" \"$@\"\n" 20 | ) 21 | file(WRITE "${CMAKE_BINARY_DIR}/launch-cxx" 22 | "#!/usr/bin/env sh\n" 23 | "# Xcode generator doesn't include the compiler as the\n" 24 | "# first argument, Ninja and Makefiles do. Handle both cases.\n" 25 | "if [ \"$1\" = \"${CMAKE_CXX_COMPILER}\" ]; then\n" 26 | " shift\n" 27 | "fi\n" 28 | "export CCACHE_CPP2=true\n" 29 | "exec \"${CXX_LAUNCHER}\" \"${CMAKE_CXX_COMPILER}\" \"$@\"\n" 30 | ) 31 | file(CHMOD 32 | "${CMAKE_BINARY_DIR}/launch-c" 33 | "${CMAKE_BINARY_DIR}/launch-cxx" 34 | FILE_PERMISSIONS 35 | OWNER_READ OWNER_EXECUTE 36 | GROUP_READ GROUP_EXECUTE 37 | WORLD_READ WORLD_EXECUTE) 38 | 39 | if(CMAKE_GENERATOR STREQUAL "Xcode") 40 | # Set Xcode project attributes to route compilation and linking 41 | # through our scripts 42 | set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c") 43 | set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx") 44 | set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c") 45 | set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx") 46 | else() 47 | # Support Unix Makefiles and Ninja 48 | set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-c") 49 | set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cxx") 50 | endif() 51 | message(STATUS "CCache enabled") 52 | else() 53 | message(WARNING "CCache disabled") 54 | endif() 55 | -------------------------------------------------------------------------------- /patches/abseil-cpp-20250814.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake 2 | index 624a3c7..8d0493d 100644 3 | --- a/CMake/AbseilHelpers.cmake 4 | +++ b/CMake/AbseilHelpers.cmake 5 | @@ -345,7 +345,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n") 6 | endif() 7 | endif() 8 | 9 | - if(ABSL_ENABLE_INSTALL) 10 | + if(ABSL_ENABLE_INSTALL AND NOT ABSL_CC_LIB_TESTONLY) 11 | install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets 12 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 13 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 14 | diff --git a/CMakeLists.txt b/CMakeLists.txt 15 | index 1e7c856..a3c3dae 100644 16 | --- a/CMakeLists.txt 17 | +++ b/CMakeLists.txt 18 | @@ -145,7 +145,7 @@ if((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS) 19 | add_library(GTest::gmock ALIAS gmock) 20 | add_library(GTest::gmock_main ALIAS gmock_main) 21 | else() 22 | - message(FATAL_ERROR "ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.") 23 | + message(WARNING "ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.") 24 | endif() 25 | endif() 26 | else() 27 | diff --git a/absl/flags/declare.h b/absl/flags/declare.h 28 | index 8d2a856..a154046 100644 29 | --- a/absl/flags/declare.h 30 | +++ b/absl/flags/declare.h 31 | @@ -59,10 +59,15 @@ ABSL_NAMESPACE_END 32 | 33 | // Internal implementation of ABSL_DECLARE_FLAG to allow macro expansion of its 34 | // arguments. Clients must use ABSL_DECLARE_FLAG instead. 35 | +#if defined(_MSC_VER) 36 | +#define ABSL_DECLARE_FLAG_INTERNAL(type, name) \ 37 | + extern absl::Flag FLAGS_##name 38 | +#else 39 | #define ABSL_DECLARE_FLAG_INTERNAL(type, name) \ 40 | extern absl::Flag FLAGS_##name; \ 41 | namespace absl /* block flags in namespaces */ {} \ 42 | /* second redeclaration is to allow applying attributes */ \ 43 | extern absl::Flag FLAGS_##name 44 | +#endif // _MSC_VER 45 | 46 | #endif // ABSL_FLAGS_DECLARE_H_ 47 | -------------------------------------------------------------------------------- /FooApp/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "bar/Bar.hpp" 17 | #include "foo/Foo.hpp" 18 | #include "msg.pb.h" 19 | 20 | void AddMsg(msg::Msg* msgPtr, const std::string& key, std::int32_t value); 21 | 22 | int main(int argc, char* argv[]) { 23 | absl::InitializeLog(); 24 | absl::SetProgramUsageMessage("FooBarApp"); 25 | absl::EnableLogPrefix(false); 26 | absl::SetStderrThreshold(absl::LogSeverity::kInfo); 27 | absl::ParseCommandLine(argc, argv); 28 | { 29 | const std::vector v = {"foo", "bar", "baz"}; 30 | std::string s = absl::StrJoin(v, "-"); 31 | LOG(INFO) << "Joined string: " << s << "\n"; 32 | } 33 | 34 | foo::Foo::staticFunction(int{0}); 35 | bar::Bar::staticFunction(int{1}); 36 | 37 | GOOGLE_PROTOBUF_VERIFY_VERSION; 38 | // Write a Message 39 | { 40 | msg::MsgList msgList; 41 | AddMsg(msgList.add_msgs(), "bar", 3); 42 | AddMsg(msgList.add_msgs(), "baz", 5); 43 | AddMsg(msgList.add_msgs(), "bop", 7); 44 | // Write the new address book back to disk. 45 | std::fstream out("msg.txt", 46 | 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 | -------------------------------------------------------------------------------- /patches/protobuf-v33.0.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 | -------------------------------------------------------------------------------- /.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}, 17 | {name: "VS22", generator: "Visual Studio 17 2022", config: Debug}, 18 | ] 19 | fail-fast: false 20 | name: amd64•Windows•CMake(${{matrix.cmake.name}},${{matrix.cmake.config}}) 21 | runs-on: windows-latest 22 | env: 23 | deps_src_key: amd64_windows_deps_src 24 | deps_build_key: amd64_windows_deps_build_${{matrix.cmake.config}} 25 | CTEST_OUTPUT_ON_FAILURE: 1 26 | steps: 27 | - uses: actions/checkout@v6 28 | 29 | # CONFIGURING CACHES 30 | - name: Cache CMake dependency source code 31 | uses: actions/cache@v5 32 | with: 33 | key: ${{env.deps_src_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 34 | path: ${{github.workspace}}/build/_deps/*-src 35 | - name: Cache CMake dependency build 36 | uses: actions/cache@v5 37 | with: 38 | key: ${{env.deps_build_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 39 | path: | 40 | ${{github.workspace}}/build/_deps/*-build 41 | ${{github.workspace}}/build/_deps/*-subbuild 42 | 43 | - name: Check CMake 44 | run: | 45 | cmake --version 46 | cmake -G || true 47 | - name: Configure 48 | run: > 49 | cmake -S. -Bbuild 50 | -G "${{matrix.cmake.generator}}" 51 | -DCMAKE_CONFIGURATION_TYPES=${{matrix.cmake.config}} 52 | -DCMAKE_INSTALL_PREFIX=install 53 | - name: Build 54 | run: > 55 | cmake --build build 56 | --config ${{matrix.cmake.config}} 57 | --target ALL_BUILD 58 | -v -j2 59 | - name: Test 60 | run: > 61 | cmake --build build 62 | --config ${{matrix.cmake.config}} 63 | --target RUN_TESTS 64 | -v 65 | - name: Install 66 | run: > 67 | cmake --build build 68 | --config ${{matrix.cmake.config}} 69 | --target INSTALL 70 | -v 71 | 72 | amd64_windows_cmake: 73 | runs-on: ubuntu-latest 74 | needs: native 75 | steps: 76 | - uses: actions/checkout@v6 77 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | env: 12 | CCACHE_BASEDIR: ${{github.workspace}} 13 | CCACHE_DIR: ${{github.workspace}}/.ccache 14 | 15 | jobs: 16 | native: 17 | strategy: 18 | matrix: 19 | cmake: [ 20 | {name: "Make", generator: "Unix Makefiles", config: Release}, 21 | {name: "Ninja", generator: "Ninja", config: Release}, 22 | {name: "NinjaMulti", generator: "Ninja Multi-Config", config: Release}, 23 | ] 24 | fail-fast: false 25 | name: amd64•Linux•CMake(${{matrix.cmake.name}}) 26 | runs-on: ubuntu-latest 27 | env: 28 | deps_src_key: amd64_linux_deps_src 29 | deps_build_key: amd64_linux_deps_build_${{matrix.cmake.name}} 30 | ccache_key: amd64_linux_ccache_${{matrix.cmake.name}} 31 | steps: 32 | - uses: actions/checkout@v6 33 | - name: Install Dependencies 34 | run: sudo apt install -y ninja-build ccache 35 | 36 | # CONFIGURING CACHES 37 | - name: Cache CMake dependency source code 38 | uses: actions/cache@v5 39 | with: 40 | key: ${{env.deps_src_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 41 | path: ${{github.workspace}}/build/_deps/*-src 42 | - name: Cache CMake dependency build 43 | uses: actions/cache@v5 44 | with: 45 | key: ${{env.deps_build_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 46 | path: | 47 | ${{github.workspace}}/build/_deps/*-build 48 | ${{github.workspace}}/build/_deps/*-subbuild 49 | - name: Cache CCache 50 | uses: actions/cache@v5 51 | with: 52 | key: ${{env.ccache_key}}-${{github.sha}} 53 | restore-keys: | 54 | ${{env.ccache_key}}-${{github.sha}} 55 | ${{env.ccache_key}} 56 | path: ${{env.CCACHE_DIR}} 57 | 58 | - name: Check CMake 59 | run: cmake --version 60 | - name: Configure 61 | run: > 62 | cmake -S. -Bbuild 63 | -G "${{matrix.cmake.generator}}" 64 | -DCMAKE_BUILD_TYPE=${{matrix.cmake.config}} 65 | -DCMAKE_INSTALL_PREFIX=install 66 | - name: Build 67 | run: > 68 | cmake --build build 69 | --config ${{matrix.cmake.config}} 70 | --target all 71 | -v -j2 72 | - name: Test 73 | run: > 74 | CTEST_OUTPUT_ON_FAILURE=1 75 | cmake --build build 76 | --config ${{matrix.cmake.config}} 77 | --target test 78 | -v 79 | - name: Install 80 | run: > 81 | cmake --build build 82 | --config ${{matrix.cmake.config}} 83 | --target install 84 | -v 85 | - name: CCache stats and cleanup 86 | run: | 87 | ccache --show-stats 88 | ccache --zero-stats 89 | 90 | amd64_linux_cmake: 91 | runs-on: ubuntu-latest 92 | needs: native 93 | steps: 94 | - uses: actions/checkout@v6 95 | -------------------------------------------------------------------------------- /.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 | env: 12 | CCACHE_BASEDIR: ${{github.workspace}} 13 | CCACHE_DIR: ${{github.workspace}}/.ccache 14 | 15 | jobs: 16 | native: 17 | strategy: 18 | matrix: 19 | cmake: [ 20 | {name: "Xcode", generator: "Xcode", config: Release, build_target: ALL_BUILD, test_target: RUN_TESTS, install_target: install}, 21 | {name: "Make", generator: "Unix Makefiles", config: Release, build_target: all, test_target: test, install_target: install}, 22 | ] 23 | fail-fast: false 24 | name: amd64•MacOS•CMake(${{matrix.cmake.name}}) 25 | runs-on: macos-15-intel 26 | env: 27 | deps_src_key: amd64_macos_deps_src 28 | deps_build_key: amd64_macos_deps_build_${{matrix.cmake.name}} 29 | ccache_key: amd64_macos_ccache_${{matrix.cmake.name}} 30 | steps: 31 | - uses: actions/checkout@v6 32 | - name: Install Dependencies 33 | run: brew install ccache 34 | 35 | # CONFIGURING CACHES 36 | - name: Cache CMake dependency source code 37 | uses: actions/cache@v5 38 | with: 39 | key: ${{env.deps_src_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 40 | path: ${{github.workspace}}/build/_deps/*-src 41 | - name: Cache CMake dependency build 42 | uses: actions/cache@v5 43 | with: 44 | key: ${{env.deps_build_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 45 | path: | 46 | ${{github.workspace}}/build/_deps/*-build 47 | ${{github.workspace}}/build/_deps/*-subbuild 48 | - name: Cache CCache 49 | uses: actions/cache@v5 50 | with: 51 | key: ${{env.ccache_key}}-${{github.sha}} 52 | restore-keys: | 53 | ${{env.ccache_key}}-${{github.sha}} 54 | ${{env.ccache_key}} 55 | path: ${{env.CCACHE_DIR}} 56 | 57 | - name: Check CMake 58 | run: cmake --version 59 | - name: Configure 60 | run: > 61 | cmake -S. -Bbuild 62 | -G "${{matrix.cmake.generator}}" 63 | -DCMAKE_BUILD_TYPE=${{matrix.cmake.config}} 64 | -DCMAKE_INSTALL_PREFIX=install 65 | - name: Build 66 | run: > 67 | cmake --build build 68 | --config ${{matrix.cmake.config}} 69 | --target ${{matrix.cmake.build_target}} 70 | -v -j2 71 | - name: Test 72 | run: > 73 | CTEST_OUTPUT_ON_FAILURE=1 74 | cmake --build build 75 | --config ${{matrix.cmake.config}} 76 | --target ${{matrix.cmake.test_target}} 77 | -v 78 | - name: Install 79 | run: > 80 | cmake --build build 81 | --config ${{matrix.cmake.config}} 82 | --target ${{matrix.cmake.install_target}} 83 | -v 84 | - name: CCache stats and cleanup 85 | run: | 86 | ccache --show-stats 87 | ccache --zero-stats 88 | 89 | amd64_macos_cmake: 90 | runs-on: ubuntu-latest 91 | needs: native 92 | steps: 93 | - uses: actions/checkout@v6 94 | -------------------------------------------------------------------------------- /.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 | env: 12 | CCACHE_BASEDIR: ${{github.workspace}} 13 | CCACHE_DIR: ${{github.workspace}}/.ccache 14 | 15 | jobs: 16 | native: 17 | strategy: 18 | matrix: 19 | cmake: [ 20 | {name: "Xcode", generator: "Xcode", config: Release, build_target: ALL_BUILD, test_target: RUN_TESTS, install_target: install}, 21 | {name: "Make", generator: "Unix Makefiles", config: Release, build_target: all, test_target: test, install_target: install}, 22 | ] 23 | fail-fast: false 24 | name: arm64•MacOS•CMake(${{matrix.cmake.name}}) 25 | runs-on: macos-latest # M1 based runner 26 | env: 27 | deps_src_key: arm64_macos_deps_src 28 | deps_build_key: arm64_macos_deps_build_${{matrix.cmake.name}} 29 | ccache_key: arm64_macos_ccache_${{matrix.cmake.name}} 30 | steps: 31 | - uses: actions/checkout@v6 32 | - name: Install Dependencies 33 | run: brew install ccache 34 | 35 | # CONFIGURING CACHES 36 | - name: Cache CMake dependency source code 37 | uses: actions/cache@v5 38 | with: 39 | key: ${{env.deps_src_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 40 | path: ${{github.workspace}}/build/_deps/*-src 41 | - name: Cache CMake dependency build 42 | uses: actions/cache@v5 43 | with: 44 | key: ${{env.deps_build_key}}-${{hashFiles('CMakeLists.txt', 'cmake/**')}} 45 | path: | 46 | ${{github.workspace}}/build/_deps/*-build 47 | ${{github.workspace}}/build/_deps/*-subbuild 48 | - name: Cache CCache 49 | uses: actions/cache@v5 50 | with: 51 | key: ${{env.ccache_key}}-${{github.sha}} 52 | restore-keys: | 53 | ${{env.ccache_key}}-${{github.sha}} 54 | ${{env.ccache_key}} 55 | path: ${{env.CCACHE_DIR}} 56 | 57 | - name: Check CMake 58 | run: cmake --version 59 | - name: Configure 60 | run: > 61 | cmake -S. -Bbuild 62 | -G "${{matrix.cmake.generator}}" 63 | -DCMAKE_BUILD_TYPE=${{matrix.cmake.config}} 64 | -DCMAKE_INSTALL_PREFIX=install 65 | - name: Build 66 | run: > 67 | cmake --build build 68 | --config ${{matrix.cmake.config}} 69 | --target ${{matrix.cmake.build_target}} 70 | -v -j2 71 | - name: Test 72 | run: > 73 | CTEST_OUTPUT_ON_FAILURE=1 74 | cmake --build build 75 | --config ${{matrix.cmake.config}} 76 | --target ${{matrix.cmake.test_target}} 77 | -v 78 | - name: Install 79 | run: > 80 | cmake --build build 81 | --config ${{matrix.cmake.config}} 82 | --target ${{matrix.cmake.install_target}} 83 | -v 84 | - name: CCache stats and cleanup 85 | run: | 86 | ccache --show-stats 87 | ccache --zero-stats 88 | 89 | arm64_macos_cmake: 90 | runs-on: ubuntu-latest 91 | needs: native 92 | steps: 93 | - uses: actions/checkout@v6 94 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /cmake/host.CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.24) 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 | FetchContent_Declare( 90 | absl 91 | GIT_REPOSITORY "https://github.com/abseil/abseil-cpp.git" 92 | GIT_TAG "20250814.1" 93 | GIT_SHALLOW TRUE 94 | PATCH_COMMAND git apply --ignore-whitespace 95 | "${CMAKE_CURRENT_LIST_DIR}/@PATCHES_PATH@/abseil-cpp-20250814.1.patch" 96 | OVERRIDE_FIND_PACKAGE 97 | ) 98 | set(ABSL_USE_SYSTEM_INCLUDES ON) 99 | set(ABSL_PROPAGATE_CXX_STD ON) 100 | set(ABSL_ENABLE_INSTALL ON) 101 | set(ABSL_BUILD_TESTING OFF) 102 | FetchContent_MakeAvailable(absl) 103 | list(POP_BACK CMAKE_MESSAGE_INDENT) 104 | message(CHECK_PASS "fetched") 105 | 106 | message(CHECK_START "Fetching Protobuf") 107 | list(APPEND CMAKE_MESSAGE_INDENT " ") 108 | FetchContent_Declare( 109 | protobuf 110 | GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git" 111 | GIT_TAG "v33.0" 112 | GIT_SHALLOW TRUE 113 | GIT_SUBMODULES "" 114 | PATCH_COMMAND git apply --ignore-whitespace 115 | "${CMAKE_CURRENT_LIST_DIR}/@PATCHES_PATH@/protobuf-v33.0.patch" 116 | ) 117 | set(protobuf_BUILD_TESTS OFF) 118 | set(protobuf_BUILD_SHARED_LIBS ON) 119 | set(protobuf_BUILD_EXPORT OFF) 120 | set(protobuf_MSVC_STATIC_RUNTIME OFF) 121 | set(protobuf_WITH_ZLIB OFF) 122 | FetchContent_MakeAvailable(protobuf) 123 | list(POP_BACK CMAKE_MESSAGE_INDENT) 124 | message(CHECK_PASS "fetched") 125 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Bar/tests/bar_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace bar { 9 | 10 | TEST(BarTest, FreeFunction) { 11 | EXPECT_NO_THROW(freeFunction(42)); 12 | EXPECT_NO_THROW(freeFunction(int64_t{42})); 13 | } 14 | 15 | TEST(BarTest, StringVectorOutput) { 16 | std::vector result; 17 | ASSERT_NO_THROW(result = stringVectorOutput(8)); 18 | EXPECT_EQ(result.size(), 8); 19 | for (const auto& it : result) { 20 | EXPECT_EQ(it, std::to_string(8)); 21 | } 22 | } 23 | 24 | TEST(BarTest, StringVectorValueInput) { 25 | const std::vector data{"1", "2", "3", "4", "5"}; 26 | int size = 0; 27 | ASSERT_NO_THROW(size = stringVectorInput(data)); 28 | EXPECT_EQ(size, 5); 29 | } 30 | 31 | TEST(BarTest, StringVectorRefInput) { 32 | const std::vector data{"1", "2", "3", "4", "5"}; 33 | int size = 0; 34 | ASSERT_NO_THROW(size = stringVectorRefInput(data)); 35 | EXPECT_EQ(size, 5); 36 | } 37 | 38 | TEST(BarTest, StringJaggedArrayOutput) { 39 | std::vector> result; 40 | ASSERT_NO_THROW(result = stringJaggedArrayOutput(8)); 41 | EXPECT_EQ(result.size(), 8); 42 | for (std::size_t i = 0; i < result.size(); ++i) { 43 | EXPECT_EQ(i + 1, result[i].size()); 44 | } 45 | for (std::size_t i = 1; i <= result.size(); ++i) { 46 | const auto& inner = result[i - 1]; 47 | for (const auto& it : inner) { 48 | EXPECT_EQ(it, std::to_string(i)); 49 | } 50 | } 51 | } 52 | 53 | TEST(BarTest, StringJaggedArrayValueInput) { 54 | const std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 55 | int size = 0; 56 | ASSERT_NO_THROW(size = stringJaggedArrayInput(data)); 57 | EXPECT_EQ(size, 2); 58 | } 59 | 60 | TEST(BarTest, StringJaggedArrayRefInput) { 61 | const std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 62 | int size = 0; 63 | ASSERT_NO_THROW(size = stringJaggedArrayRefInput(data)); 64 | EXPECT_EQ(size, 2); 65 | } 66 | 67 | TEST(BarTest, PairVectorOutput) { 68 | std::vector> result; 69 | ASSERT_NO_THROW(result = pairVectorOutput(8)); 70 | EXPECT_EQ(result.size(), 8); 71 | for (const auto& it : result) { 72 | EXPECT_EQ(it.first, 8); 73 | EXPECT_EQ(it.second, 8); 74 | } 75 | } 76 | 77 | TEST(BarTest, PairVectorValueInput) { 78 | const std::vector> data{{1, 2}, {3, 4}, {5, 6}}; 79 | int size = 0; 80 | ASSERT_NO_THROW(size = pairVectorInput(data)); 81 | EXPECT_EQ(size, 3); 82 | } 83 | 84 | TEST(BarTest, PairVectorRefInput) { 85 | const std::vector> data{{1, 2}, {3, 4}, {5, 6}}; 86 | int size = 0; 87 | ASSERT_NO_THROW(size = pairVectorRefInput(data)); 88 | EXPECT_EQ(size, 3); 89 | } 90 | 91 | TEST(BarTest, PairJaggedArrayOutput) { 92 | std::vector>> result; 93 | ASSERT_NO_THROW(result = pairJaggedArrayOutput(8)); 94 | EXPECT_EQ(result.size(), 8); 95 | for (std::size_t i = 0; i < result.size(); ++i) { 96 | EXPECT_EQ(i + 1, result[i].size()); 97 | } 98 | for (int i = 1; i <= static_cast(result.size()); ++i) { 99 | const auto& inner = result[i - 1]; 100 | for (const auto& it : inner) { 101 | EXPECT_EQ(it, std::make_pair(i, i)); 102 | } 103 | } 104 | } 105 | 106 | TEST(BarTest, PairJaggedArrayValueInput) { 107 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, 108 | {{4, 4}, {5, 5}}}; 109 | int size = 0; 110 | ASSERT_NO_THROW(size = pairJaggedArrayInput(data)); 111 | EXPECT_EQ(size, 2); 112 | } 113 | 114 | TEST(BarTest, PairJaggedArrayRefInput) { 115 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, 116 | {{4, 4}, {5, 5}}}; 117 | int size = 0; 118 | ASSERT_NO_THROW(size = pairJaggedArrayRefInput(data)); 119 | EXPECT_EQ(size, 2); 120 | } 121 | 122 | TEST(BarTest, StaticMethods) { 123 | EXPECT_NO_THROW(Bar::staticFunction(42)); 124 | EXPECT_NO_THROW(Bar::staticFunction(int64_t{42})); 125 | } 126 | 127 | TEST(BarTest, Constructor) { 128 | Bar* b = new Bar(); 129 | EXPECT_NE(b, nullptr); 130 | } 131 | 132 | TEST(BarTest, IntMethods) { 133 | Bar bar; 134 | ASSERT_NO_THROW(bar.setInt(42)); 135 | EXPECT_EQ(42, bar.getInt()); 136 | } 137 | 138 | TEST(BarTest, Int64Methods) { 139 | Bar bar; 140 | ASSERT_NO_THROW(bar.setInt64(31)); 141 | EXPECT_EQ(31, bar.getInt64()); 142 | } 143 | 144 | TEST(BarTest, PrintMethod) { 145 | Bar bar; 146 | std::string str(""); 147 | ASSERT_NO_THROW(str = bar()); 148 | EXPECT_EQ("\"Bar\":{\"int\":0,\"int64\":0}", str); 149 | } 150 | 151 | } // namespace bar 152 | -------------------------------------------------------------------------------- /Foo/tests/foo_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace foo { 9 | 10 | TEST(FooTest, FreeFunction) { 11 | EXPECT_NO_THROW(freeFunction(42)); 12 | EXPECT_NO_THROW(freeFunction(int64_t{42})); 13 | } 14 | 15 | TEST(FooTest, StringVectorOutput) { 16 | std::vector result; 17 | ASSERT_NO_THROW(result = stringVectorOutput(8)); 18 | EXPECT_EQ(result.size(), 8); 19 | for (const auto& it : result) { 20 | EXPECT_EQ(it, std::to_string(8)); 21 | } 22 | } 23 | 24 | TEST(FooTest, StringVectorValueInput) { 25 | const std::vector data{"1", "2", "3", "4", "5"}; 26 | int size = 0; 27 | ASSERT_NO_THROW(size = stringVectorInput(data)); 28 | EXPECT_EQ(size, 5); 29 | } 30 | 31 | TEST(FooTest, StringVectorRefInput) { 32 | const std::vector data{"1", "2", "3", "4", "5"}; 33 | int size = 0; 34 | ASSERT_NO_THROW(size = stringVectorRefInput(data)); 35 | EXPECT_EQ(size, 5); 36 | } 37 | 38 | TEST(FooTest, StringJaggedArrayOutput) { 39 | std::vector> result; 40 | ASSERT_NO_THROW(result = stringJaggedArrayOutput(8)); 41 | EXPECT_EQ(result.size(), 8); 42 | for (std::size_t i = 0; i < result.size(); ++i) { 43 | EXPECT_EQ(i + 1, result[i].size()); 44 | } 45 | for (std::size_t i = 1; i <= result.size(); ++i) { 46 | const auto& inner = result[i - 1]; 47 | for (const auto& it : inner) { 48 | EXPECT_EQ(it, std::to_string(i)); 49 | } 50 | } 51 | } 52 | 53 | TEST(FooTest, StringJaggedArrayValueInput) { 54 | const std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 55 | int size = 0; 56 | ASSERT_NO_THROW(size = stringJaggedArrayInput(data)); 57 | EXPECT_EQ(size, 2); 58 | } 59 | 60 | TEST(FooTest, StringJaggedArrayRefInput) { 61 | const std::vector> data{{"1", "2", "3"}, {"4", "5"}}; 62 | int size = 0; 63 | ASSERT_NO_THROW(size = stringJaggedArrayRefInput(data)); 64 | EXPECT_EQ(size, 2); 65 | } 66 | 67 | TEST(FooTest, PairVectorOutput) { 68 | std::vector> result; 69 | ASSERT_NO_THROW(result = pairVectorOutput(8)); 70 | EXPECT_EQ(result.size(), 8); 71 | for (const auto& it : result) { 72 | EXPECT_EQ(it.first, 8); 73 | EXPECT_EQ(it.second, 8); 74 | } 75 | } 76 | 77 | TEST(FooTest, PairVectorValueInput) { 78 | const std::vector> data{{1, 2}, {3, 4}, {5, 6}}; 79 | int size = 0; 80 | ASSERT_NO_THROW(size = pairVectorInput(data)); 81 | EXPECT_EQ(size, 3); 82 | } 83 | 84 | TEST(FooTest, PairVectorRefInput) { 85 | const std::vector> data{{1, 2}, {3, 4}, {5, 6}}; 86 | int size = 0; 87 | ASSERT_NO_THROW(size = pairVectorRefInput(data)); 88 | EXPECT_EQ(size, 3); 89 | } 90 | 91 | TEST(FooTest, PairJaggedArrayOutput) { 92 | std::vector>> result; 93 | ASSERT_NO_THROW(result = pairJaggedArrayOutput(8)); 94 | EXPECT_EQ(result.size(), 8); 95 | for (std::size_t i = 0; i < result.size(); ++i) { 96 | EXPECT_EQ(i + 1, result[i].size()); 97 | } 98 | for (int i = 1; i <= static_cast(result.size()); ++i) { 99 | const auto& inner = result[i - 1]; 100 | for (const auto& it : inner) { 101 | EXPECT_EQ(it, std::make_pair(i, i)); 102 | } 103 | } 104 | } 105 | 106 | TEST(FooTest, PairJaggedArrayValueInput) { 107 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, 108 | {{4, 4}, {5, 5}}}; 109 | int size = 0; 110 | ASSERT_NO_THROW(size = pairJaggedArrayInput(data)); 111 | EXPECT_EQ(size, 2); 112 | } 113 | 114 | TEST(FooTest, PairJaggedArrayRefInput) { 115 | std::vector>> data{{{1, 1}, {2, 2}, {3, 3}}, 116 | {{4, 4}, {5, 5}}}; 117 | int size = 0; 118 | ASSERT_NO_THROW(size = pairJaggedArrayRefInput(data)); 119 | EXPECT_EQ(size, 2); 120 | } 121 | 122 | TEST(FooTest, StaticMethods) { 123 | EXPECT_NO_THROW(Foo::staticFunction(42)); 124 | EXPECT_NO_THROW(Foo::staticFunction(int64_t{42})); 125 | } 126 | 127 | TEST(FooTest, Constructor) { 128 | Foo* b = new Foo(); 129 | EXPECT_NE(b, nullptr); 130 | } 131 | 132 | TEST(FooTest, IntMethods) { 133 | Foo foo; 134 | ASSERT_NO_THROW(foo.setInt(42)); 135 | EXPECT_EQ(42, foo.getInt()); 136 | } 137 | 138 | TEST(FooTest, Int64Methods) { 139 | Foo foo; 140 | ASSERT_NO_THROW(foo.setInt64(31)); 141 | EXPECT_EQ(31, foo.getInt64()); 142 | } 143 | 144 | TEST(FooTest, PrintMethod) { 145 | Foo foo; 146 | std::string str(""); 147 | ASSERT_NO_THROW(str = foo()); 148 | EXPECT_EQ("\"Foo\":{\"int\":0,\"int64\":0}", str); 149 | } 150 | 151 | } // namespace foo 152 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file is just an orchestration 2 | cmake_minimum_required(VERSION 3.24..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 C 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 20) 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 | option(BUILD_SHARED_LIBS "Build shared libraries (.dll)." ON) 58 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 59 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 60 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) 61 | # for multi-config builds (e.g. msvc) 62 | foreach(OutputConfig IN LISTS CMAKE_CONFIGURATION_TYPES) 63 | string(TOUPPER ${OutputConfig} OUTPUTCONFIG) 64 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 65 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 66 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/${OutputConfig}/${CMAKE_INSTALL_BINDIR}) 67 | endforeach() 68 | endif() 69 | 70 | if(MSVC AND BUILD_SHARED_LIBS) 71 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 72 | endif() 73 | 74 | # Enable CCache if any 75 | include(ccache) 76 | 77 | # Build deps 78 | option(BUILD_ZLIB "Build the ZLIB dependency Library" ON) 79 | message(STATUS "Build ZLIB: ${BUILD_ZLIB}") 80 | 81 | option(BUILD_absl "Build the abseil-cpp dependency Library" ON) 82 | message(STATUS "Build absl: ${BUILD_absl}") 83 | 84 | option(BUILD_re2 "Build the RE2 dependency Library" ON) 85 | message(STATUS "Build re2: ${BUILD_re2}") 86 | 87 | option(BUILD_Protobuf "Build the Protobuf dependency Library" ON) 88 | message(STATUS "Build protobuf: ${BUILD_Protobuf}") 89 | 90 | # Disable CTest targets 91 | set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1) 92 | include(CTest) 93 | 94 | if(BUILD_TESTING) 95 | option(BUILD_googletest "Build googletest" ON) 96 | option(BUILD_benchmark "Build benchmark" ON) 97 | else() 98 | set(BUILD_googletest OFF) 99 | set(BUILD_benchmark OFF) 100 | endif() 101 | message(STATUS "Build googletest: ${BUILD_googletest}") 102 | message(STATUS "Build benchmark: ${BUILD_benchmark}") 103 | 104 | option(BUILD_EXAMPLES "Build examples" ON) 105 | message(STATUS "Build examples: ${BUILD_EXAMPLES}") 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 | foreach(SUBPROJECT IN ITEMS Foo Bar FooApp) 119 | add_subdirectory(${SUBPROJECT}) 120 | endforeach() 121 | 122 | add_subdirectory(examples) 123 | -------------------------------------------------------------------------------- /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.box_version = "4.3.12" 18 | config.vm.provider "virtualbox" do |v| 19 | v.name = "ci_freebsd" 20 | end 21 | config.ssh.shell = "sh" 22 | 23 | # Disable automatic box update checking. If you disable this, then 24 | # boxes will only be checked for updates when the user runs 25 | # `vagrant box outdated`. This is not recommended. 26 | # config.vm.box_check_update = false 27 | 28 | # Create a forwarded port mapping which allows access to a specific port 29 | # within the machine from a port on the host machine. In the example below, 30 | # accessing "localhost:8080" will access port 80 on the guest machine. 31 | # NOTE: This will enable public access to the opened port 32 | # config.vm.network "forwarded_port", guest: 80, host: 8080 33 | 34 | # Create a forwarded port mapping which allows access to a specific port 35 | # within the machine from a port on the host machine and only allow access 36 | # via 127.0.0.1 to disable public access 37 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 38 | 39 | # Create a private network, which allows host-only access to the machine 40 | # using a specific IP. 41 | # config.vm.network "private_network", ip: "192.168.33.10" 42 | 43 | # Create a public network, which generally matched to bridged network. 44 | # Bridged networks make the machine appear as another physical device on 45 | # your network. 46 | # config.vm.network "public_network" 47 | 48 | # Share an additional folder to the guest VM. The first argument is 49 | # the path on the host to the actual folder. The second argument is 50 | # the path on the guest to mount the folder. And the optional third 51 | # argument is a set of non-required options. 52 | # config.vm.synced_folder "../data", "/vagrant_data" 53 | 54 | # Disable the default share of the current code directory. Doing this 55 | # provides improved isolation between the vagrant box and your host 56 | # by making sure your Vagrantfile isn't accessible to the vagrant box. 57 | # If you use this you may want to enable additional shared subfolders as 58 | # shown above. 59 | config.vm.synced_folder ".", "/vagrant", disabled: true 60 | 61 | # Provider-specific configuration so you can fine-tune various 62 | # backing providers for Vagrant. These expose provider-specific options. 63 | # Example for VirtualBox: 64 | # 65 | # config.vm.provider "virtualbox" do |vb| 66 | # # Display the VirtualBox GUI when booting the machine 67 | # vb.gui = true 68 | # 69 | # # Customize the amount of memory on the VM: 70 | # vb.memory = "1024" 71 | # end 72 | # 73 | # View the documentation for the provider you are using for more 74 | # information on available options. 75 | 76 | # Enable provisioning with a shell script. Additional provisioners such as 77 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 78 | # documentation for more information about their specific syntax and use. 79 | # note: clang installed by default 80 | config.vm.provision "env", type: "shell", inline:<<-SHELL 81 | set -x 82 | pkg update -f 83 | pkg install -y git cmake 84 | SHELL 85 | 86 | config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/" 87 | config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/" 88 | config.vm.provision "file", source: "../../../patches", destination: "$HOME/project/" 89 | config.vm.provision "file", source: "../../../Foo", destination: "$HOME/project/" 90 | config.vm.provision "file", source: "../../../Bar", destination: "$HOME/project/" 91 | config.vm.provision "file", source: "../../../FooBar", destination: "$HOME/project/" 92 | config.vm.provision "file", source: "../../../FooBarApp", destination: "$HOME/project/" 93 | config.vm.provision "file", source: "../../../examples", destination: "$HOME/project/" 94 | 95 | config.vm.provision "devel", type: "shell", inline:<<-SHELL 96 | set -x 97 | cd project 98 | ls 99 | SHELL 100 | 101 | config.vm.provision "configure", type: "shell", inline:<<-SHELL 102 | set -x 103 | cd project 104 | cmake -S. -Bbuild 105 | SHELL 106 | 107 | config.vm.provision "build", type: "shell", inline:<<-SHELL 108 | set -x 109 | cd project 110 | cmake --build build -v 111 | SHELL 112 | 113 | config.vm.provision "test", type: "shell", inline:<<-SHELL 114 | set -x 115 | cd project 116 | cmake --build build --target test -v 117 | SHELL 118 | end 119 | -------------------------------------------------------------------------------- /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.24". 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 --config Release --target test 101 | ``` 102 | ## Build directory layout 103 | 104 | 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. 105 | We want this layout (tree build --prune -P "*.so|FooApp"): 106 | 107 | ``` 108 | build 109 | ├── bin 110 | │   └── FooApp 111 | └── lib 112 |    └── lib*.so 113 | ``` 114 | 115 | ## Appendices 116 | 117 | Few links on the subject... 118 | 119 | ### Resources 120 | 121 | Project layout: 122 | * [The Pitchfork Layout Revision 1 (cxx-pflR1)](https://github.com/vector-of-bool/pitchfork) 123 | 124 | CMake: 125 | * https://llvm.org/docs/CMakePrimer.html 126 | * https://cliutils.gitlab.io/modern-cmake/ 127 | * https://cgold.readthedocs.io/en/latest/ 128 | 129 | # Contributing 130 | 131 | The [CONTRIBUTING.md](./CONTRIBUTING.md) file contains instructions on how to 132 | file the Contributor License Agreement before sending any pull requests (PRs). 133 | Of course, if you're new to the project, it's usually best to discuss any 134 | proposals and reach consensus before sending your first PR. 135 | 136 | ## License 137 | 138 | Apache 2. See the LICENSE file for details. 139 | 140 | ## Disclaimer 141 | 142 | This is not an official Google product, it is just code that happens to be 143 | owned by Google. 144 | 145 | -------------------------------------------------------------------------------- /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 | UPDATE_COMMAND git reset --hard 21 | PATCH_COMMAND git apply --ignore-whitespace 22 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/ZLIB-v1.3.1.patch" 23 | ) 24 | set(ZLIB_BUILD_EXAMPLES OFF) 25 | FetchContent_MakeAvailable(ZLIB) 26 | list(POP_BACK CMAKE_MESSAGE_INDENT) 27 | message(CHECK_PASS "fetched") 28 | endif() 29 | 30 | # ############################################################################## 31 | # ABSEIL-CPP 32 | # ############################################################################## 33 | if(BUILD_absl) 34 | message(CHECK_START "Fetching Abseil-cpp") 35 | list(APPEND CMAKE_MESSAGE_INDENT " ") 36 | FetchContent_Declare( 37 | absl 38 | GIT_REPOSITORY "https://github.com/abseil/abseil-cpp.git" 39 | GIT_TAG "20250814.1" 40 | GIT_SHALLOW TRUE 41 | UPDATE_COMMAND git reset --hard 42 | PATCH_COMMAND git apply --ignore-whitespace 43 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/abseil-cpp-20250814.1.patch" 44 | OVERRIDE_FIND_PACKAGE 45 | ) 46 | set(ABSL_USE_SYSTEM_INCLUDES ON) 47 | # We want Abseil to declare what C++ standard it was compiled with. 48 | set(ABSL_PROPAGATE_CXX_STD ON) 49 | # We want Abseil to keep the INSTALL rules enabled, even though it is a 50 | # subproject. Otherwise the install rules in this project break. 51 | set(ABSL_ENABLE_INSTALL ON) 52 | set(ABSL_BUILD_TESTING OFF) 53 | set(ABSL_BUILD_TEST_HELPERS OFF) 54 | set(ABSL_USE_EXTERNAL_GOOGLETEST ON) 55 | set(ABSL_FIND_GOOGLETEST OFF) 56 | FetchContent_MakeAvailable(absl) 57 | list(POP_BACK CMAKE_MESSAGE_INDENT) 58 | message(CHECK_PASS "fetched") 59 | endif() 60 | 61 | # ############################################################################## 62 | # RE2 63 | # ############################################################################## 64 | if(BUILD_re2) 65 | message(CHECK_START "Fetching re2") 66 | list(APPEND CMAKE_MESSAGE_INDENT " ") 67 | FetchContent_Declare( 68 | re2 69 | GIT_REPOSITORY "https://github.com/google/re2.git" 70 | GIT_TAG "2025-08-12" 71 | GIT_SHALLOW TRUE 72 | UPDATE_COMMAND git reset --hard 73 | PATCH_COMMAND git apply --ignore-whitespace 74 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/re2-2025-08-12.patch" 75 | ) 76 | set(RE2_BUILD_TESTING OFF) 77 | FetchContent_MakeAvailable(re2) 78 | list(POP_BACK CMAKE_MESSAGE_INDENT) 79 | message(CHECK_PASS "fetched") 80 | endif() 81 | 82 | # ############################################################################## 83 | # Protobuf 84 | # ############################################################################## 85 | if(BUILD_Protobuf) 86 | message(CHECK_START "Fetching Protobuf") 87 | list(APPEND CMAKE_MESSAGE_INDENT " ") 88 | FetchContent_Declare( 89 | Protobuf 90 | GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git" 91 | GIT_TAG "v33.0" 92 | GIT_SHALLOW TRUE 93 | GIT_SUBMODULES "" 94 | UPDATE_COMMAND git reset --hard 95 | PATCH_COMMAND git apply --ignore-whitespace 96 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/protobuf-v33.0.patch" 97 | ) 98 | set(protobuf_BUILD_TESTS OFF) 99 | set(protobuf_BUILD_SHARED_LIBS ON) 100 | set(protobuf_BUILD_EXPORT OFF) 101 | set(protobuf_MSVC_STATIC_RUNTIME OFF) 102 | #set(protobuf_BUILD_LIBUPB ON) 103 | FetchContent_MakeAvailable(Protobuf) 104 | list(POP_BACK CMAKE_MESSAGE_INDENT) 105 | message(CHECK_PASS "fetched") 106 | endif() 107 | 108 | ############### 109 | ## TESTING ## 110 | ############### 111 | if(BUILD_googletest) 112 | message(CHECK_START "Fetching googletest") 113 | list(APPEND CMAKE_MESSAGE_INDENT " ") 114 | FetchContent_Declare( 115 | googletest 116 | GIT_REPOSITORY https://github.com/google/googletest.git 117 | GIT_TAG v1.17.0 118 | GIT_SHALLOW TRUE 119 | UPDATE_COMMAND git reset --hard 120 | PATCH_COMMAND git apply --ignore-whitespace 121 | "${CMAKE_CURRENT_LIST_DIR}/../../patches/googletest-v1.17.0.patch" 122 | ) 123 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 124 | set(GTEST_HAS_ABSL ON) 125 | set(INSTALL_GTEST OFF) 126 | FetchContent_MakeAvailable(googletest) 127 | list(POP_BACK CMAKE_MESSAGE_INDENT) 128 | message(CHECK_PASS "fetched") 129 | endif() 130 | 131 | if(BUILD_benchmark) 132 | message(CHECK_START "Fetching benchmark") 133 | list(APPEND CMAKE_MESSAGE_INDENT " ") 134 | FetchContent_Declare( 135 | benchmark 136 | GIT_REPOSITORY https://github.com/google/benchmark.git 137 | GIT_TAG v1.9.2 138 | GIT_SHALLOW TRUE 139 | #PATCH_COMMAND git apply --ignore-whitespace "" 140 | ) 141 | set(BENCHMARK_ENABLE_TESTING OFF) 142 | set(BENCHMARK_ENABLE_WERROR OFF) 143 | set(BENCHMARK_ENABLE_INSTALL OFF) 144 | FetchContent_MakeAvailable(benchmark) 145 | list(POP_BACK CMAKE_MESSAGE_INDENT) 146 | message(CHECK_PASS "fetched") 147 | endif() 148 | -------------------------------------------------------------------------------- /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" # OpenBSD 7.4 17 | # config.vm.box_version = "4.3.12" 18 | 19 | config.vm.box = "twingly/openbsd-7.6" 20 | config.vm.box_version = "1.0.0" 21 | 22 | config.vm.provider "virtualbox" do |v| 23 | v.name = "ci_openbsd" 24 | end 25 | config.ssh.shell = "sh" 26 | 27 | # Disable automatic box update checking. If you disable this, then 28 | # boxes will only be checked for updates when the user runs 29 | # `vagrant box outdated`. This is not recommended. 30 | # config.vm.box_check_update = false 31 | 32 | # Create a forwarded port mapping which allows access to a specific port 33 | # within the machine from a port on the host machine. In the example below, 34 | # accessing "localhost:8080" will access port 80 on the guest machine. 35 | # NOTE: This will enable public access to the opened port 36 | # config.vm.network "forwarded_port", guest: 80, host: 8080 37 | 38 | # Create a forwarded port mapping which allows access to a specific port 39 | # within the machine from a port on the host machine and only allow access 40 | # via 127.0.0.1 to disable public access 41 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 42 | 43 | # Create a private network, which allows host-only access to the machine 44 | # using a specific IP. 45 | # config.vm.network "private_network", ip: "192.168.33.10" 46 | 47 | # Create a public network, which generally matched to bridged network. 48 | # Bridged networks make the machine appear as another physical device on 49 | # your network. 50 | # config.vm.network "public_network" 51 | 52 | # Share an additional folder to the guest VM. The first argument is 53 | # the path on the host to the actual folder. The second argument is 54 | # the path on the guest to mount the folder. And the optional third 55 | # argument is a set of non-required options. 56 | # config.vm.synced_folder "../data", "/vagrant_data" 57 | 58 | # Disable the default share of the current code directory. Doing this 59 | # provides improved isolation between the vagrant box and your host 60 | # by making sure your Vagrantfile isn't accessible to the vagrant box. 61 | # If you use this you may want to enable additional shared subfolders as 62 | # shown above. 63 | # config.vm.synced_folder ".", "/vagrant", disabled: true 64 | 65 | # Provider-specific configuration so you can fine-tune various 66 | # backing providers for Vagrant. These expose provider-specific options. 67 | # Example for VirtualBox: 68 | # 69 | # config.vm.provider "virtualbox" do |vb| 70 | # # Display the VirtualBox GUI when booting the machine 71 | # vb.gui = true 72 | # 73 | # # Customize the amount of memory on the VM: 74 | # vb.memory = "1024" 75 | # end 76 | # 77 | # View the documentation for the provider you are using for more 78 | # information on available options. 79 | 80 | # Enable provisioning with a shell script. Additional provisioners such as 81 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 82 | # documentation for more information about their specific syntax and use. 83 | # note: clang installed by default 84 | 85 | # Vagrant provide a openBSD 7.4 box while only 7.6 and 7.7 are still 86 | # maintained by openBSD -> older registry have been shutdown. 87 | # config.vm.provision "env", type: "shell", inline:<<-SHELL 88 | # set -x 89 | # sysupgrade 90 | # SHELL 91 | 92 | config.vm.provision "env", type: "shell", inline:<<-SHELL 93 | set -x 94 | pkg_add -u 95 | pkg_add git cmake 96 | SHELL 97 | 98 | config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/" 99 | config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/" 100 | config.vm.provision "file", source: "../../../patches", destination: "$HOME/project/" 101 | config.vm.provision "file", source: "../../../Foo", destination: "$HOME/project/" 102 | config.vm.provision "file", source: "../../../Bar", destination: "$HOME/project/" 103 | config.vm.provision "file", source: "../../../FooBar", destination: "$HOME/project/" 104 | config.vm.provision "file", source: "../../../FooBarApp", destination: "$HOME/project/" 105 | config.vm.provision "file", source: "../../../examples", destination: "$HOME/project/" 106 | 107 | config.vm.provision "devel", type: "shell", inline:<<-SHELL 108 | set -x 109 | cd project 110 | ls 111 | SHELL 112 | 113 | config.vm.provision "configure", type: "shell", inline:<<-SHELL 114 | set -x 115 | cd project 116 | cmake -S. -Bbuild 117 | SHELL 118 | 119 | config.vm.provision "build", type: "shell", inline:<<-SHELL 120 | set -x 121 | cd project 122 | cmake --build build -v 123 | SHELL 124 | 125 | config.vm.provision "test", type: "shell", inline:<<-SHELL 126 | set -x 127 | cd project 128 | cmake --build build --target test -v 129 | SHELL 130 | end 131 | -------------------------------------------------------------------------------- /patches/googletest-v1.17.0.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 | -------------------------------------------------------------------------------- /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.box_version = "4.3.12" 18 | 19 | config.vm.box = "NetBSD/NetBSD-9.1" 20 | config.vm.box_version = "1.0.0" 21 | 22 | config.vm.provider "virtualbox" do |v| 23 | v.name = "ci_netbsd" 24 | end 25 | config.ssh.shell = "sh" 26 | 27 | # Disable automatic box update checking. If you disable this, then 28 | # boxes will only be checked for updates when the user runs 29 | # `vagrant box outdated`. This is not recommended. 30 | # config.vm.box_check_update = false 31 | 32 | # Create a forwarded port mapping which allows access to a specific port 33 | # within the machine from a port on the host machine. In the example below, 34 | # accessing "localhost:8080" will access port 80 on the guest machine. 35 | # NOTE: This will enable public access to the opened port 36 | # config.vm.network "forwarded_port", guest: 80, host: 8080 37 | 38 | # Create a forwarded port mapping which allows access to a specific port 39 | # within the machine from a port on the host machine and only allow access 40 | # via 127.0.0.1 to disable public access 41 | # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" 42 | 43 | # Create a private network, which allows host-only access to the machine 44 | # using a specific IP. 45 | # config.vm.network "private_network", ip: "192.168.33.10" 46 | 47 | # Create a public network, which generally matched to bridged network. 48 | # Bridged networks make the machine appear as another physical device on 49 | # your network. 50 | # config.vm.network "public_network" 51 | 52 | # Share an additional folder to the guest VM. The first argument is 53 | # the path on the host to the actual folder. The second argument is 54 | # the path on the guest to mount the folder. And the optional third 55 | # argument is a set of non-required options. 56 | # config.vm.synced_folder "../data", "/vagrant_data" 57 | 58 | # Disable the default share of the current code directory. Doing this 59 | # provides improved isolation between the vagrant box and your host 60 | # by making sure your Vagrantfile isn't accessible to the vagrant box. 61 | # If you use this you may want to enable additional shared subfolders as 62 | # shown above. 63 | config.vm.synced_folder ".", "/vagrant", disabled: true 64 | 65 | # Provider-specific configuration so you can fine-tune various 66 | # backing providers for Vagrant. These expose provider-specific options. 67 | # Example for VirtualBox: 68 | # 69 | # config.vm.provider "virtualbox" do |vb| 70 | # # Display the VirtualBox GUI when booting the machine 71 | # vb.gui = true 72 | # 73 | # # Customize the amount of memory on the VM: 74 | # vb.memory = "1024" 75 | # end 76 | # 77 | # View the documentation for the provider you are using for more 78 | # information on available options. 79 | 80 | # Enable provisioning with a shell script. Additional provisioners such as 81 | # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the 82 | # documentation for more information about their specific syntax and use. 83 | # note: clang installed by default 84 | config.vm.provision "env", type: "shell", inline:<<-SHELL 85 | set -x 86 | pkgin upgrade 87 | pkgin -y install git cmake 88 | pkgin -y install mozilla-rootcerts-openssl 89 | SHELL 90 | 91 | config.vm.provision "gcc14", type: "shell", inline:<<-SHELL 92 | set -x 93 | pkgin -y install gcc14 94 | SHELL 95 | 96 | # config.vm.provision "gcc14", type: "shell", inline:<<-SHELL 97 | # set -x 98 | # ftp ftp://ftp.NetBSD.org/pub/pkgsrc/pkgsrc-2024Q4/pkgsrc.tar.gz 99 | # tar -xzf pkgsrc.tar.gz -C /usr 100 | # ls /usr/pkgsrc/lang 101 | # cd /usr/pkgsrc/lang/gcc14 102 | # make install clean clean-depens -j4 103 | # SHELL 104 | 105 | config.vm.provision "file", source: "../../../CMakeLists.txt", destination: "$HOME/project/" 106 | config.vm.provision "file", source: "../../../cmake", destination: "$HOME/project/" 107 | config.vm.provision "file", source: "../../../patches", destination: "$HOME/project/" 108 | config.vm.provision "file", source: "../../../Foo", destination: "$HOME/project/" 109 | config.vm.provision "file", source: "../../../Bar", destination: "$HOME/project/" 110 | config.vm.provision "file", source: "../../../FooBar", destination: "$HOME/project/" 111 | config.vm.provision "file", source: "../../../FooBarApp", destination: "$HOME/project/" 112 | config.vm.provision "file", source: "../../../examples", destination: "$HOME/project/" 113 | 114 | config.vm.provision "devel", type: "shell", inline:<<-SHELL 115 | set -x 116 | cd project 117 | ls 118 | SHELL 119 | 120 | config.vm.provision "configure", type: "shell", inline:<<-SHELL 121 | set -x 122 | cd project 123 | export CC=/usr/pkg/gcc14/bin/gcc 124 | export CXX=/usr/pkg/gcc14/bin/g++ 125 | cmake -S. -Bbuild 126 | SHELL 127 | 128 | config.vm.provision "build", type: "shell", inline:<<-SHELL 129 | set -x 130 | cd project 131 | cmake --build build -v 132 | SHELL 133 | 134 | config.vm.provision "test", type: "shell", inline:<<-SHELL 135 | set -x 136 | cd project 137 | cmake --build build --target test -v 138 | SHELL 139 | end 140 | -------------------------------------------------------------------------------- /patches/ZLIB-v1.3.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 15ceebe..8dc0df6 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,47 @@ 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 | +else() 118 | + message(FATAL_ERROR "ZLIB won't be installed") 119 | endif() 120 | + 121 | if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) 122 | install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") 123 | endif() 124 | @@ -199,20 +227,20 @@ endif() 125 | #============================================================================ 126 | if(ZLIB_BUILD_EXAMPLES) 127 | add_executable(example test/example.c) 128 | - target_link_libraries(example zlib) 129 | + target_link_libraries(example ZLIB) 130 | add_test(example example) 131 | 132 | add_executable(minigzip test/minigzip.c) 133 | - target_link_libraries(minigzip zlib) 134 | + target_link_libraries(minigzip ZLIB) 135 | 136 | if(HAVE_OFF64_T) 137 | add_executable(example64 test/example.c) 138 | - target_link_libraries(example64 zlib) 139 | + target_link_libraries(example64 ZLIB) 140 | set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 141 | add_test(example64 example64) 142 | 143 | add_executable(minigzip64 test/minigzip.c) 144 | - target_link_libraries(minigzip64 zlib) 145 | + target_link_libraries(minigzip64 ZLIB) 146 | set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") 147 | endif() 148 | endif() 149 | -------------------------------------------------------------------------------- /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( 66 | const std::vector>& data) { 67 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 68 | LOG(INFO) << "{"; 69 | for (const auto& inner : data) { 70 | LOG(INFO) << "{"; 71 | for (const auto& item : inner) { 72 | LOG(INFO) << item << ", "; 73 | } 74 | LOG(INFO) << "}, "; 75 | } 76 | LOG(INFO) << "}" << std::endl; 77 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 78 | return data.size(); 79 | } 80 | 81 | std::vector> pairVectorOutput(int level) { 82 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 83 | std::vector> result(level, std::make_pair(level, level)); 84 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 85 | return result; 86 | } 87 | 88 | int pairVectorInput(std::vector> data) { 89 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 90 | LOG(INFO) << "{"; 91 | for (const auto& item : data) { 92 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 93 | } 94 | LOG(INFO) << "}" << std::endl; 95 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 96 | return data.size(); 97 | } 98 | 99 | int pairVectorRefInput(const std::vector>& data) { 100 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 101 | LOG(INFO) << "{"; 102 | for (const auto& item : data) { 103 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 104 | } 105 | LOG(INFO) << "}" << std::endl; 106 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 107 | return data.size(); 108 | } 109 | 110 | std::vector>> pairJaggedArrayOutput(int level) { 111 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 112 | std::vector>> result; 113 | result.reserve(level); 114 | for (int i = 1; i <= level; ++i) { 115 | result.emplace_back( 116 | std::vector>(i, std::make_pair(i, i))); 117 | } 118 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 119 | return result; 120 | } 121 | 122 | int pairJaggedArrayInput(std::vector>> data) { 123 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 124 | LOG(INFO) << "{"; 125 | for (const auto& inner : data) { 126 | LOG(INFO) << "{"; 127 | for (const auto& item : inner) { 128 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 129 | } 130 | LOG(INFO) << "}, "; 131 | } 132 | LOG(INFO) << "}" << std::endl; 133 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 134 | return data.size(); 135 | } 136 | 137 | int pairJaggedArrayRefInput( 138 | const std::vector>>& data) { 139 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 140 | LOG(INFO) << "{"; 141 | for (const auto& inner : data) { 142 | LOG(INFO) << "{"; 143 | for (const auto& item : inner) { 144 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 145 | } 146 | LOG(INFO) << "}, "; 147 | } 148 | LOG(INFO) << "}" << std::endl; 149 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 150 | return data.size(); 151 | } 152 | 153 | void freeFunction(int level) { 154 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 155 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 156 | } 157 | 158 | void freeFunction(int64_t level) { 159 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" 160 | << std::endl; 161 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" 162 | << std::endl; 163 | } 164 | 165 | void Bar::staticFunction(int level) { 166 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 167 | freeFunction(level + 1); 168 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 169 | } 170 | 171 | void Bar::staticFunction(int64_t level) { 172 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" 173 | << std::endl; 174 | freeFunction(level + 1); 175 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" 176 | << std::endl; 177 | } 178 | 179 | int Bar::getInt() const { return _intValue; } 180 | 181 | void Bar::setInt(int input) { _intValue = input; } 182 | 183 | int64_t Bar::getInt64() const { return _int64Value; } 184 | 185 | void Bar::setInt64(int64_t input) { _int64Value = input; } 186 | 187 | std::string Bar::operator()() const { 188 | return std::string{"\"Bar\":{\"int\":"} + std::to_string(_intValue) + 189 | ",\"int64\":" + std::to_string(_int64Value) + "}"; 190 | } 191 | 192 | namespace { 193 | void* kVar = [] { 194 | std::cerr << "kBar" << std::endl; 195 | return nullptr; 196 | }(); 197 | } // namespace 198 | 199 | } // namespace bar 200 | -------------------------------------------------------------------------------- /Foo/src/Foo.cpp: -------------------------------------------------------------------------------- 1 | #include "foo/Foo.hpp" 2 | 3 | #include 4 | 5 | #include 6 | #include 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( 66 | const std::vector>& data) { 67 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 68 | LOG(INFO) << "{"; 69 | for (const auto& inner : data) { 70 | LOG(INFO) << "{"; 71 | for (const auto& item : inner) { 72 | LOG(INFO) << item << ", "; 73 | } 74 | LOG(INFO) << "}, "; 75 | } 76 | LOG(INFO) << "}" << std::endl; 77 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 78 | return data.size(); 79 | } 80 | 81 | std::vector> pairVectorOutput(int level) { 82 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 83 | std::vector> result(level, std::make_pair(level, level)); 84 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 85 | return result; 86 | } 87 | 88 | int pairVectorInput(std::vector> data) { 89 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 90 | LOG(INFO) << "{"; 91 | for (const auto& item : data) { 92 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 93 | } 94 | LOG(INFO) << "}" << std::endl; 95 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 96 | return data.size(); 97 | } 98 | 99 | int pairVectorRefInput(const std::vector>& data) { 100 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 101 | LOG(INFO) << "{"; 102 | for (const auto& item : data) { 103 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 104 | } 105 | LOG(INFO) << "}" << std::endl; 106 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 107 | return data.size(); 108 | } 109 | 110 | std::vector>> pairJaggedArrayOutput(int level) { 111 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "()" << std::endl; 112 | std::vector>> result; 113 | result.reserve(level); 114 | for (int i = 1; i <= level; ++i) { 115 | result.emplace_back( 116 | std::vector>(i, std::make_pair(i, i))); 117 | } 118 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "()" << std::endl; 119 | return result; 120 | } 121 | 122 | int pairJaggedArrayInput(std::vector>> data) { 123 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 124 | LOG(INFO) << "{"; 125 | for (const auto& inner : data) { 126 | LOG(INFO) << "{"; 127 | for (const auto& item : inner) { 128 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 129 | } 130 | LOG(INFO) << "}, "; 131 | } 132 | LOG(INFO) << "}" << std::endl; 133 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 134 | return data.size(); 135 | } 136 | 137 | int pairJaggedArrayRefInput( 138 | const std::vector>>& data) { 139 | LOG(INFO) << "Enter " << __func__ << "()" << std::endl; 140 | LOG(INFO) << "{"; 141 | for (const auto& inner : data) { 142 | LOG(INFO) << "{"; 143 | for (const auto& item : inner) { 144 | LOG(INFO) << "[" << item.first << "," << item.second << "], "; 145 | } 146 | LOG(INFO) << "}, "; 147 | } 148 | LOG(INFO) << "}" << std::endl; 149 | LOG(INFO) << "Exit " << __func__ << "()" << std::endl; 150 | return data.size(); 151 | } 152 | 153 | void freeFunction(int level) { 154 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 155 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 156 | } 157 | 158 | void freeFunction(int64_t level) { 159 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" 160 | << std::endl; 161 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" 162 | << std::endl; 163 | } 164 | 165 | void Foo::staticFunction(int level) { 166 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int)" << std::endl; 167 | freeFunction(level + 1); 168 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int)" << std::endl; 169 | } 170 | 171 | void Foo::staticFunction(int64_t level) { 172 | LOG(INFO) << "[" << level << "] Enter " << __func__ << "(int64_t)" 173 | << std::endl; 174 | freeFunction(level + 1); 175 | LOG(INFO) << "[" << level << "] Exit " << __func__ << "(int64_t)" 176 | << std::endl; 177 | } 178 | 179 | int Foo::getInt() const { return _intValue; } 180 | 181 | void Foo::setInt(int input) { _intValue = input; } 182 | 183 | int64_t Foo::getInt64() const { return _int64Value; } 184 | 185 | void Foo::setInt64(int64_t input) { _int64Value = input; } 186 | 187 | std::string Foo::operator()() const { 188 | return std::string{"\"Foo\":{\"int\":"} + std::to_string(_intValue) + 189 | ",\"int64\":" + std::to_string(_int64Value) + "}"; 190 | } 191 | 192 | namespace { 193 | void* kVar = [] { 194 | std::cerr << "kFoo" << std::endl; 195 | return nullptr; 196 | }(); 197 | } // namespace 198 | 199 | } // namespace foo 200 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: Align 6 | AlignArrayOfStructures: None 7 | AlignConsecutiveAssignments: 8 | Enabled: false 9 | AcrossEmptyLines: false 10 | AcrossComments: false 11 | AlignCompound: false 12 | AlignFunctionDeclarations: false 13 | AlignFunctionPointers: false 14 | PadOperators: true 15 | AlignConsecutiveBitFields: 16 | Enabled: false 17 | AcrossEmptyLines: false 18 | AcrossComments: false 19 | AlignCompound: false 20 | AlignFunctionDeclarations: false 21 | AlignFunctionPointers: false 22 | PadOperators: false 23 | AlignConsecutiveDeclarations: 24 | Enabled: false 25 | AcrossEmptyLines: false 26 | AcrossComments: false 27 | AlignCompound: false 28 | AlignFunctionDeclarations: true 29 | AlignFunctionPointers: false 30 | PadOperators: false 31 | AlignConsecutiveMacros: 32 | Enabled: false 33 | AcrossEmptyLines: false 34 | AcrossComments: false 35 | AlignCompound: false 36 | AlignFunctionDeclarations: false 37 | AlignFunctionPointers: false 38 | PadOperators: false 39 | AlignConsecutiveShortCaseStatements: 40 | Enabled: false 41 | AcrossEmptyLines: false 42 | AcrossComments: false 43 | AlignCaseArrows: false 44 | AlignCaseColons: false 45 | AlignConsecutiveTableGenBreakingDAGArgColons: 46 | Enabled: false 47 | AcrossEmptyLines: false 48 | AcrossComments: false 49 | AlignCompound: false 50 | AlignFunctionDeclarations: false 51 | AlignFunctionPointers: false 52 | PadOperators: false 53 | AlignConsecutiveTableGenCondOperatorColons: 54 | Enabled: false 55 | AcrossEmptyLines: false 56 | AcrossComments: false 57 | AlignCompound: false 58 | AlignFunctionDeclarations: false 59 | AlignFunctionPointers: false 60 | PadOperators: false 61 | AlignConsecutiveTableGenDefinitionColons: 62 | Enabled: false 63 | AcrossEmptyLines: false 64 | AcrossComments: false 65 | AlignCompound: false 66 | AlignFunctionDeclarations: false 67 | AlignFunctionPointers: false 68 | PadOperators: false 69 | AlignEscapedNewlines: Left 70 | AlignOperands: Align 71 | AlignTrailingComments: 72 | Kind: Always 73 | OverEmptyLines: 0 74 | AllowAllArgumentsOnNextLine: true 75 | AllowAllParametersOfDeclarationOnNextLine: true 76 | AllowBreakBeforeNoexceptSpecifier: Never 77 | AllowBreakBeforeQtProperty: false 78 | AllowShortBlocksOnASingleLine: Never 79 | AllowShortCaseExpressionOnASingleLine: true 80 | AllowShortCaseLabelsOnASingleLine: false 81 | AllowShortCompoundRequirementOnASingleLine: true 82 | AllowShortEnumsOnASingleLine: true 83 | AllowShortFunctionsOnASingleLine: All 84 | AllowShortIfStatementsOnASingleLine: WithoutElse 85 | AllowShortLambdasOnASingleLine: All 86 | AllowShortLoopsOnASingleLine: true 87 | AllowShortNamespacesOnASingleLine: false 88 | AlwaysBreakAfterDefinitionReturnType: None 89 | AlwaysBreakBeforeMultilineStrings: true 90 | AttributeMacros: 91 | - __capability 92 | - absl_nonnull 93 | - absl_nullable 94 | - absl_nullability_unknown 95 | BinPackArguments: true 96 | BinPackLongBracedList: true 97 | BinPackParameters: BinPack 98 | BitFieldColonSpacing: Both 99 | BracedInitializerIndentWidth: -1 100 | BraceWrapping: 101 | AfterCaseLabel: false 102 | AfterClass: false 103 | AfterControlStatement: Never 104 | AfterEnum: false 105 | AfterExternBlock: false 106 | AfterFunction: false 107 | AfterNamespace: false 108 | AfterObjCDeclaration: false 109 | AfterStruct: false 110 | AfterUnion: false 111 | BeforeCatch: false 112 | BeforeElse: false 113 | BeforeLambdaBody: false 114 | BeforeWhile: false 115 | IndentBraces: false 116 | SplitEmptyFunction: true 117 | SplitEmptyRecord: true 118 | SplitEmptyNamespace: true 119 | BreakAdjacentStringLiterals: true 120 | BreakAfterAttributes: Leave 121 | BreakAfterJavaFieldAnnotations: false 122 | BreakAfterReturnType: None 123 | BreakArrays: true 124 | BreakBeforeBinaryOperators: None 125 | BreakBeforeConceptDeclarations: Always 126 | BreakBeforeBraces: Attach 127 | BreakBeforeInlineASMColon: OnlyMultiline 128 | BreakBeforeTemplateCloser: false 129 | BreakBeforeTernaryOperators: true 130 | BreakBinaryOperations: Never 131 | BreakConstructorInitializers: BeforeColon 132 | BreakFunctionDefinitionParameters: false 133 | BreakInheritanceList: BeforeColon 134 | BreakStringLiterals: true 135 | BreakTemplateDeclarations: Yes 136 | ColumnLimit: 80 137 | CommentPragmas: '^ IWYU pragma:' 138 | CompactNamespaces: false 139 | ConstructorInitializerIndentWidth: 4 140 | ContinuationIndentWidth: 4 141 | Cpp11BracedListStyle: true 142 | DerivePointerAlignment: false 143 | DisableFormat: false 144 | EmptyLineAfterAccessModifier: Never 145 | EmptyLineBeforeAccessModifier: LogicalBlock 146 | EnumTrailingComma: Leave 147 | ExperimentalAutoDetectBinPacking: false 148 | FixNamespaceComments: true 149 | ForEachMacros: 150 | - foreach 151 | - Q_FOREACH 152 | - BOOST_FOREACH 153 | IfMacros: 154 | - KJ_IF_MAYBE 155 | IncludeBlocks: Regroup 156 | IncludeCategories: 157 | - Regex: '^' 158 | Priority: 2 159 | SortPriority: 0 160 | CaseSensitive: false 161 | - Regex: '^<.*\.h>' 162 | Priority: 1 163 | SortPriority: 0 164 | CaseSensitive: false 165 | - Regex: '^<.*' 166 | Priority: 2 167 | SortPriority: 0 168 | CaseSensitive: false 169 | - Regex: '.*' 170 | Priority: 3 171 | SortPriority: 0 172 | CaseSensitive: false 173 | IncludeIsMainRegex: '([-_](test|unittest))?$' 174 | IncludeIsMainSourceRegex: '' 175 | IndentAccessModifiers: false 176 | IndentCaseBlocks: false 177 | IndentCaseLabels: true 178 | IndentExportBlock: true 179 | IndentExternBlock: AfterExternBlock 180 | IndentGotoLabels: true 181 | IndentPPDirectives: None 182 | IndentRequiresClause: true 183 | IndentWidth: 2 184 | IndentWrappedFunctionNames: false 185 | InsertBraces: false 186 | InsertNewlineAtEOF: false 187 | InsertTrailingCommas: None 188 | IntegerLiteralSeparator: 189 | Binary: 0 190 | BinaryMinDigits: 0 191 | Decimal: 0 192 | DecimalMinDigits: 0 193 | Hex: 0 194 | HexMinDigits: 0 195 | JavaScriptQuotes: Leave 196 | JavaScriptWrapImports: true 197 | KeepEmptyLines: 198 | AtEndOfFile: false 199 | AtStartOfBlock: false 200 | AtStartOfFile: true 201 | KeepFormFeed: false 202 | LambdaBodyIndentation: Signature 203 | LineEnding: DeriveLF 204 | MacroBlockBegin: '' 205 | MacroBlockEnd: '' 206 | MainIncludeChar: Quote 207 | MaxEmptyLinesToKeep: 1 208 | NamespaceIndentation: None 209 | NumericLiteralCase: 210 | ExponentLetter: Leave 211 | HexDigit: Leave 212 | Prefix: Leave 213 | Suffix: Leave 214 | ObjCBinPackProtocolList: Never 215 | ObjCBlockIndentWidth: 2 216 | ObjCBreakBeforeNestedBlockParam: true 217 | ObjCSpaceAfterProperty: false 218 | ObjCSpaceBeforeProtocolList: true 219 | OneLineFormatOffRegex: '' 220 | PackConstructorInitializers: NextLine 221 | PenaltyBreakAssignment: 2 222 | PenaltyBreakBeforeFirstCallParameter: 1 223 | PenaltyBreakBeforeMemberAccess: 150 224 | PenaltyBreakComment: 300 225 | PenaltyBreakFirstLessLess: 120 226 | PenaltyBreakOpenParenthesis: 0 227 | PenaltyBreakScopeResolution: 500 228 | PenaltyBreakString: 1000 229 | PenaltyBreakTemplateDeclaration: 10 230 | PenaltyExcessCharacter: 1000000 231 | PenaltyIndentedWhitespace: 0 232 | PenaltyReturnTypeOnItsOwnLine: 200 233 | PointerAlignment: Left 234 | PPIndentWidth: -1 235 | QualifierAlignment: Leave 236 | RawStringFormats: 237 | - Language: Cpp 238 | Delimiters: 239 | - cc 240 | - CC 241 | - cpp 242 | - Cpp 243 | - CPP 244 | - 'c++' 245 | - 'C++' 246 | CanonicalDelimiter: '' 247 | BasedOnStyle: google 248 | - Language: TextProto 249 | Delimiters: 250 | - pb 251 | - PB 252 | - proto 253 | - PROTO 254 | EnclosingFunctions: 255 | - EqualsProto 256 | - EquivToProto 257 | - PARSE_PARTIAL_TEXT_PROTO 258 | - PARSE_TEST_PROTO 259 | - PARSE_TEXT_PROTO 260 | - ParseTextOrDie 261 | - ParseTextProtoOrDie 262 | - ParseTestProto 263 | - ParsePartialTestProto 264 | CanonicalDelimiter: pb 265 | BasedOnStyle: google 266 | ReferenceAlignment: Pointer 267 | ReflowComments: Always 268 | RemoveBracesLLVM: false 269 | RemoveEmptyLinesInUnwrappedLines: false 270 | RemoveParentheses: Leave 271 | RemoveSemicolon: false 272 | RequiresClausePosition: OwnLine 273 | RequiresExpressionIndentation: OuterScope 274 | SeparateDefinitionBlocks: Leave 275 | ShortNamespaceLines: 1 276 | SkipMacroDefinitionBody: false 277 | SortIncludes: 278 | Enabled: true 279 | IgnoreCase: false 280 | IgnoreExtension: false 281 | SortJavaStaticImport: Before 282 | SortUsingDeclarations: LexicographicNumeric 283 | SpaceAfterCStyleCast: false 284 | SpaceAfterLogicalNot: false 285 | SpaceAfterOperatorKeyword: false 286 | SpaceAfterTemplateKeyword: true 287 | SpaceAroundPointerQualifiers: Default 288 | SpaceBeforeAssignmentOperators: true 289 | SpaceBeforeCaseColon: false 290 | SpaceBeforeCpp11BracedList: false 291 | SpaceBeforeCtorInitializerColon: true 292 | SpaceBeforeInheritanceColon: true 293 | SpaceBeforeJsonColon: false 294 | SpaceBeforeParens: ControlStatements 295 | SpaceBeforeParensOptions: 296 | AfterControlStatements: true 297 | AfterForeachMacros: true 298 | AfterFunctionDefinitionName: false 299 | AfterFunctionDeclarationName: false 300 | AfterIfMacros: true 301 | AfterNot: false 302 | AfterOverloadedOperator: false 303 | AfterPlacementOperator: true 304 | AfterRequiresInClause: false 305 | AfterRequiresInExpression: false 306 | BeforeNonEmptyParentheses: false 307 | SpaceBeforeRangeBasedForLoopColon: true 308 | SpaceBeforeSquareBrackets: false 309 | SpaceInEmptyBraces: Never 310 | SpacesBeforeTrailingComments: 2 311 | SpacesInAngles: Never 312 | SpacesInContainerLiterals: true 313 | SpacesInLineCommentPrefix: 314 | Minimum: 1 315 | Maximum: -1 316 | SpacesInParens: Never 317 | SpacesInParensOptions: 318 | ExceptDoubleParentheses: false 319 | InCStyleCasts: false 320 | InConditionalStatements: false 321 | InEmptyParentheses: false 322 | Other: false 323 | SpacesInSquareBrackets: false 324 | Standard: Auto 325 | StatementAttributeLikeMacros: 326 | - Q_EMIT 327 | StatementMacros: 328 | - Q_UNUSED 329 | - QT_REQUIRE_VERSION 330 | TableGenBreakInsideDAGArg: DontBreak 331 | TabWidth: 8 332 | UseTab: Never 333 | VerilogBreakBetweenInstancePorts: true 334 | WhitespaceSensitiveMacros: 335 | - BOOST_PP_STRINGIZE 336 | - CF_SWIFT_NAME 337 | - NS_SWIFT_NAME 338 | - PP_STRINGIZE 339 | - STRINGIZE 340 | WrapNamespaceBodyWithEmptyLines: Leave 341 | ... 342 | 343 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | ################## 32 | ## PROTO FILE ## 33 | ################## 34 | # get_cpp_proto() 35 | # CMake macro to generate Protobuf cpp sources 36 | # Parameters: 37 | # the proto c++ headers list 38 | # the proto c++ sources list 39 | # e.g.: 40 | # get_cpp_proto(PROTO_HDRS PROTO_SRCS) 41 | macro(get_cpp_proto PROTO_HDRS PROTO_SRCS) 42 | file(GLOB_RECURSE PROTO_FILES RELATIVE ${PROJECT_SOURCE_DIR} "*.proto") 43 | ## Get Protobuf include dir 44 | get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES) 45 | foreach(dir IN LISTS protobuf_dirs) 46 | if (NOT "${dir}" MATCHES "INSTALL_INTERFACE|-NOTFOUND") 47 | message(STATUS "protoc(cc) Adding proto path: ${dir}") 48 | list(APPEND PROTO_DIRS "--proto_path=${dir}") 49 | endif() 50 | endforeach() 51 | 52 | foreach(PROTO_FILE IN LISTS PROTO_FILES) 53 | message(STATUS "protoc(cc) .proto: ${PROTO_FILE}") 54 | get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY) 55 | get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE) 56 | set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h) 57 | set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc) 58 | message(STATUS "protoc(cc) hdr: ${PROTO_HDR}") 59 | message(STATUS "protoc(cc) src: ${PROTO_SRC}") 60 | add_custom_command( 61 | OUTPUT ${PROTO_SRC} ${PROTO_HDR} 62 | COMMAND ${PROTOC_PRG} 63 | "--proto_path=${PROJECT_SOURCE_DIR}" 64 | ${PROTO_DIRS} 65 | "--cpp_out=dllexport_decl=PROTO_DLL:${PROJECT_BINARY_DIR}" 66 | ${PROTO_FILE} 67 | DEPENDS ${PROTO_NAME}.proto ${PROTOC_PRG} 68 | COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}" 69 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 70 | VERBATIM) 71 | list(APPEND ${PROTO_HDRS} ${PROTO_HDR}) 72 | list(APPEND ${PROTO_SRCS} ${PROTO_SRC}) 73 | endforeach() 74 | endmacro() 75 | 76 | ################### 77 | ## C++ Library ## 78 | ################### 79 | # add_cxx_library() 80 | # CMake function to generate and build C++ library. 81 | # Parameters: 82 | # NAME: CMake target name 83 | # [HEADERS]: List of headers files 84 | # SOURCES: List of source files 85 | # [TYPE]: SHARED, STATIC or INTERFACE 86 | # [COMPILE_DEFINITIONS]: List of private compile definitions 87 | # [COMPILE_OPTIONS]: List of private compile options 88 | # [LINK_LIBRARIES]: List of **public** libraries to use when linking 89 | # note: ortools::ortools is always linked to the target 90 | # [LINK_OPTIONS]: List of private link options 91 | # [INSTALL_DIR]: relative path to install public headers 92 | # e.g.: 93 | # add_cxx_library( 94 | # NAME 95 | # foo 96 | # HEADERS 97 | # foo.h 98 | # SOURCES 99 | # foo.cc 100 | # ${PROJECT_SOURCE_DIR}/Foo/foo.cc 101 | # TYPE 102 | # SHARED 103 | # LINK_LIBRARIES 104 | # GTest::gmock 105 | # GTest::gtest_main 106 | # TESTING 107 | # ) 108 | function(add_cxx_library) 109 | set(options "TESTING") 110 | set(oneValueArgs "NAME;TYPE;INSTALL_DIR") 111 | set(multiValueArgs 112 | "HEADERS;SOURCES;COMPILE_DEFINITIONS;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS") 113 | cmake_parse_arguments(LIBRARY 114 | "${options}" 115 | "${oneValueArgs}" 116 | "${multiValueArgs}" 117 | ${ARGN} 118 | ) 119 | if(LIBRARY_TESTING AND NOT BUILD_TESTING) 120 | return() 121 | endif() 122 | 123 | if(NOT LIBRARY_NAME) 124 | message(FATAL_ERROR "no NAME provided") 125 | endif() 126 | if(NOT LIBRARY_SOURCES) 127 | message(FATAL_ERROR "no SOURCES provided") 128 | endif() 129 | message(STATUS "Configuring library ${LIBRARY_NAME} ...") 130 | 131 | add_library(${LIBRARY_NAME} ${LIBRARY_TYPE} "") 132 | if(LIBRARY_TYPE STREQUAL "INTERFACE") 133 | target_include_directories(${LIBRARY_NAME} INTERFACE 134 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 135 | target_link_libraries(${LIBRARY_NAME} INTERFACE ${LIBRARY_LINK_LIBRARIES}) 136 | target_link_options(${LIBRARY_NAME} INTERFACE ${LIBRARY_LINK_OPTIONS}) 137 | else() 138 | target_include_directories(${LIBRARY_NAME} PUBLIC 139 | $ 140 | $ 141 | ) 142 | target_sources(${LIBRARY_NAME} PRIVATE 143 | ${LIBRARY_HEADERS} 144 | ${LIBRARY_SOURCES} 145 | ) 146 | target_compile_features(${LIBRARY_NAME} PRIVATE cxx_std_20) 147 | target_compile_definitions(${LIBRARY_NAME} PRIVATE ${LIBRARY_COMPILE_DEFINITIONS}) 148 | target_compile_options(${LIBRARY_NAME} PRIVATE ${LIBRARY_COMPILE_OPTIONS}) 149 | target_link_libraries(${LIBRARY_NAME} PUBLIC ${LIBRARY_LINK_LIBRARIES}) 150 | target_link_options(${LIBRARY_NAME} PRIVATE ${LIBRARY_LINK_OPTIONS}) 151 | endif() 152 | set_target_properties(${LIBRARY_NAME} PROPERTIES 153 | VERSION ${PROJECT_VERSION} 154 | POSITION_INDEPENDENT_CODE ON 155 | PUBLIC_HEADER ${LIBRARY_HEADERS} 156 | ) 157 | 158 | if(APPLE) 159 | set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path") 160 | elseif(UNIX) 161 | set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN") 162 | endif() 163 | 164 | # Install 165 | include(GNUInstallDirs) 166 | install(TARGETS ${LIBRARY_NAME} 167 | EXPORT ${PROJECT_NAME}Targets 168 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${LIBRARY_INSTALL_DIR} 169 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 170 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 171 | #RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 172 | ) 173 | add_library(${PROJECT_NAMESPACE}::${LIBRARY_NAME} ALIAS ${LIBRARY_NAME}) 174 | message(STATUS "Configuring library ${LIBRARY_NAME} ...DONE") 175 | endfunction() 176 | 177 | ################ 178 | ## C++ Test ## 179 | ################ 180 | # add_cxx_test() 181 | # CMake function to generate and build C++ test. 182 | # Parameters: 183 | # NAME: CMake target name 184 | # SOURCES: List of source files 185 | # [COMPILE_DEFINITIONS]: List of private compile definitions 186 | # [COMPILE_OPTIONS]: List of private compile options 187 | # [LINK_LIBRARIES]: List of private libraries to use when linking 188 | # note: ortools::ortools is always linked to the target 189 | # [LINK_OPTIONS]: List of private link options 190 | # e.g.: 191 | # add_cxx_test( 192 | # NAME 193 | # foo_test 194 | # SOURCES 195 | # foo_test.cc 196 | # ${PROJECT_SOURCE_DIR}/Foo/foo_test.cc 197 | # LINK_LIBRARIES 198 | # GTest::gmock 199 | # GTest::gtest_main 200 | # ) 201 | function(add_cxx_test) 202 | set(options "") 203 | set(oneValueArgs "NAME") 204 | set(multiValueArgs 205 | "SOURCES;COMPILE_DEFINITIONS;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS") 206 | cmake_parse_arguments(TEST 207 | "${options}" 208 | "${oneValueArgs}" 209 | "${multiValueArgs}" 210 | ${ARGN} 211 | ) 212 | if(NOT BUILD_TESTING) 213 | return() 214 | endif() 215 | 216 | if(NOT TEST_NAME) 217 | message(FATAL_ERROR "no NAME provided") 218 | endif() 219 | if(NOT TEST_SOURCES) 220 | message(FATAL_ERROR "no SOURCES provided") 221 | endif() 222 | message(STATUS "Configuring test ${TEST_NAME} ...") 223 | 224 | add_executable(${TEST_NAME} "") 225 | target_sources(${TEST_NAME} PRIVATE ${TEST_SOURCES}) 226 | target_include_directories(${TEST_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 227 | target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_COMPILE_DEFINITIONS}) 228 | target_compile_features(${TEST_NAME} PRIVATE cxx_std_20) 229 | target_compile_options(${TEST_NAME} PRIVATE ${TEST_COMPILE_OPTIONS}) 230 | target_link_libraries(${TEST_NAME} PRIVATE 231 | GTest::gtest 232 | GTest::gtest_main 233 | ${TEST_LINK_LIBRARIES} 234 | ) 235 | target_link_options(${TEST_NAME} PRIVATE ${TEST_LINK_OPTIONS}) 236 | 237 | include(GNUInstallDirs) 238 | if(APPLE) 239 | set_target_properties(${TEST_NAME} PROPERTIES 240 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") 241 | elseif(UNIX) 242 | cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR 243 | BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR} 244 | OUTPUT_VARIABLE libdir_relative_path) 245 | set_target_properties(${TEST_NAME} PROPERTIES 246 | INSTALL_RPATH "$ORIGIN/${libdir_relative_path}:$ORIGIN") 247 | endif() 248 | 249 | add_test( 250 | NAME cxx_${TEST_NAME} 251 | COMMAND ${TEST_NAME} 252 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 253 | ) 254 | message(STATUS "Configuring test ${TEST_NAME} ...DONE") 255 | endfunction() 256 | 257 | ################### 258 | ## C++ Example ## 259 | ################### 260 | # add_cxx_example() 261 | # CMake function to generate and build C++ library. 262 | # Parameters: 263 | # NAME: CMake target name 264 | # [HEADERS]: List of headers files 265 | # SOURCES: List of source files 266 | # [COMPILE_DEFINITIONS]: List of private compile definitions 267 | # [COMPILE_OPTIONS]: List of private compile options 268 | # [LINK_LIBRARIES]: List of **public** libraries to use when linking 269 | # note: ortools::ortools is always linked to the target 270 | # [LINK_OPTIONS]: List of private link options 271 | # [INSTALL_DIR]: relative path to install public headers 272 | # e.g.: 273 | # add_cxx_example( 274 | # NAME 275 | # foo 276 | # HEADERS 277 | # foo.h 278 | # SOURCES 279 | # foo.cc 280 | # ${PROJECT_SOURCE_DIR}/Foo/foo.cc 281 | # LINK_LIBRARIES 282 | # GTest::gmock 283 | # GTest::gtest_main 284 | # ) 285 | function(add_cxx_example) 286 | set(options "") 287 | set(oneValueArgs "NAME;INSTALL_DIR") 288 | set(multiValueArgs 289 | "HEADERS;SOURCES;COMPILE_DEFINITIONS;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS") 290 | cmake_parse_arguments(EXAMPLE 291 | "${options}" 292 | "${oneValueArgs}" 293 | "${multiValueArgs}" 294 | ${ARGN} 295 | ) 296 | if(NOT BUILD_EXAMPLES) 297 | return() 298 | endif() 299 | 300 | if(NOT EXAMPLE_NAME) 301 | message(FATAL_ERROR "no NAME provided") 302 | endif() 303 | if(NOT EXAMPLE_SOURCES) 304 | message(FATAL_ERROR "no SOURCES provided") 305 | endif() 306 | message(STATUS "Configuring library ${EXAMPLE_NAME} ...") 307 | 308 | add_executable(${EXAMPLE_NAME} "") 309 | target_sources(${EXAMPLE_NAME} PRIVATE ${EXAMPLE_SOURCES}) 310 | target_include_directories(${EXAMPLE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 311 | target_compile_definitions(${EXAMPLE_NAME} PRIVATE ${EXAMPLE_COMPILE_DEFINITIONS}) 312 | target_compile_features(${EXAMPLE_NAME} PRIVATE cxx_std_20) 313 | target_compile_options(${EXAMPLE_NAME} PRIVATE ${EXAMPLE_COMPILE_OPTIONS}) 314 | target_link_libraries(${EXAMPLE_NAME} PRIVATE ${EXAMPLE_LINK_LIBRARIES}) 315 | target_link_options(${EXAMPLE_NAME} PRIVATE ${EXAMPLE_LINK_OPTIONS}) 316 | 317 | include(GNUInstallDirs) 318 | if(APPLE) 319 | set_target_properties(${EXAMPLE_NAME} PROPERTIES 320 | INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path") 321 | elseif(UNIX) 322 | cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR 323 | BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR} 324 | OUTPUT_VARIABLE libdir_relative_path) 325 | set_target_properties(${EXAMPLE_NAME} PROPERTIES 326 | INSTALL_RPATH "$ORIGIN/${libdir_relative_path}:$ORIGIN") 327 | endif() 328 | 329 | install(TARGETS ${EXAMPLE_NAME}) 330 | add_test( 331 | NAME cxx_${EXAMPLE_NAME} 332 | COMMAND ${EXAMPLE_NAME} 333 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 334 | ) 335 | message(STATUS "Configuring example ${EXAMPLE_NAME}: ...DONE") 336 | endfunction() 337 | 338 | ################### 339 | ## CMake Install ## 340 | ################### 341 | include(GNUInstallDirs) 342 | #include(GenerateExportHeader) 343 | #GENERATE_EXPORT_HEADER(${PROJECT_NAME}) 344 | #install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}_export.h 345 | # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 346 | install(EXPORT ${PROJECT_NAME}Targets 347 | NAMESPACE ${PROJECT_NAMESPACE}:: 348 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} 349 | COMPONENT Devel) 350 | include(CMakePackageConfigHelpers) 351 | configure_package_config_file(cmake/${PROJECT_NAME}Config.cmake.in 352 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 353 | INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 354 | NO_SET_AND_CHECK_MACRO 355 | NO_CHECK_REQUIRED_COMPONENTS_MACRO) 356 | write_basic_package_version_file( 357 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 358 | COMPATIBILITY SameMajorVersion) 359 | install( 360 | FILES 361 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 362 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 363 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 364 | COMPONENT Devel) 365 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------