예제 #1
0
  @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;
  }
예제 #2
0
    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();
    }
예제 #3
0
  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;
  }
예제 #5
0
 /**
  * @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);
  }
예제 #7
0
  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;
  }
예제 #8
0
 @Override
 public HasAndroidResourceDeps apply(BuildRule rule) {
   return (HasAndroidResourceDeps) rule.getBuildable();
 }