diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java index e20608c1b2d1de..61f44dc131d48e 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java @@ -73,6 +73,19 @@ public final String getCanonicalRepoName() { */ public abstract int getCompatibilityLevel(); + /** + * Target patterns identifying execution platforms to register when this module is selected. Note + * that these are what was written in module files verbatim, and don't contain canonical repo + * names. + */ + public abstract ImmutableList getExecutionPlatformsToRegister(); + + /** + * Target patterns identifying toolchains to register when this module is selected. Note that + * these are what was written in module files verbatim, and don't contain canonical repo names. + */ + public abstract ImmutableList getToolchainsToRegister(); + /** * The direct dependencies of this module. The key type is the repo name of the dep, and the value * type is the ModuleKey (name+version) of the dep. @@ -125,7 +138,9 @@ public static Builder builder() { .setName("") .setVersion(Version.EMPTY) .setKey(ModuleKey.ROOT) - .setCompatibilityLevel(0); + .setCompatibilityLevel(0) + .setExecutionPlatformsToRegister(ImmutableList.of()) + .setToolchainsToRegister(ImmutableList.of()); } /** @@ -153,6 +168,12 @@ public abstract static class Builder { /** Optional; defaults to {@code 0}. */ public abstract Builder setCompatibilityLevel(int value); + /** Optional; defaults to an empty list. */ + public abstract Builder setExecutionPlatformsToRegister(ImmutableList value); + + /** Optional; defaults to an empty list. */ + public abstract Builder setToolchainsToRegister(ImmutableList value); + public abstract Builder setDeps(ImmutableMap value); abstract ImmutableMap.Builder depsBuilder(); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileGlobals.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileGlobals.java index 3bb56c75dc89ea..ef7ed904084e64 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileGlobals.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileGlobals.java @@ -122,12 +122,38 @@ private void addRepoNameUsage(String repoName, String how, Location where) throw named = true, positional = false, defaultValue = "0"), + @Param( + name = "execution_platforms_to_register", + doc = + "A list of already-defined execution platforms to be registered when this module is" + + " selected. Should be a list of absolute target patterns (ie. beginning with" + + " either @ or //). See toolchain resolution for more" + + " information.", + named = true, + positional = false, + allowedTypes = {@ParamType(type = Iterable.class, generic1 = String.class)}, + defaultValue = "[]"), + @Param( + name = "toolchains_to_register", + doc = + "A list of already-defined toolchains to be registered when this module is" + + " selected. Should be a list of absolute target patterns (ie. beginning with" + + " either @ or //). See toolchain resolution for more" + + " information.", + named = true, + positional = false, + allowedTypes = {@ParamType(type = Iterable.class, generic1 = String.class)}, + defaultValue = "[]"), }, useStarlarkThread = true) public void module( String name, String version, StarlarkInt compatibilityLevel, + Iterable executionPlatformsToRegister, + Iterable toolchainsToRegister, StarlarkThread thread) throws EvalException { if (moduleCalled) { @@ -144,10 +170,29 @@ public void module( module .setName(name) .setVersion(parsedVersion) - .setCompatibilityLevel(compatibilityLevel.toInt("compatibility_level")); + .setCompatibilityLevel(compatibilityLevel.toInt("compatibility_level")) + .setExecutionPlatformsToRegister( + checkAllAbsolutePatterns( + executionPlatformsToRegister, "execution_platforms_to_register")) + .setToolchainsToRegister( + checkAllAbsolutePatterns(toolchainsToRegister, "toolchains_to_register")); addRepoNameUsage(name, "as the current module name", thread.getCallerLocation()); } + private static ImmutableList checkAllAbsolutePatterns(Iterable iterable, String where) + throws EvalException { + Sequence list = Sequence.cast(iterable, String.class, where); + for (String item : list) { + if (!item.startsWith("//") && !item.startsWith("@")) { + throw Starlark.errorf( + "Expected absolute target patterns (must begin with '//' or '@') for '%s' argument, but" + + " got '%s' as an argument", + where, item); + } + } + return list.getImmutableList(); + } + @StarlarkMethod( name = "bazel_dep", doc = "Declares a direct dependency on another Bazel module.", diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java index 107620bb5bd0bc..60d6ca23b26575 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java @@ -24,7 +24,8 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.platform.PlatformInfo; import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils; -import com.google.devtools.build.lib.bazel.bzlmod.ExternalDepsException; +import com.google.devtools.build.lib.bazel.bzlmod.BazelModuleResolutionValue; +import com.google.devtools.build.lib.bazel.bzlmod.Module; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelConstants; import com.google.devtools.build.lib.cmdline.RepositoryName; @@ -34,6 +35,7 @@ import com.google.devtools.build.lib.packages.Package; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.pkgcache.FilteringPolicy; +import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction; import com.google.devtools.build.lib.server.FailureDetails.Analysis; import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code; import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; @@ -96,6 +98,13 @@ public SkyValue compute(SkyKey skyKey, Environment env) } } + // Get registered execution platforms from bzlmod. + ImmutableList bzlmodExecutionPlatforms = getBzlmodExecutionPlatforms(env); + if (bzlmodExecutionPlatforms == null) { + return null; + } + targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodExecutionPlatforms)); + // Get the registered execution platforms from the WORKSPACE. ImmutableList workspaceExecutionPlatforms = getWorkspaceExecutionPlatforms(env); if (workspaceExecutionPlatforms == null) { @@ -146,6 +155,36 @@ public static ImmutableList getWorkspaceExecutionPlatforms(Enviro return externalPackage.getRegisteredExecutionPlatforms(); } + @Nullable + private static ImmutableList getBzlmodExecutionPlatforms(Environment env) + throws InterruptedException, RegisteredExecutionPlatformsFunctionException { + if (!RepositoryDelegatorFunction.ENABLE_BZLMOD.get(env)) { + return ImmutableList.of(); + } + BazelModuleResolutionValue bazelModuleResolutionValue = + (BazelModuleResolutionValue) env.getValue(BazelModuleResolutionValue.KEY); + if (bazelModuleResolutionValue == null) { + return null; + } + ImmutableList.Builder executionPlatforms = ImmutableList.builder(); + for (Module module : bazelModuleResolutionValue.getDepGraph().values()) { + TargetPattern.Parser parser = + new TargetPattern.Parser( + PathFragment.EMPTY_FRAGMENT, + RepositoryName.createFromValidStrippedName(module.getCanonicalRepoName()), + bazelModuleResolutionValue.getFullRepoMapping(module.getKey())); + for (String pattern : module.getExecutionPlatformsToRegister()) { + try { + executionPlatforms.add(parser.parse(pattern)); + } catch (TargetParsingException e) { + throw new RegisteredExecutionPlatformsFunctionException( + new InvalidExecutionPlatformLabelException(pattern, e), Transience.PERSISTENT); + } + } + } + return executionPlatforms.build(); + } + private static ImmutableList configureRegisteredExecutionPlatforms( Environment env, BuildConfiguration configuration, List