Skip to content

Commit b2eedf2

Browse files
tetrominocopybara-github
authored andcommitted
Support packages assembled from package pieces in query and genquery machinery
For a package loaded with lazy macro expansion, Target.getPackage() returns null, so we now need to use TargetProvider/PackageProvider to retrieve a target's package's BUILD file target or to iterate sibling targets. As a follow-up, we'd want to avoid unnecessarily loading full packages in implementations of TargetProvider.getTarget() and in TargetLoadingUtil - but that requires another new skyfunction. Working towards #23852 PiperOrigin-RevId: 792276714 Change-Id: I76266c10d4f5d6e087a6f38c6b6bfe06eb72603b
1 parent 8e552b0 commit b2eedf2

29 files changed

+773
-107
lines changed

src/main/java/com/google/devtools/build/lib/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ java_library(
430430
"//src/main/java/com/google/devtools/build/lib/metrics:garbage-collection-metrics-util",
431431
"//src/main/java/com/google/devtools/build/lib/metrics/criticalpath",
432432
"//src/main/java/com/google/devtools/build/lib/packages",
433+
"//src/main/java/com/google/devtools/build/lib/packages:package_piece_identifier",
433434
"//src/main/java/com/google/devtools/build/lib/packages/semantics",
434435
"//src/main/java/com/google/devtools/build/lib/pkgcache",
435436
"//src/main/java/com/google/devtools/build/lib/pkgcache:package_options",

src/main/java/com/google/devtools/build/lib/pkgcache/AbstractRecursivePackageProvider.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ protected AbstractRecursivePackageProvider() {
2828
@Override
2929
public Target getTarget(ExtendedEventHandler eventHandler, Label label)
3030
throws NoSuchPackageException, NoSuchTargetException, InterruptedException {
31+
// TODO(https://github.com/bazelbuild/bazel/issues/23852): don't expand the full package if lazy
32+
// macro expansion is enabled.
3133
return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName());
3234
}
3335

src/main/java/com/google/devtools/build/lib/pkgcache/CompileOneDependencyTransformer.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.devtools.build.lib.events.ExtendedEventHandler;
2626
import com.google.devtools.build.lib.packages.BuildType;
2727
import com.google.devtools.build.lib.packages.FileTarget;
28+
import com.google.devtools.build.lib.packages.NoSuchPackageException;
2829
import com.google.devtools.build.lib.packages.NoSuchThingException;
2930
import com.google.devtools.build.lib.packages.OutputFile;
3031
import com.google.devtools.build.lib.packages.Package;
@@ -93,8 +94,19 @@ private Target transformCompileOneDependency(ExtendedEventHandler eventHandler,
9394
}
9495

9596
Rule result = null;
96-
Iterable<Rule> orderedRuleList =
97-
getOrderedRuleList(packageProvider.getPackage(eventHandler, target.getPackageoid()));
97+
Iterable<Rule> orderedRuleList;
98+
try {
99+
orderedRuleList = getOrderedRuleList(packageProvider.getPackage(eventHandler, target));
100+
} catch (NoSuchPackageException e) {
101+
// Only possible if lazy macro expansion is enabled, and an error was encountered when loading
102+
// a different package piece of this package.
103+
throw new TargetParsingException(
104+
"Package of --compile_one_dependency target '"
105+
+ target.getLabel()
106+
+ "' could not be loaded",
107+
e,
108+
e.getDetailedExitCode());
109+
}
98110
for (Rule rule : orderedRuleList) {
99111
Set<Label> labels = getInputLabels(rule);
100112
if (listContainsFile(eventHandler, labels, target.getLabel(), Sets.<Label>newHashSet())) {

src/main/java/com/google/devtools/build/lib/pkgcache/PackageProvider.java

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,20 @@
1414

1515
package com.google.devtools.build.lib.pkgcache;
1616

17+
import static com.google.common.base.Preconditions.checkState;
18+
19+
import com.google.common.collect.ImmutableCollection;
1720
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
1821
import com.google.devtools.build.lib.events.ExtendedEventHandler;
22+
import com.google.devtools.build.lib.events.StoredEventHandler;
1923
import com.google.devtools.build.lib.io.InconsistentFilesystemException;
24+
import com.google.devtools.build.lib.packages.InputFile;
2025
import com.google.devtools.build.lib.packages.NoSuchPackageException;
26+
import com.google.devtools.build.lib.packages.NoSuchPackagePieceException;
2127
import com.google.devtools.build.lib.packages.Package;
28+
import com.google.devtools.build.lib.packages.PackagePiece;
2229
import com.google.devtools.build.lib.packages.Packageoid;
30+
import com.google.devtools.build.lib.packages.Target;
2331

2432
/**
2533
* API for retrieving packages. Implementations generally load packages to fulfill requests.
@@ -46,23 +54,21 @@ Package getPackage(ExtendedEventHandler eventHandler, PackageIdentifier packageN
4654
throws NoSuchPackageException, InterruptedException;
4755

4856
/**
49-
* If a {@link Packageoid} is a {@link Package}, returns it; otherwise, loads and returns the full
50-
* package containing it.
57+
* If a {@link Target} is owned by a monolithic {@link Package}, returns it; otherwise, loads and
58+
* returns the full package encompassing the target's package piece.
5159
*
60+
* @throws NoSuchPackageException if target is owned by a {@link PackagePiece}, and the full
61+
* package could not be loaded due to an error while loading a different package piece.
5262
* @throws InterruptedException if the package loading was interrupted.
5363
*/
54-
default Package getPackage(ExtendedEventHandler eventHandler, Packageoid packageoid)
55-
throws InterruptedException {
64+
default Package getPackage(ExtendedEventHandler eventHandler, Target target)
65+
throws NoSuchPackageException, InterruptedException {
66+
Packageoid packageoid = target.getPackageoid();
5667
if (packageoid instanceof Package pkg) {
68+
// Monolithic package.
5769
return pkg;
5870
}
59-
try {
60-
return getPackage(eventHandler, packageoid.getPackageIdentifier());
61-
} catch (NoSuchPackageException e) {
62-
// Cannot happen: for a packageoid to exists, its package's BUILD file must also exist and be
63-
// parseable.
64-
throw new AssertionError("Failed to load package " + packageoid.getPackageIdentifier(), e);
65-
}
71+
return getPackage(eventHandler, packageoid.getPackageIdentifier());
6672
}
6773

6874
/**
@@ -84,4 +90,63 @@ default Package getPackage(ExtendedEventHandler eventHandler, Packageoid package
8490
*/
8591
boolean isPackage(ExtendedEventHandler eventHandler, PackageIdentifier packageName)
8692
throws InconsistentFilesystemException, InterruptedException;
93+
94+
/**
95+
* Returns the BUILD file target of the given package, loading, parsing and evaluating either the
96+
* full package (if lazy macro expansion is disabled) or just the package piece owning the BUILD
97+
* file (if lazy macro expansion is enabled) if it is not already loaded.
98+
*
99+
* @throws NoSuchPackageException if the package could not be found
100+
* @throws NoSuchPackagePieceException if lazy macro expansion is enabled, and the package piece
101+
* owning the BUILD file failed validation
102+
* @throws InterruptedException if the package loading was interrupted
103+
*/
104+
InputFile getBuildFile(ExtendedEventHandler eventHandler, PackageIdentifier packageName)
105+
throws NoSuchPackageException, NoSuchPackagePieceException, InterruptedException;
106+
107+
@Override
108+
default InputFile getBuildFile(Target target) throws InterruptedException {
109+
Packageoid packageoid = target.getPackageoid();
110+
if (packageoid instanceof Package pkg) {
111+
// Monolithic package.
112+
return pkg.getBuildFile();
113+
} else if (packageoid instanceof PackagePiece.ForBuildFile forBuildFile) {
114+
// Lazy macro expansion, target is top-level.
115+
return forBuildFile.getBuildFile();
116+
} else {
117+
// Lazy macro expansion, target is in a PackagePiece.ForMacro, we need to retrieve the
118+
// BUILD file from the (already loaded) PackagePiece.ForBuildFile.
119+
StoredEventHandler localEventHandler = new StoredEventHandler();
120+
InputFile buildFile;
121+
try {
122+
buildFile =
123+
getBuildFile(localEventHandler, target.getPackageMetadata().packageIdentifier());
124+
} catch (NoSuchPackageException | NoSuchPackagePieceException e) {
125+
// If a PackagePiece.ForMacro exists, its corresponding PackagePiece.ForBuildFile must also
126+
// exist (and already be loaded).
127+
throw new IllegalStateException(
128+
String.format(
129+
"Bug in package loading machinery: failed to load package piece for BUILD file of"
130+
+ " already-loaded target %s",
131+
target),
132+
e);
133+
}
134+
// If PackagePiece.ForMacro was loaded, its corresponding PackagePiece.ForBuildFile could not
135+
// be in error.
136+
checkState(
137+
!localEventHandler.hasErrors(),
138+
"Bug in package loading machinery: unexpected error while retrieving package piece for"
139+
+ " BUILD file of already-loaded target %s: %s",
140+
target,
141+
localEventHandler.getEvents());
142+
return buildFile;
143+
}
144+
}
145+
146+
@Override
147+
default ImmutableCollection<Target> getSiblingTargetsInPackage(
148+
ExtendedEventHandler eventHandler, Target target)
149+
throws NoSuchPackageException, InterruptedException {
150+
return getPackage(eventHandler, target).getTargets().values();
151+
}
87152
}

src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.google.devtools.build.lib.events.ExtendedEventHandler;
2424
import com.google.devtools.build.lib.io.InconsistentFilesystemException;
2525
import com.google.devtools.build.lib.io.ProcessPackageDirectoryException;
26+
import com.google.devtools.build.lib.packages.InputFile;
2627
import com.google.devtools.build.lib.packages.NoSuchPackageException;
2728
import com.google.devtools.build.lib.packages.NoSuchTargetException;
2829
import com.google.devtools.build.lib.packages.Package;
@@ -108,7 +109,8 @@ default Set<PackageIdentifier> bulkIsPackage(
108109
}
109110

110111
/**
111-
* A {@link RecursivePackageProvider} in terms of a map of pre-fetched packages.
112+
* A {@link RecursivePackageProvider} in terms of a map of pre-fetched, fully macro-expanded
113+
* packages.
112114
*
113115
* <p>Note that this class implements neither {@link #streamPackagesUnderDirectory} nor {@link
114116
* #bulkGetPackages}, so it can only be used for use cases that do not call either of these
@@ -119,6 +121,8 @@ default Set<PackageIdentifier> bulkIsPackage(
119121
*
120122
* @see com.google.devtools.build.lib.cmdline.TargetPattern.Type
121123
*/
124+
// TODO(bazel-team): should we avoid forcing symbolic macro expansion, and use a backing map of
125+
// packageoids-for-build-file instead?
122126
class PackageBackedRecursivePackageProvider implements RecursivePackageProvider {
123127
private final Map<PackageIdentifier, Package> packages;
124128

@@ -136,6 +140,12 @@ public Package getPackage(ExtendedEventHandler eventHandler, PackageIdentifier p
136140
return pkg;
137141
}
138142

143+
@Override
144+
public InputFile getBuildFile(ExtendedEventHandler eventHandler, PackageIdentifier packageName)
145+
throws NoSuchPackageException {
146+
return getPackage(eventHandler, packageName).getBuildFile();
147+
}
148+
139149
@Override
140150
public boolean isPackage(ExtendedEventHandler eventHandler, PackageIdentifier packageName) {
141151
return packages.containsKey(packageName);

src/main/java/com/google/devtools/build/lib/pkgcache/TargetProvider.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414

1515
package com.google.devtools.build.lib.pkgcache;
1616

17+
import com.google.common.collect.ImmutableCollection;
1718
import com.google.devtools.build.lib.cmdline.Label;
1819
import com.google.devtools.build.lib.events.ExtendedEventHandler;
20+
import com.google.devtools.build.lib.packages.InputFile;
1921
import com.google.devtools.build.lib.packages.NoSuchPackageException;
2022
import com.google.devtools.build.lib.packages.NoSuchTargetException;
2123
import com.google.devtools.build.lib.packages.Target;
@@ -37,4 +39,18 @@ public interface TargetProvider {
3739
*/
3840
Target getTarget(ExtendedEventHandler eventHandler, Label label)
3941
throws NoSuchPackageException, NoSuchTargetException, InterruptedException;
42+
43+
/** Returns the BUILD file target of the package which contains the given target. */
44+
InputFile getBuildFile(Target target) throws InterruptedException;
45+
46+
/**
47+
* Returns all targets in the package which contains the given target.
48+
*
49+
* @throws NoSuchPackageException if the lazy macro expansion is enabled and some of the pieces of
50+
* the full package could not be loaded.
51+
* @throws InterruptedException if the package loading was interrupted
52+
*/
53+
ImmutableCollection<Target> getSiblingTargetsInPackage(
54+
ExtendedEventHandler eventHandler, Target target)
55+
throws NoSuchPackageException, InterruptedException;
4056
}

src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -988,9 +988,13 @@ public Uniquifier<SkyKey> createSkyKeyUniquifier() {
988988

989989
@ThreadSafe
990990
@Override
991-
public Collection<Target> getSiblingTargetsInPackage(Target target) {
992-
// TODO(https://github.com/bazelbuild/bazel/issues/23852): support lazy macro expansion
993-
return target.getPackage().getTargets().values();
991+
public Collection<Target> getSiblingTargetsInPackage(Target target)
992+
throws QueryException, InterruptedException {
993+
try {
994+
return graphBackedRecursivePackageProvider.getSiblingTargetsInPackage(eventHandler, target);
995+
} catch (NoSuchPackageException e) {
996+
throw new QueryException(e.getMessage(), e, e.getDetailedExitCode().getFailureDetail());
997+
}
994998
}
995999

9961000
@ThreadSafe
@@ -1057,9 +1061,14 @@ public QueryTaskFuture<Void> evalTargetPatternKey(
10571061
public TransitiveLoadFilesHelper<Target> getTransitiveLoadFilesHelper() {
10581062
return new TransitiveLoadFilesHelperForTargets() {
10591063
@Override
1060-
public Target getLoadFileTarget(Target originalTarget, Label bzlLabel) {
1061-
// TODO(https://github.com/bazelbuild/bazel/issues/23852): support lazy macro expansion
1062-
return new FakeLoadTarget(bzlLabel, originalTarget.getPackage());
1064+
public Target getLoadFileTarget(Target originalTarget, Label bzlLabel)
1065+
throws InterruptedException {
1066+
return new FakeLoadTarget(bzlLabel, getBuildFileTarget(originalTarget).getPackageoid());
1067+
}
1068+
1069+
@Override
1070+
public Target getBuildFileTarget(Target originalTarget) throws InterruptedException {
1071+
return graphBackedRecursivePackageProvider.getBuildFile(originalTarget);
10631072
}
10641073

10651074
@Override
@@ -1084,12 +1093,11 @@ public Target maybeGetBuildFileTargetForLoadFileTarget(Target originalTarget, La
10841093
.build())
10851094
.build());
10861095
}
1087-
// TODO(https://github.com/bazelbuild/bazel/issues/23852): support lazy macro expansion
10881096
return new FakeLoadTarget(
10891097
Label.createUnvalidated(
10901098
packageIdentifier,
10911099
packageLookupValue.getBuildFileName().getFilenameFragment().getBaseName()),
1092-
originalTarget.getPackage());
1100+
getBuildFileTarget(originalTarget).getPackageoid());
10931101
}
10941102
};
10951103
}

src/main/java/com/google/devtools/build/lib/query2/common/AbstractBlazeQueryEnvironment.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,6 @@ public PackageIdentifier getPkgId(Target target) {
498498
return target.getLabel().getPackageIdentifier();
499499
}
500500

501-
@Override
502-
public Target getBuildFileTarget(Target originalTarget) {
503-
// TODO(https://github.com/bazelbuild/bazel/issues/23852): support lazy macro expansion
504-
return originalTarget.getPackage().getBuildFile();
505-
}
506-
507501
@Override
508502
public void visitLoads(
509503
Target originalTarget, LoadGraphVisitor<QueryException, InterruptedException> visitor)

src/main/java/com/google/devtools/build/lib/query2/compat/FakeLoadTarget.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,20 @@ public class FakeLoadTarget implements Target {
3434
private final Label label;
3535
private final Packageoid pkg;
3636

37-
public FakeLoadTarget(Label label, Package pkg) {
37+
/**
38+
* @param packageoidOfBuildFile the {@link Packageoid} owning the package's BUILD file: in other
39+
* words, either a monolithic {@link Package} (under eager symbolic macro expansion), or a
40+
* {@link PackagePiece.ForBuildFile} (under lazy symbolic macro expansion).
41+
*/
42+
public FakeLoadTarget(Label label, Packageoid packageoidOfBuildFile) {
3843
this.label = Preconditions.checkNotNull(label);
39-
this.pkg = Preconditions.checkNotNull(pkg);
40-
}
41-
42-
// Fake load targets should be in the same package piece as the package's BUILD file.
43-
public FakeLoadTarget(Label label, PackagePiece.ForBuildFile pkgPiece) {
44-
this.label = Preconditions.checkNotNull(label);
45-
this.pkg = Preconditions.checkNotNull(pkgPiece);
44+
Preconditions.checkNotNull(packageoidOfBuildFile);
45+
Preconditions.checkArgument(
46+
(packageoidOfBuildFile instanceof Package pkg && pkg.getBuildFile().getPackageoid() == pkg)
47+
|| packageoidOfBuildFile instanceof PackagePiece.ForBuildFile,
48+
"%s must be either a monolithic package or a top-level package piece",
49+
packageoidOfBuildFile);
50+
this.pkg = packageoidOfBuildFile;
4651
}
4752

4853
@Override

src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ void samePkgDirectRdeps(Iterable<T> from, QueryExpression caller, Callback<T> ca
240240
}
241241

242242
/** Returns all of the targets in <code>target</code>'s package, in some stable order. */
243-
Collection<T> getSiblingTargetsInPackage(T target) throws QueryException;
243+
Collection<T> getSiblingTargetsInPackage(T target) throws QueryException, InterruptedException;
244244

245245
/**
246246
* Invokes {@code callback} with the set of target nodes in the graph for the specified target
@@ -570,9 +570,9 @@ void visitLoads(
570570
T originalTarget, LoadGraphVisitor<QueryException, InterruptedException> visitor)
571571
throws QueryException, InterruptedException;
572572

573-
T getBuildFileTarget(T originalTarget);
573+
T getBuildFileTarget(T originalTarget) throws InterruptedException;
574574

575-
T getLoadFileTarget(T originalTarget, Label bzlLabel);
575+
T getLoadFileTarget(T originalTarget, Label bzlLabel) throws InterruptedException;
576576

577577
@Nullable
578578
T maybeGetBuildFileTargetForLoadFileTarget(T originalTarget, Label bzlLabel)

0 commit comments

Comments
 (0)