Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

# file: 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:

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:

conan profile show

To the conan.profiles.default.settings.build_type and conan.profiles.default.settings."compiler.cppstd" options correspond, respectivelly, 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/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/bin/clang', 'cpp': '/nix/store/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/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/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/bin/clang', 'cpp': '/nix/store/va889lnfilh11sjb1rcnrdvp813jpg03-clang-wrapper-21.1.8/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:

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.