bazel: cxx_builtin_include_directory doesn't work with non-absolute path

Description of the problem / feature request:

I’m trying to use gcc cross-compiler as external dependency, when I’m specifying cxx_builtin_include_directory as external/cross_toolchain/... or %package(@cross_toolchain//...) I’m getting error:

 '/private/var/tmp/_bazel_ilya/d86e0e7cfe53385dc3edff3c0d9662b6/external/cross_toolchain/lib/gcc/x86_64-unknown-linux-gnu/7.3.0/include/stddef.h'
 '/private/var/tmp/_bazel_ilya/d86e0e7cfe53385dc3edff3c0d9662b6/external/cross_toolchain/lib/gcc/x86_64-unknown-linux-gnu/7.3.0/include/stdarg.h'

It works only if you specify absolute path to include directory.

Bugs: what’s the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

You can find minimal example here: https://github.com/ipolyakovskiy/bazel-crosscompile-example

To build:

bazel build --config=docker //:hello
INFO: Analysed target //:hello (0 packages loaded).
INFO: Found 1 target...
ERROR: /Users/ilya/hello-bazel-docker/BUILD:1:1: undeclared inclusion(s) in rule '//:hello':
this rule is missing dependency declarations for the following files included by 'hello.c':
  '/private/var/tmp/_bazel_ilya/d86e0e7cfe53385dc3edff3c0d9662b6/external/cross_toolchain/lib/gcc/x86_64-unknown-linux-gnu/7.3.0/include/stddef.h'
  '/private/var/tmp/_bazel_ilya/d86e0e7cfe53385dc3edff3c0d9662b6/external/cross_toolchain/lib/gcc/x86_64-unknown-linux-gnu/7.3.0/include/stdarg.h'
Target //:hello failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.723s, Critical Path: 0.58s
FAILED: Build did NOT complete successfully

What operating system are you running Bazel on?

macOS 10.12.6

What’s the output of bazel info release?

Tried with release 0.10.0-homebrew and development version also

If bazel info release returns “development version” or “(@non-git)”, tell us how you built Bazel.

development version was build form sources by bazel build //src:bazel

What’s the output of git remote get-url origin ; git rev-parse master ; git rev-parse HEAD ?

https://bazel.googlesource.com/bazel
e7541262293977598ad96d9eb7a83b439eedd634
e7541262293977598ad96d9eb7a83b439eedd634

Have you found anything relevant by searching the web?

Nothing

Any other information, logs, or outputs that you want to share?

AFAIU problem is here: https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java#L1233

Paths which are not absolute just discarded. So is it a bug or intentional behavior? If it is intentional, how I should specify include path in such example?

If it is a bug I can create pull-request with merging execRoot and includePath, which is absolute path to include directory in such case.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 2
  • Comments: 15 (3 by maintainers)

Commits related to this issue

Most upvoted comments

It’s usually quite important to pass -no-canonical-prefixes and -fno-canonical-system-headers to prevent GCC from “helpfully” normalizing system header paths into something Bazel doesn’t know about.

For us, building compiler from source was the easiest way around this problem. As a bonus we could use GCC trunk instead of an older version. But yes, annoying.

The advice in this issue will not work for non-standard compilers. GIven today’s crosstool documentation, it’s really not clear how to overcome this rule is missing dependency declarations for the following files included by ... errors.

This is also an issue with clang, which does not support -fno-canonical-system-headers, and -no-canonical-prefixes does not seem to help.

I’ve played a bit more with GCC and indeed the blame falls on Ubuntu maintainers. They build GCC with some configuration flag (not sure which, maybe enable-multilib or enable-multiarch) that effectively renders the -no-canonical-headers useless.

What works for us is to:

  • Add -nostdinc++ -isystem path/to/include (relative to the external workspace root) to the default compiler flags.
  • Not add anything in cxx_builtin_include_directories.

A bit dirty with these extra flags in the compile line though.

With this, the include checker doesn’t complain. Not sure if it’s a bug or a feature 😅

This still seems to be an issue. I have defined a custom cc toolchain and have set cxx_builtin_include_directories as:

        cxx_builtin_include_directories = [
            "external/x86_64_linux_musl/usr/include",
            "external/x86_64_linux_musl/include",
            "external/x86_64_linux_musl/include/c++/10.2.1/",
            "external/x86_64_linux_musl/usr/include/c++/10.2.1/",
        ],

and get errors such as 

undeclared inclusion(s) in rule ‘//main:hello-greet’: this rule is missing dependency declarations for the following files included by ‘main/hello-greet.cc’: ‘/home/jheaff1/.cache/bazel/_bazel_jheaff1/0ac7dd591c66afb95b2d2d0ded26378b/external/x86_64_linux_musl/include/stdc-predef.h’


The documentation is a tad confusing. It states that cxx_builtin_include_directories should be “the exact paths used by the compiler, and are generally relative to the exec root.”. It then states that “Relative paths are resolved relative to the configuration file directory.”

If indeed the paths are relative to the toolchain configuration file directory, is there any way I can derive the <exec root>/external directory from the toolchain configuration file directory?