How to create a working LLVM-based stdEnv for C++ development?

This afternoon I unknowingly entered into the rabbit hole of creating a C++ development environment that is based in LLVM.

I quickly realized that this sounds much easier than it is.. The first hint was this Github issue:

I also made my way through this forum, and dug this out:

Endgoal

I would like:

  • A reproducible, isolated environment, where I can compile C++ applications using most of the LLVM tools (i.e. ofc. glibc is the exception, this will have to be the one that is provided by the system)
  • Be able to choose between libc++ and libstdc++, i.e. I want to really be able to switch this. If this would require two shells, that is ofc. fine as well.

Attempt

{
  description = "A LLVM-based C/C++ development environment";

  inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2411.715519.tar.gz";

  outputs = { self, nixpkgs }:
    let
      supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
      forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
        pkgs = import nixpkgs { inherit system; };
      });
    in
    {
      devShells = forEachSupportedSystem ({ pkgs }: {
        default = pkgs.mkShell.override {
          stdenv = pkgs.pkgsLLVM.stdenv;
        } {
          packages = with pkgs; [
            clang-tools
            clang
            libcxx
            libunwind
            cmake
            codespell
            conan
            ninja
            doxygen
          ] ++ (if system == "aarch64-darwin" then [ ] else [ gdb ]);
        };
      });
    };
}

What is wrong with this attempt?

(some of the below issues are fixed in the above flake, but they were problems along the way)

  • missing headers, i.e. using gcc headers instead of llvm headers
  • uses ld instead of lld
  • cannot link libc++ (or libc++abi and libunwind), e.g. library not around or not in the linkers path
  • also, I was missing llvm-ar, llvm-nm, llvm-ranlib, etc. or the wrong ones were used during a build, i.e. ar, nm, instead of the llvm version.
  • undefined references to some symbols (I was compiling a reference library, so this should not have been a configuration error, but might be related to the previous point)

Notes

1 Like

Yeah it such a rabbit hole. Here’s another working config that is free of gcc. It should meet all your needs I assume. leetcode/flake.nix at 236ff9aed530ec6886ceb12acd1ab5ea17fed97b · Congee/leetcode · GitHub

FYI we’re currently using this as an overlay:

It has some bugs (I believe libgcc_s is still in the RPATH of outputs this toolchain produces; I’m not certain whether the llvm bintools override actually works) but accomplishes the general gist of “build with clang/libc++/libunwind” and doesn’t require excessive rebuilds (of clang or llvm tooling). For libstdc++ you could potentially try to add some conditionals to differentiate between the two.

Your flake does not compile for me on my PC. I currently don’t have access to it and try to debug it tomorrow.

This works fine for me:

I can choose btw. gcc and clang environment.
The gcc or clang stdenv is passed to package.nix where stdenv.mkDerivation is called.

Hi, can you share your state now ?

1 Like

I have just spent an inordinate amount of time on this. What surprised me is that libcxx doesn’t work on the 25.11 system package. If you put llvmPackages.clangWithLibcAndBasicRtAndLibcxx in your configuration.nix packages list, this is what clang++ does by default…

$ clang++ -stdlib=libc++ hello.cpp
/nix/store/dc9vaz50jg7mibk9xvqw5dqv89cxzla3-binutils-2.44/bin/ld: cannot find -lc++: No such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Using a devShell like this solves that problem…

devShells.${system}.default = pkgs.mkShell {
  stdenv = pkgs.llvmPackages.libcxxStdenv;
  buildInputs = with pkgs.llvmPackages; [ clang libcxx lld lldb clang-tools compiler-rt ];
};

But, even after a nix develop, the environment still has this set…

CC=gcc
NIX_CC=/nix/store/vr15iyyykg9zai6fpgvhcgyw7gckl78w-gcc-wrapper-14.3.0

I have a conan project that builds protobuf, and that overrides CC to clang. All of the C code builds, but when it attempts to build protobuf, (my first C++ dependency), llvmPackage’s clang includes GCC’s c++ headers from the libcxx devShell.

/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/mutex:917:(.text+0x1e802): undefined reference to `std::__throw_system_error(int)'
/nix/store/dc9vaz50jg7mibk9xvqw5dqv89cxzla3-binutils-2.44/bin/ld: libprotobufd.a(generated_message_reflection.cc.o): in function `google::protobuf::Reflection::AddFloat(google::protobuf::Message*, google::protobuf::FieldDescriptor const*, float) const':
/nix/store/kzq78n13l8w24jn8bx4djj79k5j717f1-gcc-14.3.0/include/c++/14.3.0/mutex:843:(.text+0x1ec08): undefined reference to `std::__once_callable'

I’ve gone as far as removing gcc from my system packages to avoid this, but even that doesn’t work since it appears LLVM 21 has a GCC 14.3 depedency.

On Fedora, clang works with LLVM’s libcxx deployed to /usr/bin by default and I just use that for my direnv. What would be amazing is if NixOS had a stock devShell with some way of easily enabling lld and libcxx. Or, if clangWithLibcAndBasicRtAndLibcxx package did all of this automatically even if it was run from a system package.

I’m new to NixOS, so this could be a dumb and adjacent question, but am I using nix --eval wrong? I was attempting to verify if I was my living my life wrong with LLVM, but I see this…

$ sudo nix-channel --update
$ sudo nixos-rebuild switch
$ nix flake update
$ home-manager switch --flake .
$ exit
$ ssh nixos
$ cd myproject
$ nix develop
$ nix eval --raw nixpkgs#llvmPackages.clangWithLibcAndBasicRtAndLibcxx --output-lock-file /home/hoyhoy/.config/home-manager/flake.lock
/nix/store/ahmlf2pywvfnpr7asiv4kqg81ixjbl15-clang-wrapper-21.1.7
$ ls /nix/store/ahmlf2pywvfnpr7asiv4kqg81ixjbl15-clang-wrapper-21.1.7
ls: cannot access '/nix/store/ahmlf2pywvfnpr7asiv4kqg81ixjbl15-clang-wrapper-21.1.7': No such file or directory
$ clang --version
clang version 21.1.2
$ readlink -f $(which clang)
/nix/store/bpmq0ln49bp0iak5xlmqgib0vlywz64n-clang-wrapper-21.1.2/bin/clang

Yeah, it’s never recommended to put compilers in your NixOS config.

This is close but not right. You need to override mkShell like this:

(pkgs.mkShell.override {
  stdenv = pkgs.llvmPackages.libcxxStdenv;
}) {
  packages = with pkgs.llvmPackages; [ clang-tools lldb ];
}

Note that libcxxStdenv already includes clang, libcxx, lld, compiler-rt.

1 Like

Thanks a lot, this solves the wrapper problem…

  outputs =
    { self, nixpkgs, home-manager, ... }:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      devShells.${system}.default = pkgs.mkShell.override {
        stdenv = pkgs.llvmPackages.libcxxStdenv;
      } {
        packages = with pkgs.llvmPackages; [ clang-tools lldb lld ];
      };
  }
CC=clang
NIX_CC=/nix/store/j0h36rpw197ysbja3lqnjh46zvy38zhp-clang-wrapper-21.1.2
NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu=1

But there are still a couple of odd issues…

(1) How do I query for all the compiler binaries using the nix develop shell? nix eval reports a non-existent package when querying the flake. I’m guessing this is the latest (uninstalled) unstable 21.x version?

$ clang --version
clang version 21.1.2

$ nix eval --raw nixpkgs#llvmPackages.clangWithLibcAndBasicRtAndLibcxx --output-lock-file /home/hoyhoy/.config/home-manager/flake.lock
/nix/store/ahmlf2pywvfnpr7asiv4kqg81ixjbl15-clang-wrapper-21.1.7

(2) How do I enable compiler-rt features? For instance, lld to the package list doesn’t update the stdenv as LD=ld in the environment.

Is adding export LD=${pkgs.llvmPackages}/bin/lld to a shellHook the only way to do that? Or is there a better approach? I really want -fuse-ld=lld added to the CFLAGS and CXXFLAGS as well. On Fedora and Darwin, I just add it to the system clang.cfg and clang++.cfg…

It seems like there should be some way of enabling lld, -fsanitize=address, -fsanitize=undefined, -fsanitize=memory, and -fsanitize=thread from libcxxStdenv settings since they’re all compiler-rt settings.

Is there some way to enable the sanitizers in the nix shell using the libcxxStdenv? It looked like there is an msan instrumented libcxx as well. Is there an automated way of linking to that? I have a conan build script that does this, but I’d like to merge that into a flake if possible. What would be amazing is if I could just enable it as part of the llvm package and have the development shell automatically inject the instrumented -L flags rpath…

I’m doing this now with custom conan settings, but conan really isn’t advanced enough to do this. I have a large library of bash scripts that I use to enable different compilers at the moment. I’m testing nix to see if it’s possible to do this declaratively with a modularized flake…

address_sanitizer: [null, True]
data_flow_sanitizer: [null, True]
hwaddress_sanitizer: [null, True]
kernel_address_sanitizer: [null, True]
thread_sanitizer: [null, True]
undefined_behavior_sanitizer: [null, True]
pointer_compare_sanitizer: [null, True] # only valid with address or kernel_address
pointer_subtract_sanitizer: [null, True] # only valid with address or kernel_address
shadow_call_stack_sanitizer: [null, True]
leak_sanitizer: [null, True]
stack_protector: [null, True]
stack_check: [null, True]

I guess the MSAN-instrumented libcxx isn’t available on Fedora 43. I forgot I compiled it myself. It’d be amazing to bring this into the stock NixOS llvmPackage with an enable flag.

This sounds like the nixpkgs in your Flake is older than the one on your system.

No, I just remembered that libcxxStdenv only provides a few things. If you want it to be a pure LLVM environment, replace libcxxStdenv with overrideCC stdenv llvmPackages.clangUseLLVM.

I have nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; in my flake.nix and system.stateVersion = "25.11"; in my /etc/configuration.nix. Is 21.1.7 the latest 25.11 LLVM release? Or is that unstable?

It’d be really useful if there was some way to pull all of the llvm binaries out of the stdenv in a unified way. From devShell bash, the only way I could query the LLVM_ROOT is with llvm_root=$(dirname "$(dirname "$(realpath "$(which clang)")")"). I tried using llvm’s llvm-config, but that doesn’t work either since llvm root is different than clang’s root.

Trying this now. With every other platfrom, I just pass back the LLVM_ROOT and derive the binary locations from there. NixOS is tricky because the llvm binaries, clang binaries and libcxx binaries are all in different locations.

The other problem I hit was during linking, the rpath wasn’t being set for libcxx. So, the binaries would all fail with could not load libc++.so.1. I have internal conan tooling for overriding libcxx since MSAN requires an instrumented version. On every other LLVM deployment I’ve ever used, clang automatically configures the libcxx path, but typically libcxx exists in ${CMAKE_INSTALL_PATH}/lib.

The good news is – I was able to build our monster project using this flake. The bad news is – our tests deadlock attempting to open a log file.

MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7dada6de0000
mmap(0x7dbba6de0000, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7dbba6de0000
futex(0x7f2da7ff30a0, FUTEX_WAIT_PRIVATE, 2, NULL

These cxxtests are very, very old and run on aix-ppc64, linux-armv8 (Asahi, RHEL10), linux-ppc64le, linux-s390x (RHEL8), macos-armv8, macos-x86_64, windows-x86_64 (25H2), solaris-sparc, solaris-x86_64, hpux-itanium, linux-x86_64 (Debian, Void, Fedora, Asahi, RHEL (6 to 10)).

Unfortunately, the tests immediately deadlock on NixOS with LLVM binaries.

I have several processes attempting to open a common XML log file using a C++ ofstream…

std::ofstream ofs("cxxtest.xml", std::ofstream::out);

This ofstream deadlocks forever in the new call..

21.1.2 is 25.11, 21.1.7 is 26.05.

From what I remember, a lot should be exposed via the CC wrapper & stdenv already or else things like linking, C++, and compiler-rt wouldn’t work.

Yeah, we split LLVM up (and are working on doing that to GCC as well) since not everything needs all of LLVM. Wouldn’t make sense to have lld when you only need libLLVM.

That is strange

I figured out the deadlock. My cmake was defining the symbolizer to be ${C_COMPILER_PATH}/llvm-symbolizer and that caused LLVM ASAN instrumentation to deadlock.

I had to use the outPath from the llvm package for the path symbolizer instead of the path to clang. There doesn’t seem to be a normal cmake-way of doing this. A few people in the cmake forums were using CMAKE_ADDR2LINE, but that’s not a standard…

    -DCMAKE_C_COMPILER:FILEPATH=${CC}
    -DCMAKE_CXX_COMPILER:FILEPATH=${CXX}
    -DCMAKE_RANLIB:FILEPATH=${RANLIB}
    -DCMAKE_AR:FILEPATH=${AR}
    -DCMAKE_ASM_COMPILER:FILEPATH=${CC}
    -DCMAKE_LINKER:FILEPATH=${LD}
    -DCMAKE_NM:FILEPATH=${NM}
    -DCMAKE_LIPO:FILEPATH=${LIPO}
    -DCMAKE_OBJCOPY:FILEPATH=${OBJCOPY}
    -DCMAKE_OBJDUMP:FILEPATH=${OBJDUMP}
    -DCMAKE_STRIP:FILEPATH=${STRIP}
    -DCMAKE_READELF:FILEPATH=${READELF}
    # I never set addr2line before since it's not really a build input...
    # My sanitizer tooling needs it to set the defaults for each binary.
    # On _most_ llvm deployments (except Xcode's AppleClang),
    # `llvm-symbolizer` exists in llvm's `${CMAKE_INSTALL_PATH}/bin`.

    -DCMAKE_ADDR2LINE:FILEPATH=${ADDR2LINE}

I had to nixos-ify our find_program() cmake to override the symbolizer path location because previously I assumed it would be in the same path as the compiler itself.

function(configure_c_compiler)
    if (NOT UNIX)
        # only used for debug instrumentation on POSIX platforms
        return()
    endif ()

    get_filename_component(c_compiler_path ${CMAKE_C_COMPILER} DIRECTORY)

    if (c_compiler_path)
        message(STATUS "c_compiler_path=${c_compiler_path}")
    else ()
        message(STATUS "Could not find C compiler.  This shouldn't happen.")
    endif ()

    set(C_COMPILER_PATH "${c_compiler_path}" CACHE FILEPATH "Location of C compiler")

    if (CMAKE_ADDR2LINE AND EXISTS "${CMAKE_ADDR2LINE}")
        set(addr2line_program "${CMAKE_ADDR2LINE}")
    else ()
        set(llvm_symbolizer "${c_compiler_path}/llvm-symbolizer")

        find_program(addr2line_program PATHS "${c_compiler_path}" NAMES addr2line OPTIONAL)

        if (CMAKE_C_COMPILER_ID MATCHES Clang AND EXISTS "${llvm_symbolizer}")
            set(addr2line_program "${llvm_symbolizer}")
        elseif (addr2line_program)
            set(addr2line_program "${addr2line_program}")
        else ()
            message(STATUS "Could not find addr2line.")
        endif()
    endif ()

    if (EXISTS "${addr2line_program}")
        message(STATUS "Found addr2line=${addr2line_program}")
        set(CMAKE_ADDR2LINE "${addr2line_program}" CACHE FILEPATH "Location of addr2line (llvm-symbolizer for Clang)")
    endif ()

endfunction ()

Now, the latest tragedy running the binaries…

Your application is linked against incompatible ASan runtimes

ldd seems ok… Maybe the compiler-rt library path needs to be in the binary rpath…

linux-vdso.so.1 (0x00007f43bb707000)
        libm.so.6 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/libm.so.6 (0x00007f43b8318000)
        libdl.so.2 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/libdl.so.2 (0x00007f43bb6fa000)
        librt.so.1 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/librt.so.1 (0x00007f43bb6f5000)
        libpthread.so.0 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/libpthread.so.0 (0x00007f43bb6ee000)
        libc++.so.1 => /nix/store/i4si6cf5icjxfnphzrd769nf8jkypiz9-libcxx-21.1.2/lib/libc++.so.1 (0x00007f43b81fc000)
        libc++abi.so.1 => /nix/store/i4si6cf5icjxfnphzrd769nf8jkypiz9-libcxx-21.1.2/lib/libc++abi.so.1 (0x00007f43b81b2000)
        libresolv.so.2 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/libresolv.so.2 (0x00007f43b819f000)
        libunwind.so.1 => /nix/store/hi4davhj0sipk1dm6np5syk9r8sjn1cp-libunwind-21.1.2/lib/libunwind.so.1 (0x00007f43b8190000)
        libc.so.6 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/libc.so.6 (0x00007f43b7e00000)
        /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib/ld-linux-x86-64.so.2 => /nix/store/xx7cm72qy2c0643cm1ipngd87aqwkcdp-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 (0x00007f43bb709000)
        libatomic.so.1 => /nix/store/xm08aqdd7pxcdhm0ak6aqb1v7hw5q6ri-gcc-14.3.0-lib/lib/libatomic.so.1 (0x00007f43b8184000)
        libgcc_s.so.1 => /nix/store/xm08aqdd7pxcdhm0ak6aqb1v7hw5q6ri-gcc-14.3.0-lib/lib/libgcc_s.so.1 (0x00007f43b8156000)

strace reports this, which seems like it should be OK..

openat(AT_FDCWD, "/nix/store/wp328h9diq2ybqyml065qyflwzx14iry-clang-wrapper-21.1.2/resource-root/lib/linux/libclang_rt.asan-x86_64.so", O_RDONLY|O_CLOEXEC) = 10

compiler-rt is static so it will not show up. It’s something you do not want to have dynamically linked.

It could be if the llvm stdenv specified -static-libasan. Probably wouldn’t matter for me anyway since conan would likely remove all of the nix flags…

Future note… It did matter for me. Even setting -static-libasan and recompiling my dependency chain, libclang_rt.asan-x86_64.so was still loaded at runtime and not statically linked to libclang_rt.asan-x86_64.a.

I ended up generating these in my conan jinja2 profile for conan and it seems to have worked…


{# The path to libc++.so #}
{% set llvm_lib_dir = platform.os.getenv("LLVM_LIB", default=(llvm_root ~ "/lib")) %}

{# The path to libclang_rt.asan-x86_64.so  #}
{% set llvm_compiler_rt_lib_dir = platform.os.getenv("LLVM_COMPILER_RT_LIB", default=None) %}

{% if is_nix_os %}
  {% set _ = compiler.ldflags.append("-Wl,-rpath," ~ llvm_lib_dir) %}
  {% set _ = compiler.flags.append("-shared-asan") %}
  {% set _ = compiler.ldflags.append("-Wl,-rpath," ~ llvm_compiler_rt_lib_dir) %}
  {% set _ = compiler.flags.append("-Wl,--no-as-needed") %}
{% endif %}

My devshell looks like this now…

{
  description = "Conan Build Flake";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
  };

  outputs = { self, nixpkgs, ... }:
  let
    system = "x86_64-linux";
    pkgs = nixpkgs.legacyPackages.${system};

    devPackages = with pkgs; [
      automake
      autoconf
      conan
      ccache
      cmake
      gperf
      gnumake
      libtool
      nasm
      m4
      perl
      python3
      ruby_3_4
      stdenv
    ];

    buildStdenv = with pkgs; overrideCC stdenv pkgs.llvmPackages.clangUseLLVM;
  in {
    devShells.${system}.default = pkgs.mkShell.override { 
      stdenv = buildStdenv;
    }
    {
      packages = with pkgs.llvmPackages; [
        bintools
        clang-tools
        lldb
        lld
        llvm
      ] ++ devPackages;

      NIX_ENFORCE_NO_NATIVE = false;
      LLVM_LIB = "${pkgs.llvmPackages.libcxx}/lib";
      LLVM_COMPILER_RT_LIB = "${pkgs.llvmPackages.compiler-rt}/lib/linux";
    };
  };
}

The only thing not working is my shellHook. Doesn’t seem to be sourcing this into my devShell environment. Maybe needs an eval…

Solved the ASAN mismatch error. I had to compile all of my conan dependencies with the new linker flags via the mentioned cmake fixes and manually configuring the output binaries’ the rpaths to {pkgs.llvmPackages.libcxx}/lib" and ${pkgs.llvmPackages.compiler-rt}/lib/linux.

Still can’t figure out how to make a shellHook run after the devShell environment is loaded. My script relies on the paths being set. It doesn’t seem possible – postShellHook and userHook didn’t work either. This is sort of temporary until I port my bash script over to nix which is the better way to do it. Am I missing something?

Here’s the cross-platform j2 conan configuration that configures a conan build with using nixos devShell from the flake…

The asan library is shared. So, the rpath must be set either by devShell or manually. I attempted setting -static-libasan, but LLVM was still loading the dynamic libclang_rt.asan-x86_64.so.

Switching to LDFAGS="-shared-libasan -Wl,--no-as-needed" and fixing the cmake link specification is what solved the Your application is linked against incompatible ASan runtimes errors.

{% set in_nix_shell = os.getenv("IN_NIX_SHELL") is not none %}
{% set is_nix_os = os.getenv("ID") == "nixos" %}
{% set is_nix = in_nix_shell or is_nix_os %}

{# LLVM libcxx and compiler-rt sanitizers configuration #}
{% if current_os == "Macos" and not is_xcode %}
  {# At some point, darwin will use the LLVM_TRIPLE here... #}
  {% set compiler.lib_dirs = [ llvm_lib_dir , llvm_lib_dir ~ "/darwin" ] %}
{% elif is_nix_os %}
  {% set llvm_compiler_rt_lib_dir = platform.os.getenv("LLVM_COMPILER_RT_ROOT", default=None) %}

  {% if llvm_compiler_rt_lib_dir is none %}
    {{ 0/0 }}
  {% endif %}
  
  {% set llvm_compiler_rt_lib_path = llvm_compiler_rt_lib_dir ~ "/lib/linux" %}

  {% set _ = compiler.ldflags.extend( [ 
    "-fuse-ld=lld",
    "-Wl,-rpath," ~ llvm_lib_dir,
    "-L" ~ llvm_lib_dir,
    "-Wl,-rpath," ~ llvm_compiler_rt_lib_path,
    "-L" ~ llvm_compiler_rt_lib_path,
    "-shared-libasan",
    "-Wl,--no-as-needed"
  ] ) %}

  {% set _ = compiler.flags.extend([ "-shared-libasan", "-fuse-ld=lld" ]) %}
  {% set compiler.lib_dirs = [ llvm_lib_dir, llvm_compiler_rt_lib_path ] %}
{% elif current_os == "Linux" %}
  {% set compiler.lib_dirs = [ llvm_lib_dir ~ "/" ~ llvm_triple ] %}
{% endif %}
{# conan jina2 profile setup #}

{% set _ = profile.build_configuration.update(
  {
    "tools.build:compiler_executables": { "c" : compiler.cc, "cpp": compiler.cxx },
    "tools.build:defines": compiler.definitions,
    "tools.build:cflags": compiler.dependency_options.flags,
    "tools.build:cxxflags": compiler.dependency_options.flags,
    "tools.build:exelinkflags": compiler.ldflags,
    "tools.build:sharedlinkflags": compiler.ldflags
  })
%}

This caused an issue as well… Ancient cmake syntax that overwrote the conan/nix linker options…

set_target_properties(mylib PROPERTIES LINK_FLAGS "-Wl,-rpath,'$ORIGIN'")
set_target_properties(build PROPERTIES SKIP_BUILD_RPATH TRUE)

Should have been this:

target_link_options(mylib PRIVATE "-Wl,-rpath,$ORIGIN")

I suppressed the SKIP_BUILD_RPATH call for my debug build, but left it for release mode.

G’day,

Thanks for the thread guys

I’ve also been trying to get a relatively complex ( well, at least to me ) project Nix-ified, with both gcc and clang stuff ( xdp2 project )

Part of the challenge is that while there is some great documentation, there are many different versions of packages. These names probably make sense to some people, and I’m sure those more familiar think it’s obvious, but I’ve certainly struggled.

For example, if you search for the llvm package, there are MANY packages:

Things seem to get most hairy with the order of definition, which are mutually exclusive, and these sorts of combinatorial possibilities.

What’s the difference? = I can vaguely guess

What order should they be included in?

Which ones can’t be combined without trying to build and it blowing up?

It would be amazing to have:

  1. Overview document with the design intention. This doc would explain how and why the packages are categorized and split up the way they are

  2. For each package, to have more detailed explanation

Maybe this already exists somewhere more upstream in the clang, although I suspect people who have been dealing with for years “just know”

… Sorry, it this sounds ungrateful. I’ve recently successfully packaged up Apache Traffic Server 10, and Performance Co Pilot, and these where both relatively straight forward and great! … The main discovery has been Nix mostly does “the right thing” which is awesome. But when things are segfault-ing and you’re trying to understand why, it’s a bit confusing :pray: