/** * Generates an empty manifest for a rule that does not directly specify resources. * * <p><strong>Note:</strong> This generated manifest can then be used as the primary manifest when * merging with dependencies. * * @return the generated ApplicationManifest */ public static ApplicationManifest generatedManifest(RuleContext ruleContext) { Artifact generatedManifest = ruleContext.getUniqueDirectoryArtifact( ruleContext.getRule().getName() + "_generated", new PathFragment("AndroidManifest.xml"), ruleContext.getBinOrGenfilesDirectory()); String manifestPackage; if (ruleContext.attributes().isAttributeValueExplicitlySpecified("custom_package")) { manifestPackage = ruleContext.attributes().get("custom_package", Type.STRING); } else { manifestPackage = JavaUtil.getJavaFullClassname(ruleContext.getRule().getPackage().getNameFragment()); } String contents = Joiner.on("\n") .join( "<?xml version=\"1.0\" encoding=\"utf-8\"?>", "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"", " package=\"" + manifestPackage + "\">", " <application>", " </application>", "</manifest>"); ruleContext .getAnalysisEnvironment() .registerAction( new FileWriteAction( ruleContext.getActionOwner(), generatedManifest, contents, false /* makeExecutable */)); return new ApplicationManifest(generatedManifest); }
private static void validateAssetsAndAssetsDir(RuleContext ruleContext) throws RuleErrorException { if (ruleContext.attributes().isAttributeValueExplicitlySpecified("assets") ^ ruleContext.attributes().isAttributeValueExplicitlySpecified("assets_dir")) { ruleContext.ruleError( "'assets' and 'assets_dir' should be either both empty or both non-empty"); throw new RuleErrorException(); } }
/** Returns whether the includes should include each of the proto generated headers. */ boolean needsPerProtoIncludes() { if (ruleContext .attributes() .has(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN)) { return ruleContext .attributes() .get(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN); } return false; }
/** Returns whether the generated header files should have be of type pb.h or pbobjc.h. */ boolean usesObjcHeaderNames() { if (ruleContext .attributes() .has(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN)) { return ruleContext .attributes() .get(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN); } return false; }
public static String getJavaPackage(RuleContext ruleContext) { if (ruleContext.attributes().isAttributeValueExplicitlySpecified("custom_package")) { return ruleContext.attributes().get("custom_package", Type.STRING); } else { PathFragment nameFragment = ruleContext.getRule().getPackage().getNameFragment(); String packageName = JavaUtil.getJavaFullClassname(nameFragment); if (packageName != null) { return packageName; } else { // This is a workaround for libraries that don't follow the standard Bazel package format return nameFragment.getPathString().replace('/', '.'); } } }
private Bundling bundling( RuleContext ruleContext, ObjcProvider objcProvider, String bundleDirFormat, String bundleName, DottedVersion minimumOsVersion) { ImmutableList<BundleableFile> extraBundleFiles; AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); if (appleConfiguration.getBundlingPlatform() == Platform.IOS_DEVICE) { extraBundleFiles = ImmutableList.of( new BundleableFile( new Attributes(ruleContext).provisioningProfile(), PROVISIONING_PROFILE_BUNDLE_FILE)); } else { extraBundleFiles = ImmutableList.of(); } String primaryBundleId = null; String fallbackBundleId = null; if (ruleContext.attributes().isAttributeValueExplicitlySpecified("bundle_id")) { primaryBundleId = ruleContext.attributes().get("bundle_id", Type.STRING); } else { fallbackBundleId = ruleContext.attributes().get("bundle_id", Type.STRING); } Bundling.Builder bundling = new Builder() .setName(bundleName) // Architecture that determines which nested bundles are kept. .setArchitecture(appleConfiguration.getDependencySingleArchitecture()) .setBundleDirFormat(bundleDirFormat) .addExtraBundleFiles(extraBundleFiles) .setObjcProvider(objcProvider) .addInfoplistInputFromRule(ruleContext) .addInfoplistInput(getGeneratedVersionPlist()) .addInfoplistInput(getGeneratedEnvironmentPlist()) .setAutomaticEntriesInfoplistInput(getGeneratedAutomaticPlist()) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) .setPrimaryBundleId(primaryBundleId) .setFallbackBundleId(fallbackBundleId) .setMinimumOsVersion(minimumOsVersion); if (ObjcRuleClasses.useLaunchStoryboard(ruleContext)) { bundling.addInfoplistInput(getLaunchStoryboardPlist()); } return bundling.build(); }
private static Collection<Artifact> getTargetListAttribute( RuleContext ruleContext, String attributeName) { return (ruleContext.attributes().has(attributeName, BuildType.LABEL_LIST) && ruleContext.getAttributeMode(attributeName) == Mode.TARGET) ? ruleContext.getPrerequisiteArtifacts(attributeName, Mode.TARGET).list() : ImmutableList.<Artifact>of(); }
public static PathFragment getAssetDir(RuleContext ruleContext) { return new PathFragment( ruleContext .attributes() .get( AndroidResourcesProvider.ResourceType.ASSETS.getAttribute() + "_dir", Type.STRING)); }
/** * Returns the xcode version number corresponding to the {@code --xcode_version} flag, if there is * an available {@code xcode_version} target which recognizes the flag value as either an official * version or an alias. Returns null if no such target is found. */ @Nullable private DottedVersion resolveExplicitlyDefinedVersion(RuleContext ruleContext) { AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class); Optional<DottedVersion> versionOverrideFlag = configuration.getXcodeVersionOverrideFlag(); if (versionOverrideFlag.isPresent()) { // The version override flag is not necessarily an actual version - it may be a version // alias. DottedVersion explicitVerison = aliasesToVersionMap(ruleContext).get(versionOverrideFlag.get().toString()); if (explicitVerison != null) { return explicitVerison; } } else { // No override specified. Use default. XcodeVersionProvider defaultProvider = ruleContext.getPrerequisite( XcodeConfigRule.DEFAULT_ATTR_NAME, Mode.TARGET, XcodeVersionProvider.class); if (defaultProvider != null) { return defaultProvider.getVersion(); } } boolean requireDefinedVersions = ruleContext.attributes().get(XcodeConfigRule.REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN); if (requireDefinedVersions) { ruleContext.ruleError( "xcode version config required an explicitly defined version, but none was available"); } return null; }
/** Returns the options file, or null if it was not specified. */ @Nullable Artifact getOptionsFile() { if (ruleContext.attributes().has(ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, LABEL)) { return ruleContext.getPrerequisiteArtifact( ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, Mode.HOST); } return null; }
/** * 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; } }
/** Returns the list of portable proto filters. */ ImmutableList<Artifact> getPortableProtoFilters() { if (ruleContext .attributes() .has(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, LABEL_LIST)) { return ruleContext .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, Mode.HOST) .list(); } return ImmutableList.of(); }
private String getOverridePackage(RuleContext ruleContext) { // It seems that we sometimes rename the app for God-knows-what reason. If that is the case, // pass this information to the stubifier script. if (ruleContext.attributes().isAttributeValueExplicitlySpecified("application_id")) { return ruleContext.attributes().get("application_id", Type.STRING); } TransitiveInfoCollection resourcesPrerequisite = ruleContext.getPrerequisite("resources", Mode.TARGET); if (resourcesPrerequisite != null) { ResourceContainer resourceContainer = Iterables.getOnlyElement( resourcesPrerequisite .getProvider(AndroidResourcesProvider.class) .getTransitiveAndroidResources()); return resourceContainer.getRenameManifestPackage(); } else { return null; } }
/** Validates that there are no resources defined if there are resource attribute defined. */ private static void validateNoResourcesAttribute(RuleContext ruleContext) throws RuleErrorException { if (ruleContext.attributes().isAttributeValueExplicitlySpecified("resources")) { ruleContext.attributeError( "resources", String.format( "resources cannot be set when any of %s are defined.", Joiner.on(", ").join(RESOURCES_ATTRIBUTES))); throw new RuleErrorException(); } }
public static AndroidResourcesProvider getAndroidResources(RuleContext ruleContext) { if (!ruleContext.attributes().has("resources", BuildType.LABEL)) { return null; } TransitiveInfoCollection prerequisite = ruleContext.getPrerequisite("resources", Mode.TARGET); if (prerequisite == null) { return null; } return prerequisite.getProvider(AndroidResourcesProvider.class); }
NestedSet<? extends Artifact> dependentLinkedBinaries() { if (ruleContext.attributes().getAttributeDefinition("binary") == null) { return NestedSetBuilder.emptySet(Order.STABLE_ORDER); } NestedSetBuilder<Artifact> linkedBinaries = NestedSetBuilder.stableOrder(); for (ObjcProvider provider : ruleContext.getPrerequisites("binary", Mode.DONT_CHECK, ObjcProvider.class)) { linkedBinaries.addTransitive(provider.get(ObjcProvider.LINKED_BINARY)); } return linkedBinaries.build(); }
private void validateLaunchScreen() { if (ruleContext.attributes().isAttributeValueExplicitlySpecified("launch_storyboard")) { DottedVersion minimumOs = ObjcRuleClasses.objcConfiguration(ruleContext).getMinimumOs(); if (ObjcRuleClasses.useLaunchStoryboard(ruleContext)) { if (ruleContext.attributes().isAttributeValueExplicitlySpecified("launch_image")) { ruleContext.attributeWarning( "launch_image", String.format( "launch_image was specified but since --ios_minimum_os=%s (>=8.0), the also " + "specified launch_storyboard will be used instead", minimumOs)); } } else { if (!ruleContext.attributes().isAttributeValueExplicitlySpecified("launch_image")) { ruleContext.attributeWarning( "launch_storyboard", String.format( "launch_storyboard was specified but since --ios_minimum_os=%s (<8.0) and no " + "launch_image was specified instead it will be ignored", minimumOs)); } } } }
/** Create a Rule Configured Target from the ruleContext and the ruleImplementation. */ public static ConfiguredTarget buildRule( RuleContext ruleContext, BaseFunction ruleImplementation) { String expectFailure = ruleContext.attributes().get("expect_failure", Type.STRING); try { SkylarkRuleContext skylarkRuleContext = new SkylarkRuleContext(ruleContext); SkylarkEnvironment env = ruleContext .getRule() .getRuleClassObject() .getRuleDefinitionEnvironment() .cloneEnv(ruleContext.getAnalysisEnvironment().getEventHandler()); // Collect the symbols to disable statically and pass at the next call, so we don't need to // clone the RuleDefinitionEnvironment. env.disableOnlyLoadingPhaseObjects(); Object target = ruleImplementation.call( ImmutableList.<Object>of(skylarkRuleContext), ImmutableMap.<String, Object>of(), null, env); if (ruleContext.hasErrors()) { return null; } else if (!(target instanceof SkylarkClassObject) && target != Environment.NONE) { ruleContext.ruleError("Rule implementation doesn't return a struct"); return null; } else if (!expectFailure.isEmpty()) { ruleContext.ruleError("Expected failure not found: " + expectFailure); return null; } ConfiguredTarget configuredTarget = createTarget(ruleContext, target); checkOrphanArtifacts(ruleContext); return configuredTarget; } catch (InterruptedException e) { ruleContext.ruleError(e.getMessage()); return null; } catch (EvalException e) { // If the error was expected, return an empty target. if (!expectFailure.isEmpty() && e.getMessage().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; } }
/** * Validity-checks this rule's constraint-related attributes. Returns true if all is good, returns * false and reports appropriate errors if there are any problems. */ private static boolean validateAttributes(RuleContext ruleContext) { AttributeMap attributes = ruleContext.attributes(); // Report an error if "restricted to" is explicitly set to nothing. Even if this made // conceptual sense, we don't know which groups we should apply that to. String restrictionAttr = RuleClass.RESTRICTED_ENVIRONMENT_ATTR; List<? extends TransitiveInfoCollection> restrictionEnvironments = ruleContext.getPrerequisites(restrictionAttr, RuleConfiguredTarget.Mode.DONT_CHECK); if (restrictionEnvironments.isEmpty() && attributes.isAttributeValueExplicitlySpecified(restrictionAttr)) { ruleContext.attributeError(restrictionAttr, "attribute cannot be empty"); return false; } return true; }
/** Returns all dependencies that should be constraint-checked against the current rule. */ private static Iterable<TransitiveInfoCollection> getConstraintCheckedDependencies( RuleContext ruleContext) { Set<TransitiveInfoCollection> depsToCheck = new LinkedHashSet<>(); AttributeMap attributes = ruleContext.attributes(); for (String attr : attributes.getAttributeNames()) { Attribute attrDef = attributes.getAttributeDefinition(attr); Type<?> attrType = attributes.getAttributeType(attr); // TODO(bazel-team): support a user-definable API for choosing which attributes are checked if (!attrDef.checkConstraintsOverride()) { if ((attrType != BuildType.LABEL && attrType != BuildType.LABEL_LIST) || RuleClass.isConstraintAttribute(attr) || attr.equals("visibility") // Use the same implicit deps check that query uses. This facilitates running queries to // determine exactly which rules need to be constraint-annotated for depot migrations. || !Rule.NO_IMPLICIT_DEPS.apply(ruleContext.getRule(), attrDef) // We can't identify host deps by calling BuildConfiguration.isHostConfiguration() // because --nodistinct_host_configuration subverts that call. || attrDef.getConfigurationTransition() == Attribute.ConfigurationTransition.HOST) { continue; } } for (TransitiveInfoCollection dep : ruleContext.getPrerequisites(attr, RuleConfiguredTarget.Mode.DONT_CHECK)) { // Output files inherit the environment spec of their generating rule. if (dep instanceof OutputFileConfiguredTarget) { // Note this reassignment means constraint violation errors reference the generating // rule, not the file. This makes the source of the environmental mismatch more clear. dep = ((OutputFileConfiguredTarget) dep).getGeneratingRule(); } // Input files don't support environments. We may subsequently opt them into constraint // checking, but for now just pass them by. if (dep.getProvider(SupportedEnvironmentsProvider.class) != null) { depsToCheck.add(dep); } } } return depsToCheck; }
ImmutableMap<String, Artifact> cpuSpecificBreakpadFiles() { ImmutableMap.Builder<String, Artifact> results = ImmutableMap.builder(); if (ruleContext.attributes().has("binary", BuildType.LABEL)) { for (TransitiveInfoCollection prerequisite : ruleContext.getPrerequisites("binary", Mode.DONT_CHECK)) { ObjcProvider prerequisiteProvider = prerequisite.getProvider(ObjcProvider.class); if (prerequisiteProvider != null) { Artifact sourceBreakpad = Iterables.getOnlyElement( prerequisiteProvider.get(ObjcProvider.BREAKPAD_FILE), null); if (sourceBreakpad != null) { String cpu = prerequisite.getConfiguration().getFragment(ObjcConfiguration.class).getIosCpu(); results.put(cpu, sourceBreakpad); } } } } return results.build(); }
public static AndroidIdeInfoProvider createAndroidIdeInfoProvider( RuleContext ruleContext, AndroidSemantics semantics, AndroidIdlHelper idlHelper, OutputJar resourceJar, ResourceApk resourceApk, Artifact zipAlignedApk, Iterable<Artifact> apksUnderTest) { AndroidIdeInfoProvider.Builder ideInfoProviderBuilder = new AndroidIdeInfoProvider.Builder() .setIdlClassJar(idlHelper.getIdlClassJar()) .setIdlSourceJar(idlHelper.getIdlSourceJar()) .setResourceJar(resourceJar) .addIdlParcelables(idlHelper.getIdlParcelables()) .addIdlSrcs(idlHelper.getIdlSources()) .addIdlGeneratedJavaFiles(idlHelper.getIdlGeneratedJavaSources()) .addAllApksUnderTest(apksUnderTest); if (zipAlignedApk != null) { ideInfoProviderBuilder.setApk(zipAlignedApk); } // If the rule defines resources, put those in the IDE info. Otherwise, proxy the data coming // from the android_resources rule in its direct dependencies, if such a thing exists. if (LocalResourceContainer.definesAndroidResources(ruleContext.attributes())) { ideInfoProviderBuilder .setDefinesAndroidResources(true) .addResourceSources(resourceApk.getPrimaryResource().getArtifacts(ResourceType.RESOURCES)) .addAssetSources( resourceApk.getPrimaryResource().getArtifacts(ResourceType.ASSETS), getAssetDir(ruleContext)) // Sets the possibly merged manifest and the raw manifest. .setGeneratedManifest(resourceApk.getPrimaryResource().getManifest()) .setManifest(ruleContext.getPrerequisiteArtifact("manifest", Mode.TARGET)) .setJavaPackage(getJavaPackage(ruleContext)); } else { semantics.addNonLocalResources(ruleContext, resourceApk, ideInfoProviderBuilder); } return ideInfoProviderBuilder.build(); }
@Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException { ObjcCommon common = common( ruleContext, ImmutableList.<SdkFramework>of(), ruleContext.attributes().get("alwayslink", Type.BOOLEAN), new ExtraImportLibraries(), ImmutableList.<ObjcProvider>of()); XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder(); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder().addAll(common.getCompiledArchive().asSet()); new CompilationSupport(ruleContext) .registerCompileAndArchiveActions(common) .addXcodeSettings(xcodeProviderBuilder, common) .validateAttributes(); new ResourceSupport(ruleContext).validateAttributes().addXcodeSettings(xcodeProviderBuilder); new XcodeSupport(ruleContext) .addFilesToBuild(filesToBuild) .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC) .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET)) .addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET)) .addNonPropagatedDependencies( xcodeProviderBuilder, new Attribute("non_propagated_deps", Mode.TARGET)) .registerActions(xcodeProviderBuilder.build()); return ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()) .addProvider(XcodeProvider.class, xcodeProviderBuilder.build()) .addProvider(ObjcProvider.class, common.getObjcProvider()) .addProvider(J2ObjcSrcsProvider.class, J2ObjcSrcsProvider.buildFrom(ruleContext)) .addProvider( J2ObjcMappingFileProvider.class, ObjcRuleClasses.j2ObjcMappingFileProvider(ruleContext)) .build(); }
@Override public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException, InterruptedException { TransitiveInfoCollection lipoContextCollector = ruleContext.getPrerequisite(":lipo_context_collector", Mode.DONT_CHECK); if (lipoContextCollector != null && lipoContextCollector.getProvider(LipoContextProvider.class) == null) { ruleContext.ruleError("--lipo_context must point to a cc_binary or a cc_test rule"); return null; } CppConfiguration cppConfiguration = Preconditions.checkNotNull(ruleContext.getFragment(CppConfiguration.class)); Path fdoZip = ruleContext.getConfiguration().getCompilationMode() == CompilationMode.OPT ? cppConfiguration.getFdoZip() : null; SkyKey fdoKey = FdoSupportValue.key( cppConfiguration.getLipoMode(), fdoZip, cppConfiguration.getFdoInstrument()); SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv(); FdoSupportValue fdoSupport; try { fdoSupport = (FdoSupportValue) skyframeEnv.getValueOrThrow(fdoKey, FdoException.class, IOException.class); } catch (FdoException | IOException e) { ruleContext.ruleError("cannot initialize FDO: " + e.getMessage()); return null; } if (skyframeEnv.valuesMissing()) { return null; } final Label label = ruleContext.getLabel(); final NestedSet<Artifact> crosstool = ruleContext .getPrerequisite("all_files", Mode.HOST) .getProvider(FileProvider.class) .getFilesToBuild(); final NestedSet<Artifact> crosstoolMiddleman = getFiles(ruleContext, "all_files"); final NestedSet<Artifact> compile = getFiles(ruleContext, "compiler_files"); final NestedSet<Artifact> strip = getFiles(ruleContext, "strip_files"); final NestedSet<Artifact> objcopy = getFiles(ruleContext, "objcopy_files"); final NestedSet<Artifact> link = getFiles(ruleContext, "linker_files"); final NestedSet<Artifact> dwp = getFiles(ruleContext, "dwp_files"); final NestedSet<Artifact> libcLink = inputsForLibc(ruleContext); String purposePrefix = Actions.escapeLabel(label) + "_"; String runtimeSolibDirBase = "_solib_" + "_" + Actions.escapeLabel(label); final PathFragment runtimeSolibDir = ruleContext.getConfiguration().getBinFragment().getRelative(runtimeSolibDirBase); // Static runtime inputs. TransitiveInfoCollection staticRuntimeLibDep = selectDep(ruleContext, "static_runtime_libs", cppConfiguration.getStaticRuntimeLibsLabel()); final NestedSet<Artifact> staticRuntimeLinkInputs; final Artifact staticRuntimeLinkMiddleman; if (cppConfiguration.supportsEmbeddedRuntimes()) { staticRuntimeLinkInputs = staticRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild(); } else { staticRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER); } if (!staticRuntimeLinkInputs.isEmpty()) { NestedSet<Artifact> staticRuntimeLinkMiddlemanSet = CompilationHelper.getAggregatingMiddleman( ruleContext, purposePrefix + "static_runtime_link", staticRuntimeLibDep); staticRuntimeLinkMiddleman = staticRuntimeLinkMiddlemanSet.isEmpty() ? null : Iterables.getOnlyElement(staticRuntimeLinkMiddlemanSet); } else { staticRuntimeLinkMiddleman = null; } Preconditions.checkState( (staticRuntimeLinkMiddleman == null) == staticRuntimeLinkInputs.isEmpty()); // Dynamic runtime inputs. TransitiveInfoCollection dynamicRuntimeLibDep = selectDep( ruleContext, "dynamic_runtime_libs", cppConfiguration.getDynamicRuntimeLibsLabel()); final NestedSet<Artifact> dynamicRuntimeLinkInputs; final Artifact dynamicRuntimeLinkMiddleman; if (cppConfiguration.supportsEmbeddedRuntimes()) { NestedSetBuilder<Artifact> dynamicRuntimeLinkInputsBuilder = NestedSetBuilder.stableOrder(); for (Artifact artifact : dynamicRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild()) { if (CppHelper.SHARED_LIBRARY_FILETYPES.matches(artifact.getFilename())) { dynamicRuntimeLinkInputsBuilder.add( SolibSymlinkAction.getCppRuntimeSymlink( ruleContext, artifact, runtimeSolibDirBase, ruleContext.getConfiguration())); } else { dynamicRuntimeLinkInputsBuilder.add(artifact); } } dynamicRuntimeLinkInputs = dynamicRuntimeLinkInputsBuilder.build(); } else { dynamicRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER); } if (!dynamicRuntimeLinkInputs.isEmpty()) { List<Artifact> dynamicRuntimeLinkMiddlemanSet = CppHelper.getAggregatingMiddlemanForCppRuntimes( ruleContext, purposePrefix + "dynamic_runtime_link", dynamicRuntimeLibDep, runtimeSolibDirBase, ruleContext.getConfiguration()); dynamicRuntimeLinkMiddleman = dynamicRuntimeLinkMiddlemanSet.isEmpty() ? null : Iterables.getOnlyElement(dynamicRuntimeLinkMiddlemanSet); } else { dynamicRuntimeLinkMiddleman = null; } Preconditions.checkState( (dynamicRuntimeLinkMiddleman == null) == dynamicRuntimeLinkInputs.isEmpty()); CppCompilationContext.Builder contextBuilder = new CppCompilationContext.Builder(ruleContext); CppModuleMap moduleMap = createCrosstoolModuleMap(ruleContext); if (moduleMap != null) { contextBuilder.setCppModuleMap(moduleMap); } final CppCompilationContext context = contextBuilder.build(); boolean supportsParamFiles = ruleContext.attributes().get("supports_param_files", BOOLEAN); boolean supportsHeaderParsing = ruleContext.attributes().get("supports_header_parsing", BOOLEAN); NestedSetBuilder<Pair<String, String>> coverageEnvironment = NestedSetBuilder.compileOrder(); coverageEnvironment.add( Pair.of("COVERAGE_GCOV_PATH", cppConfiguration.getGcovExecutable().getPathString())); if (cppConfiguration.getFdoInstrument() != null) { coverageEnvironment.add( Pair.of("FDO_DIR", cppConfiguration.getFdoInstrument().getPathString())); } CcToolchainProvider provider = new CcToolchainProvider( cppConfiguration, crosstool, fullInputsForCrosstool(ruleContext, crosstoolMiddleman), compile, strip, objcopy, fullInputsForLink(ruleContext, link), dwp, libcLink, staticRuntimeLinkInputs, staticRuntimeLinkMiddleman, dynamicRuntimeLinkInputs, dynamicRuntimeLinkMiddleman, runtimeSolibDir, context, supportsParamFiles, supportsHeaderParsing, getBuildVariables(ruleContext), getBuiltinIncludes(ruleContext), coverageEnvironment.build()); RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext) .add(CcToolchainProvider.class, provider) .add(FdoSupportProvider.class, new FdoSupportProvider(fdoSupport.getFdoSupport())) .setFilesToBuild(new NestedSetBuilder<Artifact>(Order.STABLE_ORDER).build()) .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY)); // If output_license is specified on the cc_toolchain rule, override the transitive licenses // with that one. This is necessary because cc_toolchain is used in the target configuration, // but it is sort-of-kind-of a tool, but various parts of it are linked into the output... // ...so we trust the judgment of the author of the cc_toolchain rule to figure out what // licenses should be propagated to C++ targets. License outputLicense = ruleContext.getRule().getToolOutputLicense(ruleContext.attributes()); if (outputLicense != null && outputLicense != License.NO_LICENSE) { final NestedSet<TargetLicense> license = NestedSetBuilder.create( Order.STABLE_ORDER, new TargetLicense(ruleContext.getLabel(), outputLicense)); LicensesProvider licensesProvider = new LicensesProvider() { @Override public NestedSet<TargetLicense> getTransitiveLicenses() { return license; } }; builder.add(LicensesProvider.class, licensesProvider); } return builder.build(); }
private static Collection<String> getStringListAttribute( RuleContext ruleContext, String attributeName) { return ruleContext.attributes().has(attributeName, Type.STRING_LIST) ? ruleContext.attributes().get(attributeName, Type.STRING_LIST) : ImmutableList.<String>of(); }
/** Returns whether to use the protobuf library instead of the PB2 library. */ boolean hasPortableProtoFilters() { return ruleContext .attributes() .isAttributeValueExplicitlySpecified(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR); }
/** Returns whether the generated files should be C++ or Objective C. */ boolean outputsCpp() { if (ruleContext.attributes().has(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN)) { return ruleContext.attributes().get(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN); } return false; }
@Nullable private String stringAttribute(String attribute) { String value = ruleContext.attributes().get(attribute, Type.STRING); return value.isEmpty() ? null : value; }
private List<String> iosDeviceArgs() { return ruleContext.attributes().get("ios_device_arg", Type.STRING_LIST); }
protected static boolean isXcTest(RuleContext ruleContext) { return ruleContext.attributes().get(IS_XCTEST_ATTR, Type.BOOLEAN); }