Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cc_common.compile API broken/changed for virtual_includes in 7.2.1 to 6.2.1 #23061

Closed
FaBrand opened this issue Jul 22, 2024 · 8 comments
Closed
Labels

Comments

@FaBrand
Copy link
Contributor

FaBrand commented Jul 22, 2024

Conditions

The bug occurs when compling sources using the starlark api cc_common.compile under the following conditions:

  1. The name argument set to a different value than what ctx.label.name returns
  2. strip_include_prefix is set to the common prefix of the public_hdrs

The artifact path for the virtual includes changed, but the created -Include remained the same

7.2.1

-Include points to ctx.label.name path
_virtual_include uses the name passed to .compile

-Ibazel-out/k8-fastbuild/bin/_virtual_includes/with_other_name 


└── _virtual_includes
   └── other_name

6.2.1

-Include points to ctx.label.name path
_virtual_include uses the ctx.label.name

-Ibazel-out/k8-fastbuild/bin/_virtual_includes/with_other_name 

└── _virtual_includes
    └── with_other_name

Error Case

The include paths include -Ibazel-out/k8-fastbuild/bin/_virtual_includes/with_other_name. This points to the _virtual_includes created for the target name.

SUBCOMMAND: # //:with_other_name [action 'Compiling simple_source.cpp', configuration: 8d8536e4da590f8d06d608baf706ea28be96e39f6597af65e48789bc163466ff, execution platform: @@platforms//host:host, mnemonic: CppCompile]
<...>
  /usr/bin/gcc <...> -Ibazel-out/k8-fastbuild/bin/_virtual_includes/with_other_name <...> -c simple_source.cpp -o bazel-out/k8-fastbuild/bin/_objs/other_name/simple_source.pic.o)
# Configuration: 8d8536e4da590f8d06d608baf706ea28be96e39f6597af65e48789bc163466ff
# Execution platform: @@platforms//host:host
ERROR: /home/user/github/bazel-cc-common-compile-api/BUILD:3:13: Compiling simple_source.cpp failed: (Exit 1): gcc 
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
simple_source.cpp:1:10: fatal error: simple_header.h: No such file or directory
    1 | #include "simple_header.h"
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.
Target //:with_other_name failed to build
INFO: Elapsed time: 3.158s, Critical Path: 0.05s
INFO: 5 processes: 5 internal.
ERROR: Build did NOT complete successfully

However the files that are stripped are created in a different path, the one containing the name that is passed to .compile(name = "other_name")

$ tree bazel-bin                                                                                                                                                                                                                    
bazel-bin
├── libother_name.a-2.params
├── libother_name.so-2.params
├── _objs
│   └── other_name
└── _virtual_includes
    └── other_name
        └── simple_header.h -> /home/user/github/bazel-cc-common-compile-api/v1/simple_header.h

Good Case in bazel 6.2.1

In this case the directory created below virtual_includes matches the label name

SUBCOMMAND: # //:with_other_name [action 'Compiling simple_source.cpp', configuration: 8ff241ce6c10a03f8090d264b31eed76759a15bfceae82147884cdf314748fc6, execution platform: @local_config_platform//:host]
<...>
  /usr/bin/gcc <...> -Ibazel-out/k8-fastbuild/bin/_virtual_includes/with_other_name <...> -c simple_source.cpp -o bazel-out/k8-fastbuild/bin/_objs/other_name/simple_source.pic.o
$ tree bazel-bin
bazel-bin
├── libother_name.a
├── libother_name.a-2.params
├── libother_name.so
├── libother_name.so-2.params
├── _objs
│   └── other_name
│       ├── simple_source.pic.d
│       └── simple_source.pic.o
├── _solib_k8
│   └── liblibother_Uname.so -> /home/user/.bazel/output_base/execroot/__main__/bazel-out/k8-fastbuild/bin/libother_name.so
└── _virtual_includes
    └── with_other_name
        └── simple_header.h -> /home/user/.bazel/output_base/execroot/__main__/v1/simple_header.h

Conclusion

The created _virtual_includes/<name> does not match with the created include path anymore.

It seems to me this was "incorrect" before, aka still consistent but probably not desired like this.
It now partly changed with 7e0df68 and is now inconsistent

