public WorkspaceFactoryHelper(boolean allowOverride, String... args) { Path root = null; Path workspaceFilePath = null; try { Scratch scratch = new Scratch("/"); root = scratch.dir("/workspace"); workspaceFilePath = scratch.file("/workspace/WORKSPACE", args); } catch (IOException e) { fail("Shouldn't happen: " + e.getMessage()); } StoredEventHandler eventHandler = new StoredEventHandler(); builder = Package.newExternalPackageBuilder( Package.Builder.DefaultHelper.INSTANCE, workspaceFilePath, ""); this.factory = new WorkspaceFactory( builder, TestRuleClassProvider.getRuleClassProvider(), ImmutableList.<PackageFactory.EnvironmentExtension>of(), Mutability.create("test"), allowOverride, root, root); Exception exception = null; try { factory.parse(ParserInputSource.create(workspaceFilePath), eventHandler); } catch (BuildFileContainsErrorsException e) { exception = e; } catch (IOException | InterruptedException e) { fail("Shouldn't happen: " + e.getMessage()); } this.events = eventHandler.getEvents(); this.exception = exception; }
private static Environment.Frame createConstantsGlobals() { try (Mutability mutability = Mutability.create("CONSTANTS")) { Environment env = Environment.builder(mutability).build(); Runtime.setupConstants(env); return env.getGlobals(); } }
@Override public Environment createEnvironment(EventHandler eventHandler, Environment environment) { return Environment.builder(Mutability.create("build test")) .setGlobals(environment == null ? Environment.BUILD : environment.getGlobals()) .setEventHandler(eventHandler) .build(); }
private static Environment.Frame createSkylarkGlobals() { try (Mutability mutability = Mutability.create("SKYLARK")) { Environment env = Environment.builder(mutability).setSkylark().build(); Runtime.setupConstants(env); Runtime.setupMethodEnvironment(env, MethodLibrary.skylarkGlobalFunctions); return env.getGlobals(); } }
@Override public Environment createEnvironment(EventHandler eventHandler, Environment environment) { return Environment.builder(Mutability.create("skylark test")) .setSkylark() .setGlobals(environment == null ? Environment.SKYLARK : environment.getGlobals()) .setEventHandler(eventHandler) .build(); }
/** * Create a Rule Configured Target from the ruleContext and the ruleImplementation. The * registeredProviderTypes map indicates which keys in structs returned by skylark rules should be * interpreted as native TransitiveInfoProvider instances of type (map value). */ public static ConfiguredTarget buildRule( RuleContext ruleContext, BaseFunction ruleImplementation, Map<String, Class<? extends TransitiveInfoProvider>> registeredProviderTypes) throws InterruptedException { String expectFailure = ruleContext.attributes().get("expect_failure", Type.STRING); try (Mutability mutability = Mutability.create("configured target")) { SkylarkRuleContext skylarkRuleContext = new SkylarkRuleContext(ruleContext, Kind.RULE); Environment env = Environment.builder(mutability) .setSkylark() .setCallerLabel(ruleContext.getLabel()) .setGlobals( ruleContext .getRule() .getRuleClassObject() .getRuleDefinitionEnvironment() .getGlobals()) .setEventHandler(ruleContext.getAnalysisEnvironment().getEventHandler()) .build(); // NB: loading phase functions are not available: this is analysis already, // so we do *not* setLoadingPhase(). Object target = ruleImplementation.call( ImmutableList.<Object>of(skylarkRuleContext), ImmutableMap.<String, Object>of(), /*ast=*/ null, env); if (ruleContext.hasErrors()) { return null; } else if (!(target instanceof SkylarkClassObject) && target != Runtime.NONE && !(target instanceof Iterable)) { ruleContext.ruleError( String.format( "Rule should return a return a struct or a list, but got %s", SkylarkType.typeOf(target))); return null; } else if (!expectFailure.isEmpty()) { ruleContext.ruleError("Expected failure not found: " + expectFailure); return null; } ConfiguredTarget configuredTarget = createTarget(ruleContext, target, registeredProviderTypes); SkylarkProviderValidationUtil.checkOrphanArtifacts(ruleContext); return configuredTarget; } catch (EvalException e) { addRuleToStackTrace(e, ruleContext.getRule(), ruleImplementation); // If the error was expected, return an empty target. if (!expectFailure.isEmpty() && getMessageWithoutStackTrace(e).matches(expectFailure)) { return new com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder(ruleContext) .add(RunfilesProvider.class, RunfilesProvider.EMPTY) .build(); } ruleContext.ruleError("\n" + e.print()); return null; } }
/** Builds the Environment. */ public Environment build() { Preconditions.checkArgument(mutability.isMutable()); if (parent != null) { Preconditions.checkArgument(!parent.mutability().isMutable()); } Frame globalFrame = new Frame(mutability, parent); Frame dynamicFrame = new Frame(mutability, null); if (importedExtensions == null) { importedExtensions = ImmutableMap.of(); } return new Environment( globalFrame, dynamicFrame, eventHandler, importedExtensions, isSkylark, fileContentHashCode, isLoadingPhase); }
/** Creates the Extension to be imported. */ private Extension createExtension( BuildFileAST ast, PathFragment file, Map<PathFragment, Extension> importMap, Environment env) throws InterruptedException, SkylarkImportLookupFunctionException { StoredEventHandler eventHandler = new StoredEventHandler(); // TODO(bazel-team): this method overestimates the changes which can affect the // Skylark RuleClass. For example changes to comments or unused functions can modify the hash. // A more accurate - however much more complicated - way would be to calculate a hash based on // the transitive closure of the accessible AST nodes. try (Mutability mutability = Mutability.create("importing %s", file)) { com.google.devtools.build.lib.syntax.Environment extensionEnv = ruleClassProvider .createSkylarkRuleClassEnvironment( mutability, eventHandler, ast.getContentHashCode(), importMap) .setupOverride("native", packageFactory.getNativeModule()); ast.exec(extensionEnv, eventHandler); SkylarkRuleClassFunctions.exportRuleFunctions(extensionEnv, file); Event.replayEventsOn(env.getListener(), eventHandler.getEvents()); if (eventHandler.hasErrors()) { throw new SkylarkImportLookupFunctionException(SkylarkImportFailedException.errors(file)); } return new Extension(extensionEnv); } }
@Override public SkyValue compute(SkyKey skyKey, Environment env) throws WorkspaceFileFunctionException, InterruptedException { RootedPath workspaceRoot = (RootedPath) skyKey.argument(); FileValue workspaceFileValue = (FileValue) env.getValue(FileValue.key(workspaceRoot)); if (workspaceFileValue == null) { return null; } Path repoWorkspace = workspaceRoot.getRoot().getRelative(workspaceRoot.getRelativePath()); Builder builder = com.google.devtools.build.lib.packages.Package.newExternalPackageBuilder( repoWorkspace, packageFactory.getRuleClassProvider().getRunfilesPrefix()); try (Mutability mutability = Mutability.create("workspace %s", repoWorkspace)) { WorkspaceFactory parser = new WorkspaceFactory( builder, packageFactory.getRuleClassProvider(), mutability, installDir.getPathString()); parser.parse( ParserInputSource.create( ruleClassProvider.getDefaultWorkspaceFile(), new PathFragment("DEFAULT.WORKSPACE"))); if (!workspaceFileValue.exists()) { return new PackageValue(builder.build()); } try { parser.parse(ParserInputSource.create(repoWorkspace, workspaceFileValue.getSize())); } catch (IOException e) { throw new WorkspaceFileFunctionException(e, Transience.TRANSIENT); } } return new PackageValue(builder.build()); }
/** * Modifies a binding in the current Frame. Does not try to modify an inherited binding. This * will shadow any inherited binding, which may be an error that you want to guard against * before calling this function. * * @param env the Environment attempting the mutation * @param varname the name of the variable to be bound * @param value the value to bind to the variable */ public void put(Environment env, String varname, Object value) throws MutabilityException { Mutability.checkMutable(this, env); bindings.put(varname, value); }