Skip to content

Commit b3e12ba

Browse files
gregestrencopybara-github
authored andcommitted
Make aspect required fragments logic more robust:
- Any configured target an aspect attaches to is considered a transitive dependency. - Any aspect an aspect requires is considered a transitive dependency. PiperOrigin-RevId: 4075932
1 parent b6e10b3 commit b3e12ba

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ public ConfiguredAspect createAspect(
514514
aspectConfiguration,
515515
ruleClassProvider.getFragmentRegistry().getUniversalFragments(),
516516
configConditions.asProviders(),
517-
prerequisiteMap.values()))
517+
Iterables.concat(prerequisiteMap.values(), ImmutableList.of(associatedTarget))))
518518
.build();
519519

520520
// If allowing analysis failures, targets should be created as normal as possible, and errors

src/test/java/com/google/devtools/build/lib/analysis/RequiredConfigFragmentsTest.java

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
1919

2020
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
21+
import com.google.devtools.build.lib.analysis.config.CoreOptions.IncludeConfigFragmentsEnum;
2122
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
2223
import com.google.devtools.build.lib.packages.AspectDefinition;
2324
import com.google.devtools.build.lib.packages.AspectParameters;
@@ -31,12 +32,13 @@
3132
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
3233
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
3334
import com.google.devtools.build.lib.util.FileTypeSet;
35+
import com.google.testing.junit.testparameterinjector.TestParameter;
36+
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
3437
import org.junit.Test;
3538
import org.junit.runner.RunWith;
36-
import org.junit.runners.JUnit4;
3739

3840
/** Tests for {@link RequiredConfigFragmentsProvider}. */
39-
@RunWith(JUnit4.class)
41+
@RunWith(TestParameterInjector.class)
4042
public final class RequiredConfigFragmentsTest extends BuildViewTestCase {
4143

4244
@Test
@@ -350,4 +352,93 @@ public void starlarkAttrTransition() throws Exception {
350352
// But not the child's rule transition.
351353
assertThat(requiredFragments.getOptionsClasses()).doesNotContain(CppOptions.class);
352354
}
355+
356+
@Test
357+
public void aspectInheritsTransitiveFragmentsFromBaseCT(
358+
@TestParameter({"DIRECT", "TRANSITIVE"}) IncludeConfigFragmentsEnum setting)
359+
throws Exception {
360+
writeStarlarkTransitionsAndAllowList();
361+
scratch.file(
362+
"a/defs.bzl",
363+
"",
364+
"A1Info = provider()",
365+
"def _a1_impl(target, ctx):",
366+
" return []",
367+
"a1 = aspect(implementation = _a1_impl)",
368+
"",
369+
"def _java_depender_impl(ctx):",
370+
" return []",
371+
"java_depender = rule(",
372+
" implementation = _java_depender_impl,",
373+
" fragments = ['java'],",
374+
" attrs = {})",
375+
"",
376+
"def _r_impl(ctx):",
377+
" return []",
378+
"r = rule(",
379+
" implementation = _r_impl,",
380+
" attrs = {'dep': attr.label(aspects = [a1])})");
381+
scratch.file(
382+
"a/BUILD",
383+
"load(':defs.bzl', 'java_depender', 'r')",
384+
"java_depender(name = 'lib')",
385+
"r(name = 'r', dep = ':lib')");
386+
387+
useConfiguration("--include_config_fragments_provider=" + setting);
388+
getConfiguredTarget("//a:r");
389+
RequiredConfigFragmentsProvider requiredFragments =
390+
getAspect("//a:defs.bzl%a1").getProvider(RequiredConfigFragmentsProvider.class);
391+
392+
if (setting == IncludeConfigFragmentsEnum.TRANSITIVE) {
393+
assertThat(requiredFragments.getFragmentClasses()).contains(JavaConfiguration.class);
394+
} else {
395+
assertThat(requiredFragments.getFragmentClasses()).doesNotContain(JavaConfiguration.class);
396+
}
397+
}
398+
399+
@Test
400+
public void aspectInheritsTransitiveFragmentsFromRequiredAspect(
401+
@TestParameter({"DIRECT", "TRANSITIVE"}) IncludeConfigFragmentsEnum setting)
402+
throws Exception {
403+
scratch.file(
404+
"a/defs.bzl",
405+
"",
406+
"A1Info = provider()",
407+
"def _a1_impl(target, ctx):",
408+
" return A1Info(var = ctx.var.get('my_var', '0'))",
409+
"a1 = aspect(implementation = _a1_impl, provides = [A1Info])",
410+
"",
411+
"A2Info = provider()",
412+
"def _a2_impl(target, ctx):",
413+
" return A2Info()",
414+
"a2 = aspect(implementation = _a2_impl, required_aspect_providers = [A1Info])",
415+
"",
416+
"def _simple_rule_impl(ctx):",
417+
" return []",
418+
"simple_rule = rule(",
419+
" implementation = _simple_rule_impl,",
420+
" attrs = {})",
421+
"",
422+
"def _r_impl(ctx):",
423+
" return []",
424+
"r = rule(",
425+
" implementation = _r_impl,",
426+
" attrs = {'dep': attr.label(aspects = [a1, a2])})");
427+
scratch.file(
428+
"a/BUILD",
429+
"load(':defs.bzl', 'r', 'simple_rule')",
430+
"simple_rule(name = 'lib')",
431+
"r(name = 'r', dep = ':lib')");
432+
433+
useConfiguration("--include_config_fragments_provider=" + setting, "--define", "my_var=1");
434+
getConfiguredTarget("//a:r");
435+
RequiredConfigFragmentsProvider requiredFragments =
436+
getAspect("//a:defs.bzl%a2").getProvider(RequiredConfigFragmentsProvider.class);
437+
438+
if (setting == IncludeConfigFragmentsEnum.TRANSITIVE) {
439+
assertThat(requiredFragments.getDefines()).contains("my_var");
440+
} else {
441+
assertThat(requiredFragments.getDefines()).doesNotContain("my_var");
442+
}
443+
}
353444
}

src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package com.google.devtools.build.lib.analysis.util;
1515

1616
import static com.google.common.collect.ImmutableList.toImmutableList;
17+
import static com.google.common.collect.MoreCollectors.onlyElement;
1718
import static com.google.common.truth.Truth.assertThat;
1819
import static com.google.common.truth.Truth.assertWithMessage;
1920
import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
@@ -66,8 +67,10 @@
6667
import com.google.devtools.build.lib.analysis.AnalysisOptions;
6768
import com.google.devtools.build.lib.analysis.AnalysisResult;
6869
import com.google.devtools.build.lib.analysis.AnalysisUtils;
70+
import com.google.devtools.build.lib.analysis.AspectValue;
6971
import com.google.devtools.build.lib.analysis.BlazeDirectories;
7072
import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
73+
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
7174
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
7275
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
7376
import com.google.devtools.build.lib.analysis.DependencyResolver.Failure;
@@ -192,6 +195,7 @@
192195
import java.util.Iterator;
193196
import java.util.LinkedHashSet;
194197
import java.util.List;
198+
import java.util.Map;
195199
import java.util.NoSuchElementException;
196200
import java.util.Optional;
197201
import java.util.Set;
@@ -1083,6 +1087,26 @@ protected FileConfiguredTarget getHostFileConfiguredTarget(String label)
10831087
return (FileConfiguredTarget) getHostConfiguredTarget(label);
10841088
}
10851089

1090+
/**
1091+
* Returns the {@link ConfiguredAspect} with the given label. For example: {@code
1092+
* //my:base_target%my_aspect}.
1093+
*
1094+
* <p>Assumes only one configured aspect exists for this label. If this isn't true, or you need
1095+
* finer grained selection for different configurations, you'll need to expand this method.
1096+
*/
1097+
protected ConfiguredAspect getAspect(String label) throws Exception {
1098+
AspectValue aspect =
1099+
(AspectValue)
1100+
skyframeExecutor.getEvaluatorForTesting().getDoneValues().entrySet().stream()
1101+
.filter(
1102+
entry ->
1103+
entry.getKey() instanceof AspectKey
1104+
&& ((AspectKey) entry.getKey()).getAspectName().equals(label))
1105+
.map(Map.Entry::getValue)
1106+
.collect(onlyElement());
1107+
return aspect.getConfiguredAspect();
1108+
}
1109+
10861110
/**
10871111
* Rewrites the WORKSPACE to have the required boilerplate and the given lines of content.
10881112
*

0 commit comments

Comments
 (0)