Add support for loading .scl files
The Starlark Configuration Language (SCL) is a dialect of Starlark that resembles pure Starlark with just a few Bazel symbols (namely `visibility()` and `struct`), and a few restrictions on `load()` syntax and non-ASCII string data.
This CL adds support for loading .scl files anywhere a .bzl could be used. The restrictions on `load()` are implemented in this CL, but follow-up CLs will handle differentiating the top-level environment from .bzl, restricting non-ASCII data, and adding user documentation.
The dialect is gated on the flag `--experimental_enable_scl_dialect`.
- `BzlLoadValue` gains a new bool field on its abstract Key type to indicate whether it is for .scl. This was chosen instead of creating a new Key subclass so that .scl can work equally well in different contexts (loaded by BUILD, WORKSPACE, MODULE.bazel, or even @_builtins).
- `BzlLoadFunction.checkValidLoadLabel` and `.getLoadLabels` are both split into a public and private method. The public methods assume the load is coming from a .bzl file for validation purposes, and take a `StarlarkSemantics` to check whether the experimental flag is enabled.
- Eliminate `BzlLoadFunction.getBUILDLabel()` helper, which is obsolete.
- Modify existing tests to incidentally check that bzlmod .bzls can load .scl files and that .scl files can appear in transitive loads as reported by the Package (for `loadfiles()`).
RELNOTES: None
PiperOrigin-RevId: 528563228
Change-Id: I8493d1f33d35e1af8003dc61e5fdb626676d7e53
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/SingleExtensionEvalFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/SingleExtensionEvalFunction.java
index 74f9f63..222eb67 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/SingleExtensionEvalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/SingleExtensionEvalFunction.java
@@ -111,8 +111,7 @@
// Check that the .bzl label isn't crazy.
try {
- BzlLoadFunction.checkValidLoadLabel(
- extensionId.getBzlFileLabel(), /*fromBuiltinsRepo=*/ false);
+ BzlLoadFunction.checkValidLoadLabel(extensionId.getBzlFileLabel(), starlarkSemantics);
} catch (LabelSyntaxException e) {
throw new SingleExtensionEvalFunctionException(
ExternalDepsException.withCauseAndMessage(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java
index 4cf7d12..2641aa3 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java
@@ -197,6 +197,15 @@
public boolean experimentalEnableAndroidMigrationApis;
@Option(
+ name = "experimental_enable_scl_dialect",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS,
+ effectTags = OptionEffectTag.BUILD_FILE_SEMANTICS,
+ // TODO(brandjon): point to more extensive user documentation somewhere
+ help = "If set to true, .scl files may be used in load() statements.")
+ public boolean experimentalEnableSclDialect;
+
+ @Option(
name = "enable_bzlmod",
oldName = "experimental_enable_bzlmod",
defaultValue = "false",
@@ -677,6 +686,7 @@
.setBool(CHECK_BZL_VISIBILITY, checkBzlVisibility)
.setBool(
EXPERIMENTAL_ENABLE_ANDROID_MIGRATION_APIS, experimentalEnableAndroidMigrationApis)
+ .setBool(EXPERIMENTAL_ENABLE_SCL_DIALECT, experimentalEnableSclDialect)
.setBool(ENABLE_BZLMOD, enableBzlmod)
.setBool(
EXPERIMENTAL_JAVA_PROTO_LIBRARY_DEFAULT_HAS_SERVICES,
@@ -770,6 +780,7 @@
"-experimental_disable_external_package";
public static final String EXPERIMENTAL_ENABLE_ANDROID_MIGRATION_APIS =
"-experimental_enable_android_migration_apis";
+ public static final String EXPERIMENTAL_ENABLE_SCL_DIALECT = "-experimental_enable_scl_dialect";
public static final String ENABLE_BZLMOD = "-enable_bzlmod";
public static final String EXPERIMENTAL_JAVA_PROTO_LIBRARY_DEFAULT_HAS_SERVICES =
"+experimental_java_proto_library_default_has_services";
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
index a9e7b0e..f6012b0 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
@@ -86,7 +86,11 @@
import net.starlark.java.syntax.StringLiteral;
/**
- * A Skyframe function to look up and load a single .bzl module.
+ * A Skyframe function to look up and load a single .bzl (or .scl) module.
+ *
+ * <p>Note: Historically, all modules had the .bzl suffix, but this is no longer true now that Bazel
+ * supports the .scl dialect. In identifiers, code comments, and documentation, you should generally
+ * assume any "bzl" term could mean a .scl file as well.
*
* <p>Given a {@link Label} referencing a .bzl file, attempts to locate the file and load it. The
* Label must be absolute, and must not reference the special {@code external} package. If loading
@@ -736,6 +740,14 @@
Label label = key.getLabel();
PackageIdentifier pkg = label.getPackageIdentifier();
+ boolean isSclFlagEnabled =
+ builtins.starlarkSemantics.getBool(BuildLanguageOptions.EXPERIMENTAL_ENABLE_SCL_DIALECT);
+ if (key.isSclDialect() && !isSclFlagEnabled) {
+ throw new BzlLoadFailedException(
+ "loading .scl files requires setting --experimental_enable_scl_dialect",
+ Code.PARSE_ERROR);
+ }
+
// Determine dependency BzlLoadValue keys for the load statements in this bzl.
// Labels are resolved relative to the current repo mapping.
RepositoryMapping repoMapping = getRepositoryMapping(key, builtins.starlarkSemantics, env);
@@ -744,7 +756,13 @@
}
ImmutableList<Pair<String, Location>> programLoads = getLoadsFromProgram(prog);
ImmutableList<Label> loadLabels =
- getLoadLabels(env.getListener(), programLoads, pkg, repoMapping);
+ getLoadLabels(
+ env.getListener(),
+ programLoads,
+ pkg,
+ repoMapping,
+ key.isSclDialect(),
+ isSclFlagEnabled);
if (loadLabels == null) {
throw new BzlLoadFailedException(
String.format(
@@ -933,11 +951,59 @@
return repositoryMappingValue.getRepositoryMapping();
}
- public static void checkValidLoadLabel(Label label, boolean fromBuiltinsRepo)
+ /**
+ * Validates a label appearing in a {@code load()} statement, throwing {@link
+ * LabelSyntaxException} on failure.
+ *
+ * <p>Different restrictions apply depending on what type of source file the load appears in. For
+ * all kinds of files, {@code label}:
+ *
+ * <ul>
+ * <li>may not be within {@code @//external}.
+ * <li>must end with either {@code .bzl} or {@code .scl}.
+ * </ul>
+ *
+ * <p>For source files appearing within {@code @_builtins}, {@code label} must also be within
+ * {@code @_builtins}. (The reverse, that those files may not be loaded by user-defined files, is
+ * enforced by the fact that the {@code @_builtins} pseudorepo cannot be resolved as an ordinary
+ * repo.)
+ *
+ * <p>For .scl files only, {@code label} must end with {@code .scl} (not {@code .bzl}). (Loads in
+ * .scl also should always begin with {@code //}, but that's syntactic and can't be enforced in
+ * this method.)
+ *
+ * @param label the label to validate
+ * @param fromBuiltinsRepo true if the file containing the load is within {@code @_builtins}
+ * @param withinSclDialect true if the file containing the load is a .scl file
+ * @param mentionSclInErrorMessage true if ".scl" should be advertised as a possible extension in
+ * error messaging
+ */
+ private static void checkValidLoadLabel(
+ Label label,
+ boolean fromBuiltinsRepo,
+ boolean withinSclDialect,
+ boolean mentionSclInErrorMessage)
throws LabelSyntaxException {
- if (!label.getName().endsWith(".bzl")) {
- throw new LabelSyntaxException("The label must reference a file with extension '.bzl'");
+ // Check file extension.
+ String baseName = label.getName();
+ if (withinSclDialect) {
+ if (!baseName.endsWith(".scl")) {
+ String msg = "The label must reference a file with extension \".scl\"";
+ if (baseName.endsWith(".bzl")) {
+ msg += " (.scl files cannot load .bzl files)";
+ }
+ throw new LabelSyntaxException(msg);
+ }
+ } else {
+ if (!(baseName.endsWith(".scl") || baseName.endsWith(".bzl"))) {
+ String msg = "The label must reference a file with extension \".bzl\"";
+ if (mentionSclInErrorMessage) {
+ msg += " or \".scl\"";
+ }
+ throw new LabelSyntaxException(msg);
+ }
}
+
if (label.getPackageIdentifier().equals(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER)) {
throw new LabelSyntaxException(
"Starlark files may not be loaded from the //external package");
@@ -949,6 +1015,66 @@
}
/**
+ * Validates a label appearing in a {@code load()} statement, throwing {@link
+ * LabelSyntaxException} on failure.
+ */
+ public static void checkValidLoadLabel(Label label, StarlarkSemantics starlarkSemantics)
+ throws LabelSyntaxException {
+ checkValidLoadLabel(
+ label,
+ /* fromBuiltinsRepo= */ false,
+ /* withinSclDialect= */ false,
+ /* mentionSclInErrorMessage= */ starlarkSemantics.getBool(
+ BuildLanguageOptions.EXPERIMENTAL_ENABLE_SCL_DIALECT));
+ }
+
+ /**
+ * Given a list of {@code load("module")} strings and their locations, in source order, returns a
+ * corresponding list of Labels they each resolve to. Labels are resolved relative to {@code
+ * base}, the file's package. If any label is malformed, the function reports one or more errors
+ * to the handler and returns null.
+ *
+ * <p>If {@code withinSclDialect} is true, the labels are validated according to the rules of the
+ * .scl dialect: Only strings beginning with {@code //} are allowed (no repo syntax, no relative
+ * labels), and only .scl files may be loaded (not .bzl). If {@code isSclFlagEnabled} is true,
+ * then ".scl" is mentioned as a possible file extension in error messages.
+ */
+ @Nullable
+ private static ImmutableList<Label> getLoadLabels(
+ EventHandler handler,
+ ImmutableList<Pair<String, Location>> loads,
+ PackageIdentifier base,
+ RepositoryMapping repoMapping,
+ boolean withinSclDialect,
+ boolean isSclFlagEnabled) {
+ boolean ok = true;
+
+ ImmutableList.Builder<Label> loadLabels = ImmutableList.builderWithExpectedSize(loads.size());
+ for (Pair<String, Location> load : loads) {
+ // Parse the load statement's module string as a label. Validate the unparsed string for
+ // syntax and the parsed label for structure.
+ String unparsedLabel = load.first;
+ try {
+ if (withinSclDialect && !unparsedLabel.startsWith("//")) {
+ throw new LabelSyntaxException("in .scl files, load labels must begin with \"//\"");
+ }
+ Label label =
+ Label.parseWithPackageContext(unparsedLabel, PackageContext.of(base, repoMapping));
+ checkValidLoadLabel(
+ label,
+ /* fromBuiltinsRepo= */ StarlarkBuiltinsValue.isBuiltinsRepo(base.getRepository()),
+ /* withinSclDialect= */ withinSclDialect,
+ /* mentionSclInErrorMessage= */ isSclFlagEnabled);
+ loadLabels.add(label);
+ } catch (LabelSyntaxException ex) {
+ handler.handle(Event.error(load.second, "in load statement: " + ex.getMessage()));
+ ok = false;
+ }
+ }
+ return ok ? loadLabels.build() : null;
+ }
+
+ /**
* Given a list of {@code load("module")} strings and their locations, in source order, returns a
* corresponding list of Labels they each resolve to. Labels are resolved relative to {@code
* base}, the file's package. If any label is malformed, the function reports one or more errors
@@ -959,31 +1085,16 @@
EventHandler handler,
ImmutableList<Pair<String, Location>> loads,
PackageIdentifier base,
- RepositoryMapping repoMapping) {
- // It's redundant that getRelativeWithRemapping needs a Label;
- // a PackageIdentifier should suffice. Make one here.
- Label buildLabel = getBUILDLabel(base);
-
- boolean ok = true;
-
- ImmutableList.Builder<Label> loadLabels = ImmutableList.builderWithExpectedSize(loads.size());
- for (Pair<String, Location> load : loads) {
- // Parse the load statement's module string as a label.
- // It must end in .bzl and not be in package "//external".
- try {
- Label label =
- Label.parseWithPackageContext(
- load.first, PackageContext.of(buildLabel.getPackageIdentifier(), repoMapping));
- checkValidLoadLabel(
- label,
- /* fromBuiltinsRepo= */ StarlarkBuiltinsValue.isBuiltinsRepo(base.getRepository()));
- loadLabels.add(label);
- } catch (LabelSyntaxException ex) {
- handler.handle(Event.error(load.second, "in load statement: " + ex.getMessage()));
- ok = false;
- }
- }
- return ok ? loadLabels.build() : null;
+ RepositoryMapping repoMapping,
+ StarlarkSemantics starlarkSemantics) {
+ return getLoadLabels(
+ handler,
+ loads,
+ base,
+ repoMapping,
+ /* withinSclDialect= */ false,
+ /* isSclFlagEnabled= */ starlarkSemantics.getBool(
+ BuildLanguageOptions.EXPERIMENTAL_ENABLE_SCL_DIALECT));
}
/** Extracts load statements from compiled program (see {@link #getLoadLabels}). */
@@ -1010,15 +1121,6 @@
return loads.build();
}
- private static Label getBUILDLabel(PackageIdentifier pkgid) {
- try {
- return Label.create(pkgid, "BUILD");
- } catch (LabelSyntaxException e) {
- // Shouldn't happen; the Label is well-formed by construction.
- throw new IllegalStateException(e);
- }
- }
-
/**
* Computes the BzlLoadValue for all given .bzl load keys using ordinary Skyframe evaluation,
* returning {@code null} if Skyframe deps were missing and have been requested. {@code
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java
index d78c26a..ab14bb5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadValue.java
@@ -31,7 +31,11 @@
import net.starlark.java.eval.Module;
/**
- * A value that represents the .bzl module loaded by a Starlark {@code load()} statement.
+ * A value that represents the .bzl (or .scl) module loaded by a Starlark {@code load()} statement.
+ *
+ * <p>Note: Historically, all modules had the .bzl suffix, but this is no longer true now that Bazel
+ * supports the .scl dialect. In identifiers, code comments, and documentation, you should generally
+ * assume any "bzl" term could mean a .scl file as well.
*
* <p>The key consists of an absolute {@link Label} and the context in which the load occurs. The
* Label should not reference the special {@code external} package.
@@ -95,6 +99,22 @@
return false;
}
+ /** Returns true if the requested file follows the .scl dialect. */
+ // Note: Just as with .bzl, the same .scl file can be referred to from multiple key types, for
+ // instance if a BUILD file and a module rule both load foo.scl. Conceptually, .scl files
+ // shouldn't depend on what kind of top-level file caused them to load, but in practice, this
+ // implementation quirk means that the .scl file will be loaded twice as separate copies.
+ //
+ // This shouldn't matter except in rare edge cases, such as if a Starlark function is loaded
+ // from both copies and compared for equality. Performance wise, it also means that all
+ // transitive .scl files will be double-loaded, but we don't expect that to be significant.
+ //
+ // The alternative is to use a separate key type just for .scl, but that complicates repo logic;
+ // see BzlLoadFunction#getRepositoryMapping.
+ final boolean isSclDialect() {
+ return getLabel().getName().endsWith(".scl");
+ }
+
/**
* Constructs a new key suitable for evaluating a {@code load()} dependency of this key's .bzl
* file.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java
index a7c5c48..2e18581 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java
@@ -220,7 +220,8 @@
env.getListener(),
programLoads,
PackageIdentifier.EMPTY_PACKAGE_ID,
- EMPTY_MAIN_REPO_MAPPING);
+ EMPTY_MAIN_REPO_MAPPING,
+ starlarkSemantics);
if (loadLabels == null) {
NoSuchPackageException e =
PackageFunction.PackageFunctionException.builder()
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index ebeeccd..c0ae3f7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -1288,7 +1288,11 @@
BzlLoadFunction.getLoadsFromProgram(compiled.prog);
ImmutableList<Label> loadLabels =
BzlLoadFunction.getLoadLabels(
- env.getListener(), programLoads, packageId, repositoryMapping);
+ env.getListener(),
+ programLoads,
+ packageId,
+ repositoryMapping,
+ starlarkBuiltinsValue.starlarkSemantics);
if (loadLabels == null) {
throw PackageFunctionException.builder()
.setType(PackageFunctionException.Type.BUILD_FILE_CONTAINS_ERRORS)
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
index 768586c..d9539f9 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
@@ -297,7 +297,8 @@
ImmutableList<Pair<String, Location>> programLoads =
BzlLoadFunction.getLoadsFromStarlarkFiles(chunk);
ImmutableList<Label> loadLabels =
- BzlLoadFunction.getLoadLabels(env.getListener(), programLoads, rootPackage, repoMapping);
+ BzlLoadFunction.getLoadLabels(
+ env.getListener(), programLoads, rootPackage, repoMapping, starlarkSemantics);
if (loadLabels == null) {
NoSuchPackageException e =
PackageFunction.PackageFunctionException.builder()
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/BzlLoadFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/BzlLoadFunctionTest.java
index a673ee2..cee118c 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/BzlLoadFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/BzlLoadFunctionTest.java
@@ -210,6 +210,101 @@
checkSuccessfulLookup("//pkg:subdir/ext2.bzl");
}
+ @Test
+ public void testLoadBadExtension_sclDisabled() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=false");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext.bzl", "load(':foo.garbage', 'a')");
+ reporter.removeHandler(failFastHandler);
+ checkFailingLookup("//pkg:ext.bzl", "has invalid load statements");
+ assertContainsEvent("The label must reference a file with extension \".bzl\"");
+ assertDoesNotContainEvent(".scl");
+ }
+
+ @Test
+ public void testLoadBadExtension_sclEnabled() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=true");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext.bzl", "load(':foo.garbage', 'a')");
+ reporter.removeHandler(failFastHandler);
+ checkFailingLookup("//pkg:ext.bzl", "has invalid load statements");
+ assertContainsEvent("The label must reference a file with extension \".bzl\" or \".scl\"");
+ }
+
+ @Test
+ public void testLoadingSclRequiresExperimentalFlag() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=false");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext.scl");
+ reporter.removeHandler(failFastHandler);
+ checkFailingLookup(
+ "//pkg:ext.scl", "loading .scl files requires setting --experimental_enable_scl_dialect");
+ }
+
+ @Test
+ public void testCanLoadScl() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=true");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext.scl");
+ checkSuccessfulLookup("//pkg:ext.scl");
+ }
+
+ @Test
+ public void testCanLoadSclFromBzlAndScl() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=true");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext1.scl", "a = 1");
+ // Can use relative load label syntax from ext2a.bzl, but not from ext2b.scl.
+ scratch.file("pkg/ext2a.bzl", "load(':ext1.scl', 'a')");
+ scratch.file("pkg/ext2b.scl", "load('//pkg:ext1.scl', 'a')");
+
+ checkSuccessfulLookup("//pkg:ext2a.bzl");
+ checkSuccessfulLookup("//pkg:ext2b.scl");
+ }
+
+ @Test
+ public void testSclCannotLoadNonSclFiles() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=true");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext1a.bzl", "a = 1");
+ scratch.file("pkg/ext1a.garbage", "a = 1");
+ // Cannot use relative label.
+ scratch.file("pkg/ext2a.scl", "load('//pkg:ext1a.bzl', 'a')");
+ scratch.file("pkg/ext2b.scl", "load('//pkg:ext1b.garbage', 'a')");
+
+ reporter.removeHandler(failFastHandler);
+ checkFailingLookup("//pkg:ext2a.scl", "has invalid load statements");
+ assertContainsEvent(
+ "The label must reference a file with extension \".scl\" (.scl files cannot load .bzl"
+ + " files)");
+ eventCollector.clear();
+ checkFailingLookup("//pkg:ext2b.scl", "has invalid load statements");
+ assertContainsEvent("The label must reference a file with extension \".scl\"");
+ assertDoesNotContainEvent(".bzl");
+ }
+
+ @Test
+ public void testSclCanOnlyLoadLabelsRelativeToDefaultRepoRoot() throws Exception {
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=true");
+
+ scratch.file("pkg/BUILD");
+ scratch.file("pkg/ext1.scl", "load(':foo.scl', 'a')");
+ scratch.file("pkg/ext2.scl", "load('@repo//:foo.scl', 'a')");
+
+ reporter.removeHandler(failFastHandler);
+ checkFailingLookup("//pkg:ext1.scl", "has invalid load statements");
+ assertContainsEvent("in .scl files, load labels must begin with \"//\"");
+ eventCollector.clear();
+ checkFailingLookup("//pkg:ext2.scl", "has invalid load statements");
+ assertContainsEvent("in .scl files, load labels must begin with \"//\"");
+ }
+
private EvaluationResult<BzlLoadValue> get(SkyKey skyKey) throws Exception {
EvaluationResult<BzlLoadValue> result =
SkyframeExecutorTestUtils.evaluate(
@@ -944,7 +1039,7 @@
@Test
public void testLoadBzlFileFromBzlmod() throws Exception {
- setBuildLanguageOptions("--enable_bzlmod");
+ setBuildLanguageOptions("--enable_bzlmod", "--experimental_enable_scl_dialect");
scratch.overwriteFile("MODULE.bazel", "bazel_dep(name='foo',version='1.0')");
registry
.addModule(
@@ -957,12 +1052,13 @@
scratch.file(fooDir.getRelative("BUILD").getPathString());
scratch.file(
fooDir.getRelative("test.bzl").getPathString(),
- "load('@bar_alias//:test.bzl', 'haha')",
+ // Also test that bzlmod .bzl files can load .scl files.
+ "load('@bar_alias//:test.scl', 'haha')",
"hoho = haha");
Path barDir = moduleRoot.getRelative("bar~2.0");
scratch.file(barDir.getRelative("WORKSPACE").getPathString());
scratch.file(barDir.getRelative("BUILD").getPathString());
- scratch.file(barDir.getRelative("test.bzl").getPathString(), "haha = 5");
+ scratch.file(barDir.getRelative("test.scl").getPathString(), "haha = 5");
SkyKey skyKey = BzlLoadValue.keyForBzlmod(Label.parseCanonical("@@foo~1.0//:test.bzl"));
EvaluationResult<BzlLoadValue> result =
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
index 220f5e2..79c290f 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
@@ -610,19 +610,21 @@
public void testTransitiveStarlarkDepsStoredInPackage() throws Exception {
scratch.file("foo/BUILD", "load('//bar:ext.bzl', 'a')");
scratch.file("bar/BUILD");
- scratch.file("bar/ext.bzl", "load('//baz:ext.bzl', 'b')", "a = b");
+ scratch.file("bar/ext.bzl", "load('//baz:ext.scl', 'b')", "a = b");
scratch.file("baz/BUILD");
- scratch.file("baz/ext.bzl", "b = 1");
+ scratch.file("baz/ext.scl", "b = 1");
scratch.file("qux/BUILD");
scratch.file("qux/ext.bzl", "c = 1");
preparePackageLoading(rootDirectory);
+ // must be done after preparePackageLoading()
+ setBuildLanguageOptions("--experimental_enable_scl_dialect=true");
SkyKey skyKey = PackageIdentifier.createInMainRepo("foo");
Package pkg = validPackageWithoutErrors(skyKey);
assertThat(pkg.getStarlarkFileDependencies())
.containsExactly(
- Label.parseCanonical("//bar:ext.bzl"), Label.parseCanonical("//baz:ext.bzl"));
+ Label.parseCanonical("//bar:ext.bzl"), Label.parseCanonical("//baz:ext.scl"));
scratch.overwriteFile("bar/ext.bzl", "load('//qux:ext.bzl', 'c')", "a = c");
getSkyframeExecutor()
@@ -766,7 +768,7 @@
reporter.removeHandler(failFastHandler);
SkyKey key = PackageIdentifier.createInMainRepo("p");
SkyframeExecutorTestUtils.evaluate(skyframeExecutor, key, /*keepGoing=*/ false, reporter);
- assertContainsEvent("The label must reference a file with extension '.bzl'");
+ assertContainsEvent("The label must reference a file with extension \".bzl\"");
}
@Test