Which category does this issue belong to?

C++ Rules

What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

git clone https://github.com/FaBrand/bazel-cc-common-compile-api repro
cd repro
USE_BAZEL_VERSION=7.2.1 bazel build with_other_name

Which operating system are you running Bazel on?

Linux/Windows

What is the output of bazel info release?

release 7.2.1

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

https://github.com/FaBrand/bazel-cc-common-compile-api.git
23f05c2fa98bcc6604f5cac3a2d6fb7af88fc0c2

If this is a regression, please try to identify the Bazel commit where the bug was introduced with bazelisk --bisect.

--- Bisect Result

first bad commit is https://github.com/bazelbuild/bazel/commit/7e0df68aa4d11307dff8571ebce11d37c79c170c

Have you found anything relevant by searching the web?

I found a few changes related to _virtual_includes, but none for this specific result

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

No response

@github-actions github-actions bot added team-Rules-CPP Issues for C++ rules labels Jul 22, 2024
@FaBrand FaBrand changed the title cc_common.compile API broken/changed in 7.2.1 to 6.2.1 cc_common.compile API broken/changed for virtual_includes in 7.2.1 to 6.2.1 Jul 22, 2024
@FaBrand
Copy link
Contributor Author

FaBrand commented Jul 22, 2024

It looks like the diff is the same for these testcases that were changed in the bisected Commit:

7e0df68#diff-f087e973daabb7df3b785dd5dba1b9c8250ac046c6fcf62109b7f19eb07a7da2L5548-R5549

@FaBrand
Copy link
Contributor Author

FaBrand commented Jul 22, 2024

Created #23064 to test for the supposed error. But i don't know yet where to attempt to fix it

@FaBrand
Copy link
Contributor Author

FaBrand commented Jul 22, 2024

@meteorcloudy

@meteorcloudy
Copy link
Member

@comius @pzembrod

@FaBrand
Copy link
Contributor Author

FaBrand commented Jul 23, 2024

I believe i tracked down the root of the issue:

The virtual includes and their include paths are created here:

