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

C++ header validation fails for MSVC remote compile #19733

Open
jayconrod opened this issue Oct 4, 2023 · 15 comments
Open

C++ header validation fails for MSVC remote compile #19733

jayconrod opened this issue Oct 4, 2023 · 15 comments
Labels
help wanted Someone outside the Bazel team could own this P3 We're not considering working on this, but happy to review a PR. (No assignee) team-Rules-CPP Issues for C++ rules type: bug

Comments

@jayconrod
Copy link
Contributor

Description of the bug:

When building a cc_library that includes header files on Windows using an MSVC toolchain with remote execution, I get this error:

ERROR: C:/users/jay/code/engflow-example/cpp/BUILD:1:10: Compiling cpp/main.cc failed: undeclared inclusion(s) in rule '//cpp:cpp':
this rule is missing dependency declarations for the following files included by 'cpp/main.cc':
  'C:/_b/gjo2whp5/execroot/ws/cpp/hello.h'

Which category does this issue belong to?

C++/Objective-C Rules

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

You will need a remote execution service with Windows that can execute actions in containers. I think that makes this difficult to reproduce, though maybe Google has something internally that might work? I'm working on this at EngFlow.

Assuming you have that:

  1. Checkout cpp: rewrite example to have library, binary, and test EngFlow/example#243
  2. bazel build --config=remote_windows_x64 //cpp:cpp_lib (add --remote_executor and any other necessary flags).

Which operating system are you running Bazel on?

Windows Server 2022

What is the output of bazel info release?

release 6.3.2

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

n/a

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

n/a

Is this a regression? If yes, please try to identify the Bazel commit where the bug was introduced.

No.

Have you found anything relevant by searching the web?

Issue #9172 - Windows: Bazel cannot share cpp cache between two projects with different workspace name

PR #9188 - Windows: Ignore workspace name differences while doing header checking

PR #13339 - Remote: Use execRoot as input root and do NOT set working directory by default.

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

I spent the morning poking through the source code to figure out how this works. It looks like Bazel's CppCompile action is trying to validate that 1) headers included from srcs are in either srcs or direct dependencies' hdrs, and 2) headers are not included with absolute paths.

For MSVC, Bazel accomplishes that by enabling the /showincludes flag, which tells MSVC to print the path of each included file. The paths are absolute. The full output from one of these actions looks like this:

hello.cc
Note: including file: C:\worker\work\2\execroot\ws\cpp/hello.h
Note: including file:  C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\string
Note: including file:   C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\yvals_core.h
Note: including file:    C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\vcruntime.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\sal.h
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\concurrencysal.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\vadefs.h
Note: including file:    C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xkeycheck.h
Note: including file:   C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xstring
Note: including file:    C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\iosfwd
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\yvals.h
Note: including file:      C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\crtdbg.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt.h
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\vcruntime_new_debug.h
Note: including file:        C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\vcruntime_new.h
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\crtdefs.h
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\use_ansi.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cstdio
Note: including file:      C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\stdio.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wstdio.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_stdio_config.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cstring
Note: including file:      C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\string.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_memory.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_memcpy_s.h
Note: including file:         C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\errno.h
Note: including file:         C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\vcruntime_string.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wstring.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cwchar
Note: including file:      C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\wchar.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wconio.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wctype.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wdirect.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wio.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_share.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wprocess.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wstdlib.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_wtime.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\sys/stat.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\sys/types.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xstddef
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cstddef
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\stddef.h
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xtr1common
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cstdlib
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\math.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_math.h
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\stdlib.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_malloc.h
Note: including file:        C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_search.h
Note: including file:        C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\limits.h
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\initializer_list
Note: including file:    C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xmemory
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cstdint
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\stdint.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\limits
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cfloat
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\float.h
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\climits
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\intrin0.h
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\intrin0.inl.h
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\isa_availability.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\new
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\exception
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\type_traits
Note: including file:       C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\malloc.h
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\vcruntime_exception.h
Note: including file:        C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\eh.h
Note: including file:         C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\corecrt_terminate.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xatomic.h
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\xutility
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\utility
Note: including file:   C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include\cctype
Note: including file:    C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt\ctype.h

This line is the one that matters:

Note: including file: C:\worker\work\2\execroot\ws\cpp/hello.h

This is not hermetic. The path of the execroot could be anything. Here's it's C:\worker\work\2\execroot\ws. Normally it would be C:\worker\work\2\exec, but I've hacked it in this build to try and work around the issue (no luck).

