How to disable clang-wrapper which adds all libraries by default?

How can I make a nix-shell where I have a clang toolchain version 17 and at the same time have
fmt available in the shell but such that the clang is not wrapped such that it automatically adds the include directory, library include directory and link flags for fmt. So I want that cmake controls what is added to compile:

I have the following:

{
  description = "Cpp Playground";

  nixConfig = {
    substituters = [
      # Add here some other mirror if needed.
      "https://cache.nixos.org/"
    ];
    extra-substituters = [
      # Nix community's cache server
      "https://nix-community.cachix.org"
    ];
    extra-trusted-public-keys = [
      "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
    ];
  };

  inputs = {
    # Nixpkgs (take the systems nixpkgs version)
    nixpkgs.url = "nixpkgs";

    # You can access packages and modules from different nixpkgs revs
    # at the same time. Here's an working example:
    nixpkgsStable.url = "github:nixos/nixpkgs/nixos-23.11";
    # Also see the 'stable-packages' overlay at 'overlays/default.nix'.
  };

  outputs = {
    self,
    nixpkgs,
    nixpkgsStable,
    flake-utils,
    ...
  } @ inputs: let
    # Supported systems for your flake packages, shell, etc.
    systems = [
      "x86_64-linux"
      "aarch64-darwin"
    ];

    # This is a function that generates an attribute by calling a function you
    # pass to it, with the correct `system` and `pkgs` as arguments.
    forAllSystems = func: nixpkgs.lib.genAttrs systems (system: func system nixpkgs.legacyPackages.${system});
  in {
    # Formatter for your nix files, available through 'nix fmt'
    # Other options beside 'alejandra' include 'nixpkgs-fmt'
    formatter = forAllSystems (system: pkgs: pkgs.alejandra);

    devShells =
      forAllSystems
      (
        system: pkgs: let
          # Some Node packages for development.
          nodePackages = pkgs.callPackage ./tools/nix/node-packages/default.nix {};

          # Toolchain.
          gccVersion = "13";
          gccPkg = pkgs."gcc${gccVersion}";
          llvmVersion = "17";
          llvmPkgs = pkgs."llvmPackages_${llvmVersion}";
          clangStdEnv = pkgs.stdenvAdapters.overrideCC llvmPkgs.stdenv (llvmPkgs.clang.override {gccForLibs = gccPkg;});

          compilerLinks = pkgs.runCommand "clang-links" {} ''
            mkdir -p $out/bin
            ln -s ${llvmPkgs.clang}/bin/clang $out/bin/clang-${llvmVersion}
            ln -s ${llvmPkgs.clang}/bin/clang++ $out/bin/clang++-${llvmVersion}
            ln -s ${llvmPkgs.llvm}/bin/llvm-as $out/bin/llvm-as-${llvmVersion}
          '';

          dependencies = with pkgs; [
            # Dependencies
            fmt
            grpc
            protobuf
          ];

          nativeBuildInputs = with pkgs; [
            cmake

            # Toolchain
            # Clangd from clang-tools must come first.
            (hiPrio clang-tools.override {
              llvmPackages = llvmPkgs;
              enableLibcxx = false;
            })
            # Do not use the clangd from this package as it does not work correctly with
            # stdlib headers.
            llvmPkgs.lld
            llvmPkgs.lldb

            # Compiler Links
            compilerLinks
          ];
        in {
          default = pkgs.mkShell.override {stdenv = clangStdEnv;} rec {
            inherit nativeBuildInputs;
            packages = dependencies;
            LD_LIBRARY_PATH = nixpkgs.lib.makeLibraryPath [gccPkg.cc.lib];
          };
        }
      );
  };
}

When I compile a simple executable with

#include <fmt/format.h>

int main() {
   fmt::print("Hello world {}", 3);
}

and a CMakeLists.txt file:

project(test)

find_package(fmt CONFIG REQUIRED)
add_executable(test "main.cpp")

# I deliberately disabled linking to `fmt`, so also headers files should not be found.
# But Nix wrapps clang which adds fmt's include dir.... (I dont want this)
# target_link_libraries(test PUBLIC fmt::fmt)

nix develop
mkdir build && cd build
cmake ..
NIX_DEBUG=1 make

One can see in the output that the wrapper adds fmt includes etc to the compile which I dont want:
Why is that and
How can I fix this?

I haven’t read details here, but you add .cc to compilers to get the unwrapped one, e.g. llvmPackages.clang.cc

Thanks: the thing I am unsure is: where do I find documentation what these funny wrappers do? They seem to do all sort of things like setting flags, runpath stuff etc etc. Are these things mainly too guarantee nixos properties and such?? I guess these wrappers (stdenv) ahould be used when building a package.

Yes. On other systems you rely on global paths like /usr/include, with Nix you automatically provide stuff to compiler through these wrappers instead.

1 Like

Some docs are in this part: Nixpkgs 23.11 manual | Nix & NixOS (and cc-wrapper follows directly).

1 Like