Skip to content

Commit

Permalink
bzlmod: add BzlmodRepoRuleFunction and friends
Browse files Browse the repository at this point in the history
- BzlmodRepoRuleHelper: calculates the RepoSpec for a given repository. The actual calculation will be implemented in following changes.

- BzlmodRepoRuleFunction: Take a given repository name, look up its RepoSpec via BzlmodRepoRuleHelper, and then create a repository rule out of it. The result will be used in RepositoryDelegatorFunction.

Related: #13316

RELNOTES: None.
PiperOrigin-RevId: 382745079
  • Loading branch information
meteorcloudy authored and copybara-github committed Jul 2, 2021
1 parent 8325885 commit 348b532
Show file tree
Hide file tree
Showing 22 changed files with 793 additions and 12 deletions.
36 changes: 36 additions & 0 deletions src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,39 @@ java_library(
"//third_party:jsr305",
],
)

java_library(
name = "repo_rule_value",
srcs = [
"BzlmodRepoRuleValue.java",
],
deps = [
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
"//third_party:guava",
],
)

java_library(
name = "repo_rule_helper",
srcs = [
"BzlmodRepoRuleHelper.java",
"BzlmodRepoRuleHelperImpl.java",
],
deps = [
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common",
"//src/main/java/com/google/devtools/build/skyframe",
],
)

