-
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
Alternative _virtual_includes organization to solve MSVC issues #18683
Comments
Upgrade protobuf upb to corresponding v23.x branch Upgrade grpc to v1.55.0 NOTE: -DTENSORSTORE_USE_SYSTEM_PROTOBUF=ON doesn't appear to work properly to build gRPC after this change. I suspect that we need to generate calls to `include_directories(${Protobuf_INCLUDE_DIRS})` for protobuf dependencies, however bazel_to_cmake doesn't really have a mechanism for that. NOTE: While building on windows I ran into: fatal error C1083: Cannot open include file: 'google/protobuf/compiler/objectivec/text_format_decode_data.h': No such file or directory If this happens, then underlying issue is that MSVC cannot handle long path lengths. See related bugs: * bazelbuild/bazel#18683 * protocolbuffers/protobuf#12947 PiperOrigin-RevId: 540626233 Change-Id: I0887d0126bab695956c9d11793ac7c6764537d79
This isn't just a C++ issue; any rules which use similar virtual directories can have the same issue. For example proto, etc. |
This may also affect building gRPC. See, for example, this proto filename, which is > 100 bytes. The package name and any virtual include directories could easily be more.
|
... this has been tagged as 'help wanted'. Suppose that I started here:
And tried to replace:
with
Where else should I look for potential collisions? |
I suppose that in theory, if there were a reasonable built-in hash, it could look a bit like this:
|
This is more protos related. I don’t think hashing for virtual_includes works though. When header files are included C++ searches them in such directory structure. And if the structure isn’t there, it can’t find them. Or maybe I’m missing somethin? Virtual includes are only used with include_path and strip_include_path set in proto_library in Bazel 7. In older versions that wasn’t the case and they were almost always used. |
The suffix of the path has to remain, but the constructed space between the repository ( The above snippet attempts to change only that piece; it might not be quite right, though. |
Pure Starlark rules allow file declaration only under their own package path. That’s why there’s a long path before _virtual_includes. The reason is, so that file name conflicts are limited to a package. Native rules have some super powers and can choose more arbitrary path. But that only works because they are “centralized” by being part of Bazel. There are ways how to make this work in a decentralized manner. At the moment we don’t have any design or implementation for it. We will potentially need it for C++ rules that are using such special powers. |
So the only place the virtual_includes can be created is directly on the package path? Well, it would be nice for a rule to ask the bazel runtime for a private unique directory, otherwise it seems like this windows path issue is going to persist. |
This is a pretty serious issue --- it basically means that any use of Bazel with strip_include_prefix is very fragile on Windows and can easily be broken by minor changes that increase filename lengths. In particular, the length limit is easily triggered by the use of protobuf as a dependency, as is very common, particularly for Google projects, if the output_base is not extremely short. I understand that setting a very short output_base or output_root is a common mitigation on Windows. However, because it requires placing the output directory outside of the user's home directory, it requires explicit user intervention and can't really be done automatically. TensorStore, for example, invokes Bazel via a bundled Bazelisk automatically when invoking It would be great if a solution to this could be prioritized. |
As of Sept, upb has moved into protobuf; update to support that. This reworks how protos are generated to feel a bit closer to the aspect-like code generation of Bazel. Now each proto generator is registered, and each proto_library() rule will invoke all registered aspects; this will allow consistent and reliable invocation of protoc across all sub-repositories. The change permits removing duplicate .proto files from local_proto_mirror, and simplifies the boostrapping process. Also note, on windows the updated protobuf is more likely to trigger file not found issues due to path length; if this happens, add the bazel startup option: startup --output_user_root=C:/_out See also: bazelbuild/bazel#18683 protocolbuffers/protobuf#12947 grpc/grpc#33986 PiperOrigin-RevId: 588606143 Change-Id: Iafa5f16b0a9bbc1058a876c0cc739d82743f96a4
In this case it's not neccessary to create _virtual_includes, just setting the correct include path is enough. This should alleviate Windows problems with too long paths. Related: #18683 PiperOrigin-RevId: 626360114 Change-Id: I4e7d8ee39e58dd27601f18c4a624c1d206785abe
In this case it's not neccessary to create _virtual_includes, just setting the correct include path is enough. This should alleviate Windows problems with too long paths. Related: bazelbuild#18683 PiperOrigin-RevId: 626360114 Change-Id: I4e7d8ee39e58dd27601f18c4a624c1d206785abe
*** Reason for rollback *** Order of includes possibly changed. Example breakage: [] *** Original change description *** Optimize _virtual_includes when paths are only stripped In this case it's not neccessary to create _virtual_includes, just setting the correct include path is enough. This should alleviate Windows problems with too long paths. Related: #18683 PiperOrigin-RevId: 626960507 Change-Id: I5758ff1d4b064f5b2ebb151ea84e81405e0ec265
Update on a091d90 I spend quite some time to figure out the problem, but now it's obvious. The change can't possibly work, and I can't roll it forward. What happens is that when include path |
I see the same problem while trying to migrate from C++ visual studio solutions to Bazel in a commercial setting. Any workaround for this? |
What about still generating a virtual_includes directory but giving it a short (e.g. hash-based) path on Windows? Perhaps in general all of the output base directories on Windows could be given short unnested hash-based paths. |
*** Reason for rollback *** Order of includes possibly changed. Example breakage: [] *** Original change description *** Optimize _virtual_includes when paths are only stripped In this case it's not neccessary to create _virtual_includes, just setting the correct include path is enough. This should alleviate Windows problems with too long paths. Related: #18683 PiperOrigin-RevId: 626960507 Change-Id: I5758ff1d4b064f5b2ebb151ea84e81405e0ec265
The idea here is to set the existing config "config_msvc" not only when "msvc-cl" is specified but also when "clang-cl" is specified. Supporting clang-cl should be a quick workaround for those who look for a quick solution to cl.exe's path limitation e.g. * bazelbuild/bazel#18683 PiperOrigin-RevId: 630590450
The idea here is to set the existing config "config_msvc" not only when "msvc-cl" is specified but also when "clang-cl" is specified. Supporting clang-cl should be a quick workaround for those who look for a quick solution to cl.exe's path limitation e.g. * bazelbuild/bazel#4149 * bazelbuild/bazel#18683 PiperOrigin-RevId: 630590450
In this case it's not neccessary to create _virtual_includes, just setting the correct include path is enough. This should alleviate Windows problems with too long paths. Related: bazelbuild#18683 PiperOrigin-RevId: 626360114 Change-Id: I4e7d8ee39e58dd27601f18c4a624c1d206785abe
*** Reason for rollback *** Order of includes possibly changed. Example breakage: [] *** Original change description *** Optimize _virtual_includes when paths are only stripped In this case it's not neccessary to create _virtual_includes, just setting the correct include path is enough. This should alleviate Windows problems with too long paths. Related: bazelbuild#18683 PiperOrigin-RevId: 626960507 Change-Id: I5758ff1d4b064f5b2ebb151ea84e81405e0ec265
This is a workaround for the path-length issue on building protobuf on Windows with bazel. * protocolbuffers/protobuf#12947 * bazelbuild/bazel#18683 To work around it, specify --bazelrc=windows.bazelrc as follows. bazel --bazelrc=windows.bazelrc \ build //protocol:commands_proto \ --config oss_windows This is a preparation to support Bazel for Windows build (#948). There must be no observable behavior change in mac/Linux Bazel builds. PiperOrigin-RevId: 645622326
This issue is about a lot more than just virtual_includes now right? For example I think this failure is the same case, but not specific to headers:
|
We're experiencing this issue with this same envoy file. We're using This started occurring after updating our workflow to bzlmod (going from 6.4.0 to 8.0.0) and upgrading to gRPC 1.68.0. |
Description of the feature request:
Currently bazel constructs _virtual_includes paths for libraries in order to place files at known locations or restrict the set of files available by the compiler. These paths look somewhat like this, in the case of protobuf:
<bazel_output_base>/<hash>/execroot/<root workspace>/bazel-out/<config>/bin/external/com_google_protobuf/src/google/protobuf/compiler/objectivec/_virtual_includes/objectivec/google/protobuf/compiler/objectivec/text_format_decode_data.h
These constructed include paths are quite long, as they incorporate both the path to the bazel rule and the path to the file. Unfortunately MSVC uses a MAX_PATH of 260 characters, which leads to hard to discover errors such as:
In order to solve this, I request a feature to make _virtual_includes paths shorter.
If the virtual includes path were constructed more like:
<bazel_output_base>/<hash>/_virtual_includes/<different hash>/objectivec/google/protobuf/compiler/objectivec/text_format_decode_data.h
Then this problem would be essentially eliminated. The exact path construction doesn't matter, as long as it can eliminate much of the lengths of deep bazel rules.
This may require a rule context feature which, in essence, constructs a virtual path which encodes the entire build / workspace / package config.
Of course, links could be maintained from the current virtual include to that hash.
What underlying problem are you trying to solve with this feature?
Windows, but more importantly MSVC cl.exe, limits filename lengths to MAX_PATH (260) characters: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation https://developercommunity.visualstudio.com/t/clexe-compiler-driver-cannot-handle-long-file-path/975889
The bazel workspace and _virtual_includes repository construction runs into this limit. This has been a recurring issue in some windows builds as there are multiple ways to trigger it:
The organization of the constructed virtual includes directories exacerbates this limit.
fatal error C1083: Cannot open include file: 'google/protobuf/compiler/objectivec/text_format_decode_data.h': No such file or directory
Workarounds involve setting the output_base startup flag, such as
--output_base=C:\Out
, which is not a universal solution, or reorganizing the directory structure within a repository, which cannot always be done on mature projects.Which operating system are you running Bazel on?
Windows + MSVC (any version)
Any other information, logs, or outputs that you want to share?
For my specific build, which includes protobuf, this is an output of the @params file as supporting evidence. Here many of the bazel constructed paths are >130 characters, leaving 130 total for both the --bazel_root and the actual path.
If the bazel root is 'C:/users/laramiel/_bazel_laramiel/12345678', (which is 42 characters), that leaves at most 80 characters for the file + path in a bazel repository.
The text was updated successfully, but these errors were encountered: