Skip to content

Unpredictable compilation of targets with transitive dependencies that expose headers #96

Description

@chrisnovakovic

Some compilers, notably Apple Clang, inject their own -I options into the compiler command line. This is problematic because we use -isystem to put headers provided by transitive dependencies into the header search path (via the cc:inc: label), which allows the compiler to preempt headers with common names that cc-rules provides (and expects to be used) in the build environment.

Here's a simplified but concrete example, which uses kuba--/zip:

## third_party/cc/kuba_zip/kuba_zip.build

c_library(
    name = "kuba_zip",
    srcs = ["src/zip.c"],
    hdrs = ["src/zip.h"],
    private_hdrs = ["src/miniz.h"],
)
c_binary(
    name = "example",
    srcs = ["example.c"],
    deps = [
        "///third_party/cc/kuba_zip/kuba_zip//:kuba_zip",
    ],
)

kuba--/zip provides a single header, zip.h, which Please copies into :_example#lib_cc's build environment at src/zip.h. The label cc:inc:src on ///third_party/cc/kuba_zip/kuba_zip//:kuba_zip ensures that -isystem src is added to the header search path when compiling example.c. However, this target doesn't compile on the hosted Darwin amd64 GitHub runners, because libzip is installed under /usr/local and libzip's header at /usr/local/include/zip.h takes precedence over kuba--/zip's header at src/zip.h:

2025/11/26 14:18:59 Identified C/C++ compiler as Apple Clang 17.0.0
2025/11/26 14:18:59 Identified linker as Apple ld 1167.5
2025/11/26 14:18:59 Running `/usr/bin/cc -c -I . -std=c99 -Os -DNDEBUG -Wall -Wextra -Werror -flto -D_FILE_OFFSET_BITS=64 -fPIC -fdata-sections -ffunction-sections -fno-unique-section-names -v -std=c11 -D_XOPEN_SOURCE=600 -isystem src tools/please_pex/preamble/preamble.c`
Apple clang version 17.0.0 (clang-1700.0.13.5)
Target: x86_64-apple-darwin24.6.0
Thread model: posix
InstalledDir: /Applications/Xcode_16.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
 "/Applications/Xcode_16.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx15.0.0 -Wundef-prefix=TARGET_OS_ -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-llvm-bc -flto=full -flto-unit -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name preamble.c -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fno-strict-return -ffp-contract=on -fno-rounding-math -funwind-tables=2 -target-sdk-version=15.5 -fvisibility-inlines-hidden-static-local-var -fdefine-target-os-macros -fno-assume-unique-vtables -fno-modulemap-allow-subdirectory-search -target-cpu penryn -tune-cpu generic -debugger-tuning=lldb -fdebug-compilation-dir=/Users/runner/work/python-rules/python-rules/plz-out/tmp/tools/please_pex/preamble/_preamble#lib_cc._build -target-linker-version 1167.5 -v -ffunction-sections -fdata-sections -fno-unique-section-names -fcoverage-compilation-dir=/Users
clang -cc1 version 17.0.0 (clang-1700.0.13.5) default target x86_64-apple-darwin24.6.0
ignoring nonexistent directory "/Applications/Xcode_16.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode_16.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/SubFrameworks"
ignoring nonexistent directory "/Applications/Xcode_16.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
 .
 /usr/local/include
 src
 /Applications/Xcode_16.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/17/include
 /Applications/Xcode_16.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
 /Applications/Xcode_16.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /Applications/Xcode_16.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.

(Note the precedence of /usr/local/include over src below #include "..." search starts here:.)

I think the right way to fix this is to use -I instead of -isystem to expose headers provided by transitive dependencies to the compiler, but do it in a way that doesn't interfere with any -I options that could be passed in compiler_flags.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions