blob: f31f05c92e6d162cb94713c81475a0e0c2f35ba2 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.ant;
import com.intellij.compiler.ant.taskdefs.*;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @author Eugene Zhuravlev
* Date: Mar 19, 2004
*/
public class CompileModuleChunkTarget extends CompositeGenerator {
public CompileModuleChunkTarget(final Project project,
ModuleChunk moduleChunk,
VirtualFile[] sourceRoots,
VirtualFile[] testSourceRoots,
File baseDir,
GenerationOptions genOptions) {
final String moduleChunkName = moduleChunk.getName();
//noinspection HardCodedStringLiteral
final Tag compilerArgs = new Tag("compilerarg", Couple.of("line", BuildProperties.propertyRef(
BuildProperties.getModuleChunkCompilerArgsProperty(moduleChunkName))));
//noinspection HardCodedStringLiteral
final Couple<String> classpathRef = Couple.of("refid", BuildProperties.getClasspathProperty(moduleChunkName));
final Tag classpathTag = new Tag("classpath", classpathRef);
//noinspection HardCodedStringLiteral
final Tag bootclasspathTag =
new Tag("bootclasspath", Couple.of("refid", BuildProperties.getBootClasspathProperty(moduleChunkName)));
final PatternSetRef compilerExcludes = new PatternSetRef(BuildProperties.getExcludedFromCompilationProperty(moduleChunkName));
final String mainTargetName = BuildProperties.getCompileTargetName(moduleChunkName);
final @NonNls String productionTargetName = mainTargetName + ".production";
final @NonNls String testsTargetName = mainTargetName + ".tests";
final ChunkCustomCompilerExtension[] customCompilers = moduleChunk.getCustomCompilers();
final String customCompilersDependency = customCompilers.length != 0 || genOptions.enableFormCompiler ?
BuildProperties.TARGET_REGISTER_CUSTOM_COMPILERS : "";
final int modulesCount = moduleChunk.getModules().length;
Target mainTarget = new Target(mainTargetName, productionTargetName + "," + testsTargetName,
CompilerBundle.message("generated.ant.build.compile.modules.main.target.comment", modulesCount,
moduleChunkName), null);
String dependenciesProduction = getChunkDependenciesString(moduleChunk);
if (customCompilersDependency.length() > 0) {
if (dependenciesProduction != null && dependenciesProduction.length() > 0) {
dependenciesProduction = customCompilersDependency + "," + dependenciesProduction;
}
else {
dependenciesProduction = customCompilersDependency;
}
}
Target productionTarget = new Target(productionTargetName, dependenciesProduction,
CompilerBundle.message("generated.ant.build.compile.modules.production.classes.target.comment",
modulesCount, moduleChunkName), null);
String dependenciesTests = (customCompilersDependency.length() != 0 ? customCompilersDependency + "," : "") + productionTargetName;
Target testsTarget = new Target(testsTargetName, dependenciesTests,
CompilerBundle.message("generated.ant.build.compile.modules.tests.target.comment", modulesCount,
moduleChunkName), BuildProperties.PROPERTY_SKIP_TESTS);
if (sourceRoots.length > 0) {
final String outputPathRef = BuildProperties.propertyRef(BuildProperties.getOutputPathProperty(moduleChunkName));
final Tag srcTag = new Tag("src", Couple.of("refid", BuildProperties.getSourcepathProperty(moduleChunkName)));
productionTarget.add(new Mkdir(outputPathRef));
createCustomCompilerTasks(project, moduleChunk, genOptions, false, customCompilers, compilerArgs, bootclasspathTag,
classpathTag, compilerExcludes, srcTag, outputPathRef, productionTarget);
if (customCompilers.length == 0 || genOptions.enableFormCompiler) {
final Javac javac = new Javac(genOptions, moduleChunk, outputPathRef);
javac.add(compilerArgs);
javac.add(bootclasspathTag);
javac.add(classpathTag);
javac.add(srcTag);
javac.add(compilerExcludes);
productionTarget.add(javac);
}
productionTarget.add(createCopyTask(project, moduleChunk, sourceRoots, outputPathRef, baseDir, genOptions));
}
if (testSourceRoots.length > 0) {
final String testOutputPathRef = BuildProperties.propertyRef(BuildProperties.getOutputPathForTestsProperty(moduleChunkName));
final Tag srcTag = new Tag("src", Couple.of("refid", BuildProperties.getTestSourcepathProperty(moduleChunkName)));
final Couple<String> testClasspathRef = Couple.of("refid", BuildProperties.getTestClasspathProperty(moduleChunkName));
final Tag testClassPath = new Tag("classpath", testClasspathRef);
testsTarget.add(new Mkdir(testOutputPathRef));
createCustomCompilerTasks(project, moduleChunk, genOptions, true, customCompilers, compilerArgs, bootclasspathTag,
testClassPath, compilerExcludes, srcTag, testOutputPathRef, testsTarget);
if (customCompilers.length == 0 || genOptions.enableFormCompiler) {
final Javac javac = new Javac(genOptions, moduleChunk, testOutputPathRef);
javac.add(compilerArgs);
javac.add(bootclasspathTag);
javac.add(testClassPath);
javac.add(srcTag);
javac.add(compilerExcludes);
testsTarget.add(javac);
}
testsTarget.add(createCopyTask(project, moduleChunk, testSourceRoots, testOutputPathRef, baseDir, genOptions));
}
add(mainTarget);
add(productionTarget, 1);
add(testsTarget, 1);
}
/**
* Create custom compiler tasks
*
* @param project the project
* @param moduleChunk the module chunk
* @param genOptions generation options
* @param compileTests if true tests are being compiled
* @param customCompilers an array of custom compilers for this chunk
* @param compilerArgs the javac compiler arguments
* @param bootclasspathTag the boot classpath element for the javac compiler
* @param classpathTag the classpath tag for the javac compiler
* @param compilerExcludes the compiler excluded tag
* @param srcTag the source tag
* @param outputPathRef the output path references
* @param target the target where to add custom compiler
*/
private static void createCustomCompilerTasks(Project project,
ModuleChunk moduleChunk,
GenerationOptions genOptions,
boolean compileTests,
ChunkCustomCompilerExtension[] customCompilers,
Tag compilerArgs,
Tag bootclasspathTag,
Tag classpathTag,
PatternSetRef compilerExcludes,
Tag srcTag,
String outputPathRef,
Target target) {
if (customCompilers.length > 1) {
target.add(new Tag("fail", Couple.of("message", CompilerBundle.message(
"generated.ant.build.compile.modules.fail.custom.compilers"))));
}
for (ChunkCustomCompilerExtension ext : customCompilers) {
ext.generateCustomCompile(project, moduleChunk, genOptions, compileTests, target, compilerArgs, bootclasspathTag,
classpathTag, compilerExcludes, srcTag, outputPathRef);
}
}
private static String getChunkDependenciesString(ModuleChunk moduleChunk) {
final StringBuffer moduleDependencies = new StringBuffer();
final ModuleChunk[] dependencies = moduleChunk.getDependentChunks();
for (int idx = 0; idx < dependencies.length; idx++) {
final ModuleChunk dependency = dependencies[idx];
if (idx > 0) {
moduleDependencies.append(",");
}
moduleDependencies.append(BuildProperties.getCompileTargetName(dependency.getName()));
}
return moduleDependencies.toString();
}
private static Generator createCopyTask(final Project project,
ModuleChunk chunk,
VirtualFile[] sourceRoots,
String toDir,
File baseDir,
final GenerationOptions genOptions) {
//noinspection HardCodedStringLiteral
final Tag filesSelector = new Tag("type", Couple.of("type", "file"));
final PatternSetRef excludes = CompilerExcludes.isAvailable(project) ? new PatternSetRef(
BuildProperties.getExcludedFromCompilationProperty(chunk.getName())) : null;
final PatternSetRef resourcePatternsPatternSet = new PatternSetRef(BuildProperties.PROPERTY_COMPILER_RESOURCE_PATTERNS);
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final CompositeGenerator composite = new CompositeGenerator();
final Map<String, Copy> outputDirToTaskMap = new HashMap<String, Copy>();
for (final VirtualFile root : sourceRoots) {
final String packagePrefix = fileIndex.getPackageNameByDirectory(root);
final String targetDir =
packagePrefix != null && packagePrefix.length() > 0 ? toDir + "/" + packagePrefix.replace('.', '/') : toDir;
Copy copy = outputDirToTaskMap.get(targetDir);
if (copy == null) {
copy = new Copy(targetDir);
outputDirToTaskMap.put(targetDir, copy);
composite.add(copy);
}
final FileSet fileSet = new FileSet(
GenerationUtils.toRelativePath(root, baseDir, BuildProperties.getModuleChunkBasedirProperty(chunk), genOptions));
fileSet.add(resourcePatternsPatternSet);
fileSet.add(filesSelector);
if (excludes != null) {
fileSet.add(excludes);
}
copy.add(fileSet);
}
return composite;
}
}