You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"""Gets the ({source files}, {header files}) clangd should be told the command applies to."""
554
554
555
555
# Getting the source file is a little trickier than it might seem.
556
-
# Bazel seems to consistently put the source file being compiled either:
557
-
# before the -o flag, for GCC-formatted commands, or
558
-
# after the /c flag, for MSVC-formatted commands
559
-
# [See https://github.com/hedronvision/bazel-compile-commands-extractor/pull/72 for -c counterexample for GCC]
560
-
# This is a strong assumption about Bazel internals, so we're taking some care to check that this condition holds with asserts. That way things are less likely to fail silently if it changes some day.
561
-
# You can definitely have a proper invocation to clang/gcc/msvc where these assumptions don't hold.
556
+
557
+
# First, we do the obvious thing: Filter args to those that look like source files.
assertsource_file_candidates, f"No source files found in compile args: {compile_action.arguments}.\nPlease file an issue with this information!"
560
+
source_file=source_file_candidates[0]
561
+
562
+
# If we've got multiple candidates for source files, apply heuristics based on how Bazel tends to format commands.
563
+
# Note: Bazel, with its incremental building strategy, should only be compiling one source file per action.
564
+
iflen(source_file_candidates) >1:
565
+
# How does this case arise? Sometimes header search directories have source-file extensions. Horrible, but unfortunately true. See https://github.com/hedronvision/bazel-compile-commands-extractor/pull/37 for context and history.
566
+
# You can't simply further filter the args to those that aren't existing directories...because they can be generated directories that don't yet exist. Indeed the example in the PR (linked above) is this case.
567
+
# Bazel seems to consistently put the source file being compiled either:
568
+
# before the -o flag, for GCC-formatted commands, or
569
+
# after the /c flag, for MSVC-formatted commands
570
+
# [See https://github.com/hedronvision/bazel-compile-commands-extractor/pull/72 for -c counterexample for GCC]
571
+
# This is a strong assumption about Bazel internals, so we're taking some care to check that this condition holds with asserts. That way things are less likely to fail silently if it changes some day.
572
+
# You can definitely have a proper invocation to clang/gcc/msvc where these assumptions don't hold.
562
573
# However, parsing the command line this way is our best simple option. The other alternatives seem worse:
563
-
# You can't just filter the args to those that end with source-file extensions. The problem is that sometimes header search directories have source-file extensions. Horrible, but unfortunately true. See https://github.com/hedronvision/bazel-compile-commands-extractor/pull/37 for context and history.
564
-
# Parsing the clang invocation properly to get the positional file arguments is hard and not future-proof if new flags are added. Consider a new flag -foo. Does it also capture the next argument after it?
565
-
# Similarly, you can't just further filter the args to those that don't begin with - and aren't directories...because they can be generated directories. Indeed the example from the PR (above) is.
574
+
# Parsing the clang invocation properly to get the positional file arguments is hard and not future-proof if new flags are added. Consider a new flag -foo. Does it also capture the next argument after it?
566
575
# You might be tempted to crawl the inputs depset in the aquery output structure, but it's a fair amount of recursive code and there are other erroneous source files there, at least when building for Android in Bazel 5.1. You could fix this by intersecting the set of source files in the inputs with those listed as arguments on the command line, but I can imagine perverse, problematic cases here. It's a lot more code to still have those caveats.
567
576
# You might be tempted to get the source files out of the action message listed (just) in aquery --output=text output, but the message differs for external workspaces and tools. Plus paths with spaces are going to be hard because it's space delimited. You'd have to make even stronger assumptions than the -c.
568
577
# Concretely, the message usually has the form "action 'Compiling foo.cpp'"" -> foo.cpp. But it also has "action 'Compiling src/tools/launcher/dummy.cc [for tool]'" -> external/bazel_tools/src/tools/launcher/dummy.cc
569
578
# If we did ever go this route, you can join the output from aquery --output=text and --output=jsonproto by actionKey.
570
-
571
-
if'-o'incompile_action.arguments: # GCC, pre -o case
assert'/c'incompile_action.arguments, f"-o or /c, required for parsing sources in GCC or MSVC-formatted commands, respectively, not found in compile args: {compile_action.arguments}.\nPlease file an issue with this information!"
assertsource_file.endswith(_get_files.source_extensions), f"Source file candidate, {source_file}, seems to be wrong.\nSelected from {compile_action.arguments}.\nPlease file an issue with this information!"
579
+
if'-o'incompile_action.arguments: # GCC, pre -o case
assert'/c'incompile_action.arguments, f"-o or /c, required for parsing sources in GCC or MSVC-formatted commands, respectively, not found in compile args: {compile_action.arguments}.\nPlease file an issue with this information!"
assertsource_file.endswith(_get_files.source_extensions), f"Source file candidate, {source_file}, seems to be wrong.\nSelected from {compile_action.arguments}.\nPlease file an issue with this information!"
0 commit comments