Skip to content

GCC can't find libstdc++ headers when cross-compiling back to same platform #264865

@lilyball

Description

@lilyball

Describe the bug

When cross-compiling back to the same platform, such as with pkgsLLVM.buildPackages.gcc, GCC can't find its own libstdc++ headers. If I look at pkgsLLVM.buildPackages.gcc.cc the include/ folder is empty and the libstdc++ headers are instead found in x86_64-unknown-linux-gnu/include/c++/12.3.0/. However, GCC doesn't actually look there. If I ask GCC to print its include paths with echo | result/bin/x86_64-unknown-linux-gnu-g++ -xc++ -E -v - it says

ignoring nonexistent directory "/nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../include/c++/12.3.0"
ignoring nonexistent directory "/nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../include/c++/12.3.0/x86_64-unknown-linux-gnu"
ignoring nonexistent directory "/nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../include/c++/12.3.0/backward"
#include "..." search starts here:
#include <...> search starts here:
 /nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/include
 /nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/include
 /nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/include-fixed
 /nix/store/5wpf3nsdgdqfg2kxwb605sjc4gjqxi1h-x86_64-unknown-linux-gnu-stage-final-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../x86_64-unknown-linux-gnu/include
 /nix/store/c35ndrdaral7brqky6nrgkyni6aic5ar-glibc-x86_64-unknown-linux-gnu-2.37-8-dev/include
End of search list.

When I compare this with a non-cross-compiled gcc the headers are all in include/c++/12.3.0/ and the same command prints

ignoring nonexistent directory "/nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../include/c++/12.3.0
 /nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../include/c++/12.3.0/x86_64-unknown-linux-gnu
 /nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/../../../../include/c++/12.3.0/backward
 /nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/include
 /nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/include
 /nix/store/n8dryz4xf7ln028j37zapgzg4j47p743-gcc-12.3.0/lib/gcc/x86_64-unknown-linux-gnu/12.3.0/include-fixed
 /nix/store/4lap45ifj50lp980id60fnbvs81yj9lr-glibc-2.37-8-dev/include
End of search list.

Steps To Reproduce

Working example:

echo '#include <iostream>' | nix shell nixpkgs/5ba549eafcf3e33405e5f66decd1a72356632b96#gcc.cc -c x86_64-unknown-linux-gnu-g++ -xc++ -E -

That should print the contents of the iostream header.

Broken example:

echo '#include <iostream>' | nix shell nixpkgs/5ba549eafcf3e33405e5f66decd1a72356632b96#pkgsLLVM.buildPackages.gcc.cc -c x86_64-unknown-linux-gnu-g++ -xc++ -E -

This produces the following:

# 0 "<stdin>"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/nix/store/c35ndrdaral7brqky6nrgkyni6aic5ar-glibc-x86_64-unknown-linux-gnu-2.37-8-dev/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "<stdin>"
<stdin>:1:10: fatal error: iostream: No such file or directory
compilation terminated.

Additional context

I don't know if the problem is that the headers are in the wrong place, or if GCC is looking in the wrong place. It seems reasonable for GCC to conclude that because the target platform config matches the host platform config that it doesn't need the target-prefixed path, but I haven't managed to find any code on the Nix side that moves the includes so I think the GCC build process is putting them there and then forgetting about it.

My example here uses pkgsLLVM for convenience, but in my actual code I'm using cross-compiling with a different dummy crossSystem key in order to replace glibc using crossOverlays.

Notify maintainers

@Synthetica9 @vcunat @Ericson2314

Metadata

Please run nix-shell -p nix-info --run "nix-info -m" and paste the result.

nix run nixpkgs#nix-info -- -m
 - system: `"x86_64-linux"`
 - host os: `Linux 6.1.51, NixOS, 23.11 (Tapir), 23.11.20230919.5ba549e`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.17.0`
 - nixpkgs: `/etc/nix/inputs/nixpkgs`

Metadata

Metadata

Assignees

No one assigned

    Labels

    0.kind: bugSomething is broken6.topic: cross-compilationBuilding packages on a different platform than they will be used on
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions