rules_foreign_cc
rules_foreign_cc copied to clipboard
Cmake uses C++ compilation flags for linking
There's an issue that affects some CMake projects, nameli X265 and AOM, that is that they use the C++ compiler for linking, which means they also pick up all CXX_FLAGS from the crosstool file. When the CC toolchain configures CXX_FLAGS
to include -x c++
, this gets passed to the toolchain config as CMAKE_CXX_FLAGS_INIT
, which ends up being used in the link step too, as described in the relevant CMake documentation.
The issue here seems to be that in Bazel, CXX_FLAGS
are meant for compilation only, and not for linking, and thus passing them on to the toolchain file as CMAKE_CXX_FLAGS_INIT
isn't the right thing to do probably.
I could work around this issue by modifying @rules_foreign_cc
to instead pass the compile flags using add_compile_options
, but I was doing that manually for this single flag, and I had to also remove it from the CMAKE_CXX_FLAGS_INIT
:
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-xc++>)
There should be a better way to specify compile flags and link flags, by translating the Bazel toolchain info to the appropriate options in the toolchain file, rather than setting these INIT flags that end up being used for both compilation and linking. In general, the toolchain file should be constructed somehow… in a better way, but I'm not sure how or what is the right mapping from Bazel toolchain info values to CMake options.
For the case of -xc++
this simple workaround is sufficient, but it would be better to come up with a more complete solution. I'd be happy to contribute this if someone could help figure out what's the right mapping from Bazel features to CMake options.
There's some more detail in https://github.com/tweag/rules_nixpkgs/discussions/467.
I think for the case of passing in -x c++
we should really be creating a compiler wrapper that we use to pass to CMake as the CXX compiler; I think that such a wrapper would solve a few of these kinds of problems, but I'm not exactly sure what that wrapper's logic looks like but it would then have access to the full set of features that are configured in the bazel toolchain and so pick the appropriate flags based on whether its being used as a linker or for compilation (how you detect that is probably very subtle though!)
Yeah I was thinking something like that too, but indeed detecting whether it is being invoked as a compiler or as a linker could be brittle, most of the time the only difference in the command line seems to be the input filename extensions.
Alternatively, we could specify our own custom linker flags, something that is then picked up by the wrapper script and removed before invoking the underlying linker.