diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8e5b752..5ad4597f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: uses: vmactions/freebsd-vm@v1 with: prepare: | - pkg install -y cmake ninja bash capnproto + pkg install -y cmake ninja bash capnproto git sync: 'rsync' copyback: false @@ -148,7 +148,7 @@ jobs: strategy: fail-fast: false matrix: - config: [default, llvm, gnu32, sanitize, olddeps] + config: [default, llvm, gnu32, sanitize, olddeps, newdeps] name: build • ${{ matrix.config }} diff --git a/CMakeLists.txt b/CMakeLists.txt index bf50018a..d66de3fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,33 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -cmake_minimum_required(VERSION 3.12) +# Call cmake_minimum_required() only if it was not already called, so parent +# projects set the policy version when this project is included via +# add_subdirectory(). +# +# Rationale: Different projects have different practices for choosing policy +# versions. For example, the Bitcoin Core project sets an old policy version, +# causing CMake to use deprecated behaviors instead of new behaviors and +# maximize compatibility with a single old version of CMake, reducing variance +# between builds with newer CMake versions. By contrast CMake documentation +# recommends setting the policy version to the latest supported version of +# CMake, as an upgrading mechanism rather than a pinning mechanism, to let +# project authors fix problems before enabling newer policies, while not opting +# into deprecated policies on a longer term basis. +if(NOT DEFINED CMAKE_MINIMUM_REQUIRED_VERSION + OR CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.12) + # The left number in the range below is the minimum CMake version required to + # run this project. The right number is the CMake policy version. + # + # The purpose of the minimum version is to trigger a helpful error if a version + # of CMake is being used that is too old to work. If this number is changed, + # the version in ci/configs/olddeps.bash should be changed to match. + # + # The purpose of the policy version is to opt out of policies introduced in + # newer versions of CMake until they have been tested. If this number is + # changed, the version in ci/configs/newdeps.bash should be changed to match. + cmake_minimum_required(VERSION 3.12...4.1 FATAL_ERROR) +endif() project("Libmultiprocess" CXX) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) @@ -10,6 +36,11 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(CMAKE_CXX_STANDARD_REQUIRED YES) endif() +# Disable automatic C++20 module dependency scanning. +# CMake >=3.28 tries to use `clang-scan-deps` by default, which may not +# be installed on all platforms. We don't use named modules, so turn this off. +set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + include("cmake/compat_find.cmake") find_package(Threads REQUIRED) diff --git a/ci/README.md b/ci/README.md index fef1c022..843b61e8 100644 --- a/ci/README.md +++ b/ci/README.md @@ -21,6 +21,7 @@ CI_CONFIG=ci/configs/llvm.bash ci/scripts/run.sh CI_CONFIG=ci/configs/gnu32.bash ci/scripts/run.sh CI_CONFIG=ci/configs/sanitize.bash ci/scripts/run.sh CI_CONFIG=ci/configs/olddeps.bash ci/scripts/run.sh +CI_CONFIG=ci/configs/newdeps.bash ci/scripts/run.sh ``` By default CI jobs will reuse their build directories. `CI_CLEAN=1` can be specified to delete them before running instead. diff --git a/ci/configs/newdeps.bash b/ci/configs/newdeps.bash new file mode 100644 index 00000000..c59a76d9 --- /dev/null +++ b/ci/configs/newdeps.bash @@ -0,0 +1,7 @@ +CI_DESC="CI job using newest Cap'n Proto and cmake versions" +CI_DIR=build-newdeps +export CXXFLAGS="-Werror -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-error=array-bounds" +CAPNP_CHECKOUT=master +# cmakeVersion here should match policy version in CMakeLists.txt +NIX_ARGS=(--argstr capnprotoVersion "none" --argstr cmakeVersion "4.1.1") +BUILD_ARGS=(-k) diff --git a/ci/configs/olddeps.bash b/ci/configs/olddeps.bash index 151a300c..5e064c4d 100644 --- a/ci/configs/olddeps.bash +++ b/ci/configs/olddeps.bash @@ -4,5 +4,6 @@ CI_DIR=build-olddeps # requires an older GCC. NIXPKGS_CHANNEL=nixos-25.05 export CXXFLAGS="-Werror -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-error=array-bounds" +# cmakeVersion here should match minimum version in CMakeLists.txt NIX_ARGS=(--argstr capnprotoVersion "0.9.2" --argstr cmakeVersion "3.12.4" --argstr gccVersion "11") BUILD_ARGS=(-k) diff --git a/ci/scripts/ci.sh b/ci/scripts/ci.sh index 0022fd28..b4bd8fb4 100755 --- a/ci/scripts/ci.sh +++ b/ci/scripts/ci.sh @@ -21,10 +21,27 @@ cmake --version cmake_ver=$(cmake --version | awk '/version/{print $3; exit}') ver_ge() { [ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]; } +# If CAPNP_CHECKOUT was requested, clone and install requested Cap'n Proto branch or tag +capnp_prefix= +if [ -n "${CAPNP_CHECKOUT-}" ]; then + capnp_prefix="$PWD/capnp-install" + [ -e "capnp" ] || git clone -b "${CAPNP_CHECKOUT}" "https://github.com/capnproto/capnproto" capnp + mkdir -p capnp/build + ( + cd capnp/build + git --no-pager log -1 || true + CXXFLAGS="-std=c++20" cmake .. "-DCMAKE_INSTALL_PREFIX=${capnp_prefix}" -DBUILD_TESTING=OFF -DWITH_OPENSSL=OFF -DWITH_ZLIB=OFF + cmake --build . + cmake --install . + ) + export CMAKE_PREFIX_PATH="${capnp_prefix}:${CMAKE_PREFIX_PATH-}" +fi + src_dir=$PWD mkdir -p "$CI_DIR" cd "$CI_DIR" export CMAKE_BUILD_PARALLEL_LEVEL="$(nproc)" +git --no-pager log -1 || true cmake "$src_dir" "${CMAKE_ARGS[@]+"${CMAKE_ARGS[@]}"}" if ver_ge "$cmake_ver" "3.15"; then cmake --build . -t "${BUILD_TARGETS[@]}" -- "${BUILD_ARGS[@]+"${BUILD_ARGS[@]}"}" diff --git a/shell.nix b/shell.nix index 2d115fea..17789f31 100644 --- a/shell.nix +++ b/shell.nix @@ -55,6 +55,7 @@ let clang-tools = llvm.clang-tools.override { inherit enableLibcxx; }; cmakeHashes = { "3.12.4" = "sha256-UlVYS/0EPrcXViz/iULUcvHA5GecSUHYS6raqbKOMZQ="; + "4.1.1" = "sha256-sp9vGXM6oiS3djUHoQikJ+1Ixojh+vIrKcROHDBUkoI="; }; gcc = if gccVersion == null then null else builtins.getAttr ("gcc" + gccVersion) pkgs; cmakeBuild = if cmakeVersion == null then pkgs.cmake else (pkgs.cmake.overrideAttrs (old: { @@ -66,11 +67,12 @@ let patches = []; })).override { isMinimalBuild = true; }; in crossPkgs.mkShell { - buildInputs = [ + buildInputs = lib.optionals (capnprotoVersion != "none") [ capnproto ]; nativeBuildInputs = with pkgs; [ cmakeBuild + git include-what-you-use ninja ] ++ lib.optional (gcc != null) gcc ++ lib.optionals (!minimal) [ @@ -83,4 +85,7 @@ in crossPkgs.mkShell { # Tell IWYU where its libc++ mapping lives IWYU_MAPPING_FILE = if enableLibcxx then "${llvm.libcxx.dev}/include/c++/v1/libcxx.imp" else null; + + # Avoid "SSL certificate problem: unable to get local issuer certificate" error during git clone in ci/scripts/ci.sh + NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; }