blob: cf2bf77c937662610909f614c3a83ed4bd194829 [file] [log] [blame]
package org.jetbrains.jps.android.builder;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.android.AndroidJpsUtil;
import org.jetbrains.jps.android.AndroidPlatform;
import org.jetbrains.jps.android.model.JpsAndroidModuleExtension;
import org.jetbrains.jps.builders.*;
import org.jetbrains.jps.builders.impl.BuildRootDescriptorImpl;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.module.JpsDependencyElement;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.module.JpsModuleDependency;
import java.io.File;
import java.util.*;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidPreDexBuildTarget extends BuildTarget<AndroidPreDexBuildTarget.MyRootDescriptor> {
private static final String ID = "only";
private final JpsProject myProject;
public static final String PRE_DEXED_LIBS_DIRECTORY_NAME = "pre_dexed_libs";
public AndroidPreDexBuildTarget(@NotNull JpsProject project) {
super(MyTargetType.INSTANCE);
myProject = project;
}
@Override
public String getId() {
return ID;
}
@Override
public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex) {
final List<BuildTarget<?>> result = new ArrayList<BuildTarget<?>>();
for (JpsModule module : myProject.getModules()) {
final JpsAndroidModuleExtension extension = AndroidJpsUtil.getExtension(module);
if (extension != null) {
if (extension.isLibrary()) {
result.add(new AndroidLibraryPackagingTarget(module));
}
else {
result.add(new AndroidAarDepsBuildTarget(module));
}
}
}
return result;
}
private static void fillDepsRecursively(@NotNull JpsModule root,
@NotNull Set<JpsModule> libModules,
@NotNull Set<String> externalJars,
@NotNull BuildDataPaths dataPaths,
@NotNull AndroidPlatform platform) {
for (String jarOrLibDirPath : AndroidJpsUtil.getExternalLibraries(dataPaths, root, platform, false, false, true)) {
final String path = FileUtil.toCanonicalPath(jarOrLibDirPath);
if (path != null) {
externalJars.add(path);
}
}
for (JpsDependencyElement dependencyElement : root.getDependenciesList().getDependencies()) {
if (dependencyElement instanceof JpsModuleDependency) {
final JpsModule depModule = ((JpsModuleDependency)dependencyElement).getModule();
if (depModule != null) {
final JpsAndroidModuleExtension depExtension = AndroidJpsUtil.getExtension(depModule);
if (depExtension != null && depExtension.isLibrary()) {
if (libModules.add(depModule)) {
fillDepsRecursively(depModule, libModules, externalJars, dataPaths, platform);
}
}
}
}
}
}
@NotNull
@Override
public List<AndroidPreDexBuildTarget.MyRootDescriptor> computeRootDescriptors(JpsModel model,
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex,
BuildDataPaths dataPaths) {
final List<AndroidPreDexBuildTarget.MyRootDescriptor> result =
new ArrayList<AndroidPreDexBuildTarget.MyRootDescriptor>();
final Set<JpsModule> libModules = new HashSet<JpsModule>();
final Set<String> externalJars = new HashSet<String>();
for (JpsModule module : myProject.getModules()) {
final JpsAndroidModuleExtension extension = AndroidJpsUtil.getExtension(module);
if (extension != null && !extension.isLibrary() && extension.isPreDexingEnabled()) {
final AndroidPlatform platform = AndroidJpsUtil.getAndroidPlatform(module, null, null);
if (platform != null) {
fillDepsRecursively(module, libModules, externalJars, dataPaths, platform);
}
}
}
for (JpsModule libModule : libModules) {
final File classesJarFile = new AndroidLibraryPackagingTarget(libModule).getOutputFile(dataPaths);
result.add(new MyRootDescriptor(this, classesJarFile, libModule.getName()));
}
for (String externalJarPath : externalJars) {
result.add(new MyRootDescriptor(this, new File(externalJarPath), null));
}
return result;
}
@Nullable
@Override
public AndroidPreDexBuildTarget.MyRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex) {
for (AndroidPreDexBuildTarget.MyRootDescriptor descriptor : rootIndex.getTargetRoots(this, null)) {
if (descriptor.getRootId().equals(rootId)) {
return descriptor;
}
}
return null;
}
@NotNull
@Override
public String getPresentableName() {
return "Android Pre-DEX";
}
@NotNull
@Override
public Collection<File> getOutputRoots(CompileContext context) {
return Collections.singletonList(getOutputFile(context));
}
@NotNull
public File getOutputFile(CompileContext context) {
return getOutputDir(context.getProjectDescriptor().dataManager.getDataPaths());
}
@NotNull
public static File getOutputDir(@NotNull BuildDataPaths dataPaths) {
final File dir = AndroidJpsUtil.getDirectoryForIntermediateArtifacts(dataPaths);
return new File(dir, PRE_DEXED_LIBS_DIRECTORY_NAME);
}
@NotNull
public JpsProject getProject() {
return myProject;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AndroidPreDexBuildTarget target = (AndroidPreDexBuildTarget)o;
if (!myProject.equals(target.myProject)) return false;
return true;
}
@Override
public int hashCode() {
return myProject.hashCode();
}
public static class MyTargetType extends BuildTargetType<AndroidPreDexBuildTarget> {
public static final MyTargetType INSTANCE = new MyTargetType();
private MyTargetType() {
super(AndroidCommonUtils.PRE_DEX_BUILD_TARGET_TYPE_ID);
}
@NotNull
@Override
public List<AndroidPreDexBuildTarget> computeAllTargets(@NotNull JpsModel model) {
if (!AndroidJpsUtil.isAndroidProjectWithoutGradleFacet(model.getProject())) {
return Collections.emptyList();
}
return Collections.singletonList(new AndroidPreDexBuildTarget(model.getProject()));
}
@NotNull
@Override
public BuildTargetLoader<AndroidPreDexBuildTarget> createLoader(@NotNull final JpsModel model) {
final JpsProject project = model.getProject();
return new BuildTargetLoader<AndroidPreDexBuildTarget>() {
@Nullable
@Override
public AndroidPreDexBuildTarget createTarget(@NotNull String targetId) {
return ID.equals(targetId) && AndroidJpsUtil.isAndroidProjectWithoutGradleFacet(project) ? new AndroidPreDexBuildTarget(project) : null;
}
};
}
}
public static class MyRootDescriptor extends BuildRootDescriptorImpl {
private final String myModuleName;
private MyRootDescriptor(@NotNull BuildTarget target, @NotNull File root, @Nullable String moduleName) {
super(target, root);
myModuleName = moduleName;
}
@Nullable
public String getModuleName() {
return myModuleName;
}
}
}