java_library(
name = "repo_rule_creator",
srcs = ["BzlmodRepoRuleCreator.java"],
deps = [
"//src/main/java/com/google/devtools/build/lib/events",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/net/starlark/java/eval",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2021 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.bazel.bzlmod;

import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
import java.util.Map;
import net.starlark.java.eval.StarlarkSemantics;

/**
* An interface for {@link RepositoryRuleFunction} to create a repository rule instance with given
* parameters.
*/
public interface BzlmodRepoRuleCreator {
Rule createRule(
Package.Builder packageBuilder,
StarlarkSemantics semantics,
Map<String, Object> kwargs,
EventHandler handler)
throws InterruptedException, InvalidRuleException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2021 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.bazel.bzlmod;

import com.google.devtools.build.skyframe.SkyFunction.Environment;
import java.util.Optional;

/** A helper to get {@link RepoSpec} for Bzlmod generated repositories. */
public interface BzlmodRepoRuleHelper {
Optional<RepoSpec> getRepoSpec(Environment env, String repositoryName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2021 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.bazel.bzlmod;

import com.google.devtools.build.skyframe.SkyFunction.Environment;
import java.util.Optional;

/** A helper class to get {@link RepoSpec} for Bzlmod generated repositories. */
public final class BzlmodRepoRuleHelperImpl implements BzlmodRepoRuleHelper {

@Override
public Optional<RepoSpec> getRepoSpec(Environment env, String repositoryName) {
// TODO(pcloudy): Implement calculating RepoSpec.
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2021 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.bazel.bzlmod;

import com.google.common.collect.Interner;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.skyframe.AbstractSkyKey;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyValue;

/** The result of {@link BzlmodRepoRuleFunction}, holding a repository rule instance. */
public class BzlmodRepoRuleValue implements SkyValue {
public static final SkyFunctionName BZLMOD_REPO_RULE =
SkyFunctionName.createHermetic("BZLMOD_REPO_RULE");

private final Rule rule;

public BzlmodRepoRuleValue(Rule rule) {
this.rule = rule;
}

public Rule getRule() {
return rule;
}

public static Key key(String repositoryName) {
return Key.create(repositoryName);
}

/** Represents an unsuccessful repository lookup. */
public static final class RepoRuleNotFoundValue extends BzlmodRepoRuleValue {
private RepoRuleNotFoundValue() {
super(/* rule= */ null);
}

@Override
public Rule getRule() {
throw new IllegalStateException();
}
}

public static final RepoRuleNotFoundValue REPO_RULE_NOT_FOUND_VALUE = new RepoRuleNotFoundValue();

/** Argument for the SkyKey to request a BzlmodRepoRuleValue. */
@AutoCodec
public static class Key extends AbstractSkyKey<String> {
private static final Interner<Key> interner = BlazeInterners.newWeakInterner();

private Key(String arg) {
super(arg);
}

@AutoCodec.VisibleForSerialization
@AutoCodec.Instantiator
static Key create(String arg) {
return interner.intern(new Key(arg));
}

@Override
public SkyFunctionName functionName() {
return BZLMOD_REPO_RULE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/actions:file_metadata",
"//src/main/java/com/google/devtools/build/lib/analysis:analysis_cluster",
"//src/main/java/com/google/devtools/build/lib/analysis:blaze_directories",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:repo_rule_creator",
"//src/main/java/com/google/devtools/build/lib/bazel/debug:workspace-rule-event",
"//src/main/java/com/google/devtools/build/lib/bazel/repository",
"//src/main/java/com/google/devtools/build/lib/bazel/repository/cache",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.starlark.StarlarkAttrModule.Descriptor;
import com.google.devtools.build.lib.bazel.bzlmod.BzlmodRepoRuleCreator;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.events.EventHandler;
Expand All @@ -36,6 +37,8 @@
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.RuleFactory;
import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
import com.google.devtools.build.lib.packages.StarlarkExportable;
import com.google.devtools.build.lib.packages.WorkspaceFactoryHelper;
Expand All @@ -50,8 +53,11 @@
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkCallable;
import net.starlark.java.eval.StarlarkSemantics;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.StarlarkThread.CallStackEntry;
import net.starlark.java.eval.Tuple;
import net.starlark.java.syntax.Location;

/**
* The Starlark module containing the definition of {@code repository_rule} function to define a
Expand Down Expand Up @@ -119,7 +125,7 @@ public StarlarkCallable repositoryRule(
"A callable value that may be invoked during evaluation of the WORKSPACE file to"
+ " instantiate and return a repository rule.")
private static final class RepositoryRuleFunction
implements StarlarkCallable, StarlarkExportable {
implements StarlarkCallable, StarlarkExportable, BzlmodRepoRuleCreator {
private final RuleClass.Builder builder;
private final StarlarkCallable implementation;
private Label extensionLabel;
Expand Down Expand Up @@ -213,6 +219,23 @@ public Object call(StarlarkThread thread, Tuple args, Dict<String, Object> kwarg
throw Starlark.errorf("%s", e.getMessage());
}
}

@Override
public Rule createRule(
Package.Builder packageBuilder,
StarlarkSemantics semantics,
Map<String, Object> kwargs,
EventHandler handler)
throws InterruptedException, InvalidRuleException {
RuleClass ruleClass = builder.build(exportedName, exportedName);
BuildLangTypedAttributeValuesMap attributeValues =
new BuildLangTypedAttributeValuesMap(kwargs);
ImmutableList.Builder<CallStackEntry> callStack = ImmutableList.builder();
// TODO(pcloudy): Optimize the callstack
callStack.add(new CallStackEntry("RepositoryRuleFunction.createRule", Location.BUILTIN));
return RuleFactory.createRule(
packageBuilder, ruleClass, attributeValues, handler, semantics, callStack.build());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class LabelConstants {
public static final PathFragment WORKSPACE_FILE_NAME = PathFragment.create("WORKSPACE");
public static final PathFragment WORKSPACE_DOT_BAZEL_FILE_NAME =
PathFragment.create("WORKSPACE.bazel");
public static final PathFragment MODULE_DOT_BAZEL_FILE_NAME = PathFragment.create("MODULE.bazel");
public static final String DEFAULT_REPOSITORY_DIRECTORY = "__main__";

// With this prefix, non-main repositories are symlinked under
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public final class BazelStarlarkEnvironment {
private final ImmutableMap<String, Object> workspaceBzlEnv;
/** The top-level predeclared symbols for a bzl module in the {@code @_builtins} pseudo-repo. */
private final ImmutableMap<String, Object> builtinsBzlEnv;
/** The top-level predeclared symbols for a bzl module in the Bzlmod system. */
private final ImmutableMap<String, Object> bzlmodBzlEnv;

BazelStarlarkEnvironment(
RuleClassProvider ruleClassProvider,
Expand All @@ -73,6 +75,9 @@ public final class BazelStarlarkEnvironment {
this.uninjectedBuildBzlEnv =
createUninjectedBuildBzlEnv(ruleClassProvider, uninjectedBuildBzlNativeBindings);
this.workspaceBzlEnv = createWorkspaceBzlEnv(ruleClassProvider, workspaceBzlNativeBindings);
// TODO(pcloudy): this should be a bzlmod specific environment, but keep using the workspace
// envirnment until we implement module rules.
this.bzlmodBzlEnv = createWorkspaceBzlEnv(ruleClassProvider, workspaceBzlNativeBindings);
this.builtinsBzlEnv =
createBuiltinsBzlEnv(
ruleClassProvider, uninjectedBuildBzlNativeBindings, uninjectedBuildBzlEnv);
Expand Down Expand Up @@ -126,6 +131,11 @@ public ImmutableMap<String, Object> getBuiltinsBzlEnv() {
return builtinsBzlEnv;
}

/** Returns the environment for Bzlmod-loaded bzl files. */
public ImmutableMap<String, Object> getBzlmodBzlEnv() {
return bzlmodBzlEnv;
}

/**
* Produces everything that would be in the "native" object for BUILD-loaded bzl files if builtins
* injection didn't happen.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ private void finishInit(Builder builder) {
this.packageDirectory = filename.asPath().getParentDirectory();
String baseName = filename.getRootRelativePath().getBaseName();

if (isWorkspaceFile(baseName)) {
if (isWorkspaceFile(baseName) || isModuleDotBazelFile(baseName)) {
Preconditions.checkState(
packageIdentifier.equals(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER));
this.sourceRoot = Optional.empty();
Expand Down Expand Up @@ -485,6 +485,10 @@ private static boolean isWorkspaceFile(String baseFileName) {
|| baseFileName.equals(LabelConstants.WORKSPACE_FILE_NAME.getPathString());
}

private static boolean isModuleDotBazelFile(String baseFileName) {
return baseFileName.equals(LabelConstants.MODULE_DOT_BAZEL_FILE_NAME.getPathString());
}

/** Returns the list of transitive closure of the Starlark file dependencies of this package. */
public ImmutableList<Label> getStarlarkFileDependencies() {
return starlarkFileDependencies;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ public boolean isImmutable() {
}
}

@VisibleForTesting // exposed to WorkspaceFileFunction
@VisibleForTesting // exposed to WorkspaceFileFunction and BzlmodRepoRuleFunction
public Package.Builder newExternalPackageBuilder(
RootedPath workspacePath, String workspaceName, StarlarkSemantics starlarkSemantics) {
return Package.newExternalPackageBuilder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public RuleClass getRuleClass(String ruleClassName) {
* <p>It is the caller's responsibility to add the rule to the package (the caller may choose not
* to do so if, for example, the rule has errors).
*/
static Rule createRule(
public static Rule createRule(
Package.Builder pkgBuilder,
RuleClass ruleClass,
BuildLangTypedAttributeValuesMap attributeValues,
Expand Down Expand Up @@ -203,7 +203,7 @@ public static Rule createAndAddRule(
* not be constructed. It contains an error message.
*/
public static class InvalidRuleException extends Exception {
private InvalidRuleException(String message) {
public InvalidRuleException(String message) {
super(message);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/google/devtools/build/lib/skyframe/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ java_library(
"BuildConfigurationFunction.java",
"BuildInfoCollectionFunction.java",
"BzlLoadFunction.java",
"BzlmodRepoRuleFunction.java",
"CompletionFunction.java",
"ConfiguredTargetFunction.java",
"ConstraintValueLookupUtil.java",
Expand Down Expand Up @@ -271,6 +272,9 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/analysis:workspace_status_action",
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
"//src/main/java/com/google/devtools/build/lib/analysis/platform:utils",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:repo_rule_helper",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:repo_rule_value",
"//src/main/java/com/google/devtools/build/lib/bugreport",
"//src/main/java/com/google/devtools/build/lib/buildeventstream",
"//src/main/java/com/google/devtools/build/lib/buildeventstream/proto:build_event_stream_java_proto",
Expand Down
Loading

0 comments on commit 348b532

Please sign in to comment.