NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
17.63k stars 13.78k forks source link

CMake generates incorrect compilation database with missing include path. #104622

Open trivialfis opened 3 years ago

trivialfis commented 3 years ago

Issue description

With the cmake parameter -DCMAKE_EXPORT_COMPILE_COMMANDS=ON, cmake should generate a compilation database consumed by clang tooling. The compilation database should contain all necessary include paths.

Steps to reproduce

Using boost as a dependency for illustration: nix-shell -p cmake boost --pure

CMakeLists.txt

add_executable(main main.cc)
find_package(Boost 1.56 REQUIRED COMPONENTS filesystem)
target_link_libraries(main Boost::filesystem)

The generated compilation database does not contain any include path:

[
{
  "directory": "/home/jiaming/Workspace/NixIssues/CMake/nbuild",
  "command": "/nix/store/ppfvi0cfcpdr83klw5kx6si2l260n1gh-gcc-wrapper-9.3.0/bin/g++    -o CMakeFiles/main.dir/main.o -c /home/jiaming/Workspace/NixIssues/CMake/main.cc",
  "file": "/home/jiaming/Workspace/NixIssues/CMake/main.cc"
}
]

Technical details

 - system: `"x86_64-linux"`
 - host os: `Linux 5.8.0-28-generic, Ubuntu, 20.10 (Groovy Gorilla)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3.8`
 - channels(root): `"nixpkgs-21.03pre251181.dd1b7e377f6"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixpkgs`
knedlsepp commented 3 years ago

I think the gcc wrapper is biting us here. If you unset the following everything should work fine.

unset NIX_CFLAGS_COMPILE_FOR_TARGET
unset NIX_CFLAGS_COMPILE
unset NIX_LDFLAGS
unset NIX_LDFLAGS_FOR_TARGET
bjornfor commented 3 years ago

IMHO, cmake is also biting us.

cmake probes the compiler and populates a list of include paths (and library paths) that the compiler knows about. Because the nixpkgs gcc wrapper feeds -isystem dir flags to the unwrapped gcc, for every dir in buildInputs, cmake knows the compiler will always find those paths and will not pass those dirs to the compiler at build time.

Ref. https://stackoverflow.com/a/58589570 and direct link to cmake bug: https://gitlab.kitware.com/cmake/cmake/-/issues/17966.

From the above link(s), it seems this is an alternative workaround for the cmake side:

unset(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES)
unset(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)

I wonder if there is a way for us to use something else than -isystem dir, something with "lower priority" so that cmake doesn't put those include paths on its ignore list (e.g. CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES). CPATH maybe?

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

kotatsuyaki commented 5 months ago

Still an issue.