diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java index 74002a724aa770..8b9c7d496679e1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationContext.java @@ -94,6 +94,16 @@ public final class CcCompilationContext implements CcCompilationContextApi virtualToOriginalHeaders; + + /** + * Preserves mappings of _virtual_include directories to original paths relative to + * the workspace directory. Intended for use by compiler options like GCC's + * {@code -fdebug-prefix-map}. See {@link virtualToOriginalHeaders} for additional + * context. Unlike {@link virtualToOriginalHeaders}, this is populated even if + * coverage isn't enabled. + */ + private final NestedSet virtualToOriginalDirs; + /** * Caches the actual number of transitive headers reachable through transitiveHeaderInfos. We need * to create maps to store these and so caching this count can substantially help with memory @@ -116,6 +126,7 @@ private CcCompilationContext( CppModuleMap cppModuleMap, boolean propagateModuleMapAsActionInput, NestedSet virtualToOriginalHeaders, + NestedSet virtualToOriginalDirs, NestedSet headerTokens) { Preconditions.checkNotNull(commandLineCcCompilationContext); this.commandLineCcCompilationContext = commandLineCcCompilationContext; @@ -130,6 +141,7 @@ private CcCompilationContext( this.compilationPrerequisites = compilationPrerequisites; this.propagateModuleMapAsActionInput = propagateModuleMapAsActionInput; this.virtualToOriginalHeaders = virtualToOriginalHeaders; + this.virtualToOriginalDirs = virtualToOriginalDirs; this.transitiveHeaderCount = -1; this.headerTokens = headerTokens; } @@ -253,6 +265,12 @@ public Depset getStarlarkVirtualToOriginalHeaders(StarlarkThread thread) throws return Depset.of(Tuple.class, getVirtualToOriginalHeaders()); } + @Override + public Depset getStarlarkVirtualToOriginalDirs(StarlarkThread thread) throws EvalException { + CcModule.checkPrivateStarlarkificationAllowlist(thread); + return Depset.of(Tuple.class, getVirtualToOriginalDirs()); + } + @Override @Nullable public CppModuleMap getStarlarkModuleMap(StarlarkThread thread) throws EvalException { @@ -648,6 +666,7 @@ public static CcCompilationContext createWithExtraHeaderTokens( ccCompilationContext.cppModuleMap, ccCompilationContext.propagateModuleMapAsActionInput, ccCompilationContext.virtualToOriginalHeaders, + ccCompilationContext.virtualToOriginalDirs, headerTokens.build()); } @@ -665,6 +684,10 @@ public NestedSet getVirtualToOriginalHeaders() { return virtualToOriginalHeaders; } + public NestedSet getVirtualToOriginalDirs() { + return virtualToOriginalDirs; + } + /** * The parts of the {@code CcCompilationContext} that influence the command line of compilation * actions. @@ -725,6 +748,7 @@ public static class Builder { private CppModuleMap cppModuleMap; private boolean propagateModuleMapAsActionInput = true; private final NestedSetBuilder virtualToOriginalHeaders = NestedSetBuilder.stableOrder(); + private final NestedSetBuilder virtualToOriginalDirs = NestedSetBuilder.stableOrder(); private final NestedSetBuilder headerTokens = NestedSetBuilder.stableOrder(); /** Creates a new builder for a {@link CcCompilationContext} instance. */ @@ -799,6 +823,8 @@ private void mergeDependentCcCompilationContext( allDefines.addTransitive(otherCcCompilationContext.getDefines()); virtualToOriginalHeaders.addTransitive( otherCcCompilationContext.getVirtualToOriginalHeaders()); + virtualToOriginalDirs.addTransitive( + otherCcCompilationContext.getVirtualToOriginalDirs()); headerTokens.addTransitive(otherCcCompilationContext.getHeaderTokens()); } @@ -1073,6 +1099,12 @@ public Builder addVirtualToOriginalHeaders(NestedSet virtualToOriginalHea return this; } + @CanIgnoreReturnValue + public Builder addVirtualToOriginalDirs(NestedSet virtualToOriginalDirs) { + this.virtualToOriginalDirs.addTransitive(virtualToOriginalDirs); + return this; + } + /** Builds the {@link CcCompilationContext}. */ public CcCompilationContext build() { TransitiveSetHelper allDefines = new TransitiveSetHelper<>(); @@ -1114,6 +1146,7 @@ public CcCompilationContext build() { cppModuleMap, propagateModuleMapAsActionInput, virtualToOriginalHeaders.build(), + virtualToOriginalDirs.build(), headerTokens.build()); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java index 330068def2ad85..c44b2a53bdd137 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCompilationHelper.java @@ -1332,7 +1332,8 @@ private CcToolchainVariables setupCompileBuildVariables( ccCompilationContext.getSystemIncludeDirs(), ccCompilationContext.getFrameworkIncludeDirs(), ccCompilationContext.getDefines(), - ccCompilationContext.getNonTransitiveDefines()); + ccCompilationContext.getNonTransitiveDefines(), + ccCompilationContext.getVirtualToOriginalDirs()); if (usePrebuiltParent) { parent = buildVariables.build(); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java index a40e3509b6fe7a..9daed4cfe8d11d 100755 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java @@ -369,7 +369,8 @@ public CcToolchainVariables getCompileBuildVariables( Depset.noneableCast( frameworkIncludeDirs, String.class, "framework_include_directories"), Depset.noneableCast(defines, String.class, "preprocessor_defines").toList(), - ImmutableList.of())) + ImmutableList.of(), + /* virtualToOriginalDirs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER))) .addStringSequenceVariable("stripopts", asClassImmutableList(stripOpts)); String inputFileString = convertFromNoneable(inputFile, null); if (inputFileString != null) { @@ -807,6 +808,7 @@ public CcCompilationContext createCcCompilationContext( Object labelForMiddlemanNameObject, Object externalIncludes, Object virtualToOriginalHeaders, + Object virtualToOriginalDirs, Sequence dependentCcCompilationContexts, Sequence nonCodeInputs, Sequence looseHdrsDirsObject, @@ -878,6 +880,9 @@ public CcCompilationContext createCcCompilationContext( ccCompilationContext.addVirtualToOriginalHeaders( Depset.cast(virtualToOriginalHeaders, Tuple.class, "virtual_to_original_headers")); + ccCompilationContext.addVirtualToOriginalDirs( + Depset.cast(virtualToOriginalDirs, Tuple.class, "virtual_to_original_dirs")); + ccCompilationContext.addDependentCcCompilationContexts( Sequence.cast( dependentCcCompilationContexts, diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java index 820aa760424e18..5f83f13e4f5337 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java @@ -31,6 +31,7 @@ import java.util.Map; import net.starlark.java.eval.EvalException; import net.starlark.java.eval.StarlarkThread; +import net.starlark.java.eval.Tuple; /** Enum covering all build variables we create for all various {@link CppCompileAction}. */ public enum CompileBuildVariables { @@ -130,7 +131,12 @@ public enum CompileBuildVariables { /** Path to the memprof profile artifact */ MEMPROF_PROFILE_PATH("memprof_profile_path"), /** Variable for includes that compiler needs to include into sources. */ - INCLUDES("includes"); + INCLUDES("includes"), + /** + * A list of VIRTUAL=ORIGINAL include paths for "virtual" includes. + * Intended for use with gcc's -fdebug-prefix-map. + */ + VIRTUAL_TO_ORIGINAL_DIRS("virtual_to_original_dirs"); private final String variableName; @@ -166,7 +172,8 @@ public static CcToolchainVariables setupVariablesOrReportRuleError( NestedSet systemIncludeDirs, NestedSet frameworkIncludeDirs, Iterable defines, - Iterable localDefines) + Iterable localDefines, + NestedSet virtualToOriginalDirs) throws InterruptedException { try { if (usePic @@ -201,7 +208,8 @@ public static CcToolchainVariables setupVariablesOrReportRuleError( getSafePathStrings(systemIncludeDirs), getSafePathStrings(frameworkIncludeDirs), defines, - localDefines); + localDefines, + virtualToOriginalDirs); } catch (EvalException e) { ruleErrorConsumer.ruleError(e.getMessage()); return CcToolchainVariables.EMPTY; @@ -235,7 +243,8 @@ public static CcToolchainVariables setupVariablesOrThrowEvalException( NestedSet systemIncludeDirs, NestedSet frameworkIncludeDirs, Iterable defines, - Iterable localDefines) + Iterable localDefines, + NestedSet virtualToOriginalDirs) throws EvalException, InterruptedException { if (usePic && !featureConfiguration.isEnabled(CppRuleClasses.PIC) @@ -269,7 +278,8 @@ public static CcToolchainVariables setupVariablesOrThrowEvalException( systemIncludeDirs, frameworkIncludeDirs, defines, - localDefines); + localDefines, + virtualToOriginalDirs); } private static CcToolchainVariables setupVariables( @@ -299,7 +309,8 @@ private static CcToolchainVariables setupVariables( NestedSet systemIncludeDirs, NestedSet frameworkIncludeDirs, Iterable defines, - Iterable localDefines) { + Iterable localDefines, + NestedSet virtualToOriginalDirs) { CcToolchainVariables.Builder buildVariables = CcToolchainVariables.builder(parent); setupCommonVariablesInternal( buildVariables, @@ -315,7 +326,8 @@ private static CcToolchainVariables setupVariables( systemIncludeDirs, frameworkIncludeDirs, defines, - localDefines); + localDefines, + virtualToOriginalDirs); setupSpecificVariables( buildVariables, sourceFile, @@ -430,7 +442,8 @@ public static void setupCommonVariables( List systemIncludeDirs, List frameworkIncludeDirs, Iterable defines, - Iterable localDefines) { + Iterable localDefines, + NestedSet virtualToOriginalDirs) { setupCommonVariablesInternal( buildVariables, featureConfiguration, @@ -445,7 +458,8 @@ public static void setupCommonVariables( getSafePathStrings(systemIncludeDirs), getSafePathStrings(frameworkIncludeDirs), defines, - localDefines); + localDefines, + virtualToOriginalDirs); } private static void setupCommonVariablesInternal( @@ -462,7 +476,8 @@ private static void setupCommonVariablesInternal( NestedSet systemIncludeDirs, NestedSet frameworkIncludeDirs, Iterable defines, - Iterable localDefines) { + Iterable localDefines, + NestedSet virtualToOriginalDirs) { Preconditions.checkNotNull(directModuleMaps); Preconditions.checkNotNull(includeDirs); Preconditions.checkNotNull(quoteIncludeDirs); @@ -470,6 +485,7 @@ private static void setupCommonVariablesInternal( Preconditions.checkNotNull(frameworkIncludeDirs); Preconditions.checkNotNull(defines); Preconditions.checkNotNull(localDefines); + Preconditions.checkNotNull(virtualToOriginalDirs); if (featureConfiguration.isEnabled(CppRuleClasses.MODULE_MAPS) && cppModuleMap != null) { buildVariables.addStringVariable(MODULE_NAME.getVariableName(), cppModuleMap.getName()); @@ -510,6 +526,17 @@ private static void setupCommonVariablesInternal( buildVariables.addStringSequenceVariable(PREPROCESSOR_DEFINES.getVariableName(), allDefines); + if (!virtualToOriginalDirs.isEmpty()) { + buildVariables.addStringSequenceVariable( + VIRTUAL_TO_ORIGINAL_DIRS.getVariableName(), + Iterables.transform( + virtualToOriginalDirs.toList(), + vToA -> vToA.get(0) + "=" + vToA.get(1))); + } else { + buildVariables.addStringSequenceVariable(VIRTUAL_TO_ORIGINAL_DIRS.getVariableName(), + ImmutableList.of()); + } + buildVariables.addAllStringVariables(additionalBuildVariables); for (VariablesExtension extension : variablesExtensions) { extension.addVariables(buildVariables); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java index 030fd3f20ddf91..d2065cfa5c7955 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java @@ -198,8 +198,8 @@ private static CcToolchainVariables getVariables( ccToolchainProvider, fdoBuildStamp, codeCoverageEnabled), - /* localDefines= */ ImmutableList.of()); - } catch (EvalException e) { + /* localDefines= */ ImmutableList.of(), + /* virtualToOriginalDirs= */ NestedSetBuilder.emptySet(Order.STABLE_ORDER)); } catch (EvalException e) { throw new RuleErrorException(e.getMessage()); } } diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcCompilationContextApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcCompilationContextApi.java index 22938fc0c5d22e..3cdcc7740fee14 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcCompilationContextApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcCompilationContextApi.java @@ -169,6 +169,12 @@ public interface CcCompilationContextApi< useStarlarkThread = true) Depset getStarlarkVirtualToOriginalHeaders(StarlarkThread thread) throws EvalException; + @StarlarkMethod( + name = "virtual_to_original_dirs", + documented = false, + useStarlarkThread = true) + Depset getStarlarkVirtualToOriginalDirs(StarlarkThread thread) throws EvalException; + @StarlarkMethod( name = "module_map", documented = false, diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcModuleApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcModuleApi.java index f6817f50923114..754140a994cbb1 100755 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcModuleApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcModuleApi.java @@ -1279,6 +1279,12 @@ LinkingContextT createCcLinkingInfo( positional = false, named = true, defaultValue = "unbound"), + @Param( + name = "virtual_to_original_dirs", + documented = false, + positional = false, + named = true, + defaultValue = "unbound"), @Param( name = "dependent_cc_compilation_contexts", documented = false, @@ -1363,6 +1369,7 @@ CompilationContextT createCcCompilationContext( Object labelForMiddlemanNameObject, Object externalIncludes, Object virtualToOriginalHeaders, + Object virtualToOriginalDirs, Sequence dependentCcCompilationContexts, Sequence nonCodeInputs, Sequence looseHdrsDirs, diff --git a/src/main/starlark/builtins_bzl/common/cc/cc_common.bzl b/src/main/starlark/builtins_bzl/common/cc/cc_common.bzl index 4983b98c846e6e..b4b02e32995291 100644 --- a/src/main/starlark/builtins_bzl/common/cc/cc_common.bzl +++ b/src/main/starlark/builtins_bzl/common/cc/cc_common.bzl @@ -432,6 +432,7 @@ def _create_compilation_context( label = _UNBOUND, external_includes = _UNBOUND, virtual_to_original_headers = _UNBOUND, + virtual_to_original_dirs = _UNBOUND, dependent_cc_compilation_contexts = _UNBOUND, non_code_inputs = _UNBOUND, headers_checking_mode = _UNBOUND, @@ -447,6 +448,7 @@ def _create_compilation_context( actions != _UNBOUND or \ external_includes != _UNBOUND or \ virtual_to_original_headers != _UNBOUND or \ + virtual_to_original_dirs != _UNBOUND or \ dependent_cc_compilation_contexts != _UNBOUND or \ non_code_inputs != _UNBOUND or \ headers_checking_mode != _UNBOUND or \ @@ -471,6 +473,8 @@ def _create_compilation_context( external_includes = depset() if virtual_to_original_headers == _UNBOUND: virtual_to_original_headers = depset() + if virtual_to_original_dirs == _UNBOUND: + virtual_to_original_dirs = depset() if dependent_cc_compilation_contexts == _UNBOUND: dependent_cc_compilation_contexts = [] if non_code_inputs == _UNBOUND: @@ -508,6 +512,7 @@ def _create_compilation_context( label = label, external_includes = external_includes, virtual_to_original_headers = virtual_to_original_headers, + virtual_to_original_dirs = virtual_to_original_dirs, dependent_cc_compilation_contexts = dependent_cc_compilation_contexts, non_code_inputs = non_code_inputs, loose_hdrs_dirs = [], diff --git a/src/main/starlark/builtins_bzl/common/cc/cc_compilation_helper.bzl b/src/main/starlark/builtins_bzl/common/cc/cc_compilation_helper.bzl index 28a255223de336..1407bb2dbd4e76 100644 --- a/src/main/starlark/builtins_bzl/common/cc/cc_compilation_helper.bzl +++ b/src/main/starlark/builtins_bzl/common/cc/cc_compilation_helper.bzl @@ -102,10 +102,12 @@ def _compute_public_headers( module_map_headers = public_headers_artifacts, virtual_include_path = None, virtual_to_original_headers = depset(), + virtual_to_original_dirs = depset(), ) module_map_headers = [] virtual_to_original_headers_list = [] + original_sentinel = None for original_header in public_headers_artifacts: repo_relative_path = _repo_relative_path(original_header) if not repo_relative_path.startswith(strip_prefix): @@ -127,15 +129,33 @@ def _compute_public_headers( if config.coverage_enabled: virtual_to_original_headers_list.append((virtual_header.path, original_header.path)) + if original_sentinel == None: + original_sentinel = original_header + module_map_headers.append(original_header) virtual_headers = module_map_headers + non_module_map_headers + virtual_include_path = cc_internal.bin_or_genfiles_relative_to_unique_directory(actions = actions, unique_directory = _VIRTUAL_INCLUDES_DIR) + + if original_sentinel == None: + virtual_to_original_dirs = depset() + else: + virtual_dir = virtual_include_path + if include_prefix: + virtual_dir = paths.join(virtual_dir, include_prefix) + # rstrip in case `label.package` is "" (`paths.join('foo', '')` -> `foo/`), + # such as when the label refers to the target in the root/toplevel package + # of an external repository. + original_dir = paths.join(label.workspace_root, strip_prefix or label.package).rstrip("/") + virtual_to_original_dirs = depset(((virtual_dir, original_dir),)) # singleton + 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_include_path = virtual_include_path, virtual_to_original_headers = depset(virtual_to_original_headers_list), + virtual_to_original_dirs = virtual_to_original_dirs, ) def _generates_header_module(feature_configuration, public_headers, private_headers, generate_action): @@ -396,6 +416,7 @@ def _init_cc_compilation_context( system_includes = depset(system_include_dirs_for_context), includes = depset(include_dirs_for_context), virtual_to_original_headers = virtual_to_original_headers, + virtual_to_original_dirs = public_headers.virtual_to_original_dirs, dependent_cc_compilation_contexts = dependent_cc_compilation_contexts, non_code_inputs = additional_inputs, defines = depset(defines), @@ -425,6 +446,7 @@ def _init_cc_compilation_context( system_includes = depset(system_include_dirs_for_context), includes = depset(include_dirs_for_context), virtual_to_original_headers = virtual_to_original_headers, + virtual_to_original_dirs = public_headers.virtual_to_original_dirs, dependent_cc_compilation_contexts = dependent_cc_compilation_contexts + implementation_deps, non_code_inputs = additional_inputs, defines = depset(defines), diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD b/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD index 691b4ff598aad0..5854c155eaab79 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/BUILD @@ -177,6 +177,7 @@ java_test( "//src/main/java/com/google/devtools/build/lib/rules/cpp", "//src/main/java/com/google/devtools/build/lib/vfs", "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment", + "//src/main/java/net/starlark/java/eval", "//src/test/java/com/google/devtools/build/lib/actions/util", "//src/test/java/com/google/devtools/build/lib/analysis/util", "//src/test/java/com/google/devtools/build/lib/packages:testutil", diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java index 0ff004123e7d72..b7e1937fe310c0 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java @@ -43,6 +43,7 @@ import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.Root; import java.util.List; +import net.starlark.java.eval.Tuple; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -886,6 +887,18 @@ public void testIncludeManglingSmoke() throws Exception { getTargetConfiguration() .getBinFragment(RepositoryName.MAIN) .getRelative("third_party/a/_virtual_includes/a")); + + Tuple t = Tuple.of( + getTargetConfiguration() + .getBinFragment(RepositoryName.MAIN) + .getRelative("third_party/a/_virtual_includes/a/lib") + .getPathString(), + lib.getLabel() + .getPackageFragment() + .getRelative("v1") + .getPathString() + ); + assertThat(ccCompilationContext.getVirtualToOriginalDirs().toList()).containsExactly(t); } @Test @@ -917,12 +930,14 @@ public void testAbsoluteAndRelativeStripPrefix() throws Exception { "cc_library(name='relative', hdrs=['v1/b.h'], strip_include_prefix='v1')", "cc_library(name='absolute', hdrs=['v1/b.h'], strip_include_prefix='/third_party')"); + ConfiguredTarget relativeTarget = getConfiguredTarget("//third_party/a:relative"); + ConfiguredTarget absoluteTarget = getConfiguredTarget("//third_party/a:absolute"); CcCompilationContext relative = - getConfiguredTarget("//third_party/a:relative") + relativeTarget .get(CcInfo.PROVIDER) .getCcCompilationContext(); CcCompilationContext absolute = - getConfiguredTarget("//third_party/a:absolute") + absoluteTarget .get(CcInfo.PROVIDER) .getCcCompilationContext(); @@ -931,6 +946,26 @@ public void testAbsoluteAndRelativeStripPrefix() throws Exception { assertThat(ActionsTestUtil.prettyArtifactNames(absolute.getDeclaredIncludeSrcs())) .containsExactly( "third_party/a/_virtual_includes/absolute/a/v1/b.h", "third_party/a/v1/b.h"); + + Tuple tRel = Tuple.of( + getTargetConfiguration() + .getBinFragment(RepositoryName.MAIN) + .getRelative("third_party/a/_virtual_includes/relative") + .getPathString(), + relativeTarget + .getLabel() + .getPackageFragment() + .getRelative("v1") + .getPathString()); + assertThat(relative.getVirtualToOriginalDirs().toList()).containsExactly(tRel); + + Tuple tAbs = Tuple.of( + getTargetConfiguration() + .getBinFragment(RepositoryName.MAIN) + .getRelative("third_party/a/_virtual_includes/absolute") + .getPathString(), + "third_party"); + assertThat(absolute.getVirtualToOriginalDirs().toList()).containsExactly(tAbs); } @Test diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java index 9e163c15931267..60770b60a51499 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariablesTest.java @@ -369,6 +369,71 @@ public void testExternalIncludePathsVariable() throws Exception { .containsExactlyElementsIn(entries.build()); } + @Test + public void testVirtualToOriginalDirsVariable() throws Exception { + MockPlatformSupport.addMockK8Platform( + mockToolsConfig, analysisMock.ccSupport().getMockCrosstoolLabel()); + useConfiguration( + "--experimental_platforms=//mock_platform:mock-k8-platform", + "--extra_toolchains=//mock_platform:toolchain_cc-compiler-k8", + "--incompatible_enable_cc_toolchain_resolution", + "-c", "fastbuild"); + + // Declare add'l external repository and standalone targets. + scratch.appendFile("WORKSPACE", "local_repository(", " name = 'pkg',", " path = '/foo')"); + getSkyframeExecutor() + .invalidateFilesUnderPathForTesting( + reporter, + new ModifiedFileSet.Builder().modify(PathFragment.create("WORKSPACE")).build(), + Root.fromPath(rootDirectory)); + scratch.file("/foo/WORKSPACE", "workspace(name = 'pkg')"); + scratch.file( + "/foo/BUILD", + // No virtual includes. + "cc_library(name = 'foo',", + " hdrs = ['foo.hpp'])", + // include_prefix only. + "cc_library(name = 'foo2',", + " hdrs = ['foo.hpp'],", + " include_prefix = 'prf')", + // strip_include_prefix + "cc_library(name = 'foo3',", + " hdrs = ['dummy/foo3.hpp'],", + " strip_include_prefix = 'dummy')" + ); + + // Define binary in toplevel workspace that depends on library from external + // repository. + scratch.file( + "x/BUILD", + "cc_library(name = 'bar',", + " hdrs = ['bar.hpp'])", + "cc_library(name = 'baz',", + " hdrs = ['v1/b/c.h'],", + " strip_include_prefix='v1',", + " include_prefix='lib')", + "cc_binary(name = 'bin',", + " srcs = ['bin.cc'],", + " deps = [':bar', ':baz', '@pkg//:foo', '@pkg//:foo2', '@pkg//:foo3'])"); + scratch.file("x/bin.cc", ""); + + CcToolchainVariables variables = getCompileBuildVariables("//x:bin", "bin.o"); + + ImmutableList expected = ImmutableList.of( + "/k8-fastbuild/bin/x/_virtual_includes/baz/lib=x/v1", + "/k8-fastbuild/bin/external/pkg/_virtual_includes/foo2/prf=external/pkg", + "/k8-fastbuild/bin/external/pkg/_virtual_includes/foo3=external/pkg/dummy" + ); + assertThat( + CcToolchainVariables.toStringList( + variables, + CompileBuildVariables.VIRTUAL_TO_ORIGINAL_DIRS.getVariableName()) + .stream() + .map(x -> removeOutDirectory(x)) + .collect(ImmutableList.toImmutableList())) + .containsExactlyElementsIn(expected); + } + private String removeOutDirectory(String s) { return s.replace("blaze-out", "").replace("bazel-out", ""); } diff --git a/tools/cpp/unix_cc_toolchain_config.bzl b/tools/cpp/unix_cc_toolchain_config.bzl index 4fbeaafb86107b..f6c804289b8d5e 100644 --- a/tools/cpp/unix_cc_toolchain_config.bzl +++ b/tools/cpp/unix_cc_toolchain_config.bzl @@ -791,6 +791,21 @@ def _impl(ctx): ], ) + virtual_prefix_map_feature = feature( + name = "virtual_prefix_map", + flag_sets = [ + flag_set( + actions = all_compile_actions, + flag_groups = [ + flag_group( + flags = ["-ffile-prefix-map=%{virtual_to_original_dirs}"], + iterate_over = "virtual_to_original_dirs", + ), + ], + ), + ], + ) + strip_debug_symbols_feature = feature( name = "strip_debug_symbols", flag_sets = [ @@ -1390,6 +1405,7 @@ def _impl(ctx): archiver_flags_feature, force_pic_flags_feature, fission_support_feature, + virtual_prefix_map_feature, strip_debug_symbols_feature, coverage_feature, supports_pic_feature,