bazelbuild / bazelbuild/rules_cc
external_include_paths adds external repository root as -isystem include path
- Dominant language
- Starlark
- Stars
- 247
- Forks
- 196
- PR merge metrics
- No merged PRs in 30d
Description
When `--features=external_include_paths` is enabled, `rules_cc` appears to add the external repository root itself to `external_includes`, which is later emitted as `-isystem `. This can make non-header files in an external repository visible to angle-bracket includes.
In particular, on case-insensitive filesystems this can break libc++ includes. If an external repository contains a file named `VERSION`, and the compile action also includes `-isystem external/+`, libc++'s `#include ` can resolve to that repository's `VERSION` file instead of the standard library `` header.
Example observed in a downstream build using `libtiff` through OpenCV on macOS (see [this issue](https://github.com/bazelbuild/bazel-central-registry/issues/9776)):
```text
-isystem external/libtiff+
-isystem bazel-out/darwin_arm64-fastbuild/bin/external/libtiff+
-isystem external/libtiff+/libtiff
-isystem bazel-out/darwin_arm64-fastbuild/bin/external/libtiff+/libtiff
```
Only the `libtiff` subdirectory entries are expected from `libtiff`'s `includes = ["libtiff"]`. The root entries come from `rules_cc`'s external include path reclassification.
The problematic code appears to be in `cc/private/compile/cc_compilation_helper.bzl`:
```starlark
external_include_dirs.append(repo_path)
external_include_dirs.append(gen_include_dir)
external_include_dirs.append(bin_include_dir)
external_include_dirs.extend(quote_include_dirs)
external_include_dirs.extend(system_include_dirs)
external_include_dirs.extend(include_dirs)
```
The first three entries are implicit quote roots for the target's own repository. Reclassifying them as public system include paths for external repositories exposes the entire repository root to downstream compilation.
This is important because `external_include_paths` is very useful for treating third-party headers as system headers while still keeping warnings-as-errors for first-party code. Disabling the feature works around this specific failure but loses that behavior globally.
A possible fix is to keep converting explicit public include directories (`includes`, `system_includes`, and relevant configured include dirs) into `external_includes`, but avoid exporting the implicit external repository root/default quote include roots as system include paths to downstream dependents.
Contributor guide
Research direction
Start in cc/private/compile/cc_compilation_helper.bzl and trace the external_include_paths handling around external_include_dirs. Compare the implicit repository and generated quote roots with explicit includes such as libtiff's includes = ["libtiff"]. Done means external repositories no longer export their roots as system paths, while intended public include directories remain available for downstream compilation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100