use of com.google.devtools.build.lib.packages.SkylarkClassObject in project bazel by bazelbuild.
the class SkylarkRuleContext method buildSplitAttributeInfo.
private static SkylarkClassObject buildSplitAttributeInfo(Collection<Attribute> attributes, RuleContext ruleContext) {
ImmutableMap.Builder<String, Object> splitAttrInfos = ImmutableMap.builder();
for (Attribute attr : attributes) {
if (attr.hasSplitConfigurationTransition()) {
Map<Optional<String>, ? extends List<? extends TransitiveInfoCollection>> splitPrereqs = ruleContext.getSplitPrerequisites(attr.getName());
Map<Object, Object> splitPrereqsMap = new LinkedHashMap<>();
for (Entry<Optional<String>, ? extends List<? extends TransitiveInfoCollection>> splitPrereq : splitPrereqs.entrySet()) {
Object value;
if (attr.getType() == BuildType.LABEL) {
Preconditions.checkState(splitPrereq.getValue().size() == 1);
value = splitPrereq.getValue().get(0);
} else {
// BuildType.LABEL_LIST
value = SkylarkList.createImmutable(splitPrereq.getValue());
}
if (splitPrereq.getKey().isPresent()) {
splitPrereqsMap.put(splitPrereq.getKey().get(), value);
} else {
// If the split transition is not in effect, then the key will be missing since there's
// nothing to key on because the dependencies aren't split and getSplitPrerequisites()
// behaves like getPrerequisites(). This also means there should be only one entry in
// the map. Use None in Skylark to represent this.
Preconditions.checkState(splitPrereqs.size() == 1);
splitPrereqsMap.put(Runtime.NONE, value);
}
}
splitAttrInfos.put(attr.getPublicName(), SkylarkDict.copyOf(null, splitPrereqsMap));
}
}
return NativeClassObjectConstructor.STRUCT.create(splitAttrInfos.build(), "No attribute '%s' in split_attr. Make sure that this attribute is defined with a " + "split configuration.");
}
use of com.google.devtools.build.lib.packages.SkylarkClassObject in project bazel by bazelbuild.
the class SkylarkRuleConfiguredTargetBuilder method addStructFieldsAndBuild.
private static ConfiguredTarget addStructFieldsAndBuild(RuleContext ruleContext, RuleConfiguredTargetBuilder builder, Object target, Artifact executable, Map<String, Class<? extends TransitiveInfoProvider>> registeredProviderTypes) throws EvalException {
Location loc = null;
Boolean isParsed = false;
if (target instanceof SkylarkClassObject) {
SkylarkClassObject struct = (SkylarkClassObject) target;
loc = struct.getCreationLoc();
parseProviderKeys(struct, false, ruleContext, loc, executable, registeredProviderTypes, builder);
isParsed = true;
} else if (target instanceof Iterable) {
loc = ruleContext.getRule().getRuleClassObject().getConfiguredTargetFunction().getLocation();
for (Object o : (Iterable) target) {
SkylarkClassObject declaredProvider = SkylarkType.cast(o, SkylarkClassObject.class, loc, "A return value of a rule implementation function should be " + "a sequence of declared providers");
if (declaredProvider.getConstructor().getKey().equals(SkylarkRuleContext.getDefaultProvider().getKey())) {
parseProviderKeys(declaredProvider, true, ruleContext, loc, executable, registeredProviderTypes, builder);
isParsed = true;
} else {
Location creationLoc = declaredProvider.getCreationLocOrNull();
builder.addSkylarkDeclaredProvider(declaredProvider, creationLoc != null ? creationLoc : loc);
}
}
}
if (!isParsed) {
addSimpleProviders(builder, ruleContext, loc, executable, null, null, null, null);
}
try {
return builder.build();
} catch (IllegalArgumentException e) {
throw new EvalException(loc, e.getMessage());
}
}
use of com.google.devtools.build.lib.packages.SkylarkClassObject in project bazel by bazelbuild.
the class SkylarkRuleConfiguredTargetBuilder method buildRule.
/**
* 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, null);
Environment env = Environment.builder(mutability).setCallerLabel(ruleContext.getLabel()).setGlobals(ruleContext.getRule().getRuleClassObject().getRuleDefinitionEnvironment().getGlobals()).setEventHandler(ruleContext.getAnalysisEnvironment().getEventHandler()).build();
// 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 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;
}
}
use of com.google.devtools.build.lib.packages.SkylarkClassObject in project bazel by bazelbuild.
the class SkylarkRuleConfiguredTargetBuilder method addSimpleProviders.
private static void addSimpleProviders(RuleConfiguredTargetBuilder builder, RuleContext ruleContext, Location loc, Artifact executable, Runfiles statelessRunfiles, Runfiles dataRunfiles, Runfiles defaultRunfiles, SkylarkClassObject defaultProvider) throws EvalException {
if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
throw new EvalException(loc, "Cannot specify the provider 'runfiles' " + "together with 'data_runfiles' or 'default_runfiles'");
}
if (statelessRunfiles == null && dataRunfiles == null && defaultRunfiles == null) {
// No runfiles specified, set default
statelessRunfiles = Runfiles.EMPTY;
}
RunfilesProvider runfilesProvider = statelessRunfiles != null ? RunfilesProvider.simple(merge(statelessRunfiles, executable, ruleContext)) : RunfilesProvider.withData(// This is to keep skylark genrule consistent with the original genrule.
defaultRunfiles != null ? defaultRunfiles : Runfiles.EMPTY, dataRunfiles != null ? dataRunfiles : Runfiles.EMPTY);
builder.addProvider(RunfilesProvider.class, runfilesProvider);
Runfiles computedDefaultRunfiles = runfilesProvider.getDefaultRunfiles();
// This works because we only allowed to call a rule *_test iff it's a test type rule.
boolean testRule = TargetUtils.isTestRuleName(ruleContext.getRule().getRuleClass());
if (testRule && computedDefaultRunfiles.isEmpty()) {
throw new EvalException(loc, "Test rules have to define runfiles");
}
if (executable != null || testRule) {
RunfilesSupport runfilesSupport = computedDefaultRunfiles.isEmpty() ? null : RunfilesSupport.withExecutable(ruleContext, computedDefaultRunfiles, executable);
builder.setRunfilesSupport(runfilesSupport, executable);
}
if (ruleContext.getRule().getRuleClassObject().isSkylarkTestable()) {
SkylarkClassObject actions = ActionsProvider.create(ruleContext.getAnalysisEnvironment().getRegisteredActions());
builder.addSkylarkDeclaredProvider(actions, loc);
}
// Populate default provider fields and build it
ImmutableMap.Builder<String, Object> attrBuilder = new ImmutableMap.Builder<>();
// TODO: Add actual attributes that users expect to access from default providers
attrBuilder.put("runfiles", runfilesProvider);
SkylarkClassObject statelessDefaultProvider = new SkylarkClassObject(SkylarkRuleContext.getDefaultProvider(), attrBuilder.build());
// Add the default provider
builder.addSkylarkDeclaredProvider(statelessDefaultProvider, (defaultProvider == null) ? loc : Optional.fromNullable(defaultProvider.getCreationLocOrNull()).or(loc));
}
use of com.google.devtools.build.lib.packages.SkylarkClassObject in project bazel by bazelbuild.
the class PyCommon method checkForSharedLibraries.
/**
* Returns true if this target has an .so file in its transitive dependency closure.
*/
public static boolean checkForSharedLibraries(Iterable<TransitiveInfoCollection> deps) throws EvalException {
for (TransitiveInfoCollection dep : deps) {
SkylarkProviders providers = dep.getProvider(SkylarkProviders.class);
SkylarkClassObject provider = null;
if (providers != null) {
provider = providers.getValue(PYTHON_SKYLARK_PROVIDER_NAME, SkylarkClassObject.class);
}
if (provider != null) {
Boolean isUsingSharedLibrary = provider.getValue(IS_USING_SHARED_LIBRARY, Boolean.class);
if (Boolean.TRUE.equals(isUsingSharedLibrary)) {
return true;
}
} else if (FileType.contains(dep.getProvider(FileProvider.class).getFilesToBuild(), CppFileTypes.SHARED_LIBRARY)) {
return true;
}
}
return false;
}
Aggregations