@VisibleForTesting List<Module> createModulesForProjectConfigs() throws IOException { DependencyGraph dependencyGraph = partialGraph.getDependencyGraph(); List<Module> modules = Lists.newArrayList(); // Convert the project_config() targets into modules and find the union of all jars passed to // no_dx. ImmutableSet.Builder<Path> noDxJarsBuilder = ImmutableSet.builder(); for (BuildTarget target : partialGraph.getTargets()) { BuildRule buildRule = dependencyGraph.findBuildRuleByTarget(target); ProjectConfig projectConfig = (ProjectConfig) buildRule.getBuildable(); BuildRule srcRule = projectConfig.getSrcRule(); if (srcRule != null) { Buildable buildable = srcRule.getBuildable(); if (buildable instanceof AndroidBinary) { AndroidBinary androidBinary = (AndroidBinary) buildable; AndroidDexTransitiveDependencies binaryDexTransitiveDependencies = androidBinary.findDexTransitiveDependencies(); noDxJarsBuilder.addAll(binaryDexTransitiveDependencies.noDxClasspathEntries); } } Module module = createModuleForProjectConfig(projectConfig); modules.add(module); } ImmutableSet<Path> noDxJars = noDxJarsBuilder.build(); // Update module dependencies to apply scope="PROVIDED", where appropriate. markNoDxJarsAsProvided(modules, noDxJars); return modules; }
private SerializablePrebuiltJarRule(BuildRule rule) { Preconditions.checkState(rule.getBuildable() instanceof PrebuiltJar); this.name = getIntellijNameForRule(rule, null /* basePathToAliasMap */); PrebuiltJar prebuiltJar = (PrebuiltJar) rule.getBuildable(); this.binaryJar = prebuiltJar.getBinaryJar().toString(); if (prebuiltJar.getSourceJar().isPresent()) { this.sourceJar = prebuiltJar.getSourceJar().get().toString(); } else { this.sourceJar = null; } this.javadocUrl = prebuiltJar.getJavadocUrl().orNull(); }
public Result createBuildableForAndroidResources( BuildRuleResolver ruleResolver, boolean createBuildableIfEmptyDeps) { ImmutableSortedSet<BuildRule> originalDeps = originalBuildRuleParams.getDeps(); ImmutableList<HasAndroidResourceDeps> androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(originalDeps); if (androidResourceDeps.isEmpty() && !createBuildableIfEmptyDeps) { return new Result(originalBuildRuleParams, Optional.<DummyRDotJava>absent()); } BuildRule dummyRDotJavaBuildRule = ruleResolver.buildAndAddToIndex( DummyRDotJava.newDummyRDotJavaBuildableBuilder(buildRuleBuilderParams) .setBuildTarget(dummyRDotJavaBuildTarget) .setAndroidResourceDeps(androidResourceDeps)); final DummyRDotJava dummyRDotJava = (DummyRDotJava) dummyRDotJavaBuildRule.getBuildable(); ImmutableSortedSet<BuildRule> totalDeps = ImmutableSortedSet.<BuildRule>naturalOrder() .addAll(originalDeps) .add(dummyRDotJavaBuildRule) .build(); BuildRuleParams newBuildRuleParams = originalBuildRuleParams.copyWithChangedDeps(totalDeps); return new Result(newBuildRuleParams, Optional.of(dummyRDotJava)); }
/** * Creates/finds the set of build rules that correspond to pre-dex'd artifacts that should be * merged to create the final classes.dex for the APK. * * <p>This method may modify {@code ruleResolver}, inserting new rules into its index. */ @VisibleForTesting BuildRule createPreDexMergeRule(UberRDotJava uberRDotJava) { ImmutableSet.Builder<DexProducedFromJavaLibrary> preDexDeps = ImmutableSet.builder(); ImmutableSet<JavaLibrary> transitiveJavaDeps = Classpaths.getClasspathEntries(originalDeps).keySet(); for (JavaLibrary javaLibrary : transitiveJavaDeps) { // If the rule has no output file (which happens when a java_library has no srcs or // resources, but export_deps is true), then there will not be anything to dx. if (javaLibrary.getPathToOutputFile() == null) { continue; } // If the rule is in the no_dx list, then do not pre-dex it. if (buildRulesToExcludeFromDex.contains(javaLibrary.getBuildTarget())) { continue; } // See whether the corresponding IntermediateDexRule has already been added to the // ruleResolver. BuildTarget originalTarget = javaLibrary.getBuildTarget(); BuildTarget preDexTarget = new BuildTarget(originalTarget.getBaseName(), originalTarget.getShortName(), DEX_FLAVOR); BuildRule preDexRule = ruleResolver.get(preDexTarget); if (preDexRule != null) { preDexDeps.add((DexProducedFromJavaLibrary) preDexRule.getBuildable()); continue; } // Create the IntermediateDexRule and add it to both the ruleResolver and preDexDeps. DexProducedFromJavaLibrary preDex = new DexProducedFromJavaLibrary(preDexTarget, javaLibrary); buildRuleAndAddToIndex( preDex, BuildRuleType.PRE_DEX, preDexTarget, ImmutableSortedSet.of(ruleResolver.get(javaLibrary.getBuildTarget()))); preDexDeps.add(preDex); } ImmutableSet<DexProducedFromJavaLibrary> allPreDexDeps = preDexDeps.build(); BuildTarget buildTargetForDexMerge = createBuildTargetWithFlavor(DEX_MERGE_FLAVOR); PreDexMerge preDexMerge = new PreDexMerge( buildTargetForDexMerge, primaryDexPath, dexSplitMode, allPreDexDeps, uberRDotJava); BuildRule preDexMergeBuildRule = buildRuleAndAddToIndex( preDexMerge, BuildRuleType.DEX_MERGE, buildTargetForDexMerge, getDexMergeDeps(uberRDotJava, allPreDexDeps)); return preDexMergeBuildRule; }
/** * @param rule whose corresponding IntelliJ module name will be returned * @param basePathToAliasMap may be null if rule is a {@link PrebuiltJar} */ private static String getIntellijNameForRule( BuildRule rule, @Nullable Map<String, String> basePathToAliasMap) { // Get basis for the library/module name. String name; if (rule.getBuildable() instanceof PrebuiltJar) { PrebuiltJar prebuiltJar = (PrebuiltJar) rule.getBuildable(); String binaryJar = prebuiltJar.getBinaryJar().toString(); return getIntellijNameForBinaryJar(binaryJar); } else { String basePath = rule.getBuildTarget().getBasePath(); if (basePathToAliasMap.containsKey(basePath)) { name = basePathToAliasMap.get(basePath); } else { name = rule.getBuildTarget().getBasePath(); name = name.replace('/', '_'); // Must add a prefix to ensure that name is non-empty. name = "module_" + name; } // Normalize name. return normalizeIntelliJName(name); } }
EnhancementResult createAdditionalBuildables() { ImmutableSortedSet.Builder<BuildRule> enhancedDeps = ImmutableSortedSet.naturalOrder(); enhancedDeps.addAll(originalDeps); ImmutableSortedSet<BuildRule> resourceRules = getAndroidResourcesAsRules(); BuildTarget buildTargetForFilterResources = createBuildTargetWithFlavor(RESOURCES_FILTER_FLAVOR); FilteredResourcesProvider filteredResourcesProvider; boolean needsResourceFiltering = resourceFilter.isEnabled() || resourceCompressionMode.isStoreStringsAsAssets(); if (needsResourceFiltering) { ResourcesFilter resourcesFilter = new ResourcesFilter( buildTargetForFilterResources, androidResourceDepsFinder, resourceCompressionMode, resourceFilter); BuildRule resourcesFilterBuildRule = buildRuleAndAddToIndex( resourcesFilter, BuildRuleType.RESOURCES_FILTER, buildTargetForFilterResources, resourceRules); filteredResourcesProvider = resourcesFilter; enhancedDeps.add(resourcesFilterBuildRule); resourceRules = ImmutableSortedSet.of(resourcesFilterBuildRule); } else { filteredResourcesProvider = new IdentityResourcesProvider(androidResourceDepsFinder); } BuildTarget buildTargetForUberRDotJava = createBuildTargetWithFlavor(UBER_R_DOT_JAVA_FLAVOR); UberRDotJava uberRDotJava = new UberRDotJava( buildTargetForUberRDotJava, filteredResourcesProvider, javacOptions, androidResourceDepsFinder, shouldPreDex, shouldBuildStringSourceMap); BuildRule uberRDotJavaBuildRule = buildRuleAndAddToIndex( uberRDotJava, BuildRuleType.UBER_R_DOT_JAVA, buildTargetForUberRDotJava, resourceRules); enhancedDeps.add(uberRDotJavaBuildRule); Optional<PackageStringAssets> packageStringAssets = Optional.absent(); if (resourceCompressionMode.isStoreStringsAsAssets()) { BuildTarget buildTargetForPackageStringAssets = createBuildTargetWithFlavor(PACKAGE_STRING_ASSETS_FLAVOR); packageStringAssets = Optional.of( new PackageStringAssets( buildTargetForPackageStringAssets, filteredResourcesProvider, uberRDotJava)); BuildRule packageStringAssetsRule = buildRuleAndAddToIndex( packageStringAssets.get(), BuildRuleType.PACKAGE_STRING_ASSETS, buildTargetForPackageStringAssets, ImmutableSortedSet.of(uberRDotJavaBuildRule)); enhancedDeps.add(packageStringAssetsRule); } // Create the AaptPackageResourcesBuildable. BuildTarget buildTargetForAapt = createBuildTargetWithFlavor(AAPT_PACKAGE_FLAVOR); AaptPackageResources aaptPackageResources = new AaptPackageResources( buildTargetForAapt, manifest, filteredResourcesProvider, androidResourceDepsFinder.getAndroidTransitiveDependencies(), packageType, cpuFilters); BuildRule aaptPackageResourcesBuildRule = buildRuleAndAddToIndex( aaptPackageResources, BuildRuleType.AAPT_PACKAGE, buildTargetForAapt, getAdditionalAaptDeps(resourceRules)); enhancedDeps.add(aaptPackageResourcesBuildRule); Optional<PreDexMerge> preDexMerge = Optional.absent(); if (shouldPreDex) { BuildRule preDexMergeRule = createPreDexMergeRule(uberRDotJava); preDexMerge = Optional.of((PreDexMerge) preDexMergeRule.getBuildable()); enhancedDeps.add(preDexMergeRule); } ImmutableSortedSet<BuildRule> finalDeps; Optional<ComputeExopackageDepsAbi> computeExopackageDepsAbi = Optional.absent(); if (exopackage) { BuildTarget buildTargetForAbiCalculation = createBuildTargetWithFlavor(CALCULATE_ABI_FLAVOR); computeExopackageDepsAbi = Optional.of( new ComputeExopackageDepsAbi( buildTargetForAbiCalculation, androidResourceDepsFinder, uberRDotJava, aaptPackageResources, packageStringAssets, preDexMerge, keystore)); BuildRule computeExopackageDepsAbiRule = buildRuleAndAddToIndex( computeExopackageDepsAbi.get(), BuildRuleType.EXOPACKAGE_DEPS_ABI, buildTargetForAbiCalculation, enhancedDeps.build()); finalDeps = ImmutableSortedSet.of(computeExopackageDepsAbiRule); } else { finalDeps = enhancedDeps.build(); } return new EnhancementResult( filteredResourcesProvider, uberRDotJava, aaptPackageResources, packageStringAssets, preDexMerge, computeExopackageDepsAbi, finalDeps); }
private Module createModuleForProjectConfig(ProjectConfig projectConfig) throws IOException { BuildRule projectRule = projectConfig.getProjectRule(); Buildable buildable = projectRule.getBuildable(); Preconditions.checkState( projectRule instanceof JavaLibrary || buildable instanceof JavaLibrary || buildable instanceof JavaBinary || buildable instanceof AndroidLibrary || buildable instanceof AndroidResource || buildable instanceof AndroidBinary || buildable instanceof NdkLibrary, "project_config() does not know how to process a src_target of type %s.", projectRule.getType().getName()); LinkedHashSet<DependentModule> dependencies = Sets.newLinkedHashSet(); final BuildTarget target = projectConfig.getBuildTarget(); Module module = new Module(projectRule, target); module.name = getIntellijNameForRule(projectRule); module.isIntelliJPlugin = projectConfig.getIsIntelliJPlugin(); String relativePath = projectConfig.getBuildTarget().getBasePathWithSlash(); module.pathToImlFile = String.format("%s%s.iml", relativePath, module.name); // List the module source as the first dependency. boolean includeSourceFolder = true; // Do the tests before the sources so they appear earlier in the classpath. When tests are run, // their classpath entries may be deliberately shadowing production classpath entries. // tests folder boolean hasSourceFoldersForTestRule = addSourceFolders( module, projectConfig.getTestRule(), projectConfig.getTestsSourceRoots(), true /* isTestSource */); // test dependencies BuildRule testRule = projectConfig.getTestRule(); if (testRule != null) { walkRuleAndAdd(testRule, true /* isForTests */, dependencies, projectConfig.getSrcRule()); } // src folder boolean hasSourceFoldersForSrcRule = addSourceFolders( module, projectConfig.getSrcRule(), projectConfig.getSourceRoots(), false /* isTestSource */); addRootExcludes(module, projectConfig.getSrcRule(), projectFilesystem); // At least one of src or tests should contribute a source folder unless this is an // non-library Android project with no source roots specified. if (!hasSourceFoldersForTestRule && !hasSourceFoldersForSrcRule) { includeSourceFolder = false; } // IntelliJ expects all Android projects to have a gen/ folder, even if there is no src/ // directory specified. boolean isAndroidRule = projectRule.getProperties().is(ANDROID); if (isAndroidRule) { boolean hasSourceFolders = !module.sourceFolders.isEmpty(); module.sourceFolders.add(SourceFolder.GEN); if (!hasSourceFolders) { includeSourceFolder = true; } } // src dependencies // Note that isForTests is false even if projectRule is the project_config's test_target. walkRuleAndAdd(projectRule, false /* isForTests */, dependencies, projectConfig.getSrcRule()); String basePathWithSlash = projectConfig.getBuildTarget().getBasePathWithSlash(); // Specify another path for intellij to generate gen/ for each android module, // so that it will not disturb our glob() rules. // To specify the location of gen, Intellij requires the relative path from // the base path of current build target. module.moduleGenPath = generateRelativeGenPath(basePathWithSlash).toString(); DependentModule jdkDependency; if (isAndroidRule) { // android details if (projectRule.getBuildable() instanceof NdkLibrary) { NdkLibrary ndkLibrary = (NdkLibrary) projectRule.getBuildable(); module.isAndroidLibraryProject = true; module.keystorePath = null; module.nativeLibs = Paths.get(relativePath).relativize(ndkLibrary.getLibraryPath()).toString(); } else if (projectRule.getBuildable() instanceof AndroidResource) { AndroidResource androidResource = (AndroidResource) projectRule.getBuildable(); module.resFolder = createRelativePath(androidResource.getRes(), target); module.isAndroidLibraryProject = true; module.keystorePath = null; } else if (projectRule.getBuildable() instanceof AndroidBinary) { AndroidBinary androidBinary = (AndroidBinary) projectRule.getBuildable(); module.resFolder = null; module.isAndroidLibraryProject = false; KeystoreProperties keystoreProperties = KeystoreProperties.createFromPropertiesFile( androidBinary.getKeystore().getPathToStore(), androidBinary.getKeystore().getPathToPropertiesFile(), projectFilesystem); // getKeystore() returns a path relative to the project root, but an IntelliJ module // expects the path to the keystore to be relative to the module root. module.keystorePath = Paths.get(relativePath).relativize(keystoreProperties.getKeystore()).toString(); } else { module.isAndroidLibraryProject = true; module.keystorePath = null; } module.hasAndroidFacet = true; module.proguardConfigPath = null; // If there is a default AndroidManifest.xml specified in .buckconfig, use it if // AndroidManifest.xml is not present in the root of the [Android] IntelliJ module. if (pathToDefaultAndroidManifest.isPresent()) { String androidManifest = basePathWithSlash + "AndroidManifest.xml"; if (!projectFilesystem.exists(androidManifest)) { String manifestPath = this.pathToDefaultAndroidManifest.get(); String rootPrefix = "//"; Preconditions.checkState( manifestPath.startsWith(rootPrefix), "Currently, we expect this option to start with '%s', " + "indicating that it is relative to the root of the repository.", rootPrefix); manifestPath = manifestPath.substring(rootPrefix.length()); String relativePathToManifest = Paths.get(basePathWithSlash).relativize(Paths.get(manifestPath)).toString(); // IntelliJ requires that the path start with a slash to indicate that it is relative to // the module. module.androidManifest = "/" + relativePathToManifest; } } // List this last so that classes from modules can shadow classes in the JDK. jdkDependency = DependentModule.newInheritedJdk(); } else { module.hasAndroidFacet = false; if (module.isIntelliJPlugin()) { jdkDependency = DependentModule.newIntelliJPluginJdk(); } else { jdkDependency = DependentModule.newStandardJdk(); } } // Assign the dependencies. module.dependencies = createDependenciesInOrder(includeSourceFolder, dependencies, jdkDependency); // Annotation processing generates sources for IntelliJ to consume, but does so outside // the module directory to avoid messing up globbing. JavaLibrary javaLibrary = null; if (projectRule.getBuildable() instanceof JavaLibrary) { javaLibrary = (JavaLibrary) projectRule.getBuildable(); } else if (projectRule instanceof JavaLibrary) { javaLibrary = (JavaLibrary) projectRule; } if (javaLibrary != null) { AnnotationProcessingData processingData = javaLibrary.getAnnotationProcessingData(); Path annotationGenSrc = processingData.getGeneratedSourceFolderName(); if (annotationGenSrc != null) { module.annotationGenPath = "/" + Paths.get(basePathWithSlash).relativize(annotationGenSrc).toString(); module.annotationGenIsForTest = !hasSourceFoldersForSrcRule; } } return module; }
@Override public HasAndroidResourceDeps apply(BuildRule rule) { return (HasAndroidResourceDeps) rule.getBuildable(); }