In ShowIncludeFilter, Bazel uses a regular expression to replace everything up to .*execroot\\ with ../, so that turns into ../ws/cpp/hello.h. Later, that's joined with the local execroot within the workspace, so C:/_b/gjo2whp5/execroot/ws/cpp/hello.h, which is the path we see in the error message.

Bazel expects the path to be C:/_b/gjo2whp5/execroot/example/cpp/hello.h (example is the name of the workspace). Because it does not match, Bazel reports an error.

Tagging @meteorcloudy and @coeuvre who I think might have ideas on how to fix this. I'd be happy to work on this, but I'll need some guidance on what the solution should be and whether there's a good way to test it.

@fmeum
Copy link
Collaborator

fmeum commented Oct 5, 2023

With Bzlmod, the workspace name will always be the fixed (and relatively short) string _main. That could help.

@meteorcloudy
Copy link
Member

@jayconrod Can you check if this is still a problem with Bzlmod turned on?

@jayconrod
Copy link
Contributor Author

Bzlmod does indeed help. The build succeeded after:

  1. I created a trivial MODULE.bazel file in that repo.
  2. I change the remote execution server's execroot path to end with execroot/_main.

That's not really a satisfying solution though: many of our customers aren't using bzlmod yet, and Bazel shouldn't be sensitive to the execroot directory path anyway.

I don't think there's a way for Bazel to easily discover the execroot path from a remote action, nor is there a way for the remote server to discover the workspace name.

I was thinking about a solution where we "solve" for the execroot path from the compiler output? Basically, take the strings whose suffixes are the allowed include files, trim the common prefix?

@meteorcloudy
Copy link
Member

I was thinking about a solution where we "solve" for the execroot path from the compiler output? Basically, take the strings whose suffixes are the allowed include files, trim the common prefix?

Sorry, I don't quite understand this, can you explain this by an example? Thanks!

@jayconrod
Copy link
Contributor Author

Sure. Let's say the compiler gives you output like this (omitting lines that match system include prefixes):

Note: including file: C:\worker\work\2\exec\a.h
Note: including file: C:\worker\work\2\exec\inc/b.h
Note: including file: C:\worker\work\2\exec\inc/nest/c.h

Allowed header paths including workspace names might be:

example/a.h
example/inc/b.h

Dropping the workspace name from the path:

a.h
inc/b.h

We can match those suffixes against the compiler output to determine that C:\worker\work\2\exec\ is the execroot path. We could trim that from all other paths, then proceed with the validation.

I'm unsure about a lot of details here, particular whether this would work for external repositories and bzlmod. WDYT?

@meteorcloudy
Copy link
Member

We can match those suffixes against the compiler output to determine that C:\worker\work\2\exec\ is the execroot path.

How will this work exactly? What if there are multiple matches?

For example, the compiler output is

Note: including file: C:\worker\work\2\exec\a.h
Note: including file: C:\worker\work\2\exec\foo\a.h
Note: including file: C:\worker\work\2\exec\bar\a.h

and allowed header path is

example/a.h

I'm unsure about a lot of details here, particular whether this would work for external repositories and bzlmod. WDYT?

I think Bzlmod should only make it easier.

For headers in the main repo, the path should be
<execroot>/_main/<package path>/<header file>
For headers in the external repo, the path should be
<execroot>/_main/external/<canonical repo name>/<package path>/<header file>

So if <execroot> doesn't contain _main as a folder name, we can probably just look for _main and strip away to execroot path.

@jayconrod
Copy link
Contributor Author

I spent some time sketching out a function in Python-like pseudocode that would do what I mean. Given a set of absolute include paths, a predicate that checks whether an absolute path is a system include, and a predicate that checks whether an execroot-relative path is a valid source file, it should infer the execroot prefix.

Assuming that is_artifact function can be implemented, I think this will work pretty well. ArtifactResolver.resolveSourceArtifact is what HeaderDiscovery uses, and I think that's nearly exactly it, but I'm not sure it's safe to call speculatively. WDYT?

# Infers a common execroot directory prefix from a set of includes.
#
# include_paths is a set of absolute paths of included files, printed by MSVC.
# It may contain system includes and invalid includes.
#
# is_system_include is a function that returns whether an absolute include path
# starts with system include prefix that's part of the toolchain. These
# includes are not used to infer the execroot.
# 
# is_artifact is a function that accepts a path relative to the execroot
# and returns whether it's a file that exists and may be included (source or
# derived).
def infer_execroot_from_includes(
    include_paths,
    is_system_include,
    is_artifact):

  # First pass: gather all paths that could be the execroot .
  candidates = set()
  invalid_include_paths = set()
  for include_path in include_paths:
    if is_system_include(include_path):
      continue

    i = 0
    n = path_component_count(include_path)
    did_match = False
    while i < n:
      prefix, suffix = split_path(include_path, i)
      if is_artifact(suffix):
        add_to_set(candidates, suffix)
        did_match = True
    if not did_match:
      add_to_set(invalid_include_paths, include_path)
  found_candidates = len(candidates) > 0

  # Second pass: discard paths that are not valid for all includes.
  # Ignore system includes and invalid includes.
  for include_path in include_paths:
    if is_system_include(include_path) or
       set_contains(invalid_include_paths, include_path):
      continue
    for candidate in candidates:
      if not has_prefix(include_path, candidate) or
         not is_artifact(trim_prefix(include_path, candidate)):
        remove_from_set(candidates, candidate)

  if len(candidates) > 1:
    # If there are multiple candidates remaining, return the shortest one.
    # This is unlikely, but all valid includes will still be valid
    # regardless of what we choose, and this discards the least information.
    candidates_list = list(candidates)
    sort candidates_list by len
    return candidates_list[0]
  elif len(candidates) == 1:
    # We found exactly one possible execroot.
    return one(candidates)
  elif found_candidates:
    # We found some candidates initially but eliminated all. This is unlikely
    # but may happen if an invalid include shares a suffix with a valid
    # include, so we couldn't accurately find an execroot prefix.
    report error
  elif len(invalid_includes) > 0:
    # We found no candidates, and there was at least one invalid include.
    report error
  else:
    # No candidates, no invalid includes. This means there were no includes
    # except system includes.
    return None

@meteorcloudy
Copy link
Member

@jayconrod Thanks for writing up the code! But sorry I'll have to check this later, this week I'll focus on flipping Bzlmod by default before Bazel 7 cut.

@jayconrod
Copy link
Contributor Author

Fair enough, that's important. I'll ping this issue after BazelCon. Again, I'd be happy to write this up as a real fix, but I want to make sure this approach sounds reasonable before I spend time on that.

I've prepared a workaround today: instead of invoking cl.exe, I've configured the toolchain to invoke a wrapper program that invokes cl.exe then filters out directories prefixes that look like our execroots. I think that will unblock us in the short term.

@meteorcloudy
Copy link
Member

@jayconrod Thanks!!

jayconrod added a commit to EngFlow/example that referenced this issue Oct 10, 2023
A single file is too simple.

Also, fix the toolchain to work around
bazelbuild/bazel#19733.
jayconrod added a commit to EngFlow/example that referenced this issue Oct 11, 2023
The Windows MSVC toolchain now invokes a wrapper binary when compiling
instead of cl.exe. The wrapper binary invokes cl.exe with all arguments
but filters /showincludes output, removing EngFlow execroot paths.

For example, the line:

    Note: including file: C:\worker\work\2\exec\cpp\hello.h

is replaced with:

    Note: including file: cpp\hello.h

This is a workaround for bazelbuild/bazel#19733. Bazel invokes the compiler
with /showincludes to dump all included headers in order to validate them.
It strips anything that looks like a local execroot directory followed by
the workspace name before performing that validation. EngFlow execroot
directories don't look like local execroot directories though. We also don't
know Bazel's workspace name, so we can't work around this issue on the
server side. Using a wrapper like this instead makes the CppCompile action
slightly more hermetic by filtering out those absolute paths.

For linear/CUS-81

We'll open source this wrapper tool in a follow-up.

Also: change line endings in cpp/main.cc to be LF instead of CRLF.
jayconrod added a commit to EngFlow/example that referenced this issue Oct 11, 2023
#244)

The Windows MSVC toolchain now invokes a wrapper binary when compiling
instead of cl.exe. The wrapper binary invokes cl.exe with all arguments
but filters /showincludes output, removing EngFlow execroot paths.

For example, the line:

    Note: including file: C:\worker\work\2\exec\cpp\hello.h

is replaced with:

    Note: including file: cpp\hello.h

This is a workaround for bazelbuild/bazel#19733. Bazel invokes the compiler
with /showincludes to dump all included headers in order to validate them.
It strips anything that looks like a local execroot directory followed by
the workspace name before performing that validation. EngFlow execroot
directories don't look like local execroot directories though. We also don't
know Bazel's workspace name, so we can't work around this issue on the
server side. Using a wrapper like this instead makes the CppCompile action
slightly more hermetic by filtering out those absolute paths.

For linear/CUS-81

We'll open source this wrapper tool in a follow-up.

Also: change line endings in cpp/main.cc to be LF instead of CRLF.
jayconrod added a commit to EngFlow/example that referenced this issue Oct 16, 2023
This is a wrapper around the cl.exe compiler for Windows MSVC toolchains.
It works around bazelbuild/bazel#19733 by filtering EngFlow execroot
directories out of MSVC's /showincludes output so Bazel does not see them.
The package documentation explains this is more detail.

For linear/PE-1127, linear/CUS-81, linear/CUS-64, linear/PE-1434
jayconrod added a commit to EngFlow/example that referenced this issue Oct 17, 2023
This is a wrapper around the cl.exe compiler for Windows MSVC toolchains.
It works around bazelbuild/bazel#19733 by filtering EngFlow execroot
directories out of MSVC's /showincludes output so Bazel does not see them.
The package documentation explains this is more detail.

For linear/PE-1127, linear/CUS-81, linear/CUS-64, linear/PE-1434
jayconrod added a commit to EngFlow/example that referenced this issue Oct 17, 2023
This is a wrapper around the cl.exe compiler for Windows MSVC toolchains.
It works around bazelbuild/bazel#19733 by filtering EngFlow execroot
directories out of MSVC's /showincludes output so Bazel does not see them.
The package documentation explains this is more detail.

For linear/PE-1127, linear/CUS-81, linear/CUS-64, linear/PE-1434
@comius comius added P3 We're not considering working on this, but happy to review a PR. (No assignee) and removed untriaged labels Nov 27, 2023
@TimotheusBachinger
Copy link

I stumbled across that issue while experimenting with BRE from linux to windows and using MSVC compiler.
I am not sure if I understood everything correct here but you might be able to point me torwards a solution.

I basically use https://github.com/EngFlow/example as basis to compile a simple hello_world which only incudes iostream but it fails with undeclared inclusion(s).
It seems I can "fix" it by defining literally every single included header explicitly but it fails when I only pass the directory:

FAILURE: Only pass the include directory - this SHOULD work IMHO

# windows_x64/BUILD
....
    cxx_builtin_include_directories = [
        "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.40.33807\\include",
....
$ bazel build --config=mywinvm cpp:hello_world
....
ERROR: /home/timotheus/git_external/example/cpp/BUILD:10:10: Compiling cpp/hello_world.cc failed: undeclared inclusion(s) in rule '//cpp:hello_world':
this rule is missing dependency declarations for the following files included by 'cpp/hello_world.cc':
  'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\iostream'

SUCCESS: Passing the explicit path to the header

# windows_x64/BUILD
....
    cxx_builtin_include_directories = [
        "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.40.33807\\include\\iostream",
....
$ bazel build --config=mywinvm cpp:hello_world
....
INFO: Build completed successfully, 3 total actions

Is this related?

@meteorcloudy meteorcloudy added the help wanted Someone outside the Bazel team could own this label Jul 5, 2024
@TimotheusBachinger
Copy link

Today I took some time to debug about regarding what bazel is actually doing.
Assuming my system includes reside here:

C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\

I would then expect validateInclude to match here:

FileSystemUtils.startsWithAny(include.getExecPath(), ignoreDirs);

which again should return true here:

|| normalizedPath.charAt(other.normalizedPath.length()) == SEPARATOR_CHAR;

However, when debugging, I can see that SEPARTOR_CHAR=/, OS.additionalSeparator() returns 0 and therefore OS= com.google.devtools.build.lib.vfs.UnixOsPathPolicy@76adb233 which made me wondering: is bazel not realizing the build is executed on a windows machine?

@meteorcloudy
Copy link
Member

@TimotheusBachinger If you host machine is linux, indeed, Bazel won't be able to handle the paths correctly for Windows.. In general, cross platform builds between Windows and unix don't work well.

@TimotheusBachinger
Copy link

@meteorcloudy hum... so I am misunderstanding the whole concept? I assumed the path inclusion validation is executed on my (windows) remote executor?
I mean at the moment, I can work-around... but I hoped bazel remote executions would exactly address that scenario to build remotely on a different OS.

@meteorcloudy
Copy link
Member

Unfortunately not, as you can see the code is still java code of the bazel server, it's executed where the Bazel server is running on. I'm not sure what's the best way to resolve this. /cc @comius @coeuvre

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Someone outside the Bazel team could own this P3 We're not considering working on this, but happy to review a PR. (No assignee) team-Rules-CPP Issues for C++ rules type: bug
Projects
None yet
Development

No branches or pull requests

8 participants