Skip to content

LLVM

The way LLVM is packaged in Nix is an example of the stdenv pattern described in the previous chapter. To integrate with the LLVM compiler infrastructure, there is a pkgs.llvmPackages.libcxxStdenv derivation — however this will not provide a pure llvm stdenv in which all dependencies come from the LLVM project and none from GCC.1 A different approach would be something like this:

stdenv = pkgs.overrideCC
(
pkgs.llvmPackages.libcxxStdenv.override {
targetPlatform.useLLVM = true;
targetPlatform.linker = "lld";
}
)
pkgs.llvmPackages.clangUseLLVM

That stdenv is what the stdenv option is given, and the devShell conan-flake computes from it can then be appended to an inputsFrom option for composition:

examples/llvm-flake-parts/flake.nix
{
outputs = inputs@{ nixpkgs, flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = nixpkgs.lib.systems.flakeExposed;
imports = [
inputs.conan-flake.flakeModule
];
perSystem = { pkgs, config, ... }:
{
conan = {
profiles.default = {
settings = {
build_type = "Release";
"compiler.cppstd" = "23";
};
};
stdenv = pkgs.overrideCC
(
pkgs.llvmPackages.libcxxStdenv.override {
targetPlatform.useLLVM = true;
targetPlatform.linker = "lld";
}
)
pkgs.llvmPackages.clangUseLLVM;
};
devShells.default = pkgs.mkShell {
inputsFrom = [
config.conan.outputs.devShell
];
};
};
};
}

The above example is on the examples/llvm-flake-parts directory:

Terminal window
cd examples/llvm-flake-parts
direnv allow .

By default, conan-flake sets defaults.profiles.settings."compiler.libcxx" to "libstdc++11", which would result in the wrong choice for compiler.libcxx — with the LLVM stdenv above it is detected as libc++ instead:

Terminal window
conan profile show

To the conan.profiles.default.settings.build_type and conan.profiles.default.settings."compiler.cppstd" attributes correspond, respectively, the build_type and compiler.cppstd entries in the command output:

Host profile:
[settings]
arch=x86_64
build_type=Release
compiler=clang
compiler.cppstd=23
compiler.libcxx=libc++
compiler.version=21.1.8
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]
tools.build:compiler_executables={'c': '/nix/store/clang-wrapper/bin/clang', 'cpp': '/nix/store/clang-wrapper/bin/clang++'}
Build profile:
[settings]
arch=x86_64
build_type=Release
compiler=clang
compiler.cppstd=23
compiler.libcxx=libc++
compiler.version=21.1.8
os=Linux
[platform_tool_requires]
cmake/4.3.4
[conf]
tools.build:compiler_executables={'c': '/nix/store/clang-wrapper/bin/clang', 'cpp': '/nix/store/clang-wrapper/bin/clang++'}

The package defined in the examples/llvm-flake-parts/conanfile.py recipe — example/0.0.1 — can be created in order to validate these settings:

Terminal window
conan create . --build=missing

Lines from its output correspond to entries from the Conan profile and, ultimately, to the conan-flake options:

hello-conan: Hello World Release!
hello-conan: __x86_64__ defined
hello-conan: __cplusplus202302
hello-conan: __GNUC__4
hello-conan: __GNUC_MINOR__2
hello-conan: __clang_major__21
hello-conan: __clang_minor__1
example/0.0.1 test_package
  1. See this question, or this issue, for further details on how to create a LLVM-based stdenv for C++ development.