-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Windows: Use of strip_include_prefix causes "missing dependency declarations" errors #6337
Comments
@hlopko this is still an issue with 1.0.0. Can you please take a look? Is there a workaround available? This feature is critical for running on Windows, IMO this should be P1 if there's no workaround. |
I'am trying to make bazel rules for google/glog compatible with windows and I face the same issue. |
Workaround: add a separate cc_library that doesn't use
google/glog@1bb0133#diff-71fb65f6a0f5906fd8a4c156e6f77a7dR130 |
I'm afraid I won't be able to work on this any time soon. Maybe @meteorcloudy will have a free afternoon? :) |
Hmm. this is another "include" issue that's caused by not having sandbox on Windows. Same root cause as #5640 To summarize, the reason is You can reproduce the same issue by disabling sandbox on Linux:
There's really no good fix from Bazel side except implementing sandbox on Windows, which is not currently a priority. But users should be able to workaround by not having the headers they want to strip in the same directory as the source files. |
"not having the headers they want to strip in the same directory as the source files" is a poor solution that does not work for many use cases, because much of the time the entire reason for using strip_include_prefixes is because the code is from a third party, such as a submodule. I'm not sure what makes implementing the entire sandbox easier than detecting this aliasing between the file in |
It's because even if you don't specify
But perhaps we can fix this issue by allowing including headers in the source file's directory. |
I can confirm that the workaround suggested by @drigz works well. I've packaged it up as a macro so that you can just use cc_library to cc_library_with_strip_include_prefix in place of cc_library: # Workaround https://github.com/bazelbuild/bazel/issues/6337 by declaring
# the dependencies without strip_include_prefix.
def cc_library_with_strip_include_prefix(name, hdrs, deps = None, **kwargs):
strip_include_prefix_name = name + "_strip_include_prefix_hack"
if deps == None:
deps = []
deps = deps + [":" + strip_include_prefix_name]
native.cc_library(
name = strip_include_prefix_name,
hdrs = hdrs,
visibility = ["//visibility:private"],
)
native.cc_library(
name = name,
hdrs = hdrs,
deps = deps,
**kwargs
) However, it would be ideal if Bazel could somehow just make cc_library already have the behavior of this workaround, which presumably wouldn't require any work on a Windows sandbox, etc. Is there a reason that would be difficult to do? |
It's not a complete fix either, iirc, since sometimes the stripped prefix is needed to get the files inside the folder to include each other correctly. |
…er to the 'allowed to use' set too When a cc_library 'a' makes use of strip_include_prefix, bazel creates a symlink for the hdrs at bazel-out/.../bin/_virtual_includes/a/ Later, bazel passes -I bazel-out/.../bin/_virtual_includes/a/ to the command line to tell the compiler where to look for those headers. For each header in hdrs, bazel will either put the header artifact itself in a set of 'allowed to use' headers, or, in the case of strip_include_prefix usage, bazel will add the symlink to the header under bazel-out/.../bin/_virtual_includes/a/ as 'allowed to use'. When searching for headers, the compiler will do the following (Taken from https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html): 1. For the quote form of the include directive, the directory of the current file is searched first. 2. For the quote form of the include directive, the directories specified by -iquote options are searched in left-to-right order, as they appear on the command line. 3. Directories specified with -I options are scanned in left-to-right order. ... In the case of the following cc_library: ``` cc_library( name = 'foo', hdrs = ["lib/foo.h"], srcs = ["lib/foo.cc"], strip_include_prefix = 'lib', ) ``` if foo.cc includes foo.h as #include "foo.h" the compiler will find the header in step 1 of the search, thus will use the original header and not the symlink. The compiler will note this in the .d file. Bazel however added the symlink in the list of 'allowed to use' headers, so at some point it will error out with "undeclared inclusion(s) in rule" error due to the discrepancy. This cl tells bazel to add the original header in the 'allowed to use' headers even when it generates a symlink in the _virtual_includes directory. Fixes #3828 #6337 RELNOTES:None. PiperOrigin-RevId: 344240730
…er to the 'allowed to use' set too When a cc_library 'a' makes use of strip_include_prefix, bazel creates a symlink for the hdrs at bazel-out/.../bin/_virtual_includes/a/ Later, bazel passes -I bazel-out/.../bin/_virtual_includes/a/ to the command line to tell the compiler where to look for those headers. For each header in hdrs, bazel will either put the header artifact itself in a set of 'allowed to use' headers, or, in the case of strip_include_prefix usage, bazel will add the symlink to the header under bazel-out/.../bin/_virtual_includes/a/ as 'allowed to use'. When searching for headers, the compiler will do the following (Taken from https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html): 1. For the quote form of the include directive, the directory of the current file is searched first. 2. For the quote form of the include directive, the directories specified by -iquote options are searched in left-to-right order, as they appear on the command line. 3. Directories specified with -I options are scanned in left-to-right order. ... In the case of the following cc_library: ``` cc_library( name = 'foo', hdrs = ["lib/foo.h"], srcs = ["lib/foo.cc"], strip_include_prefix = 'lib', ) ``` if foo.cc includes foo.h as #include "foo.h" the compiler will find the header in step 1 of the search, thus will use the original header and not the symlink. The compiler will note this in the .d file. Bazel however added the symlink in the list of 'allowed to use' headers, so at some point it will error out with "undeclared inclusion(s) in rule" error due to the discrepancy. This cl tells bazel to add the original header in the 'allowed to use' headers even when it generates a symlink in the _virtual_includes directory. Fixes #3828 #6337 RELNOTES:None. PiperOrigin-RevId: 344240730
Indeed, thanks for flagging. @meteorcloudy would you do the honors? |
Eliminate `template_rule` from `utils.bzl`. This is now available as `expand_template` from bazel_skylib. Eliminate `cc_library_with_strip_include_prefix` from `utils.bzl`. The Bazel bug (bazelbuild/bazel#6337) is fixed as of Bazel 5.0. Replace uses of `genrule` with `write_file` from bazel_skylib. Eliminate unnecssary `constraint_value` -> `config_setting` aliases, now that Bazel allows constraint_value targets to be used directly in `select`. Updates bazelisk.py to fix deprecation warning: bazelbuild/bazelisk#379 PiperOrigin-RevId: 478621631 Change-Id: I2e647861a78ee456fd44bc6f23223611162a136f
Description of the problem / feature request:
On Windows, inclusion of any header file from a rule with
strip_include_prefix
set will cause a "missing dependency declaration" error to be thrown, breaking the build.Feature requests: what underlying problem are you trying to solve with this feature?
I'm trying to use Bazel as it is documented and as it works in Linux.
strip_include_prefix
is an essential tool for describing the build processes of third-party repositories that are not natively set up in Bazel (i.e., most of them). The main alternative is to modify every file that includes another file by forking or by rewriting it with genrules, both of which levy a major maintenance burden on the developer on top of already-tedious BUILD-writing.Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Make the following directory tree:
WORKSPACE, a.h, b.h:
(empty files)
BUILD:
a.cc:
In the directory, run
bazel build ...
. On Linux, this will probably succeed. On Windows, you are likely to receive an error like:What operating system are you running Bazel on?
Windows 10 build 1803
What's the output of
bazel info release
?release 0.17.2
Have you found anything relevant by searching the web?
Yes, more issues describing the same thing, that have gone unanswered for a long time: #3828
Any other information, logs, or outputs that you want to share?
This still works fine in Linux by comparison:
The text was updated successfully, but these errors were encountered: