nix-cmake now uses CMake 4.2.1, which brings several features that are valuable for our dependency management and CPS integration goals.
What changed:
- File API codemodel version updated to 2.9
- Imported targets now included in codemodel responses
- All interface library targets included (not just build participants)
- New fields:
imported,local,abstract,codemodelVersion - New dependency tracking:
linkLibraries,interfaceLinkLibraries,compileDependencies, etc.
Why this matters for nix-cmake:
This is huge for our dependency analysis and lock file generation!
# We can now introspect imported targets from the file API
cmake2nix.lib.analyzeDependencies = { buildDir }: let
codemodel = builtins.fromJSON (
builtins.readFile "${buildDir}/.cmake/api/v1/reply/codemodel-v2.9.json"
);
in {
# Extract ALL dependencies, including imported ones
importedTargets = lib.filter (t: t.imported) codemodel.configurations.0.targets;
# Get transitive link dependencies
linkGraph = lib.map (t: {
name = t.name;
links = t.linkLibraries;
interfaceLinks = t.interfaceLinkLibraries;
}) codemodel.configurations.0.targets;
};Use cases:
- Lock file generation - Parse project after configure, extract all FetchContent/CPM deps
- Dependency graph visualization - Build complete dep graphs including transitive deps
- CPS generation - Convert CMake targets to CPS format automatically
- Validation - Verify our dependency provider hooked all expected deps
New target object fields:
linkLibraries- Direct link dependenciesinterfaceLinkLibraries- Interface (header-only) dependenciescompileDependencies- Compile-time dependenciesinterfaceCompileDependencies- Interface compile dependenciesobjectDependencies- Object file dependenciesorderDependencies- Build ordering dependencies
Why this matters:
Perfect for transitive dependency resolution in CPS integration:
// Generated CPS file can now include accurate dependency info
{
"name": "mylib",
"components": {
"mylib": {
"type": "dylib",
"requires": ["fmt", "spdlog"], // from linkLibraries
"compile_requires": ["boost"] // from compileDependencies
}
}
}What changed:
- Simple toolchain file support for Emscripten
- Aligns with our toolchain hook patterns
Why this matters:
Shows CMake is moving toward simpler, declarative toolchain files - validates our cmakeToolchainHook approach.
What changed:
cmake_language(TRACE ENABLE) # Enable tracing
# ... code to trace ...
cmake_language(TRACE DISABLE) # Disable tracingWhy this matters:
Could be useful for debugging our dependency provider hook:
# In cmakeBuildHook.cmake
if(DEFINED ENV{NIX_CMAKE_DEBUG})
cmake_language(TRACE ENABLE)
endif()
macro(nix_dependency_provider method)
# ... our hook logic ...
endmacro()
cmake_language(SET_DEPENDENCY_PROVIDER nix_dependency_provider ...)What changed:
- All find modules now provide
<PackageName>_VERSION(consistent casing) - Deprecates variants like
<PACKAGENAME>_VERSIONand<PackageName>_VERSION_STRING
Why this matters:
Standardization for our parsers and CPS generation:
# Parse find_package results consistently
cmake2nix.lib.extractFoundPackages = { buildDir }:
# All packages now have consistent Foo_VERSION format
# No more guessing FooBar_VERSION vs FOOBAR_VERSION vs FooBar_VERSION_STRINGNew in 4.2:
$<TARGET_FILE_BASE_NAME:tgt POSTFIX>
$<TARGET_IMPORT_FILE_BASE_NAME:tgt POSTFIX>
# ... etcWhy this matters:
Helps with multi-output package generation and CPS file creation:
# Generate accurate CPS component locations
component.location = "@prefix@/lib/lib${baseNameWithPostfix}.so";What changed:
$<TARGET_INTERMEDIATE_DIR:tgt>
# Refers to target's intermediate files directoryWhy this matters:
Useful for build introspection and understanding CMake's internal build structure for advanced features.
The foundation for CPS integration!
set(CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES "e82e467b-f997-4464-8ace-b00808fff261")
find_package(fmt REQUIRED) # Can now find .cps files!Already documented in CPS-INTEGRATION.md.
The cmake_language(SET_DEPENDENCY_PROVIDER) we're using was stabilized across 4.0-4.2 releases with better error handling and edge case support.
New command for pkg-config integration:
cmake_pkg_config(IMPORT libfoo) # Import pkg-config packagePotential synergy with nix-cmake:
We could generate both CPS files and pkg-config .pc files from our package metadata:
cmake2nix.lib.generatePackageMetadata = { name, version, ... }: {
cps = generateCPS { inherit name version; };
pkgconfig = generatePkgConfig { inherit name version; };
};Useful for our test suite - ensure no warnings in our generated builds.
File API enhancements enable:
- Better testing of our hooks (validate all deps were intercepted)
- Dependency graph extraction for visualization
- Lock file generation without parsing CMakeLists.txt
Link dependency tracking enables:
- Accurate CPS file generation
- Transitive dependency resolution
- Better lock file format (include compile vs link deps)
CPS support (4.0+) + enhanced codemodel (4.2) enables:
- Full CPS integration as primary dependency mechanism
- Automatic conversion: CMake targets → CPS files
- Tool-agnostic package metadata
CMake 4.0-4.2 introduced several new policies. Our hooks should set appropriate cmake_minimum_required() or cmake_policy() versions:
# In cmakeBuildHook.cmake
cmake_minimum_required(VERSION 3.24...4.2)
# Ensures we get 4.2 behavior when available, but work with 3.24+-
Visual Studio 14 2015 and 15 2017 deprecated (4.0)
- Not relevant for Nix (we don't use VS generators)
-
Compatibility with CMake < 3.5 removed (4.0)
- Also not relevant - we already require 3.24+ for dependency providers
# Test: Validate our hooks intercepted all dependencies
cmake2nix.tests.validateInterception = stdenv.mkDerivation {
# ... build with our hooks ...
checkPhase = ''
# Use CMake 4.2 file API to extract dependency info
cmake -B build --graphviz=deps.dot
# Parse codemodel v2.9
codemodel="build/.cmake/api/v1/reply/codemodel-v2.json"
# Verify all expected deps are marked as imported
if ! jq '.configurations[0].targets[] | select(.imported) | .name' "$codemodel" | \
grep -q "fmt"; then
echo "ERROR: fmt not found in imported targets"
exit 1
fi
'';
};# Test: Generate CPS from CMake target
cmake2nix.tests.cpsGeneration = runCommand "test-cps-gen" {} ''
# Configure CMake project
cmake -S ${./test-project} -B build \
-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES="e82e467b-f997-4464-8ace-b00808fff261"
# Extract codemodel
codemodel="build/.cmake/api/v1/reply/codemodel-v2.json"
# Generate CPS from target info
${cmake2nix}/bin/cmake2nix generate-cps \
--from-codemodel "$codemodel" \
--target mylib \
--output $out/mylib.cps
# Validate CPS schema
${cps-validator}/bin/cps-validate $out/mylib.cps
'';Add new functions leveraging CMake 4.2:
cmake2nix.lib.introspection = {
# Extract dependency graph from file API v2.9
extractDependencyGraph = { buildDir }: ...;
# Generate CPS from CMake codemodel
codemodelToCPS = { codemodel, target }: ...;
# Validate our hooks intercepted all deps
validateInterception = { buildDir, expectedDeps }: ...;
};Update Phase 3 (Parsing) to note we can now use file API instead of parsing CMakeLists.txt:
Alternative approach:
- Configure project with CMake (let it fail if deps missing)
- Parse file API codemodel v2.9
- Extract all imported targets
- Generate lock file from that
Pros:
- No CMake language parser needed!
- Guaranteed accuracy (CMake did the parsing)
- Includes transitive deps
Cons:
- Requires partial build (even if it fails)
- Can't generate lock file without CMake
CMake 4.2 gives us exactly the tools we need to build a robust, standards-based dependency manager:
- ✅ File API v2.9 - Introspect all dependencies including imported targets
- ✅ Link dependency tracking - Build accurate transitive dependency graphs
- ✅ CPS support - Foundation for tool-agnostic package metadata
- ✅ Improved standardization - Consistent APIs across find modules
This validates our design direction and gives us multiple implementation paths forward. We can choose between:
- Path A: Parse CMakeLists.txt → generate lock file (more upfront work)
- Path B: Configure → parse file API → generate lock file (simpler, leverages CMake 4.2)
- Path C: Hybrid - parse for discovery, file API for validation
Recommendation: Path B or C - leverage CMake 4.2's excellent introspection capabilities.