blob: 979fd78703f171b0ab7adab7526296e59143f449 [file] [log] [blame]
/*
* Copyright 2000-2012 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 org.jetbrains.jps.build;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ParameterizedRunnable;
import com.sampullara.cli.Args;
import com.sampullara.cli.Argument;
import org.jetbrains.jps.api.BuildType;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.cmdline.BuildRunner;
import org.jetbrains.jps.cmdline.JpsModelLoader;
import org.jetbrains.jps.cmdline.JpsModelLoaderImpl;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.MessageHandler;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTargetType;
import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.model.JpsModel;
import java.io.File;
import java.util.*;
import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
/**
* @author nik
*/
@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"})
public class Standalone {
@Argument(value = "config", prefix = "--", description = "Path to directory containing global options (idea.config.path)")
public String configPath;
@Argument(value = "script", prefix = "--", description = "Path to Groovy script which will be used to initialize global options")
public String initializationScriptPath;
@Argument(value = "cache-dir", prefix = "--", description = "Path to directory to store build caches")
public String cacheDirPath;
@Argument(value = "modules", prefix = "--", delimiter = ",", description = "Comma-separated list of modules to compile")
public String[] modules = ArrayUtil.EMPTY_STRING_ARRAY;
@Argument(value = "all-modules", prefix = "--", description = "Compile all modules")
public boolean allModules;
@Argument(value = "artifacts", prefix = "--", delimiter = ",", description = "Comma-separated list of artifacts to build")
public String[] artifacts = ArrayUtil.EMPTY_STRING_ARRAY;
@Argument(value = "all-artifacts", prefix = "--", description = "Build all artifacts")
public boolean allArtifacts;
@Argument(value = "i", description = "Build incrementally")
public boolean incremental;
public static void main(String[] args) {
Standalone instance = new Standalone();
List<String> projectPaths;
try {
projectPaths = Args.parse(instance, args);
}
catch (Exception e) {
printUsageAndExit();
return;
}
if (projectPaths.isEmpty()) {
System.out.println("Path to project is not specified");
printUsageAndExit();
}
if (projectPaths.size() > 1) {
System.out.println("Only one project can be specified");
printUsageAndExit();
}
instance.loadAndRunBuild(projectPaths.get(0));
System.exit(0);
}
private static void printUsageAndExit() {
Args.usage(System.err, new Standalone());
System.exit(0);
}
public void loadAndRunBuild(final String projectPath) {
String globalOptionsPath = null;
if (configPath != null) {
File optionsDir = new File(configPath, "options");
if (!optionsDir.isDirectory()) {
System.err.println("'" + configPath + "' is not valid config path: " + optionsDir.getAbsolutePath() + " not found");
return;
}
globalOptionsPath = optionsDir.getAbsolutePath();
}
ParameterizedRunnable<JpsModel> initializer = null;
String scriptPath = initializationScriptPath;
if (scriptPath != null) {
File scriptFile = new File(scriptPath);
if (!scriptFile.isFile()) {
System.err.println("Script '" + scriptPath + "' not found");
return;
}
initializer = new GroovyModelInitializer(scriptFile);
}
if (modules.length == 0 && artifacts.length == 0 && !allModules && !allArtifacts) {
System.err.println("Nothing to compile: at least one of --modules, --artifacts, --all-modules or --all-artifacts parameters must be specified");
return;
}
JpsModelLoaderImpl loader = new JpsModelLoaderImpl(projectPath, globalOptionsPath, initializer);
Set<String> modulesSet = new HashSet<String>(Arrays.asList(modules));
List<String> artifactsList = Arrays.asList(artifacts);
File dataStorageRoot;
if (cacheDirPath != null) {
dataStorageRoot = new File(cacheDirPath);
}
else {
dataStorageRoot = Utils.getDataStorageRoot(projectPath);
}
if (dataStorageRoot == null) {
System.err.println("Error: Cannot determine build data storage root for project " + projectPath);
return;
}
long start = System.currentTimeMillis();
try {
runBuild(loader, dataStorageRoot, !incremental, modulesSet, allModules, artifactsList, allArtifacts, true, new ConsoleMessageHandler());
}
catch (Throwable t) {
System.err.println("Internal error: " + t.getMessage());
t.printStackTrace();
}
System.out.println("Build finished in " + Utils.formatDuration(System.currentTimeMillis() - start));
}
@Deprecated
public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet,
List<String> artifactsList, final boolean includeTests, final MessageHandler messageHandler) throws Exception {
runBuild(loader, dataStorageRoot, forceBuild, modulesSet, modulesSet.isEmpty(), artifactsList, includeTests, messageHandler);
}
public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet,
final boolean allModules, List<String> artifactsList, final boolean includeTests,
final MessageHandler messageHandler) throws Exception {
runBuild(loader, dataStorageRoot, forceBuild, modulesSet, allModules, artifactsList, false, includeTests, messageHandler);
}
public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet,
final boolean allModules, List<String> artifactsList, boolean allArtifacts, final boolean includeTests,
final MessageHandler messageHandler) throws Exception {
List<TargetTypeBuildScope> scopes = new ArrayList<TargetTypeBuildScope>();
for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
if (includeTests || !type.isTests()) {
TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder().setTypeId(type.getTypeId()).setForceBuild(forceBuild);
if (allModules) {
scopes.add(builder.setAllTargets(true).build());
}
else if (!modulesSet.isEmpty()) {
scopes.add(builder.addAllTargetId(modulesSet).build());
}
}
}
TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder()
.setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId())
.setForceBuild(forceBuild);
if (allArtifacts) {
scopes.add(builder.setAllTargets(true).build());
}
else if (!artifactsList.isEmpty()) {
scopes.add(builder.addAllTargetId(artifactsList).build());
}
runBuild(loader, dataStorageRoot, messageHandler, scopes, true);
}
public static void runBuild(JpsModelLoader loader, File dataStorageRoot, MessageHandler messageHandler, List<TargetTypeBuildScope> scopes,
boolean includeDependenciesToScope) throws Exception {
final BuildRunner buildRunner = new BuildRunner(loader, Collections.<String>emptyList(), Collections.<String, String>emptyMap()
);
ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true));
try {
buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, BuildType.BUILD, scopes, includeDependenciesToScope);
}
finally {
descriptor.release();
}
}
private static class ConsoleMessageHandler implements MessageHandler {
@Override
public void processMessage(BuildMessage msg) {
String messageText = msg.getMessageText();
if (messageText.isEmpty()) return;
if (msg.getKind() == BuildMessage.Kind.ERROR) {
System.err.println("Error: " + messageText);
}
else if (msg.getKind() != BuildMessage.Kind.PROGRESS || !messageText.startsWith("Compiled") && !messageText.startsWith("Copying")) {
System.out.println(messageText);
}
}
}
}