List of usage examples for com.google.common.collect ImmutableSet isEmpty
boolean isEmpty();
From source file:com.facebook.buck.ide.intellij.deprecated.Project.java
/** * Walks the dependencies of a build rule and adds the appropriate DependentModules to the * specified dependencies collection. All library dependencies will be added before any module * dependencies. See {@code ProjectTest#testThatJarsAreListedBeforeModules()} for details on why * this behavior is important.//from ww w .jav a 2s. co m */ @SuppressWarnings("PMD.LooseCoupling") private void walkRuleAndAdd(final BuildRule rule, final boolean isForTests, final LinkedHashSet<SerializableDependentModule> dependencies, @Nullable final BuildRule srcTarget) { final Path basePathForRule = rule.getBuildTarget().getBasePath(); Set<BuildRule> targetsToWalk; if (rule instanceof JavaTest) { targetsToWalk = ((JavaTest) rule).getCompiledTestsLibrary().getBuildDeps(); } else { targetsToWalk = rule.getBuildDeps(); } new AbstractBreadthFirstTraversal<BuildRule>(targetsToWalk) { private final LinkedHashSet<SerializableDependentModule> librariesToAdd = Sets.newLinkedHashSet(); private final LinkedHashSet<SerializableDependentModule> modulesToAdd = Sets.newLinkedHashSet(); @Override public ImmutableSet<BuildRule> visit(BuildRule dep) { // Hack: we don't want uber R.java to show up in the deps that IntelliJ sees. if (dep.getBuildTarget().toString().endsWith("_uber_r_dot_java")) { return ImmutableSet.of(); } ImmutableSet<BuildRule> depsToVisit; if (rule.getProperties().is(PACKAGING) || dep instanceof AndroidResource || dep == rule) { depsToVisit = dep.getBuildDeps(); } else if (dep.getProperties().is(LIBRARY) && dep instanceof ExportDependencies) { depsToVisit = ((ExportDependencies) dep).getExportedDeps(); } else { depsToVisit = ImmutableSet.of(); } // Special Case: If we are traversing the test_target and we encounter a library rule in the // same package that is not the src_target, then we should traverse the deps. Consider the // following build file: // // android_library( // name = 'lib', // srcs = glob(['*.java'], excludes = ['*Test.java']), // deps = [ // # LOTS OF DEPS // ], // ) // // java_test( // name = 'test', // srcs = glob(['*Test.java']), // deps = [ // ':lib', // # MOAR DEPS // ], // ) // // project_config( // test_target = ':test', // ) // // Note that the only source folder for this IntelliJ module is the current directory. Thus, // the current directory should be treated as a source folder with test sources, but it // should contain the union of :lib and :test's deps as dependent modules. if (isForTests && depsToVisit.isEmpty() && dep.getBuildTarget().getBasePath().equals(basePathForRule) && !dep.equals(srcTarget)) { depsToVisit = dep.getBuildDeps(); } SerializableDependentModule dependentModule; if (androidAars.contains(dep)) { AndroidPrebuiltAar aar = androidAars.getParentAar(dep); dependentModule = SerializableDependentModule.newLibrary(aar.getBuildTarget(), getIntellijNameForAar(aar)); } else if (dep instanceof PrebuiltJar) { libraryJars.add(dep); String libraryName = getIntellijNameForRule(dep); dependentModule = SerializableDependentModule.newLibrary(dep.getBuildTarget(), libraryName); } else if (dep instanceof AndroidPrebuiltAar) { androidAars.add((AndroidPrebuiltAar) dep); String libraryName = getIntellijNameForAar(dep); dependentModule = SerializableDependentModule.newLibrary(dep.getBuildTarget(), libraryName); } else if ((dep instanceof CxxLibrary) || (dep instanceof NdkLibrary) || (dep instanceof JavaLibrary) || (dep instanceof AndroidResource)) { String moduleName = getIntellijNameForRule(dep); dependentModule = SerializableDependentModule.newModule(dep.getBuildTarget(), moduleName); } else { return depsToVisit; } if (librariesToAdd.contains(dependentModule) || modulesToAdd.contains(dependentModule)) { return depsToVisit; } if (isForTests) { dependentModule.scope = "TEST"; } else { // If the dependentModule has already been added in the "TEST" scope, then it should be // removed and then re-added using the current (compile) scope. String currentScope = dependentModule.scope; dependentModule.scope = "TEST"; if (dependencies.contains(dependentModule)) { dependencies.remove(dependentModule); } dependentModule.scope = currentScope; } // Slate the module for addition to the dependencies collection. Modules are added to // dependencies collection once the traversal is complete in the onComplete() method. if (dependentModule.isLibrary()) { librariesToAdd.add(dependentModule); } else { modulesToAdd.add(dependentModule); } return depsToVisit; } @Override protected void onComplete() { dependencies.addAll(librariesToAdd); dependencies.addAll(modulesToAdd); } }.start(); }
From source file:com.facebook.buck.jvm.java.intellij.Project.java
/** * Walks the dependencies of a build rule and adds the appropriate DependentModules to the * specified dependencies collection. All library dependencies will be added before any module * dependencies. See {@code ProjectTest#testThatJarsAreListedBeforeModules()} for details on why * this behavior is important./*from w w w . j a v a 2 s.c om*/ */ @SuppressWarnings("PMD.LooseCoupling") private void walkRuleAndAdd(final BuildRule rule, final boolean isForTests, final LinkedHashSet<SerializableDependentModule> dependencies, @Nullable final BuildRule srcTarget) { final Path basePathForRule = rule.getBuildTarget().getBasePath(); Set<BuildRule> targetsToWalk; if (rule instanceof JavaTest) { targetsToWalk = ((JavaTest) rule).getCompiledTestsLibrary().getDeps(); } else { targetsToWalk = rule.getDeps(); } new AbstractBreadthFirstTraversal<BuildRule>(targetsToWalk) { private final LinkedHashSet<SerializableDependentModule> librariesToAdd = Sets.newLinkedHashSet(); private final LinkedHashSet<SerializableDependentModule> modulesToAdd = Sets.newLinkedHashSet(); @Override public ImmutableSet<BuildRule> visit(BuildRule dep) { // Hack: we don't want uber R.java to show up in the deps that IntelliJ sees. if (dep.getBuildTarget().toString().endsWith("_uber_r_dot_java")) { return ImmutableSet.of(); } ImmutableSet<BuildRule> depsToVisit; if (rule.getProperties().is(PACKAGING) || dep instanceof AndroidResource || dep == rule) { depsToVisit = dep.getDeps(); } else if (dep.getProperties().is(LIBRARY) && dep instanceof ExportDependencies) { depsToVisit = ((ExportDependencies) dep).getExportedDeps(); } else { depsToVisit = ImmutableSet.of(); } // Special Case: If we are traversing the test_target and we encounter a library rule in the // same package that is not the src_target, then we should traverse the deps. Consider the // following build file: // // android_library( // name = 'lib', // srcs = glob(['*.java'], excludes = ['*Test.java']), // deps = [ // # LOTS OF DEPS // ], // ) // // java_test( // name = 'test', // srcs = glob(['*Test.java']), // deps = [ // ':lib', // # MOAR DEPS // ], // ) // // project_config( // test_target = ':test', // ) // // Note that the only source folder for this IntelliJ module is the current directory. Thus, // the current directory should be treated as a source folder with test sources, but it // should contain the union of :lib and :test's deps as dependent modules. if (isForTests && depsToVisit.isEmpty() && dep.getBuildTarget().getBasePath().equals(basePathForRule) && !dep.equals(srcTarget)) { depsToVisit = dep.getDeps(); } SerializableDependentModule dependentModule; if (androidAars.contains(dep)) { AndroidPrebuiltAar aar = androidAars.getParentAar(dep); dependentModule = SerializableDependentModule.newLibrary(aar.getBuildTarget(), getIntellijNameForAar(aar)); } else if (dep instanceof PrebuiltJar) { libraryJars.add(dep); String libraryName = getIntellijNameForRule(dep); dependentModule = SerializableDependentModule.newLibrary(dep.getBuildTarget(), libraryName); } else if (dep instanceof AndroidPrebuiltAar) { androidAars.add((AndroidPrebuiltAar) dep); String libraryName = getIntellijNameForAar(dep); dependentModule = SerializableDependentModule.newLibrary(dep.getBuildTarget(), libraryName); } else if ((dep instanceof CxxLibrary) || (dep instanceof NdkLibrary) || (dep instanceof JavaLibrary) || (dep instanceof AndroidResource)) { String moduleName = getIntellijNameForRule(dep); dependentModule = SerializableDependentModule.newModule(dep.getBuildTarget(), moduleName); } else { return depsToVisit; } if (librariesToAdd.contains(dependentModule) || modulesToAdd.contains(dependentModule)) { return depsToVisit; } if (isForTests) { dependentModule.scope = "TEST"; } else { // If the dependentModule has already been added in the "TEST" scope, then it should be // removed and then re-added using the current (compile) scope. String currentScope = dependentModule.scope; dependentModule.scope = "TEST"; if (dependencies.contains(dependentModule)) { dependencies.remove(dependentModule); } dependentModule.scope = currentScope; } // Slate the module for addition to the dependencies collection. Modules are added to // dependencies collection once the traversal is complete in the onComplete() method. if (dependentModule.isLibrary()) { librariesToAdd.add(dependentModule); } else { modulesToAdd.add(dependentModule); } return depsToVisit; } @Override protected void onComplete() { dependencies.addAll(librariesToAdd); dependencies.addAll(modulesToAdd); } }.start(); }
From source file:com.facebook.buck.command.Project.java
/** * Walks the dependencies of a build rule and adds the appropriate DependentModules to the * specified dependencies collection. All library dependencies will be added before any module * dependencies. See {@link ProjectTest#testThatJarsAreListedBeforeModules()} for details on why * this behavior is important./*www . j a v a2 s. c om*/ */ private void walkRuleAndAdd(final BuildRule rule, final boolean isForTests, final LinkedHashSet<DependentModule> dependencies, @Nullable final BuildRule srcTarget) { final String basePathForRule = rule.getBuildTarget().getBasePath(); new AbstractDependencyVisitor(rule, true /* excludeRoot */) { private final LinkedHashSet<DependentModule> librariesToAdd = Sets.newLinkedHashSet(); private final LinkedHashSet<DependentModule> modulesToAdd = Sets.newLinkedHashSet(); @Override public ImmutableSet<BuildRule> visit(BuildRule dep) { ImmutableSet<BuildRule> depsToVisit; if (rule.getProperties().is(PACKAGING) || dep.getBuildable() instanceof AndroidResource || dep == rule) { depsToVisit = dep.getDeps(); } else if (dep.getProperties().is(LIBRARY) && dep instanceof ExportDependencies) { depsToVisit = ((ExportDependencies) dep).getExportedDeps(); } else if (dep.getProperties().is(LIBRARY) && dep.getBuildable() instanceof ExportDependencies) { depsToVisit = ((ExportDependencies) dep.getBuildable()).getExportedDeps(); } else { depsToVisit = ImmutableSet.of(); } // Special Case: If we are traversing the test_target and we encounter a library rule in the // same package that is not the src_target, then we should traverse the deps. Consider the // following build file: // // android_library( // name = 'lib', // srcs = glob(['*.java'], excludes = ['*Test.java']), // deps = [ // # LOTS OF DEPS // ], // ) // // java_test( // name = 'test', // srcs = glob(['*Test.java']), // deps = [ // ':lib', // # MOAR DEPS // ], // ) // // project_config( // test_target = ':test', // ) // // Note that the only source folder for this IntelliJ module is the current directory. Thus, // the current directory should be treated as a source folder with test sources, but it // should contain the union of :lib and :test's deps as dependent modules. if (isForTests && depsToVisit.isEmpty() && dep.getBuildTarget().getBasePath().equals(basePathForRule) && !dep.equals(srcTarget)) { depsToVisit = dep.getDeps(); } DependentModule dependentModule; if (dep.getBuildable() instanceof PrebuiltJar) { libraryJars.add(dep); String libraryName = getIntellijNameForRule(dep); dependentModule = DependentModule.newLibrary(dep.getBuildTarget(), libraryName); } else if (dep instanceof NdkLibrary) { String moduleName = getIntellijNameForRule(dep); dependentModule = DependentModule.newModule(dep.getBuildTarget(), moduleName); } else if (dep.getFullyQualifiedName().startsWith(ANDROID_GEN_BUILD_TARGET_PREFIX)) { return depsToVisit; } else if ((dep.getBuildable() instanceof JavaLibrary) || dep.getBuildable() instanceof AndroidResource) { String moduleName = getIntellijNameForRule(dep); dependentModule = DependentModule.newModule(dep.getBuildTarget(), moduleName); } else { return depsToVisit; } if (isForTests) { dependentModule.scope = "TEST"; } else { // If the dependentModule has already been added in the "TEST" scope, then it should be // removed and then re-added using the current (compile) scope. String currentScope = dependentModule.scope; dependentModule.scope = "TEST"; if (dependencies.contains(dependentModule)) { dependencies.remove(dependentModule); } dependentModule.scope = currentScope; } // Slate the module for addition to the dependencies collection. Modules are added to // dependencies collection once the traversal is complete in the onComplete() method. if (dependentModule.isLibrary()) { librariesToAdd.add(dependentModule); } else { modulesToAdd.add(dependentModule); } return depsToVisit; } @Override protected void onComplete() { dependencies.addAll(librariesToAdd); dependencies.addAll(modulesToAdd); } }.start(); }
From source file:com.facebook.buck.apple.ProjectGenerator.java
private PBXNativeTarget generateBinaryTarget(PBXProject project, Optional<? extends TargetNode<? extends HasAppleBundleFields>> bundle, TargetNode<? extends CxxLibraryDescription.Arg> targetNode, ProductType productType, String productOutputFormat, Optional<Path> infoPlistOptional, boolean includeFrameworks, ImmutableSet<AppleResourceDescription.Arg> recursiveResources, ImmutableSet<AppleResourceDescription.Arg> directResources, ImmutableSet<AppleAssetCatalogDescription.Arg> recursiveAssetCatalogs, ImmutableSet<AppleAssetCatalogDescription.Arg> directAssetCatalogs, Optional<Iterable<PBXBuildPhase>> copyFilesPhases, Optional<TargetNode<AppleBundleDescription.Arg>> bundleLoaderNode) throws IOException { LOG.debug("Generating binary target for node %s", targetNode); TargetNode<?> buildTargetNode = bundle.isPresent() ? bundle.get() : targetNode; final BuildTarget buildTarget = buildTargetNode.getBuildTarget(); String buildTargetName = getProductNameForBuildTarget(buildTarget); CxxLibraryDescription.Arg arg = targetNode.getConstructorArg(); NewNativeTargetProjectMutator mutator = new NewNativeTargetProjectMutator(pathRelativizer, sourcePathResolver);//from ww w . j av a 2s .c o m ImmutableSet<SourcePath> exportedHeaders = ImmutableSet.copyOf(getHeaderSourcePaths(arg.exportedHeaders)); ImmutableSet<SourcePath> headers = ImmutableSet.copyOf(getHeaderSourcePaths(arg.headers)); ImmutableMap<CxxSource.Type, ImmutableList<String>> langPreprocessorFlags = targetNode .getConstructorArg().langPreprocessorFlags.get(); mutator.setTargetName(getXcodeTargetName(buildTarget)).setLangPreprocessorFlags(langPreprocessorFlags) .setProduct(productType, buildTargetName, Paths.get(String.format(productOutputFormat, buildTargetName))) .setSourcesWithFlags(ImmutableSet.copyOf(arg.srcs.get())).setPublicHeaders(exportedHeaders) .setPrivateHeaders(headers).setPrefixHeader(arg.prefixHeader) .setRecursiveResources(recursiveResources).setDirectResources(directResources); if (bundle.isPresent()) { HasAppleBundleFields bundleArg = bundle.get().getConstructorArg(); mutator.setInfoPlist(Optional.of(bundleArg.getInfoPlist())); } Optional<TargetNode<AppleNativeTargetDescriptionArg>> appleTargetNode = targetNode .castArg(AppleNativeTargetDescriptionArg.class); if (appleTargetNode.isPresent()) { AppleNativeTargetDescriptionArg appleArg = appleTargetNode.get().getConstructorArg(); mutator = mutator.setExtraXcodeSources(ImmutableSet.copyOf(appleArg.extraXcodeSources.get())); } if (options.contains(Option.CREATE_DIRECTORY_STRUCTURE)) { mutator.setTargetGroupPath(FluentIterable.from(buildTarget.getBasePath()) .transform(Functions.toStringFunction()).toList()); } if (!recursiveAssetCatalogs.isEmpty()) { mutator.setRecursiveAssetCatalogs(recursiveAssetCatalogs); } if (!directAssetCatalogs.isEmpty()) { mutator.setDirectAssetCatalogs(directAssetCatalogs); } if (includeFrameworks) { ImmutableSet.Builder<FrameworkPath> frameworksBuilder = ImmutableSet.builder(); frameworksBuilder.addAll(targetNode.getConstructorArg().frameworks.get()); frameworksBuilder.addAll(targetNode.getConstructorArg().libraries.get()); frameworksBuilder.addAll(collectRecursiveFrameworkDependencies(ImmutableList.of(targetNode))); mutator.setFrameworks(frameworksBuilder.build()); mutator.setArchives(collectRecursiveLibraryDependencies(ImmutableList.of(targetNode))); } // TODO(Task #3772930): Go through all dependencies of the rule // and add any shell script rules here ImmutableList.Builder<TargetNode<?>> preScriptPhases = ImmutableList.builder(); ImmutableList.Builder<TargetNode<?>> postScriptPhases = ImmutableList.builder(); boolean skipRNBundle = ReactNativeFlavors.skipBundling(buildTargetNode.getBuildTarget()); if (bundle.isPresent() && targetNode != bundle.get()) { collectBuildScriptDependencies(targetGraph.getAll(bundle.get().getDeclaredDeps()), preScriptPhases, postScriptPhases, skipRNBundle); } collectBuildScriptDependencies(targetGraph.getAll(targetNode.getDeclaredDeps()), preScriptPhases, postScriptPhases, skipRNBundle); mutator.setPreBuildRunScriptPhasesFromTargetNodes(preScriptPhases.build()); if (copyFilesPhases.isPresent()) { mutator.setCopyFilesPhases(copyFilesPhases.get()); } mutator.setPostBuildRunScriptPhasesFromTargetNodes(postScriptPhases.build()); mutator.skipReactNativeBundle(skipRNBundle); NewNativeTargetProjectMutator.Result targetBuilderResult; try { targetBuilderResult = mutator.buildTargetAndAddToProject(project); } catch (NoSuchBuildTargetException e) { throw new HumanReadableException(e); } PBXGroup targetGroup = targetBuilderResult.targetGroup; SourceTreePath buckFilePath = new SourceTreePath(PBXReference.SourceTree.SOURCE_ROOT, pathRelativizer.outputPathToBuildTargetPath(buildTarget).resolve(buildFileName), Optional.<String>absent()); PBXFileReference buckReference = targetGroup.getOrCreateFileReferenceBySourceTreePath(buckFilePath); buckReference.setExplicitFileType(Optional.of("text.script.python")); // -- configurations ImmutableMap.Builder<String, String> extraSettingsBuilder = ImmutableMap.builder(); extraSettingsBuilder.put("TARGET_NAME", buildTargetName).put("SRCROOT", pathRelativizer.outputPathToBuildTargetPath(buildTarget).toString()); if (bundleLoaderNode.isPresent()) { TargetNode<AppleBundleDescription.Arg> bundleLoader = bundleLoaderNode.get(); String bundleLoaderProductName = getProductNameForBuildTarget(bundleLoader.getBuildTarget()); String bundleLoaderBundleName = bundleLoaderProductName + "." + getExtensionString(bundleLoader.getConstructorArg().getExtension()); // NOTE(grp): This is a hack. We need to support both deep (OS X) and flat (iOS) // style bundles for the bundle loader, but at this point we don't know what platform // the bundle loader (or current target) is going to be built for. However, we can be // sure that it's the same as the target (presumably a test) we're building right now. // // Using that knowledge, we can do build setting tricks to defer choosing the bundle // loader path until Xcode build time, when the platform is known. There's no build // setting that conclusively says whether the current platform uses deep bundles: // that would be too easy. But in the cases we care about (unit test bundles), the // current bundle will have a style matching the style of the bundle loader app, so // we can take advantage of that to do the determination. // // Unfortunately, the build setting for the bundle structure (CONTENTS_FOLDER_PATH) // includes the WRAPPER_NAME, so we can't just interpolate that in. Instead, we have // to use another trick with build setting operations and evaluation. By using the // $(:file) operation, we can extract the last component of the contents path: either // "Contents" or the current bundle name. Then, we can interpolate with that expected // result in the build setting name to conditionally choose a different loader path. // The conditional that decdies which path is used. This is a complex Xcode build setting // expression that expands to one of two values, depending on the last path component of // the CONTENTS_FOLDER_PATH variable. As described above, this will be either "Contents" // for deep bundles or the bundle file name itself for flat bundles. Finally, to santiize // the potentially invalid build setting names from the bundle file name, it converts that // to an identifier. We rely on BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_<bundle file name> // being undefined (and thus expanding to nothing) for the path resolution to work. // // The operations on the CONTENTS_FOLDER_PATH are documented here: // http://codeworkshop.net/posts/xcode-build-setting-transformations String bundleLoaderOutputPathConditional = "$(BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_$(CONTENTS_FOLDER_PATH:file:identifier))"; // If the $(CONTENTS_FOLDER_PATH:file:identifier) expands to this, we add the deep bundle // path into the bundle loader. See above for the case when it will expand to this value. String bundleLoaderOutputPathDeepSetting = "BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_Contents"; String bundleLoaderOutputPathDeepValue = "Contents/MacOS/"; String bundleLoaderOutputPathValue = Joiner.on('/').join(getTargetOutputPath(bundleLoader), bundleLoaderBundleName, bundleLoaderOutputPathConditional, bundleLoaderProductName); extraSettingsBuilder.put(bundleLoaderOutputPathDeepSetting, bundleLoaderOutputPathDeepValue) .put("BUNDLE_LOADER", bundleLoaderOutputPathValue).put("TEST_HOST", "$(BUNDLE_LOADER)"); } if (infoPlistOptional.isPresent()) { Path infoPlistPath = pathRelativizer.outputDirToRootRelative(infoPlistOptional.get()); extraSettingsBuilder.put("INFOPLIST_FILE", infoPlistPath.toString()); } Optional<SourcePath> prefixHeaderOptional = targetNode.getConstructorArg().prefixHeader; if (prefixHeaderOptional.isPresent()) { Path prefixHeaderRelative = sourcePathResolver.apply(prefixHeaderOptional.get()); Path prefixHeaderPath = pathRelativizer.outputDirToRootRelative(prefixHeaderRelative); extraSettingsBuilder.put("GCC_PREFIX_HEADER", prefixHeaderPath.toString()); extraSettingsBuilder.put("GCC_PRECOMPILE_PREFIX_HEADER", "YES"); } extraSettingsBuilder.put("USE_HEADERMAP", "NO"); ImmutableMap.Builder<String, String> defaultSettingsBuilder = ImmutableMap.builder(); defaultSettingsBuilder.put("REPO_ROOT", projectFilesystem.getRootPath().toAbsolutePath().normalize().toString()); defaultSettingsBuilder.put(PRODUCT_NAME, getProductName(buildTargetNode, buildTarget)); if (bundle.isPresent()) { defaultSettingsBuilder.put("WRAPPER_EXTENSION", getExtensionString(bundle.get().getConstructorArg().getExtension())); } // We use BUILT_PRODUCTS_DIR as the root for the everything being built. Target- // specific output is placed within CONFIGURATION_BUILD_DIR, inside BUILT_PRODUCTS_DIR. // That allows Copy Files build phases to reference files in the CONFIGURATION_BUILD_DIR // of other targets by using paths relative to the target-independent BUILT_PRODUCTS_DIR. defaultSettingsBuilder.put("BUILT_PRODUCTS_DIR", // $EFFECTIVE_PLATFORM_NAME starts with a dash, so this expands to something like: // $SYMROOT/Debug-iphonesimulator Joiner.on('/').join("$SYMROOT", "$CONFIGURATION$EFFECTIVE_PLATFORM_NAME")); defaultSettingsBuilder.put("CONFIGURATION_BUILD_DIR", "$BUILT_PRODUCTS_DIR"); if (!bundle.isPresent() && (targetNode.getType().equals(AppleLibraryDescription.TYPE) || targetNode.getType().equals(CxxLibraryDescription.TYPE))) { defaultSettingsBuilder.put("EXECUTABLE_PREFIX", "lib"); } ImmutableMap.Builder<String, String> appendConfigsBuilder = ImmutableMap.builder(); ImmutableSet<Path> recursiveHeaderSearchPaths = collectRecursiveHeaderSearchPaths(targetNode); ImmutableSet<Path> headerMapBases = recursiveHeaderSearchPaths.isEmpty() ? ImmutableSet.<Path>of() : ImmutableSet.of(pathRelativizer.outputDirToRootRelative(BuckConstant.BUCK_OUTPUT_PATH)); appendConfigsBuilder .put("HEADER_SEARCH_PATHS", Joiner.on(' ').join(Iterables.concat(recursiveHeaderSearchPaths, headerMapBases))) .put("LIBRARY_SEARCH_PATHS", Joiner.on(' ').join(collectRecursiveLibrarySearchPaths(ImmutableSet.of(targetNode)))) .put("FRAMEWORK_SEARCH_PATHS", Joiner.on(' ').join(collectRecursiveFrameworkSearchPaths(ImmutableList.of(targetNode)))) .put("OTHER_CFLAGS", Joiner.on(' ') .join(Iterables.transform( Iterables.concat(cxxBuckConfig.getFlags("cflags").or(DEFAULT_CFLAGS), collectRecursiveExportedPreprocessorFlags( ImmutableList.of(targetNode)), targetNode.getConstructorArg().compilerFlags.get(), targetNode.getConstructorArg().preprocessorFlags.get()), Escaper.BASH_ESCAPER))) .put("OTHER_CPLUSPLUSFLAGS", Joiner.on(' ') .join(Iterables.transform( Iterables.concat(cxxBuckConfig.getFlags("cxxflags").or(DEFAULT_CXXFLAGS), collectRecursiveExportedPreprocessorFlags( ImmutableList.of(targetNode)), targetNode.getConstructorArg().compilerFlags.get(), targetNode.getConstructorArg().preprocessorFlags.get()), Escaper.BASH_ESCAPER))) .put("OTHER_LDFLAGS", Joiner.on(' ') .join(Iterables .transform( Iterables.concat(targetNode.getConstructorArg().linkerFlags.get(), collectRecursiveExportedLinkerFlags( ImmutableList.of(targetNode))), Escaper.BASH_ESCAPER))); ImmutableMap<String, String> appendedConfig = appendConfigsBuilder.build(); Optional<ImmutableSortedMap<String, ImmutableMap<String, String>>> configs = getXcodeBuildConfigurationsForTargetNode( targetNode, appendedConfig); PBXNativeTarget target = targetBuilderResult.target; setTargetBuildConfigurations(getConfigurationNameToXcconfigPath(buildTarget), target, project.getMainGroup(), configs.get(), extraSettingsBuilder.build(), defaultSettingsBuilder.build(), appendedConfig); // -- phases createHeaderSymlinkTree(sourcePathResolver, getPublicCxxHeaders(targetNode), AppleDescriptions.getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PUBLIC)); createHeaderSymlinkTree(sourcePathResolver, getPrivateCxxHeaders(targetNode), AppleDescriptions.getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PRIVATE)); if (appleTargetNode.isPresent()) { // Use Core Data models from immediate dependencies only. addCoreDataModelsIntoTarget(appleTargetNode.get(), targetGroup); } return target; }
From source file:com.facebook.buck.apple.project_generator.ProjectGenerator.java
private PBXNativeTarget generateBinaryTarget(PBXProject project, Optional<? extends TargetNode<? extends HasAppleBundleFields, ?>> bundle, TargetNode<? extends CxxLibraryDescription.Arg, ?> targetNode, ProductType productType, String productOutputFormat, Optional<Path> infoPlistOptional, boolean includeFrameworks, ImmutableSet<AppleResourceDescription.Arg> recursiveResources, ImmutableSet<AppleResourceDescription.Arg> directResources, ImmutableSet<AppleAssetCatalogDescription.Arg> recursiveAssetCatalogs, ImmutableSet<AppleAssetCatalogDescription.Arg> directAssetCatalogs, ImmutableSet<AppleWrapperResourceArg> wrapperResources, Optional<Iterable<PBXBuildPhase>> copyFilesPhases, Optional<TargetNode<AppleBundleDescription.Arg, ?>> bundleLoaderNode) throws IOException { LOG.debug("Generating binary target for node %s", targetNode); TargetNode<?, ?> buildTargetNode = bundle.isPresent() ? bundle.get() : targetNode; final BuildTarget buildTarget = buildTargetNode.getBuildTarget(); String buildTargetName = getProductNameForBuildTarget(buildTarget); CxxLibraryDescription.Arg arg = targetNode.getConstructorArg(); NewNativeTargetProjectMutator mutator = new NewNativeTargetProjectMutator(pathRelativizer, sourcePathResolver);//from w ww. j av a 2 s. c om ImmutableSet<SourcePath> exportedHeaders = ImmutableSet.copyOf(getHeaderSourcePaths(arg.exportedHeaders)); ImmutableSet<SourcePath> headers = ImmutableSet.copyOf(getHeaderSourcePaths(arg.headers)); ImmutableMap<CxxSource.Type, ImmutableList<String>> langPreprocessorFlags = targetNode .getConstructorArg().langPreprocessorFlags; mutator.setTargetName(getXcodeTargetName(buildTarget)).setProduct(productType, buildTargetName, Paths.get(String.format(productOutputFormat, buildTargetName))); boolean isFocusedOnTarget = shouldIncludeBuildTargetIntoFocusedProject(focusModules, buildTarget); if (isFocusedOnTarget) { mutator.setLangPreprocessorFlags(langPreprocessorFlags).setPublicHeaders(exportedHeaders) .setPrefixHeader(arg.prefixHeader).setSourcesWithFlags(ImmutableSet.copyOf(arg.srcs)) .setPrivateHeaders(headers).setRecursiveResources(recursiveResources) .setDirectResources(directResources).setWrapperResources(wrapperResources); } if (bundle.isPresent() && isFocusedOnTarget) { HasAppleBundleFields bundleArg = bundle.get().getConstructorArg(); mutator.setInfoPlist(Optional.of(bundleArg.getInfoPlist())); } mutator.setBridgingHeader(arg.bridgingHeader); Optional<TargetNode<AppleNativeTargetDescriptionArg, ?>> appleTargetNode = targetNode .castArg(AppleNativeTargetDescriptionArg.class); if (appleTargetNode.isPresent() && isFocusedOnTarget) { AppleNativeTargetDescriptionArg appleArg = appleTargetNode.get().getConstructorArg(); mutator = mutator.setExtraXcodeSources(ImmutableSet.copyOf(appleArg.extraXcodeSources)); } if (options.contains(Option.CREATE_DIRECTORY_STRUCTURE) && isFocusedOnTarget) { mutator.setTargetGroupPath(StreamSupport.stream(buildTarget.getBasePath().spliterator(), false) .map(Object::toString).collect(MoreCollectors.toImmutableList())); } if (!recursiveAssetCatalogs.isEmpty() && isFocusedOnTarget) { mutator.setRecursiveAssetCatalogs(recursiveAssetCatalogs); } if (!directAssetCatalogs.isEmpty() && isFocusedOnTarget) { mutator.setDirectAssetCatalogs(directAssetCatalogs); } if (includeFrameworks && isFocusedOnTarget) { ImmutableSet.Builder<FrameworkPath> frameworksBuilder = ImmutableSet.builder(); frameworksBuilder.addAll(targetNode.getConstructorArg().frameworks); frameworksBuilder.addAll(targetNode.getConstructorArg().libraries); frameworksBuilder.addAll(collectRecursiveFrameworkDependencies(ImmutableList.of(targetNode))); mutator.setFrameworks(frameworksBuilder.build()); mutator.setArchives(collectRecursiveLibraryDependencies(ImmutableList.of(targetNode))); } // TODO(Task #3772930): Go through all dependencies of the rule // and add any shell script rules here ImmutableList.Builder<TargetNode<?, ?>> preScriptPhases = ImmutableList.builder(); ImmutableList.Builder<TargetNode<?, ?>> postScriptPhases = ImmutableList.builder(); if (bundle.isPresent() && targetNode != bundle.get() && isFocusedOnTarget) { collectBuildScriptDependencies(targetGraph.getAll(bundle.get().getDeclaredDeps()), preScriptPhases, postScriptPhases); } collectBuildScriptDependencies(targetGraph.getAll(targetNode.getDeclaredDeps()), preScriptPhases, postScriptPhases); if (isFocusedOnTarget) { mutator.setPreBuildRunScriptPhasesFromTargetNodes(preScriptPhases.build()); if (copyFilesPhases.isPresent()) { mutator.setCopyFilesPhases(copyFilesPhases.get()); } mutator.setPostBuildRunScriptPhasesFromTargetNodes(postScriptPhases.build()); } NewNativeTargetProjectMutator.Result targetBuilderResult; targetBuilderResult = mutator.buildTargetAndAddToProject(project, isFocusedOnTarget); Optional<PBXGroup> targetGroup = targetBuilderResult.targetGroup; if (isFocusedOnTarget) { SourceTreePath buckFilePath = new SourceTreePath(PBXReference.SourceTree.SOURCE_ROOT, pathRelativizer.outputPathToBuildTargetPath(buildTarget).resolve(buildFileName), Optional.empty()); PBXFileReference buckReference = targetGroup.get() .getOrCreateFileReferenceBySourceTreePath(buckFilePath); buckReference.setExplicitFileType(Optional.of("text.script.python")); } // -- configurations ImmutableMap.Builder<String, String> extraSettingsBuilder = ImmutableMap.builder(); extraSettingsBuilder.put("TARGET_NAME", buildTargetName).put("SRCROOT", pathRelativizer.outputPathToBuildTargetPath(buildTarget).toString()); if (productType == ProductType.UI_TEST && isFocusedOnTarget) { if (bundleLoaderNode.isPresent()) { BuildTarget testTarget = bundleLoaderNode.get().getBuildTarget(); extraSettingsBuilder.put("TEST_TARGET_NAME", getXcodeTargetName(testTarget)); } else { throw new HumanReadableException( "The test rule '%s' is configured with 'is_ui_test' but has no test_host_app", buildTargetName); } } else if (bundleLoaderNode.isPresent() && isFocusedOnTarget) { TargetNode<AppleBundleDescription.Arg, ?> bundleLoader = bundleLoaderNode.get(); String bundleLoaderProductName = getProductNameForBuildTarget(bundleLoader.getBuildTarget()); String bundleLoaderBundleName = bundleLoaderProductName + "." + getExtensionString(bundleLoader.getConstructorArg().getExtension()); // NOTE(grp): This is a hack. We need to support both deep (OS X) and flat (iOS) // style bundles for the bundle loader, but at this point we don't know what platform // the bundle loader (or current target) is going to be built for. However, we can be // sure that it's the same as the target (presumably a test) we're building right now. // // Using that knowledge, we can do build setting tricks to defer choosing the bundle // loader path until Xcode build time, when the platform is known. There's no build // setting that conclusively says whether the current platform uses deep bundles: // that would be too easy. But in the cases we care about (unit test bundles), the // current bundle will have a style matching the style of the bundle loader app, so // we can take advantage of that to do the determination. // // Unfortunately, the build setting for the bundle structure (CONTENTS_FOLDER_PATH) // includes the WRAPPER_NAME, so we can't just interpolate that in. Instead, we have // to use another trick with build setting operations and evaluation. By using the // $(:file) operation, we can extract the last component of the contents path: either // "Contents" or the current bundle name. Then, we can interpolate with that expected // result in the build setting name to conditionally choose a different loader path. // The conditional that decdies which path is used. This is a complex Xcode build setting // expression that expands to one of two values, depending on the last path component of // the CONTENTS_FOLDER_PATH variable. As described above, this will be either "Contents" // for deep bundles or the bundle file name itself for flat bundles. Finally, to santiize // the potentially invalid build setting names from the bundle file name, it converts that // to an identifier. We rely on BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_<bundle file name> // being undefined (and thus expanding to nothing) for the path resolution to work. // // The operations on the CONTENTS_FOLDER_PATH are documented here: // http://codeworkshop.net/posts/xcode-build-setting-transformations String bundleLoaderOutputPathConditional = "$(BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_$(CONTENTS_FOLDER_PATH:file:identifier))"; // If the $(CONTENTS_FOLDER_PATH:file:identifier) expands to this, we add the deep bundle // path into the bundle loader. See above for the case when it will expand to this value. String bundleLoaderOutputPathDeepSetting = "BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_Contents"; String bundleLoaderOutputPathDeepValue = "Contents/MacOS/"; String bundleLoaderOutputPathValue = Joiner.on('/').join(getTargetOutputPath(bundleLoader), bundleLoaderBundleName, bundleLoaderOutputPathConditional, bundleLoaderProductName); extraSettingsBuilder.put(bundleLoaderOutputPathDeepSetting, bundleLoaderOutputPathDeepValue) .put("BUNDLE_LOADER", bundleLoaderOutputPathValue).put("TEST_HOST", "$(BUNDLE_LOADER)"); } if (infoPlistOptional.isPresent()) { Path infoPlistPath = pathRelativizer.outputDirToRootRelative(infoPlistOptional.get()); extraSettingsBuilder.put("INFOPLIST_FILE", infoPlistPath.toString()); } if (arg.bridgingHeader.isPresent()) { Path bridgingHeaderPath = pathRelativizer .outputDirToRootRelative(sourcePathResolver.apply(arg.bridgingHeader.get())); extraSettingsBuilder.put("SWIFT_OBJC_BRIDGING_HEADER", Joiner.on('/').join("$(SRCROOT)", bridgingHeaderPath.toString())); } Optional<String> swiftVersion = swiftBuckConfig.getVersion(); if (swiftVersion.isPresent()) { extraSettingsBuilder.put("SWIFT_VERSION", swiftVersion.get()); } Optional<SourcePath> prefixHeaderOptional = targetNode.getConstructorArg().prefixHeader; if (prefixHeaderOptional.isPresent()) { Path prefixHeaderRelative = sourcePathResolver.apply(prefixHeaderOptional.get()); Path prefixHeaderPath = pathRelativizer.outputDirToRootRelative(prefixHeaderRelative); extraSettingsBuilder.put("GCC_PREFIX_HEADER", prefixHeaderPath.toString()); extraSettingsBuilder.put("GCC_PRECOMPILE_PREFIX_HEADER", "YES"); } extraSettingsBuilder.put("USE_HEADERMAP", "NO"); ImmutableMap.Builder<String, String> defaultSettingsBuilder = ImmutableMap.builder(); defaultSettingsBuilder.put("REPO_ROOT", projectFilesystem.getRootPath().toAbsolutePath().normalize().toString()); defaultSettingsBuilder.put(PRODUCT_NAME, getProductName(buildTargetNode, buildTarget)); if (bundle.isPresent()) { defaultSettingsBuilder.put("WRAPPER_EXTENSION", getExtensionString(bundle.get().getConstructorArg().getExtension())); } // We use BUILT_PRODUCTS_DIR as the root for the everything being built. Target- // specific output is placed within CONFIGURATION_BUILD_DIR, inside BUILT_PRODUCTS_DIR. // That allows Copy Files build phases to reference files in the CONFIGURATION_BUILD_DIR // of other targets by using paths relative to the target-independent BUILT_PRODUCTS_DIR. defaultSettingsBuilder.put("BUILT_PRODUCTS_DIR", // $EFFECTIVE_PLATFORM_NAME starts with a dash, so this expands to something like: // $SYMROOT/Debug-iphonesimulator Joiner.on('/').join("$SYMROOT", "$CONFIGURATION$EFFECTIVE_PLATFORM_NAME")); defaultSettingsBuilder.put("CONFIGURATION_BUILD_DIR", "$BUILT_PRODUCTS_DIR"); boolean nodeIsAppleLibrary = targetNode.getDescription() instanceof AppleLibraryDescription; boolean nodeIsCxxLibrary = targetNode.getDescription() instanceof CxxLibraryDescription; if (!bundle.isPresent() && (nodeIsAppleLibrary || nodeIsCxxLibrary)) { defaultSettingsBuilder.put("EXECUTABLE_PREFIX", "lib"); } ImmutableMap.Builder<String, String> appendConfigsBuilder = ImmutableMap.builder(); if (isFocusedOnTarget) { ImmutableSet<Path> recursiveHeaderSearchPaths = collectRecursiveHeaderSearchPaths(targetNode); ImmutableSet<Path> headerMapBases = recursiveHeaderSearchPaths.isEmpty() ? ImmutableSet.of() : ImmutableSet.of(pathRelativizer .outputDirToRootRelative(buildTargetNode.getFilesystem().getBuckPaths().getBuckOut())); appendConfigsBuilder .put("HEADER_SEARCH_PATHS", Joiner.on(' ').join(Iterables.concat(recursiveHeaderSearchPaths, headerMapBases))) .put("LIBRARY_SEARCH_PATHS", Joiner.on(' ').join(collectRecursiveLibrarySearchPaths(ImmutableSet.of(targetNode)))) .put("FRAMEWORK_SEARCH_PATHS", Joiner.on(' ') .join(collectRecursiveFrameworkSearchPaths(ImmutableList.of(targetNode)))); Iterable<String> otherCFlags = Iterables.concat(cxxBuckConfig.getFlags("cflags").orElse(DEFAULT_CFLAGS), collectRecursiveExportedPreprocessorFlags(ImmutableList.of(targetNode)), targetNode.getConstructorArg().compilerFlags, targetNode.getConstructorArg().preprocessorFlags); Iterable<String> otherCxxFlags = Iterables.concat( cxxBuckConfig.getFlags("cxxflags").orElse(DEFAULT_CXXFLAGS), collectRecursiveExportedPreprocessorFlags(ImmutableList.of(targetNode)), targetNode.getConstructorArg().compilerFlags, targetNode.getConstructorArg().preprocessorFlags); Iterable<String> otherLdFlags = Iterables.concat(targetNode.getConstructorArg().linkerFlags, collectRecursiveExportedLinkerFlags(ImmutableList.of(targetNode))); appendConfigsBuilder .put("OTHER_CFLAGS", Joiner.on(' ').join(Iterables.transform(otherCFlags, Escaper.BASH_ESCAPER))) .put("OTHER_CPLUSPLUSFLAGS", Joiner.on(' ').join(Iterables.transform(otherCxxFlags, Escaper.BASH_ESCAPER))) .put("OTHER_LDFLAGS", Joiner.on(' ').join(Iterables.transform(otherLdFlags, Escaper.BASH_ESCAPER))); ImmutableMultimap.Builder<String, ImmutableList<String>> platformFlagsBuilder = ImmutableMultimap .builder(); for (Pair<Pattern, ImmutableList<String>> flags : Iterables.concat( targetNode.getConstructorArg().platformCompilerFlags.getPatternsAndValues(), targetNode.getConstructorArg().platformPreprocessorFlags.getPatternsAndValues(), collectRecursiveExportedPlatformPreprocessorFlags(ImmutableList.of(targetNode)))) { String sdk = flags.getFirst().pattern().replaceAll("[*.]", ""); platformFlagsBuilder.put(sdk, flags.getSecond()); } ImmutableMultimap<String, ImmutableList<String>> platformFlags = platformFlagsBuilder.build(); for (String sdk : platformFlags.keySet()) { appendConfigsBuilder.put(String.format("OTHER_CFLAGS[sdk=*%s*]", sdk), Joiner.on(' ') .join(Iterables.transform( Iterables.concat(otherCFlags, Iterables.concat(platformFlags.get(sdk))), Escaper.BASH_ESCAPER))) .put(String.format("OTHER_CPLUSPLUSFLAGS[sdk=*%s*]", sdk), Joiner.on(' ') .join(Iterables.transform( Iterables.concat(otherCxxFlags, Iterables.concat(platformFlags.get(sdk))), Escaper.BASH_ESCAPER))); } ImmutableMultimap.Builder<String, ImmutableList<String>> platformLinkerFlagsBuilder = ImmutableMultimap .builder(); for (Pair<Pattern, ImmutableList<String>> flags : Iterables.concat( targetNode.getConstructorArg().platformLinkerFlags.getPatternsAndValues(), collectRecursiveExportedPlatformLinkerFlags(ImmutableList.of(targetNode)))) { String sdk = flags.getFirst().pattern().replaceAll("[*.]", ""); platformLinkerFlagsBuilder.put(sdk, flags.getSecond()); } ImmutableMultimap<String, ImmutableList<String>> platformLinkerFlags = platformLinkerFlagsBuilder .build(); for (String sdk : platformLinkerFlags.keySet()) { appendConfigsBuilder .put(String.format("OTHER_LDFLAGS[sdk=*%s*]", sdk), Joiner.on( ' ').join( Iterables .transform( Iterables.concat(otherLdFlags, Iterables.concat( platformLinkerFlags.get(sdk))), Escaper.BASH_ESCAPER))); } } PBXNativeTarget target = targetBuilderResult.target; if (isFocusedOnTarget) { ImmutableMap<String, String> appendedConfig = appendConfigsBuilder.build(); Optional<ImmutableSortedMap<String, ImmutableMap<String, String>>> configs = getXcodeBuildConfigurationsForTargetNode( targetNode, appendedConfig); setTargetBuildConfigurations(getConfigurationNameToXcconfigPath(buildTarget), target, project.getMainGroup(), configs.get(), extraSettingsBuilder.build(), defaultSettingsBuilder.build(), appendedConfig); } // -- phases boolean headerMapDisabled = options.contains(Option.DISABLE_HEADER_MAPS); createHeaderSymlinkTree(sourcePathResolver, getPublicCxxHeaders(targetNode), getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PUBLIC), arg.xcodePublicHeadersSymlinks.orElse(true) || headerMapDisabled); if (isFocusedOnTarget) { createHeaderSymlinkTree(sourcePathResolver, getPrivateCxxHeaders(targetNode), getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PRIVATE), arg.xcodePrivateHeadersSymlinks.orElse(true) || headerMapDisabled); } if (appleTargetNode.isPresent() && isFocusedOnTarget) { // Use Core Data models from immediate dependencies only. addCoreDataModelsIntoTarget(appleTargetNode.get(), targetGroup.get()); addSceneKitAssetsIntoTarget(appleTargetNode.get(), targetGroup.get()); } return target; }
From source file:edu.buaa.satla.analysis.core.predicate.PredicateAbstractionManager.java
/** * Compute an abstraction of the conjunction of an AbstractionFormula and * a PathFormula. The AbstractionFormula will be used in its instantiated form, * so the indices there should match those from the PathFormula. * @param abstractionFormula An AbstractionFormula that is used as input. * @param pathFormula A PathFormula that is used as input. * @param predicates The set of predicates used for abstraction. * @return An AbstractionFormula instance representing an abstraction of * "abstractionFormula & pathFormula" with pathFormula as the block formula. * @throws InterruptedException//w w w . j a v a 2s. c om */ public AbstractionFormula buildAbstraction(CFANode location, AbstractionFormula abstractionFormula, PathFormula pathFormula, Collection<AbstractionPredicate> pPredicates) throws SolverException, InterruptedException { stats.numCallsAbstraction++; logger.log(Level.FINEST, "Computing abstraction", stats.numCallsAbstraction, "with", pPredicates.size(), "predicates"); logger.log(Level.ALL, "Old abstraction:", abstractionFormula.asFormula()); logger.log(Level.ALL, "Path formula:", pathFormula); logger.log(Level.ALL, "Predicates:", pPredicates); BooleanFormula absFormula = abstractionFormula.asInstantiatedFormula(); BooleanFormula symbFormula = buildFormula(pathFormula.getFormula()); BooleanFormula f = bfmgr.and(absFormula, symbFormula); final SSAMap ssa = pathFormula.getSsa(); ImmutableSet<AbstractionPredicate> predicates = getRelevantPredicates(pPredicates, f, ssa); // Try to reuse stored abstractions if (reuseAbstractionsFrom != null && !abstractionReuseDisabledBecauseOfAmbiguity) { stats.abstractionReuseTime.start(); ProverEnvironment reuseEnv = solver.newProverEnvironment(); try { reuseEnv.push(f); Deque<Pair<Integer, Integer>> tryReuseBasedOnPredecessors = new ArrayDeque<>(); Set<Integer> idsOfStoredAbstractionReused = abstractionFormula.getIdsOfStoredAbstractionReused(); for (Integer id : idsOfStoredAbstractionReused) { tryReuseBasedOnPredecessors.add(Pair.of(id, 0)); } if (tryReuseBasedOnPredecessors.isEmpty()) { tryReuseBasedOnPredecessors.add(Pair.of(abstractionStorage.getRootAbstractionId(), 0)); } while (!tryReuseBasedOnPredecessors.isEmpty()) { final Pair<Integer, Integer> tryBasedOn = tryReuseBasedOnPredecessors.pop(); final int tryBasedOnAbstractionId = tryBasedOn.getFirst(); final int tryLevel = tryBasedOn.getSecond(); if (tryLevel > maxAbstractionReusePrescan) { continue; } Set<AbstractionNode> candidateAbstractions = getSuccessorsInAbstractionTree( tryBasedOnAbstractionId); Preconditions.checkNotNull(candidateAbstractions); //logger.log(Level.WARNING, "Raw candidates based on", tryBasedOnAbstractionId, ":", candidateAbstractions); Iterator<AbstractionNode> candidateIterator = candidateAbstractions.iterator(); while (candidateIterator.hasNext()) { AbstractionNode an = candidateIterator.next(); Preconditions.checkNotNull(an); tryReuseBasedOnPredecessors.add(Pair.of(an.getId(), tryLevel + 1)); if (bfmgr.isTrue(an.getFormula())) { candidateIterator.remove(); continue; } if (an.getLocationId().isPresent()) { if (location.getNodeNumber() != an.getLocationId().get()) { candidateIterator.remove(); continue; } } } //logger.log(Level.WARNING, "Filtered candidates", "location", location.getNodeNumber(), "abstraction", tryBasedOnAbstractionId, ":", candidateAbstractions); if (candidateAbstractions.size() > 1) { logger.log(Level.WARNING, "Too many abstraction candidates on location", location, "for abstraction", tryBasedOnAbstractionId, ". Disabling abstraction reuse!"); this.abstractionReuseDisabledBecauseOfAmbiguity = true; tryReuseBasedOnPredecessors.clear(); continue; } Set<Integer> reuseIds = Sets.newTreeSet(); BooleanFormula reuseFormula = bfmgr.makeBoolean(true); for (AbstractionNode an : candidateAbstractions) { reuseFormula = bfmgr.and(reuseFormula, an.getFormula()); abstractionStorage.markAbstractionBeingReused(an.getId()); reuseIds.add(an.getId()); } BooleanFormula instantiatedReuseFormula = fmgr.instantiate(reuseFormula, ssa); stats.abstractionReuseImplicationTime.start(); reuseEnv.push(bfmgr.not(instantiatedReuseFormula)); boolean implication = reuseEnv.isUnsat(); reuseEnv.pop(); stats.abstractionReuseImplicationTime.stop(); if (implication) { stats.numAbstractionReuses++; Region reuseFormulaRegion = buildRegionFromFormula(reuseFormula); return new AbstractionFormula(fmgr, reuseFormulaRegion, reuseFormula, instantiatedReuseFormula, pathFormula, reuseIds); } } } finally { reuseEnv.close(); stats.abstractionReuseTime.stop(); } } // <-- End of reuse // Shortcut if the precision is empty if (pPredicates.isEmpty()) { logger.log(Level.FINEST, "Abstraction", stats.numCallsAbstraction, "with empty precision is true"); stats.numSymbolicAbstractions++; return makeTrueAbstractionFormula(pathFormula); } // caching Pair<BooleanFormula, ImmutableSet<AbstractionPredicate>> absKey = null; if (useCache) { absKey = Pair.of(f, predicates); AbstractionFormula result = abstractionCache.get(absKey); if (result != null) { // create new abstraction object to have a unique abstraction id // instantiate the formula with the current indices BooleanFormula stateFormula = result.asFormula(); BooleanFormula instantiatedFormula = fmgr.instantiate(stateFormula, ssa); result = new AbstractionFormula(fmgr, result.asRegion(), stateFormula, instantiatedFormula, pathFormula, result.getIdsOfStoredAbstractionReused()); logger.log(Level.FINEST, "Abstraction", stats.numCallsAbstraction, "was cached"); logger.log(Level.ALL, "Abstraction result is", result.asFormula()); stats.numCallsAbstractionCached++; return result; } boolean unsatisfiable = unsatisfiabilityCache.contains(symbFormula) || unsatisfiabilityCache.contains(f); if (unsatisfiable) { // block is infeasible logger.log(Level.FINEST, "Block feasibility of abstraction", stats.numCallsAbstraction, "was cached and is false."); stats.numCallsAbstractionCached++; return new AbstractionFormula(fmgr, rmgr.makeFalse(), bfmgr.makeBoolean(false), bfmgr.makeBoolean(false), pathFormula, noAbstractionReuse); } } // We update statistics here because we want to ignore calls // where the result was in the cache. stats.numTotalPredicates += pPredicates.size(); stats.maxPredicates = Math.max(stats.maxPredicates, pPredicates.size()); stats.numIrrelevantPredicates += pPredicates.size() - predicates.size(); // Compute result for those predicates // where we can trivially identify their truthness in the result Region abs = rmgr.makeTrue(); if (identifyTrivialPredicates) { stats.trivialPredicatesTime.start(); abs = identifyTrivialPredicates(predicates, abstractionFormula, pathFormula); // Calculate the set of predicates we still need to use for abstraction. predicates = from(predicates).filter(not(in(amgr.extractPredicates(abs)))).toSet(); stats.trivialPredicatesTime.stop(); } try (ProverEnvironment thmProver = solver.newProverEnvironment()) { thmProver.push(f); if (predicates.isEmpty()) { stats.numSatCheckAbstractions++; stats.abstractionSolveTime.start(); boolean feasibility; try { feasibility = !thmProver.isUnsat(); } finally { stats.abstractionSolveTime.stop(); } if (!feasibility) { abs = rmgr.makeFalse(); } } else { if (abstractionType != AbstractionType.BOOLEAN) { // First do cartesian abstraction if desired stats.cartesianAbstractionTime.start(); try { abs = rmgr.makeAnd(abs, buildCartesianAbstraction(f, ssa, thmProver, predicates)); } finally { stats.cartesianAbstractionTime.stop(); } } if (abstractionType == AbstractionType.COMBINED) { // Calculate the set of predicates that cartesian abstraction couldn't handle. predicates = from(predicates).filter(not(in(amgr.extractPredicates(abs)))).toSet(); } if (abstractionType != AbstractionType.CARTESIAN && !predicates.isEmpty()) { // Last do boolean abstraction if desired and necessary stats.numBooleanAbsPredicates += predicates.size(); stats.booleanAbstractionTime.start(); try { abs = rmgr.makeAnd(abs, buildBooleanAbstraction(location, ssa, thmProver, predicates)); } finally { stats.booleanAbstractionTime.stop(); } // Warning: // buildBooleanAbstraction() does not clean up thmProver, so do not use it here. } } } AbstractionFormula result = makeAbstractionFormula(abs, ssa, pathFormula); if (useCache) { abstractionCache.put(absKey, result); if (result.isFalse()) { unsatisfiabilityCache.add(f); } } long abstractionTime = TimeSpan.sum(stats.abstractionSolveTime.getLengthOfLastInterval(), stats.abstractionEnumTime.getLengthOfLastOuterInterval()).asMillis(); logger.log(Level.FINEST, "Computing abstraction took", abstractionTime, "ms"); logger.log(Level.ALL, "Abstraction result is", result.asFormula()); if (dumpHardAbstractions && abstractionTime > 10000) { // we want to dump "hard" problems... Path dumpFile; dumpFile = fmgr.formatFormulaOutputFile("abstraction", stats.numCallsAbstraction, "input", 0); fmgr.dumpFormulaToFile(f, dumpFile); dumpFile = fmgr.formatFormulaOutputFile("abstraction", stats.numCallsAbstraction, "predicates", 0); try (Writer w = dumpFile.asCharSink(StandardCharsets.UTF_8).openBufferedStream()) { Joiner.on('\n').appendTo(w, predicates); } catch (IOException e) { logger.logUserException(Level.WARNING, e, "Failed to wrote predicates to file"); } dumpFile = fmgr.formatFormulaOutputFile("abstraction", stats.numCallsAbstraction, "result", 0); fmgr.dumpFormulaToFile(result.asInstantiatedFormula(), dumpFile); } return result; }
From source file:org.sosy_lab.cpachecker.cpa.predicate.PredicateAbstractionManager.java
/** * Compute an abstraction of the conjunction of an AbstractionFormula and * a PathFormula. The AbstractionFormula will be used in its instantiated form, * so the indices there should match those from the PathFormula. * @param abstractionFormula An AbstractionFormula that is used as input. * @param pathFormula A PathFormula that is used as input. * @param predicates The set of predicates used for abstraction. * @return An AbstractionFormula instance representing an abstraction of * "abstractionFormula & pathFormula" with pathFormula as the block formula. * @throws InterruptedException/* ww w . j a va 2 s. c o m*/ */ public AbstractionFormula buildAbstraction(CFANode location, AbstractionFormula abstractionFormula, PathFormula pathFormula, Collection<AbstractionPredicate> pPredicates) throws SolverException, InterruptedException { stats.numCallsAbstraction++; logger.log(Level.FINEST, "Computing abstraction", stats.numCallsAbstraction, "with", pPredicates.size(), "predicates"); logger.log(Level.ALL, "Old abstraction:", abstractionFormula.asFormula()); logger.log(Level.ALL, "Path formula:", pathFormula); logger.log(Level.ALL, "Predicates:", pPredicates); BooleanFormula absFormula = abstractionFormula.asInstantiatedFormula(); BooleanFormula symbFormula = buildFormula(pathFormula.getFormula()); BooleanFormula f = bfmgr.and(absFormula, symbFormula); final SSAMap ssa = pathFormula.getSsa(); ImmutableSet<AbstractionPredicate> predicates = getRelevantPredicates(pPredicates, f, ssa); // Try to reuse stored abstractions if (reuseAbstractionsFrom != null && !abstractionReuseDisabledBecauseOfAmbiguity) { stats.abstractionReuseTime.start(); ProverEnvironment reuseEnv = solver.newProverEnvironment(); try { reuseEnv.push(f); Deque<Pair<Integer, Integer>> tryReuseBasedOnPredecessors = new ArrayDeque<>(); Set<Integer> idsOfStoredAbstractionReused = abstractionFormula.getIdsOfStoredAbstractionReused(); for (Integer id : idsOfStoredAbstractionReused) { tryReuseBasedOnPredecessors.add(Pair.of(id, 0)); } if (tryReuseBasedOnPredecessors.isEmpty()) { tryReuseBasedOnPredecessors.add(Pair.of(abstractionStorage.getRootAbstractionId(), 0)); } while (!tryReuseBasedOnPredecessors.isEmpty()) { final Pair<Integer, Integer> tryBasedOn = tryReuseBasedOnPredecessors.pop(); final int tryBasedOnAbstractionId = tryBasedOn.getFirst(); final int tryLevel = tryBasedOn.getSecond(); if (tryLevel > maxAbstractionReusePrescan) { continue; } Set<AbstractionNode> candidateAbstractions = getSuccessorsInAbstractionTree( tryBasedOnAbstractionId); Preconditions.checkNotNull(candidateAbstractions); //logger.log(Level.WARNING, "Raw candidates based on", tryBasedOnAbstractionId, ":", candidateAbstractions); Iterator<AbstractionNode> candidateIterator = candidateAbstractions.iterator(); while (candidateIterator.hasNext()) { AbstractionNode an = candidateIterator.next(); Preconditions.checkNotNull(an); tryReuseBasedOnPredecessors.add(Pair.of(an.getId(), tryLevel + 1)); if (bfmgr.isTrue(an.getFormula())) { candidateIterator.remove(); continue; } if (an.getLocationId().isPresent()) { if (location.getNodeNumber() != an.getLocationId().get()) { candidateIterator.remove(); continue; } } } //logger.log(Level.WARNING, "Filtered candidates", "location", location.getNodeNumber(), "abstraction", tryBasedOnAbstractionId, ":", candidateAbstractions); if (candidateAbstractions.size() > 1) { logger.log(Level.WARNING, "Too many abstraction candidates on location", location, "for abstraction", tryBasedOnAbstractionId, ". Disabling abstraction reuse!"); this.abstractionReuseDisabledBecauseOfAmbiguity = true; tryReuseBasedOnPredecessors.clear(); continue; } Set<Integer> reuseIds = Sets.newTreeSet(); BooleanFormula reuseFormula = bfmgr.makeBoolean(true); for (AbstractionNode an : candidateAbstractions) { reuseFormula = bfmgr.and(reuseFormula, an.getFormula()); abstractionStorage.markAbstractionBeingReused(an.getId()); reuseIds.add(an.getId()); } BooleanFormula instantiatedReuseFormula = fmgr.instantiate(reuseFormula, ssa); stats.abstractionReuseImplicationTime.start(); reuseEnv.push(bfmgr.not(instantiatedReuseFormula)); boolean implication = reuseEnv.isUnsat(); reuseEnv.pop(); stats.abstractionReuseImplicationTime.stop(); if (implication) { stats.numAbstractionReuses++; Region reuseFormulaRegion = buildRegionFromFormula(reuseFormula); return new AbstractionFormula(fmgr, reuseFormulaRegion, reuseFormula, instantiatedReuseFormula, pathFormula, reuseIds); } } } finally { reuseEnv.close(); stats.abstractionReuseTime.stop(); } } // <-- End of reuse // Shortcut if the precision is empty if (pPredicates.isEmpty() && (abstractionType != AbstractionType.ELIMINATION)) { logger.log(Level.FINEST, "Abstraction", stats.numCallsAbstraction, "with empty precision is true"); stats.numSymbolicAbstractions++; return makeTrueAbstractionFormula(pathFormula); } // caching Pair<BooleanFormula, ImmutableSet<AbstractionPredicate>> absKey = null; if (useCache) { absKey = Pair.of(f, predicates); AbstractionFormula result = abstractionCache.get(absKey); if (result != null) { // create new abstraction object to have a unique abstraction id // instantiate the formula with the current indices BooleanFormula stateFormula = result.asFormula(); BooleanFormula instantiatedFormula = fmgr.instantiate(stateFormula, ssa); result = new AbstractionFormula(fmgr, result.asRegion(), stateFormula, instantiatedFormula, pathFormula, result.getIdsOfStoredAbstractionReused()); logger.log(Level.FINEST, "Abstraction", stats.numCallsAbstraction, "was cached"); logger.log(Level.ALL, "Abstraction result is", result.asFormula()); stats.numCallsAbstractionCached++; return result; } boolean unsatisfiable = unsatisfiabilityCache.contains(symbFormula) || unsatisfiabilityCache.contains(f); if (unsatisfiable) { // block is infeasible logger.log(Level.FINEST, "Block feasibility of abstraction", stats.numCallsAbstraction, "was cached and is false."); stats.numCallsAbstractionCached++; return new AbstractionFormula(fmgr, rmgr.makeFalse(), bfmgr.makeBoolean(false), bfmgr.makeBoolean(false), pathFormula, noAbstractionReuse); } } // We update statistics here because we want to ignore calls // where the result was in the cache. stats.numTotalPredicates += pPredicates.size(); stats.maxPredicates = Math.max(stats.maxPredicates, pPredicates.size()); stats.numIrrelevantPredicates += pPredicates.size() - predicates.size(); // Compute result for those predicates // where we can trivially identify their truthness in the result Region abs = rmgr.makeTrue(); if (identifyTrivialPredicates) { stats.trivialPredicatesTime.start(); abs = identifyTrivialPredicates(predicates, abstractionFormula, pathFormula); // Calculate the set of predicates we still need to use for abstraction. predicates = from(predicates).filter(not(in(amgr.extractPredicates(abs)))).toSet(); stats.trivialPredicatesTime.stop(); } try (ProverEnvironment thmProver = solver.newProverEnvironment()) { thmProver.push(f); if (predicates.isEmpty() && (abstractionType != AbstractionType.ELIMINATION)) { stats.numSatCheckAbstractions++; stats.abstractionSolveTime.start(); boolean feasibility; try { feasibility = !thmProver.isUnsat(); } finally { stats.abstractionSolveTime.stop(); } if (!feasibility) { abs = rmgr.makeFalse(); } } else if (abstractionType == AbstractionType.ELIMINATION) { stats.quantifierEliminationTime.start(); try { abs = rmgr.makeAnd(abs, eliminateIrrelevantVariablePropositions(f, location, ssa, thmProver, predicates)); } finally { stats.quantifierEliminationTime.stop(); } } else { if (abstractionType != AbstractionType.BOOLEAN) { // First do cartesian abstraction if desired stats.cartesianAbstractionTime.start(); try { abs = rmgr.makeAnd(abs, buildCartesianAbstraction(f, ssa, thmProver, predicates)); } finally { stats.cartesianAbstractionTime.stop(); } } if (abstractionType == AbstractionType.COMBINED) { // Calculate the set of predicates that cartesian abstraction couldn't handle. predicates = from(predicates).filter(not(in(amgr.extractPredicates(abs)))).toSet(); } if (abstractionType != AbstractionType.CARTESIAN && !predicates.isEmpty()) { // Last do boolean abstraction if desired and necessary stats.numBooleanAbsPredicates += predicates.size(); stats.booleanAbstractionTime.start(); try { abs = rmgr.makeAnd(abs, buildBooleanAbstraction(ssa, thmProver, predicates)); } finally { stats.booleanAbstractionTime.stop(); } // Warning: // buildBooleanAbstraction() does not clean up thmProver, so do not use it here. } } } AbstractionFormula result = makeAbstractionFormula(abs, ssa, pathFormula); if (useCache) { abstractionCache.put(absKey, result); if (result.isFalse()) { unsatisfiabilityCache.add(f); } } long abstractionTime = TimeSpan.sum(stats.abstractionSolveTime.getLengthOfLastInterval(), stats.abstractionEnumTime.getLengthOfLastOuterInterval()).asMillis(); logger.log(Level.FINEST, "Computing abstraction took", abstractionTime, "ms"); logger.log(Level.ALL, "Abstraction result is", result.asFormula()); if (dumpHardAbstractions && abstractionTime > 10000) { // we want to dump "hard" problems... Path dumpFile; dumpFile = fmgr.formatFormulaOutputFile("abstraction", stats.numCallsAbstraction, "input", 0); fmgr.dumpFormulaToFile(f, dumpFile); dumpFile = fmgr.formatFormulaOutputFile("abstraction", stats.numCallsAbstraction, "predicates", 0); try (Writer w = dumpFile.asCharSink(StandardCharsets.UTF_8).openBufferedStream()) { Joiner.on('\n').appendTo(w, predicates); } catch (IOException e) { logger.logUserException(Level.WARNING, e, "Failed to wrote predicates to file"); } dumpFile = fmgr.formatFormulaOutputFile("abstraction", stats.numCallsAbstraction, "result", 0); fmgr.dumpFormulaToFile(result.asInstantiatedFormula(), dumpFile); } return result; }
From source file:com.outerspacecat.icalendar.RecurrenceRuleType.java
/** * Parses a recurrence rule. Does not support leap seconds, if a seconds field * of 60 is encountered, then {@link CalendarParseException} will be thrown. * //from w w w . j a va 2 s. c om * @param seq the value to parse. Must be non {@code null}. * @return a recurrence rule. Never {@code null}. * @throws CalendarParseException if {@code seq} does not represent a valid * recurrence rule */ public static RecurrenceRuleType parse(final CharSequence seq) throws CalendarParseException { Preconditions.checkNotNull(seq, "seq required"); Chronology chronology = null; Frequency frequency = null; LocalDate untilDate = null; ParsedDateTime untilDateTime = null; Integer count = null; int interval = 0; ImmutableSet<Integer> bySecond = null; ImmutableSet<Integer> byMinute = null; ImmutableSet<Integer> byHour = null; ImmutableSet<DayOfWeekOccurrence> byDay = null; ImmutableSet<Integer> byMonthDay = null; ImmutableSet<Integer> byYearDay = null; ImmutableSet<Integer> byWeekNo = null; ImmutableSet<Integer> byMonth = null; ImmutableSet<Integer> bySetPos = null; DayOfWeek weekStart = null; Skip skip = null; String[] parts = seq.toString().toUpperCase().split(";"); for (String pair : parts) { String[] kv = pair.split("="); if (kv.length != 2) throw new CalendarParseException("invalid rule: " + seq); if (kv[0].equals("RSCALE")) { if (chronology != null) throw new CalendarParseException("invalid rule: " + seq); chronology = NameToChronology.get(kv[1]); if (chronology == null) throw new CalendarParseException("invalid rule: " + seq); } else if (kv[0].equals("FREQ")) { if (frequency != null) throw new CalendarParseException("invalid rule: " + seq); try { frequency = Enum.valueOf(Frequency.class, kv[1]); } catch (IllegalArgumentException e) { throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("UNTIL")) { if (untilDate != null || untilDateTime != null || count != null) throw new CalendarParseException("invalid rule: " + seq); try { untilDateTime = ParsedDateTime.parse(kv[1]); } catch (CalendarParseException e) { try { untilDate = LocalDate.from(DateTimeFormatter.BASIC_ISO_DATE.parse(kv[1])); } catch (DateTimeException e2) { throw new CalendarParseException("invalid rule: " + seq); } } } else if (kv[0].equals("COUNT")) { if (untilDate != null || untilDateTime != null || count != null) throw new CalendarParseException("invalid rule: " + seq); try { count = Integer.parseInt(kv[1]); if (count <= 0) throw new CalendarParseException("invalid rule: " + seq); } catch (NumberFormatException e) { throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("INTERVAL")) { if (interval > 0) throw new CalendarParseException("invalid rule: " + seq); try { interval = Integer.parseInt(kv[1]); if (interval <= 0) throw new CalendarParseException("invalid rule: " + seq); } catch (NumberFormatException e) { throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYSECOND")) { if (bySecond != null) throw new CalendarParseException("invalid rule: " + seq); bySecond = parseIntegerList(kv[1]); for (Integer i : bySecond) { if (i < 0 || i > 59) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYMINUTE")) { if (byMinute != null) throw new CalendarParseException("invalid rule: " + seq); byMinute = parseIntegerList(kv[1]); for (Integer i : byMinute) { if (i < 0 || i > 59) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYHOUR")) { if (byHour != null) throw new CalendarParseException("invalid rule: " + seq); byHour = parseIntegerList(kv[1]); for (Integer i : byHour) { if (i < 0 || i > 23) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYDAY")) { if (byDay != null) throw new CalendarParseException("invalid rule: " + seq); ImmutableSet.Builder<DayOfWeekOccurrence> builder = ImmutableSet.builder(); String[] byDayParts = kv[1].split(","); for (String p : byDayParts) { Matcher m = ByDayPattern.matcher(p); if (!m.matches()) throw new CalendarParseException("invalid rule: " + seq); Integer week = null; String g = m.group(1); if (g != null) { if (g.startsWith("+")) g = g.substring(1); week = Integer.parseInt(g); if (week < -53 || week > 53 || week == 0) throw new CalendarParseException("invalid rule: " + seq); } DayOfWeek weekday = dayOfWeekFromICalendar(m.group(2)); builder.add(new DayOfWeekOccurrence(Optional.fromNullable(week), weekday)); } byDay = builder.build(); } else if (kv[0].equals("BYMONTHDAY")) { if (byMonthDay != null) throw new CalendarParseException("invalid rule: " + seq); byMonthDay = parseIntegerList(kv[1]); for (Integer i : byMonthDay) { if (i < 1 || i > 31) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYYEARDAY")) { if (byYearDay != null) throw new CalendarParseException("invalid rule: " + seq); byYearDay = parseIntegerList(kv[1]); for (Integer i : byYearDay) { if (i < -366 || i > 366 || i == 0) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYWEEKNO")) { if (byWeekNo != null) throw new CalendarParseException("invalid rule: " + seq); byWeekNo = parseIntegerList(kv[1]); for (Integer i : byWeekNo) { if (i < -53 || i > 53 || i == 0) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYMONTH")) { if (byMonth != null) throw new CalendarParseException("invalid rule: " + seq); byMonth = parseIntegerList(kv[1]); for (Integer i : byMonth) { if (i < 1 || i > 12) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("BYSETPOS")) { if (bySetPos != null) throw new CalendarParseException("invalid rule: " + seq); bySetPos = parseIntegerList(kv[1]); for (Integer i : bySetPos) { if (i < -366 || i > 366 || i == 0) throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("WKST")) { if (weekStart != null) throw new CalendarParseException("invalid rule: " + seq); try { weekStart = dayOfWeekFromICalendar(kv[1]); } catch (IllegalArgumentException e) { throw new CalendarParseException("invalid rule: " + seq); } } else if (kv[0].equals("SKIP")) { if (weekStart != null) throw new CalendarParseException("invalid rule: " + seq); try { skip = Skip.valueOf(kv[1]); } catch (IllegalArgumentException e) { throw new CalendarParseException("invalid rule: " + seq); } } else { throw new CalendarParseException("invalid rule: " + seq); } } if (frequency == null) throw new CalendarParseException("invalid rule: " + seq); if (interval < 1) interval = 1; if (bySecond == null) bySecond = ImmutableSet.of(); if (byMinute == null) byMinute = ImmutableSet.of(); if (byHour == null) byHour = ImmutableSet.of(); if (byDay == null) byDay = ImmutableSet.of(); if (byMonthDay == null) byMonthDay = ImmutableSet.of(); if (byYearDay == null) byYearDay = ImmutableSet.of(); if (byWeekNo == null) byWeekNo = ImmutableSet.of(); if (byMonth == null) byMonth = ImmutableSet.of(); if (bySetPos == null) bySetPos = ImmutableSet.of(); if (weekStart == null) weekStart = DayOfWeek.MONDAY; if (!bySetPos.isEmpty() && bySecond.isEmpty() && byMinute.isEmpty() && byHour.isEmpty() && byDay.isEmpty() && byMonthDay.isEmpty() && byYearDay.isEmpty() && byWeekNo.isEmpty() && byMonth.isEmpty()) throw new CalendarParseException("invalid rule: " + seq); if (frequency != Frequency.MONTHLY && frequency != Frequency.YEARLY) { for (DayOfWeekOccurrence day : byDay) { if (day.getOccurrence().isPresent()) throw new CalendarParseException("invalid rule: " + seq); } } if (frequency == Frequency.YEARLY && !byWeekNo.isEmpty()) { for (DayOfWeekOccurrence day : byDay) { if (day.getOccurrence().isPresent()) throw new CalendarParseException("invalid rule: " + seq); } } if (frequency == Frequency.WEEKLY && !byMonthDay.isEmpty()) throw new CalendarParseException("invalid rule: " + seq); if ((frequency == Frequency.DAILY || frequency == Frequency.WEEKLY || frequency == Frequency.MONTHLY) && !byYearDay.isEmpty()) throw new CalendarParseException("invalid rule: " + seq); if (frequency != Frequency.YEARLY && !byWeekNo.isEmpty()) throw new CalendarParseException("invalid rule: " + seq); if (skip == null) { if (chronology == null) { skip = Skip.YES; } else { skip = Skip.BACKWARD; } } if (chronology == null) chronology = IsoChronology.INSTANCE; return new RecurrenceRuleType(chronology, frequency, untilDate, untilDateTime, count, interval, bySecond, byMinute, byHour, byDay, byMonthDay, byYearDay, byWeekNo, byMonth, bySetPos, weekStart, skip); }
From source file:com.facebook.buck.features.apple.project.ProjectGenerator.java
private PBXNativeTarget generateBinaryTarget(PBXProject project, Optional<? extends TargetNode<? extends HasAppleBundleFields>> bundle, TargetNode<? extends CxxLibraryDescription.CommonArg> targetNode, ProductType productType, String productOutputFormat, Optional<Path> infoPlistOptional, boolean includeFrameworks, ImmutableSet<AppleResourceDescriptionArg> recursiveResources, ImmutableSet<AppleResourceDescriptionArg> directResources, ImmutableSet<AppleAssetCatalogDescriptionArg> recursiveAssetCatalogs, ImmutableSet<AppleAssetCatalogDescriptionArg> directAssetCatalogs, ImmutableSet<AppleWrapperResourceArg> wrapperResources, Optional<Iterable<PBXBuildPhase>> copyFilesPhases, Optional<TargetNode<AppleBundleDescriptionArg>> bundleLoaderNode) throws IOException { LOG.debug("Generating binary target for node %s", targetNode); TargetNode<?> buildTargetNode = bundle.isPresent() ? bundle.get() : targetNode; BuildTarget buildTarget = buildTargetNode.getBuildTarget(); boolean containsSwiftCode = projGenerationStateCache.targetContainsSwiftSourceCode(targetNode); String buildTargetName = getProductNameForBuildTargetNode(buildTargetNode); CxxLibraryDescription.CommonArg arg = targetNode.getConstructorArg(); NewNativeTargetProjectMutator mutator = new NewNativeTargetProjectMutator(pathRelativizer, this::resolveSourcePath); // Both exported headers and exported platform headers will be put into the symlink tree // exported platform headers will be excluded and then included by platform ImmutableSet.Builder<SourcePath> exportedHeadersBuilder = ImmutableSet.builder(); exportedHeadersBuilder.addAll(getHeaderSourcePaths(arg.getExportedHeaders())); PatternMatchedCollection<SourceSortedSet> exportedPlatformHeaders = arg.getExportedPlatformHeaders(); for (SourceSortedSet headersSet : exportedPlatformHeaders.getValues()) { exportedHeadersBuilder.addAll(getHeaderSourcePaths(headersSet)); }//from ww w .j ava2 s.c om ImmutableSet<SourcePath> exportedHeaders = exportedHeadersBuilder.build(); ImmutableSet.Builder<SourcePath> headersBuilder = ImmutableSet.builder(); headersBuilder.addAll(getHeaderSourcePaths(arg.getHeaders())); for (SourceSortedSet headersSet : arg.getPlatformHeaders().getValues()) { headersBuilder.addAll(getHeaderSourcePaths(headersSet)); } ImmutableSet<SourcePath> headers = headersBuilder.build(); ImmutableMap<CxxSource.Type, ImmutableList<StringWithMacros>> langPreprocessorFlags = targetNode .getConstructorArg().getLangPreprocessorFlags(); boolean isFocusedOnTarget = focusModules.isFocusedOn(buildTarget); Optional<String> swiftVersion = getSwiftVersionForTargetNode(targetNode); boolean hasSwiftVersionArg = swiftVersion.isPresent(); if (!swiftVersion.isPresent()) { swiftVersion = swiftBuckConfig.getVersion(); } mutator.setTargetName(getXcodeTargetName(buildTarget)).setProduct(productType, buildTargetName, Paths.get(String.format(productOutputFormat, buildTargetName))); boolean isModularAppleLibrary = isModularAppleLibrary(targetNode) && isFocusedOnTarget; mutator.setFrameworkHeadersEnabled(isModularAppleLibrary); ImmutableMap.Builder<String, String> swiftDepsSettingsBuilder = ImmutableMap.builder(); ImmutableList.Builder<String> swiftDebugLinkerFlagsBuilder = ImmutableList.builder(); ImmutableMap.Builder<String, String> extraSettingsBuilder = ImmutableMap.builder(); ImmutableMap.Builder<String, String> defaultSettingsBuilder = ImmutableMap.builder(); ImmutableList<Pair<Pattern, SourceSortedSet>> platformHeaders = arg.getPlatformHeaders() .getPatternsAndValues(); ImmutableList.Builder<Pair<Pattern, Iterable<SourcePath>>> platformHeadersIterableBuilder = ImmutableList .builder(); for (Pair<Pattern, SourceSortedSet> platformHeader : platformHeaders) { platformHeadersIterableBuilder .add(new Pair<>(platformHeader.getFirst(), getHeaderSourcePaths(platformHeader.getSecond()))); } ImmutableList<Pair<Pattern, SourceSortedSet>> exportedPlatformHeadersPatternsAndValues = exportedPlatformHeaders .getPatternsAndValues(); for (Pair<Pattern, SourceSortedSet> exportedPlatformHeader : exportedPlatformHeadersPatternsAndValues) { platformHeadersIterableBuilder.add(new Pair<>(exportedPlatformHeader.getFirst(), getHeaderSourcePaths(exportedPlatformHeader.getSecond()))); } ImmutableList<Pair<Pattern, Iterable<SourcePath>>> platformHeadersIterable = platformHeadersIterableBuilder .build(); ImmutableList<Pair<Pattern, ImmutableSortedSet<SourceWithFlags>>> platformSources = arg.getPlatformSrcs() .getPatternsAndValues(); ImmutableMap<String, ImmutableSortedSet<String>> platformExcludedSourcesMapping = ProjectGenerator .gatherExcludedSources( appleCxxFlavors.stream().map(f -> applePlatformAndArchitecture(f).getFirst()) .collect(ImmutableSet.toImmutableSet()), platformSources, platformHeadersIterable, outputDirectory, defaultPathResolver); for (Map.Entry<String, ImmutableSortedSet<String>> platformExcludedSources : platformExcludedSourcesMapping .entrySet()) { if (platformExcludedSources.getValue().size() > 0) { extraSettingsBuilder.put(platformExcludedSources.getKey(), String.join(" ", platformExcludedSources.getValue())); } } ImmutableSortedSet<SourceWithFlags> nonPlatformSrcs = arg.getSrcs(); ImmutableSortedSet.Builder<SourceWithFlags> allSrcsBuilder = ImmutableSortedSet.naturalOrder(); allSrcsBuilder.addAll(nonPlatformSrcs); for (Pair<Pattern, ImmutableSortedSet<SourceWithFlags>> platformSource : platformSources) { allSrcsBuilder.addAll(platformSource.getSecond()); } ImmutableSortedSet<SourceWithFlags> allSrcs = allSrcsBuilder.build(); if (!options.shouldGenerateHeaderSymlinkTreesOnly()) { if (isFocusedOnTarget) { filesAddedBuilder.addAll( allSrcs.stream().map(s -> s.getSourcePath()).collect(ImmutableList.toImmutableList())); mutator.setLangPreprocessorFlags(ImmutableMap.copyOf( Maps.transformValues(langPreprocessorFlags, f -> convertStringWithMacros(targetNode, f)))) .setPublicHeaders(exportedHeaders).setPrefixHeader(getPrefixHeaderSourcePath(arg)) .setSourcesWithFlags(ImmutableSet.copyOf(allSrcs)).setPrivateHeaders(headers) .setRecursiveResources(recursiveResources).setDirectResources(directResources) .setWrapperResources(wrapperResources) .setExtraXcodeSources(ImmutableSet.copyOf(arg.getExtraXcodeSources())) .setExtraXcodeFiles(ImmutableSet.copyOf(arg.getExtraXcodeFiles())); } if (bundle.isPresent() && isFocusedOnTarget) { HasAppleBundleFields bundleArg = bundle.get().getConstructorArg(); mutator.setInfoPlist(Optional.of(bundleArg.getInfoPlist())); } mutator.setBridgingHeader(arg.getBridgingHeader()); if (options.shouldCreateDirectoryStructure() && isFocusedOnTarget) { mutator.setTargetGroupPath( RichStream.from(buildTarget.getBasePath()).map(Object::toString).toImmutableList()); } if (!recursiveAssetCatalogs.isEmpty() && isFocusedOnTarget) { mutator.setRecursiveAssetCatalogs(recursiveAssetCatalogs); } if (!directAssetCatalogs.isEmpty() && isFocusedOnTarget) { mutator.setDirectAssetCatalogs(directAssetCatalogs); } FluentIterable<TargetNode<?>> depTargetNodes = collectRecursiveLibraryDepTargets(targetNode); if (includeFrameworks && isFocusedOnTarget) { if (!options.shouldAddLinkedLibrariesAsFlags()) { mutator.setFrameworks(getSytemFrameworksLibsForTargetNode(targetNode)); } if (sharedLibraryToBundle.isPresent()) { // Replace target nodes of libraries which are actually constituents of embedded // frameworks to the bundle representing the embedded framework. // This will be converted to a reference to the xcode build product for the embedded // framework rather than the dylib depTargetNodes = swapSharedLibrariesForBundles(depTargetNodes, sharedLibraryToBundle.get()); } ImmutableSet<PBXFileReference> targetNodeDeps = filterRecursiveLibraryDependenciesForLinkerPhase( depTargetNodes); if (isTargetNodeApplicationTestTarget(targetNode, bundleLoaderNode)) { ImmutableSet<PBXFileReference> bundleLoaderDeps = bundleLoaderNode.isPresent() ? collectRecursiveLibraryDependencies(bundleLoaderNode.get()) : ImmutableSet.of(); mutator.setArchives(Sets.difference(targetNodeDeps, bundleLoaderDeps)); } else { mutator.setArchives(targetNodeDeps); } } if (isFocusedOnTarget) { ImmutableSet<TargetNode<?>> swiftDepTargets = filterRecursiveLibraryDepTargetsWithSwiftSources( depTargetNodes); if (!includeFrameworks && !swiftDepTargets.isEmpty()) { // If the current target, which is non-shared (e.g., static lib), depends on other focused // targets which include Swift code, we must ensure those are treated as dependencies so // that Xcode builds the targets in the correct order. Unfortunately, those deps can be // part of other projects which would require cross-project references. // // Thankfully, there's an easy workaround because we can just create a phony copy phase // which depends on the outputs of the deps (i.e., the static libs). The copy phase // will effectively say "Copy libX.a from Products Dir into Products Dir" which is a nop. // To be on the safe side, we're explicitly marking the copy phase as only running for // deployment postprocessing (i.e., "Copy only when installing") and disabling // deployment postprocessing (it's enabled by default for release builds). CopyFilePhaseDestinationSpec.Builder destSpecBuilder = CopyFilePhaseDestinationSpec.builder(); destSpecBuilder.setDestination(PBXCopyFilesBuildPhase.Destination.PRODUCTS); PBXCopyFilesBuildPhase copyFiles = new PBXCopyFilesBuildPhase(destSpecBuilder.build()); copyFiles.setRunOnlyForDeploymentPostprocessing(Optional.of(Boolean.TRUE)); copyFiles.setName(Optional.of("Fake Swift Dependencies (Copy Files Phase)")); ImmutableSet<PBXFileReference> swiftDepsFileRefs = targetNodesSetToPBXFileReference( swiftDepTargets); for (PBXFileReference fileRef : swiftDepsFileRefs) { PBXBuildFile buildFile = new PBXBuildFile(fileRef); copyFiles.getFiles().add(buildFile); } swiftDepsSettingsBuilder.put("DEPLOYMENT_POSTPROCESSING", "NO"); mutator.setSwiftDependenciesBuildPhase(copyFiles); } if (includeFrameworks && !swiftDepTargets.isEmpty() && shouldEmbedSwiftRuntimeInBundleTarget(bundle) && swiftBuckConfig.getProjectEmbedRuntime()) { // This is a binary that transitively depends on a library that uses Swift. We must ensure // that the Swift runtime is bundled. swiftDepsSettingsBuilder.put("ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); } if (includeFrameworks && !swiftDepTargets.isEmpty() && swiftBuckConfig.getProjectAddASTPaths()) { for (TargetNode<?> swiftNode : swiftDepTargets) { String swiftModulePath = String.format( "${BUILT_PRODUCTS_DIR}/%s.swiftmodule/${CURRENT_ARCH}.swiftmodule", getModuleName(swiftNode)); swiftDebugLinkerFlagsBuilder.add("-Xlinker"); swiftDebugLinkerFlagsBuilder.add("-add_ast_path"); swiftDebugLinkerFlagsBuilder.add("-Xlinker"); swiftDebugLinkerFlagsBuilder.add(swiftModulePath); } } } // TODO(Task #3772930): Go through all dependencies of the rule // and add any shell script rules here ImmutableList.Builder<TargetNode<?>> preScriptPhasesBuilder = ImmutableList.builder(); ImmutableList.Builder<TargetNode<?>> postScriptPhasesBuilder = ImmutableList.builder(); if (bundle.isPresent() && targetNode != bundle.get() && isFocusedOnTarget) { collectBuildScriptDependencies(targetGraph.getAll(bundle.get().getDeclaredDeps()), preScriptPhasesBuilder, postScriptPhasesBuilder); } collectBuildScriptDependencies(targetGraph.getAll(targetNode.getDeclaredDeps()), preScriptPhasesBuilder, postScriptPhasesBuilder); if (isFocusedOnTarget) { ImmutableList<TargetNode<?>> preScriptPhases = preScriptPhasesBuilder.build(); ImmutableList<TargetNode<?>> postScriptPhases = postScriptPhasesBuilder.build(); mutator.setPreBuildRunScriptPhasesFromTargetNodes(preScriptPhases, actionGraphBuilderForNode::apply); if (copyFilesPhases.isPresent()) { mutator.setCopyFilesPhases(copyFilesPhases.get()); } mutator.setPostBuildRunScriptPhasesFromTargetNodes(postScriptPhases, actionGraphBuilderForNode::apply); ImmutableList<TargetNode<?>> scriptPhases = Stream .concat(preScriptPhases.stream(), postScriptPhases.stream()) .collect(ImmutableList.toImmutableList()); mutator.collectFilesToCopyInXcode(filesToCopyInXcodeBuilder, scriptPhases, projectCell, actionGraphBuilderForNode::apply); } } NewNativeTargetProjectMutator.Result targetBuilderResult = mutator.buildTargetAndAddToProject(project, isFocusedOnTarget); PBXNativeTarget target = targetBuilderResult.target; Optional<PBXGroup> targetGroup = targetBuilderResult.targetGroup; extraSettingsBuilder.putAll(swiftDepsSettingsBuilder.build()); setAppIconSettings(recursiveAssetCatalogs, directAssetCatalogs, buildTarget, defaultSettingsBuilder); setLaunchImageSettings(recursiveAssetCatalogs, directAssetCatalogs, buildTarget, defaultSettingsBuilder); ImmutableSortedMap<Path, SourcePath> publicCxxHeaders = getPublicCxxHeaders(targetNode); if (isModularAppleLibrary(targetNode) && isFrameworkProductType(productType)) { // Modular frameworks should not include Buck-generated hmaps as they break the VFS overlay // that's generated by Xcode and consequently, all headers part of a framework's umbrella // header fail the modularity test, as they're expected to be mapped by the VFS layer under // $BUILT_PRODUCTS_DIR/Module.framework/Versions/A/Headers. publicCxxHeaders = ImmutableSortedMap.of(); } if (!options.shouldGenerateHeaderSymlinkTreesOnly()) { if (isFocusedOnTarget) { SourceTreePath buckFilePath = new SourceTreePath(PBXReference.SourceTree.SOURCE_ROOT, pathRelativizer.outputPathToBuildTargetPath(buildTarget).resolve(buildFileName), Optional.empty()); PBXFileReference buckReference = targetGroup.get() .getOrCreateFileReferenceBySourceTreePath(buckFilePath); buckReference.setExplicitFileType(Optional.of("text.script.python")); } // Watch dependencies need to have explicit target dependencies setup in order for Xcode to // build them properly within the IDE. It is unable to match the implicit dependency because // of the different in flavor between the targets (iphoneos vs watchos). if (bundle.isPresent() && isFocusedOnTarget) { collectProjectTargetWatchDependencies(targetNode.getBuildTarget().getFlavorPostfix(), target, targetGraph.getAll(bundle.get().getExtraDeps())); } // -- configurations extraSettingsBuilder.put("TARGET_NAME", buildTargetName).put("SRCROOT", pathRelativizer.outputPathToBuildTargetPath(buildTarget).toString()); if (productType == ProductTypes.UI_TEST && isFocusedOnTarget) { if (bundleLoaderNode.isPresent()) { BuildTarget testTarget = bundleLoaderNode.get().getBuildTarget(); extraSettingsBuilder.put("TEST_TARGET_NAME", getXcodeTargetName(testTarget)); addPBXTargetDependency(target, testTarget); } else { throw new HumanReadableException( "The test rule '%s' is configured with 'is_ui_test' but has no test_host_app", buildTargetName); } } else if (bundleLoaderNode.isPresent() && isFocusedOnTarget) { TargetNode<AppleBundleDescriptionArg> bundleLoader = bundleLoaderNode.get(); String bundleLoaderProductName = getProductName(bundleLoader); String bundleLoaderBundleName = bundleLoaderProductName + "." + getExtensionString(bundleLoader.getConstructorArg().getExtension()); // NOTE(grp): This is a hack. We need to support both deep (OS X) and flat (iOS) // style bundles for the bundle loader, but at this point we don't know what platform // the bundle loader (or current target) is going to be built for. However, we can be // sure that it's the same as the target (presumably a test) we're building right now. // // Using that knowledge, we can do build setting tricks to defer choosing the bundle // loader path until Xcode build time, when the platform is known. There's no build // setting that conclusively says whether the current platform uses deep bundles: // that would be too easy. But in the cases we care about (unit test bundles), the // current bundle will have a style matching the style of the bundle loader app, so // we can take advantage of that to do the determination. // // Unfortunately, the build setting for the bundle structure (CONTENTS_FOLDER_PATH) // includes the WRAPPER_NAME, so we can't just interpolate that in. Instead, we have // to use another trick with build setting operations and evaluation. By using the // $(:file) operation, we can extract the last component of the contents path: either // "Contents" or the current bundle name. Then, we can interpolate with that expected // result in the build setting name to conditionally choose a different loader path. // The conditional that decides which path is used. This is a complex Xcode build setting // expression that expands to one of two values, depending on the last path component of // the CONTENTS_FOLDER_PATH variable. As described above, this will be either "Contents" // for deep bundles or the bundle file name itself for flat bundles. Finally, to santiize // the potentially invalid build setting names from the bundle file name, it converts that // to an identifier. We rely on BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_<bundle file name> // being undefined (and thus expanding to nothing) for the path resolution to work. // // The operations on the CONTENTS_FOLDER_PATH are documented here: // http://codeworkshop.net/posts/xcode-build-setting-transformations String bundleLoaderOutputPathConditional = "$(BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_$(CONTENTS_FOLDER_PATH:file:identifier))"; // If the $(CONTENTS_FOLDER_PATH:file:identifier) expands to this, we add the deep bundle // path into the bundle loader. See above for the case when it will expand to this value. extraSettingsBuilder.put("BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_Contents", Joiner.on('/').join(getTargetOutputPath(bundleLoader), bundleLoaderBundleName, "Contents/MacOS", bundleLoaderProductName)); extraSettingsBuilder.put( "BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_" + getProductName(bundle.get()) + "_" + getExtensionString(bundle.get().getConstructorArg().getExtension()), Joiner.on('/').join(getTargetOutputPath(bundleLoader), bundleLoaderBundleName, bundleLoaderProductName)); extraSettingsBuilder.put("BUNDLE_LOADER", bundleLoaderOutputPathConditional).put("TEST_HOST", "$(BUNDLE_LOADER)"); addPBXTargetDependency(target, bundleLoader.getBuildTarget()); } if (infoPlistOptional.isPresent()) { Path infoPlistPath = pathRelativizer.outputDirToRootRelative(infoPlistOptional.get()); extraSettingsBuilder.put("INFOPLIST_FILE", infoPlistPath.toString()); } if (arg.getBridgingHeader().isPresent()) { Path bridgingHeaderPath = pathRelativizer .outputDirToRootRelative(resolveSourcePath(arg.getBridgingHeader().get())); extraSettingsBuilder.put("SWIFT_OBJC_BRIDGING_HEADER", Joiner.on('/').join("$(SRCROOT)", bridgingHeaderPath.toString())); } swiftVersion.ifPresent(s -> extraSettingsBuilder.put("SWIFT_VERSION", s)); swiftVersion.ifPresent(s -> extraSettingsBuilder.put("PRODUCT_MODULE_NAME", getModuleName(targetNode))); if (hasSwiftVersionArg && containsSwiftCode && isFocusedOnTarget) { extraSettingsBuilder.put("SWIFT_OBJC_INTERFACE_HEADER_NAME", getSwiftObjCGeneratedHeaderName(buildTargetNode)); if (swiftBuckConfig.getProjectWMO()) { // We must disable "Index While Building" as there's a bug in the LLVM infra which // makes the compilation fail. extraSettingsBuilder.put("COMPILER_INDEX_STORE_ENABLE", "NO"); // This is a hidden Xcode setting which is needed for two reasons: // - Stops Xcode adding .o files for each Swift compilation unit to dependency db // which is used during linking (which will fail with WMO). // - Turns on WMO itself. // // Note that setting SWIFT_OPTIMIZATION_LEVEL (which is public) to '-Owholemodule' // ends up crashing the Swift compiler for some reason while this doesn't. extraSettingsBuilder.put("SWIFT_WHOLE_MODULE_OPTIMIZATION", "YES"); } } Optional<SourcePath> prefixHeaderOptional = getPrefixHeaderSourcePath(targetNode.getConstructorArg()); if (prefixHeaderOptional.isPresent()) { Path prefixHeaderRelative = resolveSourcePath(prefixHeaderOptional.get()); Path prefixHeaderPath = pathRelativizer.outputDirToRootRelative(prefixHeaderRelative); extraSettingsBuilder.put("GCC_PREFIX_HEADER", prefixHeaderPath.toString()); extraSettingsBuilder.put("GCC_PRECOMPILE_PREFIX_HEADER", "YES"); } boolean shouldSetUseHeadermap = false; if (isModularAppleLibrary) { extraSettingsBuilder.put("CLANG_ENABLE_MODULES", "YES"); extraSettingsBuilder.put("DEFINES_MODULE", "YES"); if (isFrameworkProductType(productType)) { // Modular frameworks need to have both USE_HEADERMAP enabled so that Xcode generates // .framework VFS overlays, in modular libraries we handle this in buck shouldSetUseHeadermap = true; } } extraSettingsBuilder.put("USE_HEADERMAP", shouldSetUseHeadermap ? "YES" : "NO"); defaultSettingsBuilder.put("REPO_ROOT", projectFilesystem.getRootPath().toAbsolutePath().normalize().toString()); if (hasSwiftVersionArg && containsSwiftCode && isFocusedOnTarget) { // We need to be able to control the directory where Xcode places the derived sources, so // that the Obj-C Generated Header can be included in the header map and imported through // a framework-style import like <Module/Module-Swift.h> Path derivedSourcesDir = getDerivedSourcesDirectoryForBuildTarget(buildTarget, projectFilesystem); Path derivedSourceDirRelativeToProjectRoot = pathRelativizer .outputDirToRootRelative(derivedSourcesDir); defaultSettingsBuilder.put("DERIVED_FILE_DIR", derivedSourceDirRelativeToProjectRoot.toString()); } defaultSettingsBuilder.put(PRODUCT_NAME, getProductName(buildTargetNode)); bundle.ifPresent(bundleNode -> defaultSettingsBuilder.put("WRAPPER_EXTENSION", getExtensionString(bundleNode.getConstructorArg().getExtension()))); // We use BUILT_PRODUCTS_DIR as the root for the everything being built. Target- // specific output is placed within CONFIGURATION_BUILD_DIR, inside BUILT_PRODUCTS_DIR. // That allows Copy Files build phases to reference files in the CONFIGURATION_BUILD_DIR // of other targets by using paths relative to the target-independent BUILT_PRODUCTS_DIR. defaultSettingsBuilder.put("BUILT_PRODUCTS_DIR", // $EFFECTIVE_PLATFORM_NAME starts with a dash, so this expands to something like: // $SYMROOT/Debug-iphonesimulator Joiner.on('/').join("$SYMROOT", "$CONFIGURATION$EFFECTIVE_PLATFORM_NAME")); defaultSettingsBuilder.put("CONFIGURATION_BUILD_DIR", "$BUILT_PRODUCTS_DIR"); boolean nodeIsAppleLibrary = targetNode.getDescription() instanceof AppleLibraryDescription; boolean nodeIsCxxLibrary = targetNode.getDescription() instanceof CxxLibraryDescription; if (!bundle.isPresent() && (nodeIsAppleLibrary || nodeIsCxxLibrary)) { defaultSettingsBuilder.put("EXECUTABLE_PREFIX", "lib"); } if (isFocusedOnTarget) { ImmutableSet<Path> recursiveHeaderSearchPaths = collectRecursiveHeaderSearchPaths(targetNode); ImmutableSet<Path> headerMapBases = collectRecursiveHeaderMapBases(targetNode); ImmutableMap.Builder<String, String> appendConfigsBuilder = ImmutableMap.builder(); appendConfigsBuilder.putAll(getFrameworkAndLibrarySearchPathConfigs(targetNode, includeFrameworks)); appendConfigsBuilder.put("HEADER_SEARCH_PATHS", Joiner.on(' ').join(Iterables.concat(recursiveHeaderSearchPaths, headerMapBases))); if (hasSwiftVersionArg && containsSwiftCode && isFocusedOnTarget) { ImmutableSet<Path> swiftIncludePaths = collectRecursiveSwiftIncludePaths(targetNode); Stream<String> allValues = Streams.concat(Stream.of("$BUILT_PRODUCTS_DIR"), Streams .stream(swiftIncludePaths).map((path) -> path.toString()).map(Escaper.BASH_ESCAPER)); appendConfigsBuilder.put("SWIFT_INCLUDE_PATHS", allValues.collect(Collectors.joining(" "))); } ImmutableList.Builder<String> targetSpecificSwiftFlags = ImmutableList.builder(); Optional<TargetNode<SwiftCommonArg>> swiftTargetNode = TargetNodes.castArg(targetNode, SwiftCommonArg.class); targetSpecificSwiftFlags.addAll(swiftTargetNode.map( x -> convertStringWithMacros(targetNode, x.getConstructorArg().getSwiftCompilerFlags())) .orElse(ImmutableList.of())); if (containsSwiftCode && isModularAppleLibrary && publicCxxHeaders.size() > 0) { targetSpecificSwiftFlags.addAll(collectModularTargetSpecificSwiftFlags(targetNode)); } ImmutableList<String> testingOverlay = getFlagsForExcludesForModulesUnderTests(targetNode); Iterable<String> otherSwiftFlags = Iterables.concat( swiftBuckConfig.getCompilerFlags().orElse(DEFAULT_SWIFTFLAGS), targetSpecificSwiftFlags.build()); Iterable<String> otherCFlags = ImmutableList.<String>builder() .addAll(cxxBuckConfig.getCflags().orElse(DEFAULT_CFLAGS)) .addAll(cxxBuckConfig.getCppflags().orElse(DEFAULT_CPPFLAGS)) .addAll(convertStringWithMacros(targetNode, collectRecursiveExportedPreprocessorFlags(targetNode))) .addAll(convertStringWithMacros(targetNode, targetNode.getConstructorArg().getCompilerFlags())) .addAll(convertStringWithMacros(targetNode, targetNode.getConstructorArg().getPreprocessorFlags())) .addAll(convertStringWithMacros(targetNode, collectRecursiveSystemPreprocessorFlags(targetNode))) .addAll(testingOverlay).build(); Iterable<String> otherCxxFlags = ImmutableList.<String>builder() .addAll(cxxBuckConfig.getCxxflags().orElse(DEFAULT_CXXFLAGS)) .addAll(cxxBuckConfig.getCxxppflags().orElse(DEFAULT_CXXPPFLAGS)) .addAll(convertStringWithMacros(targetNode, collectRecursiveExportedPreprocessorFlags(targetNode))) .addAll(convertStringWithMacros(targetNode, targetNode.getConstructorArg().getCompilerFlags())) .addAll(convertStringWithMacros(targetNode, targetNode.getConstructorArg().getPreprocessorFlags())) .addAll(convertStringWithMacros(targetNode, collectRecursiveSystemPreprocessorFlags(targetNode))) .addAll(testingOverlay).build(); appendConfigsBuilder .put("OTHER_SWIFT_FLAGS", Streams.stream(otherSwiftFlags).map(Escaper.BASH_ESCAPER) .collect(Collectors.joining(" "))) .put("OTHER_CFLAGS", Streams.stream(otherCFlags).map(Escaper.BASH_ESCAPER) .collect(Collectors.joining(" "))) .put("OTHER_CPLUSPLUSFLAGS", Streams.stream(otherCxxFlags).map(Escaper.BASH_ESCAPER) .collect(Collectors.joining(" "))); Iterable<String> otherLdFlags = ImmutableList.<String>builder() .addAll(cxxBuckConfig.getLdflags().orElse(DEFAULT_LDFLAGS)) .addAll(appleConfig.linkAllObjC() ? ImmutableList.of("-ObjC") : ImmutableList.of()) .addAll(convertStringWithMacros(targetNode, Iterables.concat(targetNode.getConstructorArg().getLinkerFlags(), collectRecursiveExportedLinkerFlags(targetNode)))) .addAll(swiftDebugLinkerFlagsBuilder.build()).build(); updateOtherLinkerFlagsForOptions(targetNode, bundleLoaderNode, appendConfigsBuilder, otherLdFlags); ImmutableMultimap<String, ImmutableList<String>> platformFlags = convertPlatformFlags(targetNode, Iterables.concat( ImmutableList.of(targetNode.getConstructorArg().getPlatformCompilerFlags()), ImmutableList.of(targetNode.getConstructorArg().getPlatformPreprocessorFlags()), collectRecursiveExportedPlatformPreprocessorFlags(targetNode))); for (String platform : platformFlags.keySet()) { appendConfigsBuilder.put(generateConfigKey("OTHER_CFLAGS", platform), Streams.stream(Iterables.transform( Iterables.concat(otherCFlags, Iterables.concat(platformFlags.get(platform))), Escaper.BASH_ESCAPER::apply)).collect( Collectors.joining(" "))) .put(generateConfigKey("OTHER_CPLUSPLUSFLAGS", platform), Streams.stream(Iterables.transform( Iterables.concat(otherCxxFlags, Iterables.concat(platformFlags.get(platform))), Escaper.BASH_ESCAPER::apply)).collect(Collectors.joining(" "))); } ImmutableMultimap<String, ImmutableList<String>> platformLinkerFlags = convertPlatformFlags( targetNode, Iterables.concat(ImmutableList.of(targetNode.getConstructorArg().getPlatformLinkerFlags()), collectRecursiveExportedPlatformLinkerFlags(targetNode))); for (String platform : platformLinkerFlags.keySet()) { appendConfigsBuilder .put(generateConfigKey("OTHER_LDFLAGS", platform), Streams.stream( Iterables .transform( Iterables.concat(otherLdFlags, Iterables.concat( platformLinkerFlags.get(platform))), Escaper.BASH_ESCAPER::apply)) .collect(Collectors.joining(" "))); } ImmutableMap<String, String> appendedConfig = appendConfigsBuilder.build(); Optional<ImmutableSortedMap<String, ImmutableMap<String, String>>> configs = getXcodeBuildConfigurationsForTargetNode( targetNode); setTargetBuildConfigurations(buildTarget, target, project.getMainGroup(), configs.get(), getTargetCxxBuildConfigurationForTargetNode(targetNode, appendedConfig), extraSettingsBuilder.build(), defaultSettingsBuilder.build(), appendedConfig); } } Optional<String> moduleName = isModularAppleLibrary ? Optional.of(getModuleName(targetNode)) : Optional.empty(); // -- phases createHeaderSymlinkTree(publicCxxHeaders, getSwiftPublicHeaderMapEntriesForTarget(targetNode), moduleName, getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PUBLIC), arg.getXcodePublicHeadersSymlinks().orElse(cxxBuckConfig.getPublicHeadersSymlinksEnabled()) || !options.shouldUseHeaderMaps() || isModularAppleLibrary, !shouldMergeHeaderMaps(), options.shouldGenerateMissingUmbrellaHeader()); if (isFocusedOnTarget) { createHeaderSymlinkTree(getPrivateCxxHeaders(targetNode), ImmutableMap.of(), // private interfaces never have a modulemap Optional.empty(), getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PRIVATE), arg.getXcodePrivateHeadersSymlinks().orElse(cxxBuckConfig.getPrivateHeadersSymlinksEnabled()) || !options.shouldUseHeaderMaps(), options.shouldUseHeaderMaps(), options.shouldGenerateMissingUmbrellaHeader()); } Optional<TargetNode<AppleNativeTargetDescriptionArg>> appleTargetNode = TargetNodes.castArg(targetNode, AppleNativeTargetDescriptionArg.class); if (appleTargetNode.isPresent() && isFocusedOnTarget && !options.shouldGenerateHeaderSymlinkTreesOnly()) { // Use Core Data models from immediate dependencies only. addCoreDataModelsIntoTarget(appleTargetNode.get(), targetGroup.get()); addSceneKitAssetsIntoTarget(appleTargetNode.get(), targetGroup.get()); } if (bundle.isPresent() && isFocusedOnTarget && !options.shouldGenerateHeaderSymlinkTreesOnly()) { addEntitlementsPlistIntoTarget(bundle.get(), targetGroup.get()); } return target; }