bazelbuild / bazelbuild/rules_cc

external_include_paths adds external repository root as -isystem include path

Open
#801 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.