if not original_header.path == include_path:
virtual_include_dir = paths.join(paths.join(cc_helper.package_source_root(label.workspace_name, label.package, is_sibling_repository_layout), _VIRTUAL_INCLUDES_DIR), label.name)
virtual_header = actions.declare_shareable_artifact(paths.join(virtual_include_dir, include_path))
actions.symlink(
output = virtual_header,
target_file = original_header,
progress_message = "Symlinking virtual headers for %{label}",
use_exec_root_for_source = USE_EXEC_ROOT_FOR_VIRTUAL_INCLUDES_SYMLINKS,
)
module_map_headers.append(virtual_header)
if config.coverage_enabled:
virtual_to_original_headers_list.append((virtual_header.path, original_header.path))
module_map_headers.append(original_header)
virtual_headers = module_map_headers + non_module_map_headers
return struct(
headers = virtual_headers,
module_map_headers = module_map_headers,
virtual_include_path = cc_internal.bin_or_genfiles_relative_to_unique_directory(actions = actions, unique_directory = _VIRTUAL_INCLUDES_DIR),
virtual_to_original_headers = depset(virtual_to_original_headers_list),

virtual_include_dir points to the _virtual_include that is created from the Label in the rule_context

The discrepancy is introduced here:
https://github.com/bazelbuild/bazel/blob/master/src/main/starlark/builtins_bzl/common/cc/cc_compilation_helper.bzl#L137

Which uses the label name internally to construct the unique _virtual_include dir that does not match the symlinked header from virtual_include_dir

Backtrace of name

The label is originally created here:

protected Label getCallerLabel(StarlarkActionFactory actions, String name) throws EvalException {
try {
return Label.create(
actions.getRuleContext().getActionOwner().getLabel().getPackageIdentifier(), name);
} catch (LabelSyntaxException e) {
throw Starlark.errorf("%s", e.getMessage());
}
}

coming from:

Label label = getCallerLabel(actions, name);

which gets the name from the api of cc_common.compile

@FaBrand
Copy link
Contributor Author

FaBrand commented Jul 23, 2024

@comius @pzembrod I linked the PR that i managed to fix the error with. Would be awesome if you can take a look. If possible i would want to include this in the next 7.x release as well.

There is a merge conflict with the cleanup in https://github.com/bazelbuild/bazel/pull/23071/files#diff-8c47ef0983742d8167b5bdaf3b4c6fe872365949ecf0ef64098e38458ba5a3a1L347-L366
But it should be easy to solve

@FaBrand
Copy link
Contributor Author

FaBrand commented Jul 30, 2024

@fmeum @meteorcloudy Sry for being annoying. I know that you are not the owners here, but I saw you as being active contributors in seemingly related parts so i am trying to reach somebody to get some feedback on the issue/fix🤞

I am happy to update the PR if there is anything more to do

fmeum pushed a commit to fmeum/bazel that referenced this issue Aug 20, 2024
So far only the generated header in the virtual includes is tested but the Include path pointing to that directory isnt

This is a testcase to reproduce the suspected error reported here:
- bazelbuild#23061

Assuming that the location of the file is asserted:
```Java
    assertThat(artifactsToStrings(ccInfo.getCcCompilationContext().getDirectPublicHdrs()))
        .contains("bin third_party/bar/_virtual_includes/starlark_lib_suffix/starlark_lib.h");
```
Adding a testcase for the include path seems reasonable.

A local run of the testcase shows the error:
```
1) testStripIncludePrefixIncludePath(com.google.devtools.build.lib.rules.cpp.StarlarkCcCommonTest)
value of: getIncludeDirs().onlyElement()
expected: bazel-out/k8-fastbuild/bin/third_party/bar/_virtual_includes/starlark_lib_suffix
but was : bazel-out/k8-fastbuild/bin/third_party/bar/_virtual_includes/starlark_lib
        at com.google.devtools.build.lib.rules.cpp.StarlarkCcCommonTest.testStripIncludePrefixIncludePath(StarlarkCcCommonTest.java:5902)

FAILURES!!!
Tests run: 73,  Failures: 1
```

The change in behaviour was introduced in bazelbuild@7e0df68#diff-403c46ec3075b8e9e6d490ce955db88dae2d457b8046608884039b18b10ab6ccR774

Fixes: bazelbuild#23061

Closes bazelbuild#23071.

PiperOrigin-RevId: 660681269
Change-Id: Ia3f8a8a6cf8bf0e093416a247e348e6de6719584
github-merge-queue bot pushed a commit that referenced this issue Sep 19, 2024
So far only the generated header in the virtual includes is tested but
the Include path pointing to that directory isnt

This is a testcase to reproduce the suspected error reported here:
- #23061

Assuming that the location of the file is asserted:
```Java
    assertThat(artifactsToStrings(ccInfo.getCcCompilationContext().getDirectPublicHdrs()))
        .contains("bin third_party/bar/_virtual_includes/starlark_lib_suffix/starlark_lib.h");
```
Adding a testcase for the include path seems reasonable.

A local run of the testcase shows the error:
```
1) testStripIncludePrefixIncludePath(com.google.devtools.build.lib.rules.cpp.StarlarkCcCommonTest)
value of: getIncludeDirs().onlyElement()
expected: bazel-out/k8-fastbuild/bin/third_party/bar/_virtual_includes/starlark_lib_suffix
but was : bazel-out/k8-fastbuild/bin/third_party/bar/_virtual_includes/starlark_lib
        at com.google.devtools.build.lib.rules.cpp.StarlarkCcCommonTest.testStripIncludePrefixIncludePath(StarlarkCcCommonTest.java:5902)

FAILURES!!!
Tests run: 73,  Failures: 1
```

The change in behaviour was introduced in
7e0df68#diff-403c46ec3075b8e9e6d490ce955db88dae2d457b8046608884039b18b10ab6ccR774

Fixes: #23061

Closes #23071.

PiperOrigin-RevId: 660681269
Change-Id: Ia3f8a8a6cf8bf0e093416a247e348e6de6719584

Closes #23221

Co-authored-by: FaBrand <[email protected]>
@iancha1992
Copy link
Member

A fix for this issue has been included in Bazel 7.4.0 RC1. Please test out the release candidate and report any issues as soon as possible.
If you're using Bazelisk, you can point to the latest RC by setting USE_BAZEL_VERSION=7.4.0rc1. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants