Add a 'local_defines' attribute to cc_* rules
Currently, the only way to specify non-transitive defines is through the 'copts' attribute, which is not platform independent. the cc_*.local_defines has the task to pass define values to the compile command line to the given cc_* rule, but not to its dependents.
Fixes #7939
RELNOTES: cc_* rules support non-transitive defines through a 'local_defines' attribute.
PiperOrigin-RevId: 262315252
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
index 289690f..0f0a5ff 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
@@ -76,6 +76,7 @@
SkylarkList<String> systemIncludes,
SkylarkList<String> frameworkIncludes,
SkylarkList<String> defines,
+ SkylarkList<String> localDefines,
SkylarkList<String> userCompileFlags,
SkylarkList<CcCompilationContext> ccCompilationContexts,
String name,
@@ -96,6 +97,7 @@
systemIncludes,
frameworkIncludes,
defines,
+ localDefines,
userCompileFlags,
ccCompilationContexts,
name,
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java
index c0e7ead..80fa950 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCppRuleClasses.java
@@ -168,14 +168,21 @@
Subject to <a href="${link make-variables}">"Make" variable</a> substitution and
<a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>.
Each string, which must consist of a single Bourne shell token,
- is prepended with <code>-D</code> (or <code>/D</code> on Windows) and added to
- <code>COPTS</code>.
- Unlike <a href="#cc_binary.copts"><code>copts</code></a>, these flags are added for the
- target and every rule that depends on it! Be very careful, since this may have
- far-reaching effects. When in doubt, add "-D" (or <code>/D</code> on Windows) flags to
- <a href="#cc_binary.copts"><code>copts</code></a> instead.
+ is prepended with <code>-D</code> and added to the compile command line to this target,
+ as well as to every rule that depends on it. Be very careful, since this may have
+ far-reaching effects. When in doubt, add define values to
+ <a href="#cc_binary.local_defines"><code>local_defines</code></a> instead.
<!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
.add(attr("defines", STRING_LIST))
+ /*<!-- #BLAZE_RULE($cc_decl_rule).ATTRIBUTE(local_defines) -->
+ List of defines to add to the compile line.
+ Subject to <a href="${link make-variables}">"Make" variable</a> substitution and
+ <a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>.
+ Each string, which must consist of a single Bourne shell token,
+ is prepended with <code>-D</code> and added to the compile command line for this target,
+ but not to its dependents.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
+ .add(attr("local_defines", STRING_LIST))
/*<!-- #BLAZE_RULE($cc_decl_rule).ATTRIBUTE(includes) -->
List of include dirs to be added to the compile line.
<p>
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index a507574..795aae3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -533,6 +533,7 @@
}
private static final String DEFINES_ATTRIBUTE = "defines";
+ private static final String LOCAL_DEFINES_ATTRIBUTE = "local_defines";
/**
* Returns a list of define tokens from "defines" attribute.
@@ -543,22 +544,40 @@
* <p>But we require that the "defines" attribute consists of a single token.
*/
public List<String> getDefines() {
+ return getDefinesFromAttribute(DEFINES_ATTRIBUTE);
+ }
+
+ /**
+ * Returns a list of define tokens from "local_defines" attribute.
+ *
+ * <p>We tokenize the "local_defines" attribute, to ensure that the handling of quotes and
+ * backslash escapes is consistent Bazel's treatment of the "copts" attribute.
+ *
+ * <p>But we require that the "local_defines" attribute consists of a single token.
+ */
+ public List<String> getNonTransitiveDefines() {
+ return getDefinesFromAttribute(LOCAL_DEFINES_ATTRIBUTE);
+ }
+
+ private List<String> getDefinesFromAttribute(String attr) {
List<String> defines = new ArrayList<>();
- for (String define : ruleContext.getExpander().list(DEFINES_ATTRIBUTE)) {
+ for (String define : ruleContext.getExpander().list(attr)) {
List<String> tokens = new ArrayList<>();
try {
ShellUtils.tokenize(tokens, define);
if (tokens.size() == 1) {
defines.add(tokens.get(0));
} else if (tokens.isEmpty()) {
- ruleContext.attributeError(DEFINES_ATTRIBUTE, "empty definition not allowed");
+ ruleContext.attributeError(attr, "empty definition not allowed");
} else {
- ruleContext.attributeError(DEFINES_ATTRIBUTE,
- "definition contains too many tokens (found " + tokens.size()
- + ", expecting exactly one)");
+ ruleContext.attributeError(
+ attr,
+ String.format(
+ "definition contains too many tokens (found %d, expecting exactly one)",
+ tokens.size()));
}
} catch (ShellUtils.TokenizationException e) {
- ruleContext.attributeError(DEFINES_ATTRIBUTE, e.getMessage());
+ ruleContext.attributeError(attr, e.getMessage());
}
}
return defines;
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 0e84756..c22e183 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
@@ -138,6 +138,12 @@
}
@Override
+ public SkylarkNestedSet getSkylarkNonTransitiveDefines() {
+ return SkylarkNestedSet.of(
+ String.class, NestedSetBuilder.wrap(Order.STABLE_ORDER, getNonTransitiveDefines()));
+ }
+
+ @Override
public SkylarkNestedSet getSkylarkHeaders() {
return SkylarkNestedSet.of(Artifact.class, getDeclaredIncludeSrcs());
}
@@ -400,15 +406,22 @@
}
/**
- * Returns the set of defines needed to compile this target (possibly empty
- * but never null). This includes definitions from the transitive deps closure
- * for the target. The order of the returned collection is deterministic.
+ * Returns the set of defines needed to compile this target. This includes definitions from the
+ * transitive deps closure for the target. The order of the returned collection is deterministic.
*/
public ImmutableList<String> getDefines() {
return commandLineCcCompilationContext.defines;
}
/**
+ * Returns the set of defines needed to compile this target. This doesn't include definitions from
+ * the transitive deps closure for the target.
+ */
+ ImmutableList<String> getNonTransitiveDefines() {
+ return commandLineCcCompilationContext.localDefines;
+ }
+
+ /**
* Returns a {@code CcCompilationContext} that is based on a given {@code CcCompilationContext}
* but returns empty sets for {@link #getDeclaredIncludeDirs()}.
*/
@@ -481,18 +494,21 @@
private final ImmutableList<PathFragment> systemIncludeDirs;
private final ImmutableList<PathFragment> frameworkIncludeDirs;
private final ImmutableList<String> defines;
+ private final ImmutableList<String> localDefines;
CommandLineCcCompilationContext(
ImmutableList<PathFragment> includeDirs,
ImmutableList<PathFragment> quoteIncludeDirs,
ImmutableList<PathFragment> systemIncludeDirs,
ImmutableList<PathFragment> frameworkIncludeDirs,
- ImmutableList<String> defines) {
+ ImmutableList<String> defines,
+ ImmutableList<String> localDefines) {
this.includeDirs = includeDirs;
this.quoteIncludeDirs = quoteIncludeDirs;
this.systemIncludeDirs = systemIncludeDirs;
this.frameworkIncludeDirs = frameworkIncludeDirs;
this.defines = defines;
+ this.localDefines = localDefines;
}
}
@@ -524,6 +540,7 @@
private final NestedSetBuilder<Artifact> transitivePicModules = NestedSetBuilder.stableOrder();
private final Set<Artifact> directModuleMaps = new LinkedHashSet<>();
private final Set<String> defines = new LinkedHashSet<>();
+ private final Set<String> localDefines = new LinkedHashSet<>();
private CppModuleMap cppModuleMap;
private CppModuleMap verificationModuleMap;
private boolean propagateModuleMapAsActionInput = true;
@@ -733,6 +750,12 @@
return this;
}
+ /** Adds multiple non-transitive defines. */
+ public Builder addNonTransitiveDefines(Iterable<String> defines) {
+ Iterables.addAll(this.localDefines, defines);
+ return this;
+ }
+
/** Sets the C++ module map. */
public Builder setCppModuleMap(CppModuleMap cppModuleMap) {
this.cppModuleMap = cppModuleMap;
@@ -806,7 +829,8 @@
ImmutableList.copyOf(quoteIncludeDirs),
ImmutableList.copyOf(systemIncludeDirs),
ImmutableList.copyOf(frameworkIncludeDirs),
- ImmutableList.copyOf(defines)),
+ ImmutableList.copyOf(defines),
+ ImmutableList.copyOf(localDefines)),
// TODO(b/110873917): We don't have the middle man compilation prerequisite, therefore, we
// use the compilation prerequisites as they were passed to the builder, i.e. we use every
// header instead of a middle man.
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 14a2fb5..c281f6e 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
@@ -237,6 +237,7 @@
private ImmutableList<String> copts = ImmutableList.of();
private CoptsFilter coptsFilter = CoptsFilter.alwaysPasses();
private final Set<String> defines = new LinkedHashSet<>();
+ private final Set<String> localDefines = new LinkedHashSet<>();
private final List<CcCompilationContext> ccCompilationContexts = new ArrayList<>();
private Set<PathFragment> looseIncludeDirs = ImmutableSet.of();
private final List<PathFragment> systemIncludeDirs = new ArrayList<>();
@@ -334,6 +335,7 @@
setCopts(Iterables.concat(common.getCopts(), additionalCopts));
addDefines(common.getDefines());
+ addNonTransitiveDefines(common.getNonTransitiveDefines());
setLooseIncludeDirs(common.getLooseIncludeDirs());
addSystemIncludeDirs(common.getSystemIncludeDirs());
setCoptsFilter(common.getCoptsFilter());
@@ -535,12 +537,24 @@
this.coptsFilter = Preconditions.checkNotNull(coptsFilter);
}
- /** Adds the given defines to the compiler command line. */
+ /**
+ * Adds the given defines to the compiler command line of this target as well as its dependent
+ * targets.
+ */
public CcCompilationHelper addDefines(Iterable<String> defines) {
Iterables.addAll(this.defines, defines);
return this;
}
+ /**
+ * Adds the given defines to the compiler command line. These defines are not propagated
+ * transitively to the dependent targets.
+ */
+ public CcCompilationHelper addNonTransitiveDefines(Iterable<String> defines) {
+ Iterables.addAll(this.localDefines, defines);
+ return this;
+ }
+
/** For adding CC compilation infos that affect compilation, e.g: from dependencies. */
public CcCompilationHelper addCcCompilationContexts(
Iterable<CcCompilationContext> ccCompilationContexts) {
@@ -918,6 +932,8 @@
// But defines come after those inherited from deps.
ccCompilationContextBuilder.addDefines(defines);
+ ccCompilationContextBuilder.addNonTransitiveDefines(localDefines);
+
// There are no ordering constraints for declared include dirs/srcs.
ccCompilationContextBuilder.addDeclaredIncludeSrcs(publicHeaders.getHeaders());
ccCompilationContextBuilder.addDeclaredIncludeSrcs(publicTextualHeaders);
@@ -1477,7 +1493,8 @@
ccCompilationContext.getQuoteIncludeDirs(),
ccCompilationContext.getSystemIncludeDirs(),
ccCompilationContext.getFrameworkIncludeDirs(),
- ccCompilationContext.getDefines());
+ ccCompilationContext.getDefines(),
+ ccCompilationContext.getNonTransitiveDefines());
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 da7cb04..fb8a16f 100644
--- 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
@@ -250,7 +250,8 @@
asStringNestedSet(quoteIncludeDirs),
asStringNestedSet(systemIncludeDirs),
asStringNestedSet(frameworkIncludeDirs),
- asStringNestedSet(defines));
+ asStringNestedSet(defines),
+ NestedSetBuilder.emptySet(Order.STABLE_ORDER));
}
@Override
@@ -508,7 +509,8 @@
Object includes,
Object quoteIncludes,
Object frameworkIncludes,
- Object defines)
+ Object defines,
+ Object localDefines)
throws EvalException {
CcCompilationContext.Builder ccCompilationContext =
CcCompilationContext.builder(
@@ -536,6 +538,8 @@
.map(x -> PathFragment.create(x))
.collect(ImmutableList.toImmutableList()));
ccCompilationContext.addDefines(toNestedSetOfStrings(defines, "defines").getSet(String.class));
+ ccCompilationContext.addNonTransitiveDefines(
+ toNestedSetOfArtifacts(localDefines, "local_defines").getSet(String.class));
return ccCompilationContext.build();
}
@@ -1513,6 +1517,7 @@
SkylarkList<String> systemIncludes,
SkylarkList<String> frameworkIncludes,
SkylarkList<String> defines,
+ SkylarkList<String> localDefines,
SkylarkList<String> userCompileFlags,
SkylarkList<CcCompilationContext> ccCompilationContexts,
String name,
@@ -1585,6 +1590,7 @@
.map(PathFragment::create)
.collect(ImmutableList.toImmutableList()))
.addDefines(defines)
+ .addNonTransitiveDefines(localDefines)
.setCopts(userCompileFlags)
.addAdditionalCompilationInputs(headersForClifDoNotUseThisParam)
.addAditionalIncludeScanningRoots(headersForClifDoNotUseThisParam);
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 bd4b054..9307bd3 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
@@ -17,6 +17,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.events.Location;
@@ -135,7 +136,8 @@
Iterable<PathFragment> quoteIncludeDirs,
Iterable<PathFragment> systemIncludeDirs,
Iterable<PathFragment> frameworkIncludeDirs,
- Iterable<String> defines) {
+ Iterable<String> defines,
+ Iterable<String> localDefines) {
try {
if (usePic
&& !featureConfiguration.isEnabled(CppRuleClasses.PIC)
@@ -165,7 +167,8 @@
getSafePathStrings(quoteIncludeDirs),
getSafePathStrings(systemIncludeDirs),
getSafePathStrings(frameworkIncludeDirs),
- defines);
+ defines,
+ localDefines);
} catch (EvalException e) {
ruleErrorConsumer.ruleError(e.getMessage());
return CcToolchainVariables.EMPTY;
@@ -197,7 +200,8 @@
Iterable<String> quoteIncludeDirs,
Iterable<String> systemIncludeDirs,
Iterable<String> frameworkIncludeDirs,
- Iterable<String> defines)
+ Iterable<String> defines,
+ Iterable<String> localDefines)
throws EvalException {
if (usePic
&& !featureConfiguration.isEnabled(CppRuleClasses.PIC)
@@ -227,7 +231,8 @@
quoteIncludeDirs,
systemIncludeDirs,
frameworkIncludeDirs,
- defines);
+ defines,
+ localDefines);
}
private static CcToolchainVariables setupVariables(
@@ -253,7 +258,8 @@
Iterable<String> quoteIncludeDirs,
Iterable<String> systemIncludeDirs,
Iterable<String> frameworkIncludeDirs,
- Iterable<String> defines) {
+ Iterable<String> defines,
+ Iterable<String> localDefines) {
CcToolchainVariables.Builder buildVariables = CcToolchainVariables.builder(parent);
setupCommonVariablesInternal(
buildVariables,
@@ -268,7 +274,8 @@
quoteIncludeDirs,
systemIncludeDirs,
frameworkIncludeDirs,
- defines);
+ defines,
+ localDefines);
setupSpecificVariables(
buildVariables,
sourceFile,
@@ -354,7 +361,8 @@
Iterable<PathFragment> quoteIncludeDirs,
Iterable<PathFragment> systemIncludeDirs,
Iterable<PathFragment> frameworkIncludeDirs,
- Iterable<String> defines) {
+ Iterable<String> defines,
+ Iterable<String> localDefines) {
setupCommonVariablesInternal(
buildVariables,
featureConfiguration,
@@ -368,7 +376,8 @@
getSafePathStrings(quoteIncludeDirs),
getSafePathStrings(systemIncludeDirs),
getSafePathStrings(frameworkIncludeDirs),
- defines);
+ defines,
+ localDefines);
}
private static void setupCommonVariablesInternal(
@@ -384,13 +393,15 @@
Iterable<String> quoteIncludeDirs,
Iterable<String> systemIncludeDirs,
Iterable<String> frameworkIncludeDirs,
- Iterable<String> defines) {
+ Iterable<String> defines,
+ Iterable<String> localDefines) {
Preconditions.checkNotNull(directModuleMaps);
Preconditions.checkNotNull(includeDirs);
Preconditions.checkNotNull(quoteIncludeDirs);
Preconditions.checkNotNull(systemIncludeDirs);
Preconditions.checkNotNull(frameworkIncludeDirs);
Preconditions.checkNotNull(defines);
+ Preconditions.checkNotNull(localDefines);
if (featureConfiguration.isEnabled(CppRuleClasses.MODULE_MAPS) && cppModuleMap != null) {
// If the feature is enabled and cppModuleMap is null, we are about to fail during analysis
@@ -427,12 +438,14 @@
allDefines =
ImmutableList.<String>builder()
.addAll(defines)
+ .addAll(localDefines)
.add(CppConfiguration.FDO_STAMP_MACRO + "=\"" + fdoStamp + "\"")
.build();
} else {
- allDefines = defines;
+ allDefines = Iterables.concat(defines, localDefines);
}
+
buildVariables.addStringSequenceVariable(PREPROCESSOR_DEFINES.getVariableName(), allDefines);
buildVariables.addAllStringVariables(additionalBuildVariables);
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 86c6808..f9b5eec 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
@@ -185,6 +185,7 @@
additionalLinkstampDefines,
ccToolchainProvider,
fdoBuildStamp,
- codeCoverageEnabled));
+ codeCoverageEnabled),
+ /* localDefines= */ ImmutableList.of());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java
index 6ccac29..33bebdb 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/BazelCcModuleApi.java
@@ -156,7 +156,18 @@
type = SkylarkList.class),
@Param(
name = "defines",
- doc = "Set of defines needed to compile this target. Each define is a string.",
+ doc =
+ "Set of defines needed to compile this target. Each define is a string. Propagated"
+ + " to dependents transitively.",
+ positional = false,
+ named = true,
+ defaultValue = "[]",
+ type = SkylarkList.class),
+ @Param(
+ name = "local_defines",
+ doc =
+ "Set of defines needed to compile this target. Each define is a string. Not"
+ + " propagated to dependents transitively.",
positional = false,
named = true,
defaultValue = "[]",
@@ -211,6 +222,7 @@
SkylarkList<String> systemIncludes,
SkylarkList<String> frameworkIncludes,
SkylarkList<String> defines,
+ SkylarkList<String> localDefines,
SkylarkList<String> userCompileFlags,
SkylarkList<CompilationContextT> ccCompilationContexts,
String name,
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationContextApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationContextApi.java
index 80115c8..fb0df89 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationContextApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcCompilationContextApi.java
@@ -31,11 +31,21 @@
public interface CcCompilationContextApi {
@SkylarkCallable(
name = "defines",
- doc = "Returns the set of defines needed to compile this target. Each define is a string.",
+ doc =
+ "Returns the set of defines needed to compile this target. Each define is a string."
+ + " These values are propagated to the target's transitive dependencies.",
structField = true)
SkylarkNestedSet getSkylarkDefines();
@SkylarkCallable(
+ name = "local_defines",
+ doc =
+ "Returns the set of defines needed to compile this target. Each define is a string."
+ + " These values are not propagated to the target's transitive dependencies.",
+ structField = true)
+ SkylarkNestedSet getSkylarkNonTransitiveDefines();
+
+ @SkylarkCallable(
name = "headers",
doc = "Returns the set of headers needed to compile this target.",
structField = true)
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java
index 41bddc3..97196b1 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/cpp/CcModuleApi.java
@@ -701,11 +701,22 @@
type = Object.class),
@Param(
name = "defines",
- doc = "Set of defines needed to compile this target. Each define is a string",
+ doc =
+ "Set of defines needed to compile this target. Each define is a string. Propagated"
+ + " transitively to dependents.",
positional = false,
named = true,
defaultValue = "unbound",
- type = Object.class)
+ type = Object.class),
+ @Param(
+ name = "local_defines",
+ doc =
+ "Set of defines needed to compile this target. Each define is a string. Not"
+ + " propagated transitively to dependents.",
+ positional = false,
+ named = true,
+ defaultValue = "unbound",
+ type = Object.class),
})
CompilationContextT createCcCompilationContext(
Object headers,
@@ -713,7 +724,8 @@
Object includes,
Object quoteIncludes,
Object frameworkIncludes,
- Object defines)
+ Object defines,
+ Object localDefines)
throws EvalException;
// TODO(b/65151735): Remove when cc_flags is entirely set from features.
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java
index c37b315..d156042 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/cpp/FakeCcModule.java
@@ -175,7 +175,8 @@
Object includes,
Object quoteIncludes,
Object frameworkIncludes,
- Object defines)
+ Object defines,
+ Object localDefines)
throws EvalException {
return null;
}
@@ -201,6 +202,7 @@
SkylarkList<String> includes,
SkylarkList<String> quoteIncludes,
SkylarkList<String> defines,
+ SkylarkList<String> localDefines,
SkylarkList<String> systemIncludes,
SkylarkList<String> frameworkIncludes,
SkylarkList<String> userCompileFlags,
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 a0cf9bd..67693b9 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
@@ -150,6 +150,18 @@
}
@Test
+ public void testLocalDefinesAndMakeVariables() throws Exception {
+ ConfiguredTarget l =
+ scratchConfiguredTarget(
+ "a",
+ "l",
+ "cc_library(name='l', srcs=['l.cc'], local_defines=['V=$(FOO)'], toolchains=[':v'])",
+ "make_variable_tester(name='v', variables={'FOO': 'BAR'})");
+ assertThat(l.get(CcInfo.PROVIDER).getCcCompilationContext().getNonTransitiveDefines())
+ .contains("V=BAR");
+ }
+
+ @Test
public void testMisconfiguredCrosstoolRaisesErrorWhenLinking() throws Exception {
AnalysisMock.get()
.ccSupport()
@@ -1179,6 +1191,30 @@
assertContainsSublist(action.getCompilerOptions(), ImmutableList.of("-DBAR", "-DFOO"));
}
+ @Test
+ public void testLocalDefinesNotPassedTransitively() throws Exception {
+ scratch.file(
+ "foo/BUILD",
+ "cc_library(",
+ " name = 'bar',",
+ " defines = ['TRANSITIVE_BAR'],",
+ " local_defines = ['LOCAL_BAR'],",
+ ")",
+ "cc_library(",
+ " name = 'foo',",
+ " srcs = ['foo.cc'],",
+ " defines = ['TRANSITIVE_FOO'],",
+ " local_defines = ['LOCAL_FOO'],",
+ " deps = [':bar'],",
+ ")");
+ CppCompileAction action = getCppCompileAction("//foo");
+ // Inherited defines come first.
+ assertContainsSublist(
+ action.getCompilerOptions(),
+ ImmutableList.of("-DTRANSITIVE_BAR", "-DTRANSITIVE_FOO", "-DLOCAL_FOO"));
+ assertThat(action.getCompilerOptions()).doesNotContain("-DLOCAL_BAR");
+ }
+
// Regression test - setting "-shared" caused an exception when computing the link command.
@Test
public void testLinkOptsNotPassedToStaticLink() throws Exception {
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
index 0e68213..2c8d61a 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
@@ -1062,6 +1062,7 @@
" hdrs = ['dep1.h'],",
" includes = ['dep1/baz'],",
" defines = ['DEP1'],",
+ " local_defines = ['LOCALDEP1'],",
")",
"cc_library(",
" name = 'dep2',",
@@ -1108,6 +1109,7 @@
" '_quote_include': attr.string(default='quux/abc'),",
" '_framework_include': attr.string(default='fuux/fgh'),",
" '_define': attr.string(default='MYDEFINE'),",
+ " '_local_define': attr.string(default='MYLOCALDEFINE'),",
" '_deps': attr.label_list(default=['//a:dep1', '//a:dep2'])",
" },",
" fragments = ['cpp'],",
@@ -1135,6 +1137,7 @@
List<String> mergedDefines =
((SkylarkNestedSet) myInfo.getValue("merged_defines")).getSet(String.class).toList();
assertThat(mergedDefines).containsAtLeast("MYDEFINE", "DEP1", "DEP2");
+ assertThat(mergedDefines).doesNotContain("LOCALDEP1");
List<String> mergedSystemIncludes =
((SkylarkNestedSet) myInfo.getValue("merged_system_includes"))