diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcLibraryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcLibraryRule.java
index a26da04ec94b9c..9742826f97418d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcLibraryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcLibraryRule.java
@@ -50,17 +50,17 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
*/
.add(attr("alwayslink", BOOLEAN))
.override(attr("linkstatic", BOOLEAN).value(false))
- /*
- The list of other libraries that the library target depends on. Unlike with
- deps
, the headers and include paths of these libraries (and all their
- transitive deps) are only used for compilation of this library, and not libraries that
- depend on it. Libraries specified with implementation_deps
are still linked in
- binary targets that depend on this library.
-
For now usage is limited to cc_libraries and guarded by the flag
- --experimental_cc_implementation_deps
.
+ /*
+ When --experimental_cc_interface_deps
is True, the targets listed in deps will
+ behave as implementation deps. Unlike with regular deps, the headers and include paths of
+ implementation deps (and all their transitive deps) are only used for compilation of this
+ library, and not libraries that depend on it. Libraries depended on as implementation deps
+ are still linked in binary targets that depend on this library. The dependencies listed in
+ interface_deps will continue having the same behavior as the old deps where the headers and
+ include paths are propagated downstream.
*/
.add(
- attr("implementation_deps", LABEL_LIST)
+ attr("interface_deps", LABEL_LIST)
.allowedFileTypes(FileTypeSet.NO_FILE)
.mandatoryProviders(CcInfo.PROVIDER.id()))
.advertiseStarlarkProvider(CcInfo.PROVIDER.id())
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppSemantics.java
index 79bba3e04b17e5..37cfa792c3a93d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppSemantics.java
@@ -166,4 +166,15 @@ public void validateLayeringCheckFeatures(
public boolean createEmptyArchive() {
return false;
}
+
+ @Override
+ public boolean shouldUseInterfaceDepsBehavior(RuleContext ruleContext) {
+ boolean experimentalCcInterfaceDeps =
+ ruleContext.getFragment(CppConfiguration.class).experimentalCcInterfaceDeps();
+ if (!experimentalCcInterfaceDeps
+ && ruleContext.attributes().isAttributeValueExplicitlySpecified("interface_deps")) {
+ ruleContext.attributeError("interface_deps", "requires --experimental_cc_interface_deps");
+ }
+ return experimentalCcInterfaceDeps;
+ }
}
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 61a108dacaa1dc..92565b1879be80 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
@@ -291,7 +291,7 @@ public CcCompilationContext getCcCompilationContext() {
private String stripIncludePrefix = null;
private String includePrefix = null;
- // This context is built out of deps and implementation_deps.
+ // This context is built out of interface deps and implementation deps.
private CcCompilationContext ccCompilationContext;
private final RuleErrorConsumer ruleErrorConsumer;
@@ -1241,7 +1241,7 @@ private List collectModuleMaps() {
ImmutableList.Builder builder = ImmutableList.builder();
// TODO(bazel-team): Here we use the implementationDeps to build the dependents of this rule's
// module map. This is technically incorrect for the following reasons:
- // - Clang will not issue a layering_check warning if headers from implementation_deps are
+ // - Clang will not issue a layering_check warning if headers from implementation deps are
// included from headers of this library.
// - If we were to ever build with modules, Clang might store this dependency inside the .pcm
// It should be evaluated whether this is ok. If this turned into a problem at some
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
index 8c9e1194951eea..78c95fd28645b6 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibrary.java
@@ -18,7 +18,6 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.FailAction;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
@@ -122,12 +121,7 @@ public static void init(
return;
}
- CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
- if (!cppConfiguration.experimentalCcImplementationDeps()
- && ruleContext.attributes().isAttributeValueExplicitlySpecified("implementation_deps")) {
- ruleContext.attributeError(
- "implementation_deps", "requires --experimental_cc_implementation_deps");
- }
+ boolean shouldUseInterfaceDepsBehavior = semantics.shouldUseInterfaceDepsBehavior(ruleContext);
final CcCommon common = new CcCommon(ruleContext);
common.reportInvalidOptions(ruleContext);
@@ -157,7 +151,24 @@ public static void init(
addEmptyRequiredProviders(targetBuilder);
return;
}
- Iterable ccInfosFromDeps = AnalysisUtils.getProviders(deps, CcInfo.PROVIDER);
+
+ ImmutableList.Builder interfaceDeps = ImmutableList.builder();
+ ImmutableList.Builder implementationDeps = ImmutableList.builder();
+
+ if (shouldUseInterfaceDepsBehavior) {
+ interfaceDeps.addAll(
+ CppHelper.getCompilationContextsFromDeps(
+ ImmutableList.copyOf(ruleContext.getPrerequisites("interface_deps"))));
+ implementationDeps.addAll(
+ CppHelper.getCompilationContextsFromDeps(
+ ImmutableList.copyOf(ruleContext.getPrerequisites("deps"))));
+ } else {
+ interfaceDeps.addAll(
+ CppHelper.getCompilationContextsFromDeps(
+ ImmutableList.copyOf(ruleContext.getPrerequisites("deps"))));
+ }
+ interfaceDeps.add(CcCompilationHelper.getStlCcCompilationContext(ruleContext));
+
CcCompilationHelper compilationHelper =
new CcCompilationHelper(
ruleContext,
@@ -176,15 +187,8 @@ public static void init(
.addPrivateHeaders(common.getPrivateHeaders())
.addPublicHeaders(common.getHeaders())
.setCodeCoverageEnabled(CcCompilationHelper.isCodeCoverageEnabled(ruleContext))
- .addCcCompilationContexts(
- Streams.stream(ccInfosFromDeps)
- .map(CcInfo::getCcCompilationContext)
- .collect(ImmutableList.toImmutableList()))
- .addCcCompilationContexts(
- ImmutableList.of(CcCompilationHelper.getStlCcCompilationContext(ruleContext)))
- .addImplementationDepsCcCompilationContexts(
- CppHelper.getCompilationContextsFromDeps(
- ImmutableList.copyOf(ruleContext.getPrerequisites("implementation_deps"))))
+ .addCcCompilationContexts(interfaceDeps.build())
+ .addImplementationDepsCcCompilationContexts(implementationDeps.build())
.setHeadersCheckingMode(semantics.determineHeadersCheckingMode(ruleContext));
CcLinkingHelper linkingHelper =
@@ -205,7 +209,7 @@ public static void init(
.fromCommon(ruleContext, common)
.addCcLinkingContexts(
CppHelper.getLinkingContextsFromDeps(
- ImmutableList.copyOf(ruleContext.getPrerequisites("implementation_deps"))))
+ ImmutableList.copyOf(ruleContext.getPrerequisites("interface_deps"))))
.setGrepIncludes(CppHelper.getGrepIncludes(ruleContext))
.setTestOrTestOnlyTarget(ruleContext.isTestOnlyTarget())
.addLinkopts(common.getLinkopts())
@@ -255,6 +259,8 @@ public static void init(
linkingHelper.setShouldCreateDynamicLibrary(createDynamicLibrary);
linkingHelper.setLinkerOutputArtifact(soImplArtifact);
+ CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
+
// If the reason we're not creating a dynamic library is that the toolchain
// doesn't support it, then register an action which complains when triggered,
// which only happens when some rule explicitly depends on the dynamic library.
@@ -485,7 +491,8 @@ public static void init(
.setCcLinkingContext(ccLinkingContext)
.setCcDebugInfoContext(
CppHelper.mergeCcDebugInfoContexts(
- compilationInfo.getCcCompilationOutputs(), ccInfosFromDeps))
+ compilationInfo.getCcCompilationOutputs(),
+ AnalysisUtils.getProviders(deps, CcInfo.PROVIDER)))
.setCcNativeLibraryInfo(ccNativeLibraryInfo)
.build())
.addOutputGroups(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index 7dd3c9614c74c0..eda371806c27ad 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -859,18 +859,19 @@ public boolean objcShouldGenerateDotdFiles() {
return cppOptions.objcGenerateDotdFiles;
}
+ // TODO(plf): Change in separate CL where Starlark cc_library.implementation_deps is renamed.
@StarlarkMethod(
name = "experimental_cc_implementation_deps",
documented = false,
useStarlarkThread = true)
- public boolean experimentalCcImplementationDepsForStarlark(StarlarkThread thread)
+ public boolean experimentalCcInterfaceDepsForStarlark(StarlarkThread thread)
throws EvalException {
CcModule.checkPrivateStarlarkificationAllowlist(thread);
- return experimentalCcImplementationDeps();
+ return experimentalCcInterfaceDeps();
}
- public boolean experimentalCcImplementationDeps() {
- return cppOptions.experimentalCcImplementationDeps;
+ public boolean experimentalCcInterfaceDeps() {
+ return cppOptions.experimentalCcInterfaceDeps;
}
public boolean getExperimentalCppCompileResourcesEstimation() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
index 99f70d0bbe848d..7825ef35873feb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
@@ -1047,15 +1047,15 @@ public Label getPropellerOptimizeLabel() {
public boolean objcGenerateDotdFiles;
@Option(
- name = "experimental_cc_implementation_deps",
+ name = "experimental_cc_interface_deps",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
effectTags = {
OptionEffectTag.LOADING_AND_ANALYSIS,
},
metadataTags = {OptionMetadataTag.EXPERIMENTAL},
- help = "If enabled, cc_library targets can use attribute `implementation_deps`.")
- public boolean experimentalCcImplementationDeps;
+ help = "If enabled, cc_library targets can use attribute `interface_deps`.")
+ public boolean experimentalCcInterfaceDeps;
@Option(
name = "experimental_link_static_libraries_once",
@@ -1175,7 +1175,7 @@ public FragmentOptions getHost() {
host.experimentalLinkStaticLibrariesOnce = experimentalLinkStaticLibrariesOnce;
host.experimentalEnableTargetExportCheck = experimentalEnableTargetExportCheck;
host.experimentalCcSharedLibraryDebug = experimentalCcSharedLibraryDebug;
- host.experimentalCcImplementationDeps = experimentalCcImplementationDeps;
+ host.experimentalCcInterfaceDeps = experimentalCcInterfaceDeps;
host.coptList = coptListBuilder.addAll(hostCoptList).build();
host.cxxoptList = cxxoptListBuilder.addAll(hostCxxoptList).build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
index a14f1fffc19ab0..a9c9753dbfd3c4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
@@ -99,7 +99,7 @@ public static Label ccToolchainTypeAttribute(RuleDefinitionEnvironment env) {
FileTypeSet.of(
CPP_SOURCE, C_SOURCE, CPP_HEADER, ASSEMBLER_WITH_C_PREPROCESSOR, ASSEMBLER))
.withSourceAttributes("srcs", "hdrs")
- .withDependencyAttributes("implementation_deps", "deps", "data");
+ .withDependencyAttributes("interface_deps", "deps", "data");
/** Implicit outputs for cc_binary rules. */
public static final SafeImplicitOutputsFunction CC_BINARY_STRIPPED =
@@ -464,6 +464,9 @@ public static Label ccToolchainTypeAttribute(RuleDefinitionEnvironment env) {
*/
public static final String LEGACY_IS_CC_TEST_FEATURE_NAME = "legacy_is_cc_test";
+ /** Tag used to opt in into interface_deps behavior. */
+ public static final String INTERFACE_DEPS_TAG = "__INTERFACE_DEPS__";
+
/** Ancestor for all rules that do include scanning. */
public static final class CcIncludeScanningRule implements RuleDefinition {
private final boolean addGrepIncludes;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSemantics.java
index 19eb66171ed30d..941352edfc0092 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppSemantics.java
@@ -74,4 +74,6 @@ void validateLayeringCheckFeatures(
ImmutableSet unsupportedFeatures);
boolean createEmptyArchive();
+
+ boolean shouldUseInterfaceDepsBehavior(RuleContext ruleContext);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/ObjcCppSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/ObjcCppSemantics.java
index a002ac52d27693..be12b078336c01 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/ObjcCppSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/ObjcCppSemantics.java
@@ -126,4 +126,9 @@ public void validateLayeringCheckFeatures(
public boolean createEmptyArchive() {
return false;
}
+
+ @Override
+ public boolean shouldUseInterfaceDepsBehavior(RuleContext ruleContext) {
+ return false;
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java
index 58c5c5ed458d62..83df4da35762f6 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java
@@ -1894,9 +1894,14 @@ public void testSameSymlinkedLibraryDoesNotGiveDuplicateError() throws Exception
@Test
public void testImplementationDepsCompilationContextIsNotPropagated() throws Exception {
- useConfiguration("--experimental_cc_implementation_deps");
+ useConfiguration("--experimental_cc_interface_deps");
scratch.file(
"foo/BUILD",
+ "cc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.cc'],",
+ " deps = ['lib'],",
+ ")",
"cc_library(",
" name = 'lib',",
" srcs = ['lib.cc'],",
@@ -1907,7 +1912,15 @@ public void testImplementationDepsCompilationContextIsNotPropagated() throws Exc
" srcs = ['public_dep.cc'],",
" includes = ['public_dep'],",
" hdrs = ['public_dep.h'],",
- " implementation_deps = ['implementation_dep'],",
+ " tags = ['__INTERFACE_DEPS__'],",
+ " interface_deps = ['interface_dep'],",
+ " deps = ['implementation_dep'],",
+ ")",
+ "cc_library(",
+ " name = 'interface_dep',",
+ " srcs = ['interface_dep.cc'],",
+ " includes = ['interface_dep'],",
+ " hdrs = ['interface_dep.h'],",
")",
"cc_library(",
" name = 'implementation_dep',",
@@ -1920,28 +1933,40 @@ public void testImplementationDepsCompilationContextIsNotPropagated() throws Exc
getCppCompileAction("//foo:lib").getCcCompilationContext();
assertThat(artifactsToStrings(libCompilationContext.getDeclaredIncludeSrcs()))
.contains("src foo/public_dep.h");
+ assertThat(artifactsToStrings(libCompilationContext.getDeclaredIncludeSrcs()))
+ .contains("src foo/interface_dep.h");
assertThat(artifactsToStrings(libCompilationContext.getDeclaredIncludeSrcs()))
.doesNotContain("src foo/implementation_dep.h");
assertThat(pathfragmentsToStrings(libCompilationContext.getSystemIncludeDirs()))
.contains("foo/public_dep");
assertThat(pathfragmentsToStrings(libCompilationContext.getSystemIncludeDirs()))
- .doesNotContain("implementation_dep");
+ .contains("foo/interface_dep");
+ assertThat(pathfragmentsToStrings(libCompilationContext.getSystemIncludeDirs()))
+ .doesNotContain("foo/implementation_dep");
CcCompilationContext publicDepCompilationContext =
getCppCompileAction("//foo:public_dep").getCcCompilationContext();
+ assertThat(artifactsToStrings(publicDepCompilationContext.getDeclaredIncludeSrcs()))
+ .contains("src foo/interface_dep.h");
+ assertThat(pathfragmentsToStrings(publicDepCompilationContext.getSystemIncludeDirs()))
+ .contains("foo/interface_dep");
assertThat(artifactsToStrings(publicDepCompilationContext.getDeclaredIncludeSrcs()))
.contains("src foo/implementation_dep.h");
-
assertThat(pathfragmentsToStrings(publicDepCompilationContext.getSystemIncludeDirs()))
.contains("foo/implementation_dep");
}
@Test
public void testImplementationDepsLinkingContextIsPropagated() throws Exception {
- useConfiguration("--experimental_cc_implementation_deps");
+ useConfiguration("--experimental_cc_interface_deps");
scratch.file(
"foo/BUILD",
+ "cc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.cc'],",
+ " deps = ['lib'],",
+ ")",
"cc_library(",
" name = 'lib',",
" srcs = ['lib.cc'],",
@@ -1951,7 +1976,14 @@ public void testImplementationDepsLinkingContextIsPropagated() throws Exception
" name = 'public_dep',",
" srcs = ['public_dep.cc'],",
" hdrs = ['public_dep.h'],",
- " implementation_deps = ['implementation_dep'],",
+ " tags = ['__INTERFACE_DEPS__'],",
+ " interface_deps = ['interface_dep'],",
+ " deps = ['implementation_dep'],",
+ ")",
+ "cc_library(",
+ " name = 'interface_dep',",
+ " srcs = ['interface_dep.cc'],",
+ " hdrs = ['interface_dep.h'],",
")",
"cc_library(",
" name = 'implementation_dep',",
@@ -1976,52 +2008,78 @@ public void testImplementationDepsLinkingContextIsPropagated() throws Exception
@Test
public void testImplementationDepsConfigurationHostSucceeds() throws Exception {
- useConfiguration("--experimental_cc_implementation_deps");
+ useConfiguration("--experimental_cc_interface_deps");
scratch.file(
"foo/BUILD",
- "cc_binary(",
- " name = 'bin',",
- " srcs = ['bin.cc'],",
- " deps = ['lib'],",
- ")",
- "cc_library(",
- " name = 'lib',",
- " srcs = ['lib.cc'],",
- " deps = ['public_dep'],",
- ")",
"cc_library(",
" name = 'public_dep',",
" srcs = ['public_dep.cc'],",
" hdrs = ['public_dep.h'],",
- " implementation_deps = ['implementation_dep'],",
+ " tags = ['__INTERFACE_DEPS__'],",
+ " interface_deps = ['interface_dep'],",
")",
"cc_library(",
- " name = 'implementation_dep',",
- " srcs = ['implementation_dep.cc'],",
- " hdrs = ['implementation_dep.h'],",
+ " name = 'interface_dep',",
+ " srcs = ['interface_dep.cc'],",
+ " hdrs = ['interface_dep.h'],",
")");
- getHostConfiguredTarget("//foo:bin");
- assertDoesNotContainEvent("requires --experimental_cc_implementation_deps");
+ getHostConfiguredTarget("//foo:public_dep");
+ assertDoesNotContainEvent("requires --experimental_cc_interface_deps");
}
@Test
- public void testImplementationDepsFailsWithoutFlag() throws Exception {
+ public void testInterfaceDepsFailsWithoutFlagOrTag() throws Exception {
scratch.file(
"foo/BUILD",
"cc_library(",
" name = 'lib',",
" srcs = ['lib.cc'],",
- " implementation_deps = ['implementation_dep'],",
+ " interface_deps = ['interface_dep'],",
")",
"cc_library(",
- " name = 'implementation_dep',",
- " srcs = ['implementation_dep.cc'],",
- " hdrs = ['implementation_dep.h'],",
+ " name = 'interface_dep',",
+ " srcs = ['interface_dep.cc'],",
+ " hdrs = ['interface_dep.h'],",
+ ")");
+ reporter.removeHandler(failFastHandler);
+ getConfiguredTarget("//foo:lib");
+ if (analysisMock.isThisBazel()) {
+ assertContainsEvent("requires --experimental_cc_interface_deps");
+ } else {
+ assertContainsEvent(
+ "Please include the tag '__INTERFACE_DEPS__' in tags when using the 'interface_deps'"
+ + " attribute");
+ }
+ }
+
+ @Test
+ public void testInterfaceDepsNotInAllowlistThrowsError() throws Exception {
+ if (analysisMock.isThisBazel()) {
+ // In OSS usage is controlled only by a flag and not an allowlist.
+ return;
+ }
+ scratch.overwriteFile(
+ "tools/build_defs/cc/whitelists/interface_deps/BUILD",
+ "package_group(",
+ " name = 'cc_library_interface_deps_attr_allowed',",
+ " packages = []",
+ ")");
+ scratch.file(
+ "foo/BUILD",
+ "cc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.cc'],",
+ " interface_deps = ['interface_dep'],",
+ ")",
+ "cc_library(",
+ " name = 'interface_dep',",
+ " srcs = ['interface_dep.cc'],",
+ " hdrs = ['interface_dep.h'],",
")");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//foo:lib");
- assertContainsEvent("requires --experimental_cc_implementation_deps");
+ assertContainsEvent("Only targets in the following allowlist");
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/MockCppSemantics.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/MockCppSemantics.java
index 6a479af2837524..5852c122723ecf 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/MockCppSemantics.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/MockCppSemantics.java
@@ -88,4 +88,15 @@ public void validateLayeringCheckFeatures(
public boolean createEmptyArchive() {
return false;
}
+
+ @Override
+ public boolean shouldUseInterfaceDepsBehavior(RuleContext ruleContext) {
+ boolean experimentalCcInterfaceDeps =
+ ruleContext.getFragment(CppConfiguration.class).experimentalCcInterfaceDeps();
+ if (!experimentalCcInterfaceDeps
+ && ruleContext.attributes().isAttributeValueExplicitlySpecified("interface_deps")) {
+ ruleContext.attributeError("interface_deps", "requires --experimental_cc_interface_deps");
+ }
+ return experimentalCcInterfaceDeps;
+ }
}
diff --git a/src/test/shell/bazel/bazel_layering_check_test.sh b/src/test/shell/bazel/bazel_layering_check_test.sh
index 4942f462944e99..7889adf56256c5 100755
--- a/src/test/shell/bazel/bazel_layering_check_test.sh
+++ b/src/test/shell/bazel/bazel_layering_check_test.sh
@@ -34,8 +34,8 @@ cc_library(
name = "hello_lib",
srcs = ["hello_private.h", "hellolib.cc"],
hdrs = ["hello.h"],
- deps = [":base"],
- implementation_deps = [":implementation"],
+ interface_deps = [":base"],
+ deps = [":implementation"],
)
cc_library(
@@ -134,7 +134,7 @@ function test_bazel_layering_check() {
write_files
- CC="${clang_tool}" bazel build --experimental_cc_implementation_deps \
+ CC="${clang_tool}" bazel build --experimental_cc_interface_deps \
//hello:hello --linkopt=-fuse-ld=gold --features=layering_check \
&> "${TEST_log}" || fail "Build with layering_check failed"
@@ -151,14 +151,14 @@ function test_bazel_layering_check() {
# Specifying -fuse-ld=gold explicitly to override -fuse-ld=/usr/bin/ld.gold
# passed in by cc_configure because Ubuntu-16.04 ships with an old
# clang version that doesn't accept that.
- CC="${clang_tool}" bazel build --experimental_cc_implementation_deps \
+ CC="${clang_tool}" bazel build --experimental_cc_interface_deps \
--copt=-D=private_header \
//hello:hello --linkopt=-fuse-ld=gold --features=layering_check \
&> "${TEST_log}" && fail "Build of private header violation with "\
"layering_check should have failed"
expect_log "use of private header from outside its module: 'hello_private.h'"
- CC="${clang_tool}" bazel build --experimental_cc_implementation_deps \
+ CC="${clang_tool}" bazel build --experimental_cc_interface_deps \
--copt=-D=layering_violation \
//hello:hello --linkopt=-fuse-ld=gold --features=layering_check \
&> "${TEST_log}" && fail "Build of private header violation with "\