// This test rule just executes the test bundle, so we need it available locally. @Override public ImmutableSortedSet<BuildRule> getRuntimeDeps() { return ImmutableSortedSet.<BuildRule>naturalOrder() .add(testBundle) .addAll(getResolver().filterBuildRuleInputs(xctool.asSet())) .addAll(testHostApp.asSet()) .build(); }
@Override public Optional<ImmutableSet<PreemptionVictim>> filterPreemptionVictims( ITaskConfig pendingTask, Iterable<PreemptionVictim> possibleVictims, AttributeAggregate jobState, Optional<HostOffer> offer, StoreProvider storeProvider) { // This enforces the precondition that all of the resources are from the same host. We need to // get the host for the schedulingFilter. Set<String> hosts = ImmutableSet.<String>builder() .addAll(Iterables.transform(possibleVictims, VICTIM_TO_HOST)) .addAll(Iterables.transform(offer.asSet(), OFFER_TO_HOST)) .build(); ResourceSlot slackResources = sum(Iterables.transform(offer.asSet(), OFFER_TO_RESOURCE_SLOT)); FluentIterable<PreemptionVictim> preemptableTasks = FluentIterable.from(possibleVictims).filter(preemptionFilter(pendingTask)); if (preemptableTasks.isEmpty()) { return Optional.absent(); } Set<PreemptionVictim> toPreemptTasks = Sets.newHashSet(); Iterable<PreemptionVictim> sortedVictims = resourceOrder.immutableSortedCopy(preemptableTasks); Optional<IHostAttributes> attributes = storeProvider.getAttributeStore().getHostAttributes(Iterables.getOnlyElement(hosts)); if (!attributes.isPresent()) { metrics.recordMissingAttributes(); return Optional.absent(); } for (PreemptionVictim victim : sortedVictims) { toPreemptTasks.add(victim); ResourceSlot totalResource = sum(Iterables.transform(toPreemptTasks, victimToResources)).add(slackResources); Set<Veto> vetoes = schedulingFilter.filter( new UnusedResource(totalResource, attributes.get()), new ResourceRequest(pendingTask, jobState)); if (vetoes.isEmpty()) { return Optional.of(ImmutableSet.copyOf(toPreemptTasks)); } } return Optional.absent(); }
/** * Finds the build file responsible for the given {@link Path} and invalidates all of the cached * rules dependent on it. * * @param path A {@link Path}, relative to the project root and "contained" within the build file * to find and invalidate. */ private synchronized void invalidateContainingBuildFile( Cell cell, BuildFileTree buildFiles, Path path) { Set<Path> packageBuildFiles = new HashSet<>(); // Find the closest ancestor package for the input path. We'll definitely need to invalidate // that. Optional<Path> packageBuildFile = buildFiles.getBasePathOfAncestorTarget(path); packageBuildFiles.addAll( packageBuildFile.transform(cell.getFilesystem().getAbsolutifier()).asSet()); // If we're *not* enforcing package boundary checks, it's possible for multiple ancestor // packages to reference the same file if (!cell.isEnforcingBuckPackageBoundaries()) { while (packageBuildFile.isPresent() && packageBuildFile.get().getParent() != null) { packageBuildFile = buildFiles.getBasePathOfAncestorTarget(packageBuildFile.get().getParent()); packageBuildFiles.addAll(packageBuildFile.asSet()); } } // Invalidate all the packages we found. for (Path buildFile : packageBuildFiles) { invalidatePath(cell, buildFile.resolve(cell.getBuildFileName())); } }
private void collectProviders(Set<XcodeProvider> allProviders) { if (allProviders.add(this)) { for (XcodeProvider dependency : Iterables.concat(propagatedDependencies, nonPropagatedDependencies)) { dependency.collectProviders(allProviders); } for (XcodeProvider justTestHost : testHost.asSet()) { justTestHost.collectProviders(allProviders); } for (XcodeProvider extension : extensions) { extension.collectProviders(allProviders); } } }
/** Constructs an {@link ObjcCommon} instance based on the attributes. */ private ObjcCommon common(RuleContext ruleContext, Optional<ObjcProvider> protosObjcProvider) { CompilationArtifacts compilationArtifacts = CompilationSupport.compilationArtifacts(ruleContext); ObjcCommon.Builder builder = new ObjcCommon.Builder(ruleContext) .setCompilationAttributes( CompilationAttributes.Builder.fromRuleContext(ruleContext).build()) .setCompilationArtifacts(compilationArtifacts) .setResourceAttributes(new ResourceAttributes(ruleContext)) .addDefines(ruleContext.getTokenizedStringListAttr("defines")) .addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET)) .addRuntimeDeps(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET)) .addDeps(ruleContext.getPrerequisites("bundles", Mode.TARGET)) .addDepObjcProviders(protosObjcProvider.asSet()) .addNonPropagatedDepObjcProviders( ruleContext.getPrerequisites( "non_propagated_deps", Mode.TARGET, ObjcProvider.class)) .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext)) .setHasModuleMap(); if (isXcTest(ruleContext)) { builder .addExtraSdkFrameworks(AUTOMATIC_SDK_FRAMEWORKS_FOR_XCTEST) .addDepObjcProviders(ImmutableList.of(xcTestAppProvider(ruleContext).getObjcProvider())); } // Add the memleaks library if the --ios_memleaks flag is true. The library pauses the test // after all tests have been executed so that leaks can be run. ObjcConfiguration config = ruleContext.getFragment(ObjcConfiguration.class); if (config.runMemleaks()) { builder.addDepObjcProviders( ruleContext.getPrerequisites(MEMLEAKS_DEP_ATTR, Mode.TARGET, ObjcProvider.class)); } return builder.build(); }
@Override public <A extends Arg> AppleBundle createBuildRule( TargetGraph targetGraph, BuildRuleParams params, BuildRuleResolver resolver, A args) { AppleCxxPlatform appleCxxPlatform = getAppleCxxPlatformForBuildTarget(params.getBuildTarget()); AppleBundleDestinations destinations = AppleBundleDestinations.platformDestinations( appleCxxPlatform.getAppleSdk().getApplePlatform()); ImmutableSet.Builder<SourcePath> bundleDirsBuilder = ImmutableSet.builder(); ImmutableSet.Builder<SourcePath> dirsContainingResourceDirsBuilder = ImmutableSet.builder(); ImmutableSet.Builder<SourcePath> bundleFilesBuilder = ImmutableSet.builder(); ImmutableSet.Builder<SourcePath> bundleVariantFilesBuilder = ImmutableSet.builder(); AppleResources.collectResourceDirsAndFiles( targetGraph, Preconditions.checkNotNull(targetGraph.get(params.getBuildTarget())), bundleDirsBuilder, dirsContainingResourceDirsBuilder, bundleFilesBuilder, bundleVariantFilesBuilder); ImmutableSet<SourcePath> bundleDirs = bundleDirsBuilder.build(); ImmutableSet<SourcePath> dirsContainingResourceDirs = dirsContainingResourceDirsBuilder.build(); ImmutableSet<SourcePath> bundleFiles = bundleFilesBuilder.build(); ImmutableSet<SourcePath> bundleVariantFiles = bundleVariantFilesBuilder.build(); SourcePathResolver sourcePathResolver = new SourcePathResolver(resolver); Optional<AppleAssetCatalog> assetCatalog = AppleDescriptions.createBuildRuleForTransitiveAssetCatalogDependencies( targetGraph, params, sourcePathResolver, appleCxxPlatform.getAppleSdk().getApplePlatform(), appleCxxPlatform.getActool()); // TODO(user): Sort through the changes needed to make project generation work with // binary being optional. BuildRule flavoredBinaryRule = getFlavoredBinaryRule(targetGraph, params, resolver, args); BuildRuleParams bundleParamsWithFlavoredBinaryDep = getBundleParamsWithUpdatedDeps( params, args.binary, ImmutableSet.<BuildRule>builder() .add(flavoredBinaryRule) .addAll(assetCatalog.asSet()) .addAll( BuildRules.toBuildRulesFor( params.getBuildTarget(), resolver, SourcePaths.filterBuildTargetSourcePaths( Iterables.concat( bundleFiles, bundleDirs, dirsContainingResourceDirs, bundleVariantFiles)))) .build()); ImmutableMap<SourcePath, String> extensionBundlePaths = collectFirstLevelAppleDependencyBundles(params.getDeps(), destinations); return new AppleBundle( bundleParamsWithFlavoredBinaryDep, sourcePathResolver, args.extension, args.productName, args.infoPlist, args.infoPlistSubstitutions.get(), Optional.of(flavoredBinaryRule), destinations, bundleDirs, bundleFiles, dirsContainingResourceDirs, extensionBundlePaths, Optional.of(bundleVariantFiles), appleCxxPlatform.getIbtool(), appleCxxPlatform.getDsymutil(), appleCxxPlatform.getCxxPlatform().getStrip(), assetCatalog, args.getTests(), appleCxxPlatform.getAppleSdk(), codeSignIdentityStore, provisioningProfileStore, AppleBundle.DebugInfoFormat.DSYM); }
public static Function<String, String> from(Optional<DeclaringType> optional) { return new ImportsTypeStringResolver(optional.asSet()); }
/** * {@inheritDoc} * * <p>Creates a target, including registering actions, just as {@link #create(RuleContext)} does. * The difference between {@link #create(RuleContext)} and this method is that this method does * only what is needed to support tests on the environment besides generate the Xcodeproj file and * build the app and test {@code .ipa}s. The {@link #create(RuleContext)} method delegates to this * method. */ @Override public final ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException { ProtobufSupport protoSupport = new ProtobufSupport(ruleContext).registerGenerationActions().registerCompilationActions(); Optional<ObjcProvider> protosObjcProvider = protoSupport.getObjcProvider(); Optional<XcodeProvider> protosXcodeProvider = protoSupport.getXcodeProvider(); ObjcCommon common = common(ruleContext, protosObjcProvider); if (!common.getCompilationArtifacts().get().getArchive().isPresent()) { ruleContext.ruleError(REQUIRES_SOURCE_ERROR); } if (!ruleContext.getFragment(AppleConfiguration.class).getIosMultiCpus().isEmpty()) { ruleContext.ruleError(NO_MULTI_CPUS_ERROR); } XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder().addPropagatedDependencies(protosXcodeProvider.asSet()); NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); addResourceFilesToBuild(ruleContext, common.getObjcProvider(), filesToBuild); XcodeProductType productType = getProductType(ruleContext); ExtraLinkArgs extraLinkArgs; Iterable<Artifact> extraLinkInputs; String bundleFormat; if (!isXcTest(ruleContext)) { extraLinkArgs = new ExtraLinkArgs(); extraLinkInputs = ImmutableList.of(); bundleFormat = ReleaseBundlingSupport.APP_BUNDLE_DIR_FORMAT; } else { XcodeProvider appIpaXcodeProvider = ruleContext.getPrerequisite(XCTEST_APP_ATTR, Mode.TARGET, XcodeProvider.class); xcodeProviderBuilder.setTestHost(appIpaXcodeProvider).setProductType(productType); XcTestAppProvider testApp = xcTestAppProvider(ruleContext); Artifact bundleLoader = testApp.getBundleLoader(); // -bundle causes this binary to be linked as a bundle and not require an entry point // (i.e. main()) // -bundle_loader causes the code in this test to have access to the symbols in the test rig, // or more specifically, the flag causes ld to consider the given binary when checking for // missing symbols. // -rpath @loader_path/Frameworks allows test bundles to load dylibs from the app's // Frameworks directory. extraLinkArgs = new ExtraLinkArgs( "-bundle", "-bundle_loader", bundleLoader.getExecPathString(), "-Xlinker", "-rpath", "-Xlinker", "@loader_path/Frameworks"); extraLinkInputs = ImmutableList.of(bundleLoader); bundleFormat = ReleaseBundlingSupport.XCTEST_BUNDLE_DIR_FORMAT; filesToBuild.add(testApp.getIpa()); } J2ObjcMappingFileProvider j2ObjcMappingFileProvider = J2ObjcMappingFileProvider.union( ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcMappingFileProvider.class)); J2ObjcEntryClassProvider j2ObjcEntryClassProvider = new J2ObjcEntryClassProvider.Builder() .addTransitive( ruleContext.getPrerequisites("deps", Mode.TARGET, J2ObjcEntryClassProvider.class)) .build(); new CompilationSupport(ruleContext) .registerLinkActions( common.getObjcProvider(), j2ObjcMappingFileProvider, j2ObjcEntryClassProvider, extraLinkArgs, extraLinkInputs, DsymOutputType.TEST) .registerCompileAndArchiveActions(common) .registerFullyLinkAction( common.getObjcProvider(), ruleContext.getImplicitOutputArtifact(CompilationSupport.FULLY_LINKED_LIB)) .addXcodeSettings(xcodeProviderBuilder, common) .validateAttributes(); AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); new ReleaseBundlingSupport( ruleContext, common.getObjcProvider(), LinkedBinary.LOCAL_AND_DEPENDENCIES, bundleFormat, appleConfiguration.getMinimumOsForPlatformType(PlatformType.IOS), appleConfiguration.getMultiArchPlatform(PlatformType.IOS)) .registerActions(DsymOutputType.TEST) .addXcodeSettings(xcodeProviderBuilder) .addFilesToBuild(filesToBuild, Optional.of(DsymOutputType.TEST)) .validateResources() .validateAttributes(); new ResourceSupport(ruleContext).validateAttributes().addXcodeSettings(xcodeProviderBuilder); new XcodeSupport(ruleContext) .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), productType) .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET)) .addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET)) .addNonPropagatedDependencies( xcodeProviderBuilder, new Attribute("non_propagated_deps", Mode.TARGET)) .addFilesToBuild(filesToBuild) .registerActions(xcodeProviderBuilder.build()); XcodeProvider xcodeProvider = xcodeProviderBuilder.build(); NestedSet<Artifact> filesToBuildSet = filesToBuild.build(); Runfiles.Builder runfilesBuilder = new Runfiles.Builder( ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()) .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES); NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder().addTransitive(filesToBuildSet); InstrumentedFilesProvider instrumentedFilesProvider = new CompilationSupport(ruleContext).getInstrumentedFilesProvider(common); TestSupport testSupport = new TestSupport(ruleContext) .registerTestRunnerActions() .addRunfiles(runfilesBuilder, instrumentedFilesProvider) .addFilesToBuild(filesToBuildBuilder); Artifact executable = testSupport.generatedTestScript(); Runfiles runfiles = runfilesBuilder.build(); RunfilesSupport runfilesSupport = RunfilesSupport.withExecutable(ruleContext, runfiles, executable); ImmutableMap.Builder<String, String> execInfoMapBuilder = new ImmutableMap.Builder<>(); execInfoMapBuilder.put(ExecutionRequirements.REQUIRES_DARWIN, ""); if (ruleContext.getFragment(ObjcConfiguration.class).runMemleaks()) { execInfoMapBuilder.put("nosandbox", ""); } return new RuleConfiguredTargetBuilder(ruleContext) .setFilesToBuild(filesToBuildBuilder.build()) .addProvider(xcodeProvider) .addProvider(RunfilesProvider.simple(runfiles)) .addProvider(new ExecutionInfoProvider(execInfoMapBuilder.build())) .addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider) .addProviders(testSupport.getExtraProviders()) .setRunfilesSupport(runfilesSupport, executable) .build(); }
@Override public Set<ClassName> referencedClasses() { return FluentIterable.from( Iterables.concat(ImmutableList.of(returnType), parameterWriters.values(), body.asSet())) .transformAndConcat( new Function<HasClassReferences, Set<ClassName>>() { @Override public Set<ClassName> apply(HasClassReferences input) { return input.referencedClasses(); } }) .toSet(); }
private TargetControl targetControl() { String buildFilePath = label.getPackageFragment().getSafePathString() + "/BUILD"; NestedSet<String> userHeaderSearchPaths = NestedSetBuilder.<String>linkOrder() .addTransitive(propagatedUserHeaderSearchPaths) .addTransitive(nonPropagatedUserHeaderSearchPaths) .build(); NestedSet<String> headerSearchPaths = NestedSetBuilder.<String>linkOrder() .addTransitive(propagatedHeaderSearchPaths) .addTransitive(nonPropagatedHeaderSearchPaths) .build(); // TODO(bazel-team): Add provisioning profile information when Xcodegen supports it. TargetControl.Builder targetControl = TargetControl.newBuilder() .setName(label.getName()) .setLabel(xcodeTargetName(label)) .setProductType(productType.getIdentifier()) .addSupportFile(buildFilePath) .addAllImportedLibrary(Artifact.toExecPaths(objcProvider.get(IMPORTED_LIBRARY))) .addAllImportedLibrary(Artifact.toExecPaths(ccLibraries(objcProvider))) .addAllUserHeaderSearchPath(userHeaderSearchPaths) .addAllHeaderSearchPath(headerSearchPaths) .addAllSupportFile(Artifact.toExecPaths(headers)) .addAllCopt(compilationModeCopts) .addAllCopt(CompilationSupport.DEFAULT_COMPILER_FLAGS) .addAllCopt(Interspersing.prependEach("-D", objcProvider.get(DEFINE))) .addAllCopt(copts) .addAllLinkopt( Interspersing.beforeEach("-force_load", objcProvider.get(FORCE_LOAD_FOR_XCODEGEN))) .addAllLinkopt(CompilationSupport.DEFAULT_LINKER_FLAGS) .addAllLinkopt( Interspersing.beforeEach( "-weak_framework", SdkFramework.names(objcProvider.get(WEAK_SDK_FRAMEWORK)))) .addAllBuildSetting(xcodeprojBuildSettings) .addAllBuildSetting(AppleToolchain.defaultWarningsForXcode()) .addAllSdkFramework(SdkFramework.names(objcProvider.get(SDK_FRAMEWORK))) .addAllFramework(PathFragment.safePathStrings(objcProvider.get(FRAMEWORK_DIR))) .addAllFrameworkSearchPathOnly( PathFragment.safePathStrings(objcProvider.get(FRAMEWORK_SEARCH_PATH_ONLY))) .addAllXcassetsDir(PathFragment.safePathStrings(objcProvider.get(XCASSETS_DIR))) .addAllXcdatamodel( PathFragment.safePathStrings( Xcdatamodels.datamodelDirs(objcProvider.get(XCDATAMODEL)))) .addAllBundleImport(PathFragment.safePathStrings(objcProvider.get(BUNDLE_IMPORT_DIR))) .addAllSdkDylib(objcProvider.get(SDK_DYLIB)) .addAllGeneralResourceFile( Artifact.toExecPaths(objcProvider.get(GENERAL_RESOURCE_FILE))) .addAllGeneralResourceFile( PathFragment.safePathStrings(objcProvider.get(GENERAL_RESOURCE_DIR))); if (CAN_LINK_PRODUCT_TYPES.contains(productType)) { // For builds with --ios_multi_cpus set, we may have several copies of some XCodeProviders // in the dependencies (one per cpu architecture). We deduplicate the corresponding // xcode target names with a LinkedHashSet before adding to the TargetControl. Set<String> jreTargetNames = new HashSet<>(); for (XcodeProvider jreDependency : jreDependencies) { jreTargetNames.add(jreDependency.dependencyXcodeTargetName()); } Set<DependencyControl> dependencySet = new LinkedHashSet<>(); Set<DependencyControl> jreDependencySet = new LinkedHashSet<>(); for (XcodeProvider dependency : propagatedDependencies) { // Only add a library target to a binary's dependencies if it has source files to compile // and it is not from the "non_propagated_deps" attribute. Xcode cannot build targets // without a source file in the PBXSourceFilesBuildPhase, so if such a target is present in // the control file, it is only to get Xcodegen to put headers and resources not used by the // final binary in the Project Navigator. // // The exceptions to this rule are objc_bundle_library and ios_extension targets. Bundles // are generally used for resources and can lack a PBXSourceFilesBuildPhase in the project // file and still be considered valid by Xcode. // // ios_extension targets are an exception because they have no CompilationArtifact object // but do have a dummy source file to make Xcode happy. boolean hasSources = dependency.compilationArtifacts.isPresent() && dependency.compilationArtifacts.get().getArchive().isPresent(); if (hasSources || (dependency.productType == XcodeProductType.BUNDLE || (dependency.productType == XcodeProductType.WATCH_OS1_APPLICATION))) { String dependencyXcodeTargetName = dependency.dependencyXcodeTargetName(); Set<DependencyControl> set = jreTargetNames.contains(dependencyXcodeTargetName) ? jreDependencySet : dependencySet; set.add(DependencyControl.newBuilder().setTargetLabel(dependencyXcodeTargetName).build()); } } for (DependencyControl dependencyControl : dependencySet) { targetControl.addDependency(dependencyControl); } // Make sure that JRE dependencies are ordered after other propagated dependencies. for (DependencyControl dependencyControl : jreDependencySet) { targetControl.addDependency(dependencyControl); } } for (XcodeProvider justTestHost : testHost.asSet()) { targetControl.addDependency( DependencyControl.newBuilder() .setTargetLabel(xcodeTargetName(justTestHost.label)) .setTestHost(true) .build()); } for (XcodeProvider extension : extensions) { targetControl.addDependency( DependencyControl.newBuilder().setTargetLabel(xcodeTargetName(extension.label)).build()); } if (bundleInfoplist.isPresent()) { targetControl.setInfoplist(bundleInfoplist.get().getExecPathString()); } for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) { targetControl .addAllSourceFile(Artifact.toExecPaths(artifacts.getSrcs())) .addAllSupportFile(Artifact.toExecPaths(artifacts.getAdditionalHdrs())) .addAllSupportFile(Artifact.toExecPaths(artifacts.getPrivateHdrs())) .addAllNonArcSourceFile(Artifact.toExecPaths(artifacts.getNonArcSrcs())); for (Artifact pchFile : artifacts.getPchFile().asSet()) { targetControl .setPchPath(pchFile.getExecPathString()) .addSupportFile(pchFile.getExecPathString()); } } for (Artifact artifact : additionalSources) { targetControl.addSourceFile(artifact.getExecPathString()); } if (objcProvider.is(Flag.USES_CPP)) { targetControl.addSdkDylib("libc++"); } return targetControl.build(); }