diff --git a/doc/build-helpers/testers.chapter.md b/doc/build-helpers/testers.chapter.md index 9e46635c600c..7f7e6bd7d3e7 100644 --- a/doc/build-helpers/testers.chapter.md +++ b/doc/build-helpers/testers.chapter.md @@ -40,6 +40,26 @@ If the `moduleNames` argument is omitted, `hasPkgConfigModules` will use `meta.p ::: +## `hasCmakeConfigModules` {#tester-hasCmakeConfigModules} + +Checks whether a package exposes a given list of `*config.cmake` modules. +Note the moduleNames used in cmake find_package are case sensitive. + +:::{.example #ex-hascmakeconfigmodules} + +# Check that `*config.cmake` modules are exposed using explicit module names + +```nix +{ + passthru.tests.cmake-config = testers.hasCmakeConfigModules { + package = finalAttrs.finalPackage; + moduleNames = [ "Foo" ]; + }; +} +``` + +::: + ## `lycheeLinkCheck` {#tester-lycheeLinkCheck} Check a packaged static site's links with the [`lychee` package](https://search.nixos.org/packages?show=lychee&type=packages&query=lychee). diff --git a/doc/redirects.json b/doc/redirects.json index 4c243c6cc852..b93961666a4b 100644 --- a/doc/redirects.json +++ b/doc/redirects.json @@ -1694,6 +1694,12 @@ "ex-haspkgconfigmodules-explicitmodules": [ "index.html#ex-haspkgconfigmodules-explicitmodules" ], + "tester-hasCmakeConfigModules": [ + "index.html#tester-hasCmakeConfigModules" + ], + "ex-hascmakeconfigmodules": [ + "index.html#ex-hascmakeconfigmodules" + ], "tester-lycheeLinkCheck": [ "index.html#tester-lycheeLinkCheck" ], diff --git a/pkgs/build-support/testers/default.nix b/pkgs/build-support/testers/default.nix index b48320f7e270..3a2fcbfa4d1d 100644 --- a/pkgs/build-support/testers/default.nix +++ b/pkgs/build-support/testers/default.nix @@ -225,6 +225,8 @@ ); hasPkgConfigModules = callPackage ./hasPkgConfigModules/tester.nix { }; + hasCmakeConfigModules = callPackage ./hasCmakeConfigModules/tester.nix { }; + testMetaPkgConfig = callPackage ./testMetaPkgConfig/tester.nix { }; shellcheck = callPackage ./shellcheck/tester.nix { }; diff --git a/pkgs/build-support/testers/hasCmakeConfigModules/tester.nix b/pkgs/build-support/testers/hasCmakeConfigModules/tester.nix new file mode 100644 index 000000000000..85938ef3bf4f --- /dev/null +++ b/pkgs/build-support/testers/hasCmakeConfigModules/tester.nix @@ -0,0 +1,86 @@ +# Static arguments +{ + lib, + runCommandCC, + cmake, +}: + +# Tester arguments +{ + package, + moduleNames, + # Extra nativeBuildInputs needed to pass the cmake find_package test, e.g. pkg-config. + nativeBuildInputs ? [ ], + # buildInputs is used to help pass the cmake find_package test. + # The purpose of buildInputs here is to allow us to iteratively add + # any missing dependencies required by the *Config.cmake module + # during testing. This allows us to test and fix the CMake setup + # without rebuilding the finalPackage each time. Once all required + # packages are properly added to the finalPackage's propagateBuildInputs, + # this buildInputs should be set to an empty list []. + buildInputs ? [ ], + # Extra cmakeFlags needed to pass the cmake find_package test. + # Can be used to set verbose/debug flags. + cmakeFlags ? [ ], + testName ? "check-cmake-config-${package.pname or package.name}", + version ? package.version or null, + versionCheck ? false, +}: + +runCommandCC testName + { + inherit moduleNames versionCheck cmakeFlags; + version = if versionCheck then version else null; + nativeBuildInputs = [ + cmake + ] ++ nativeBuildInputs; + buildInputs = [ package ] ++ buildInputs; + meta = + { + description = "Test whether ${package.name} exposes cmake-config modules ${lib.concatStringsSep ", " moduleNames}"; + } + # Make sure licensing info etc is preserved, as this is a concern for e.g. cache.nixos.org, + # as hydra can't check this meta info in dependencies. + # The test itself is just Nixpkgs, with MIT license. + // builtins.intersectAttrs { + available = throw "unused"; + broken = throw "unused"; + insecure = throw "unused"; + license = throw "unused"; + maintainers = throw "unused"; + teams = throw "unused"; + platforms = throw "unused"; + unfree = throw "unused"; + unsupported = throw "unused"; + } package.meta; + } + '' + touch "$out" + notFound=0 + for moduleName in $moduleNames; do + echo "checking cmake-config module $moduleName" + + cat < CMakeLists.txt + cmake_minimum_required(VERSION 3.14) + project(CheckCmakeModule) + + find_package($moduleName $version EXACT NO_MODULE REQUIRED) + EOF + + echoCmd 'cmake flags' $cmakeFlags + set +e + cmake . $cmakeFlags + r=$? + set -e + if [[ $r = 0 ]]; then + echo "✅ cmake-config module $moduleName exists" + else + echo "❌ cmake-config module $moduleName was not found" + ((notFound+=1)) + fi + done + + if [[ $notFound -ne 0 ]]; then + exit 1 + fi + ''