001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.cli.jvm;
018
019 import com.google.common.base.Splitter;
020 import com.google.common.collect.Lists;
021 import com.intellij.openapi.Disposable;
022 import com.intellij.openapi.util.text.StringUtil;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.jet.cli.common.CLICompiler;
025 import org.jetbrains.jet.cli.common.CLIConfigurationKeys;
026 import org.jetbrains.jet.cli.common.ExitCode;
027 import org.jetbrains.jet.cli.common.arguments.CompilerArgumentsUtil;
028 import org.jetbrains.jet.cli.common.arguments.K2JVMCompilerArguments;
029 import org.jetbrains.jet.cli.common.messages.*;
030 import org.jetbrains.jet.cli.jvm.compiler.CommandLineScriptUtils;
031 import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
032 import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
033 import org.jetbrains.jet.cli.jvm.compiler.KotlinToJVMBytecodeCompiler;
034 import org.jetbrains.jet.cli.jvm.repl.ReplFromTerminal;
035 import org.jetbrains.jet.codegen.CompilationException;
036 import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
037 import org.jetbrains.jet.config.CommonConfigurationKeys;
038 import org.jetbrains.jet.config.CompilerConfiguration;
039 import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
040 import org.jetbrains.jet.utils.KotlinPaths;
041 import org.jetbrains.jet.utils.KotlinPathsFromHomeDir;
042 import org.jetbrains.jet.utils.PathUtil;
043
044 import java.io.File;
045 import java.util.Arrays;
046 import java.util.Collections;
047 import java.util.List;
048
049 import static com.google.common.base.Predicates.in;
050 import static org.jetbrains.jet.cli.common.ExitCode.INTERNAL_ERROR;
051 import static org.jetbrains.jet.cli.common.ExitCode.OK;
052
053 @SuppressWarnings("UseOfSystemOutOrSystemErr")
054 public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
055
056 public static void main(String... args) {
057 doMain(new K2JVMCompiler(), args);
058 }
059
060 @Override
061 @NotNull
062 protected ExitCode doExecute(
063 @NotNull K2JVMCompilerArguments arguments,
064 @NotNull MessageCollector messageCollector,
065 @NotNull Disposable rootDisposable
066 ) {
067 KotlinPaths paths = arguments.kotlinHome != null
068 ? new KotlinPathsFromHomeDir(new File(arguments.kotlinHome))
069 : PathUtil.getKotlinPathsForCompiler();
070
071 messageCollector.report(CompilerMessageSeverity.LOGGING,
072 "Using Kotlin home directory " + paths.getHomePath(), CompilerMessageLocation.NO_LOCATION);
073
074 CompilerConfiguration configuration = new CompilerConfiguration();
075
076 try {
077 configuration.addAll(JVMConfigurationKeys.CLASSPATH_KEY, getClasspath(paths, arguments));
078 configuration.addAll(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, getAnnotationsPath(paths, arguments));
079 }
080 catch (Throwable t) {
081 MessageCollectorUtil.reportException(messageCollector, t);
082 return INTERNAL_ERROR;
083 }
084
085 if (!arguments.script &&
086 arguments.module == null &&
087 arguments.src == null &&
088 arguments.freeArgs.isEmpty() &&
089 !arguments.version
090 ) {
091 ReplFromTerminal.run(rootDisposable, configuration);
092 return ExitCode.OK;
093 }
094 else if (arguments.module != null) {
095 }
096 else if (arguments.script) {
097 configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, arguments.freeArgs.get(0));
098 }
099 else {
100 if (arguments.src != null) {
101 List<String> sourcePathsSplitByPathSeparator
102 = Arrays.asList(arguments.src.split(StringUtil.escapeToRegexp(File.pathSeparator)));
103 configuration.addAll(CommonConfigurationKeys.SOURCE_ROOTS_KEY, sourcePathsSplitByPathSeparator);
104 }
105 for (String freeArg : arguments.freeArgs) {
106 configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, freeArg);
107 }
108 }
109
110 configuration.put(JVMConfigurationKeys.SCRIPT_PARAMETERS, arguments.script
111 ? CommandLineScriptUtils.scriptParameters()
112 : Collections.<AnalyzerScriptParameter>emptyList());
113
114 configuration.put(JVMConfigurationKeys.GENERATE_NOT_NULL_ASSERTIONS, arguments.notNullAssertions);
115 configuration.put(JVMConfigurationKeys.GENERATE_NOT_NULL_PARAMETER_ASSERTIONS, arguments.notNullParamAssertions);
116 configuration.put(JVMConfigurationKeys.ENABLE_INLINE,
117 CompilerArgumentsUtil.optionToBooleanFlag(arguments.inline, InlineCodegenUtil.DEFAULT_INLINE_FLAG));
118
119 configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector);
120
121 messageCollector.report(CompilerMessageSeverity.LOGGING, "Configuring the compilation environment",
122 CompilerMessageLocation.NO_LOCATION);
123 try {
124 configureEnvironment(configuration, arguments);
125
126 File jar = arguments.jar != null ? new File(arguments.jar) : null;
127 File outputDir = arguments.outputDir != null ? new File(arguments.outputDir) : null;
128
129 if (arguments.module != null) {
130 MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector, in(CompilerMessageSeverity.VERBOSE));
131 CompileEnvironmentUtil.ModuleScriptData moduleScript = CompileEnvironmentUtil.loadModuleDescriptions(
132 paths, arguments.module, sanitizedCollector);
133 if (moduleScript.getIncrementalCacheDir() != null) {
134 configuration.put(JVMConfigurationKeys.INCREMENTAL_CACHE_BASE_DIR, new File(moduleScript.getIncrementalCacheDir()));
135 }
136
137 if (outputDir != null) {
138 messageCollector.report(CompilerMessageSeverity.WARNING, "The '-output' option is ignored because '-module' is specified",
139 CompilerMessageLocation.NO_LOCATION);
140 }
141
142 File directory = new File(arguments.module).getAbsoluteFile().getParentFile();
143 KotlinToJVMBytecodeCompiler.compileModules(configuration, moduleScript.getModules(),
144 directory, jar,
145 arguments.includeRuntime);
146 }
147 else if (arguments.script) {
148 List<String> scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size());
149 JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(rootDisposable, configuration);
150 KotlinToJVMBytecodeCompiler.compileAndExecuteScript(paths, environment, scriptArgs);
151 }
152 else {
153 JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(rootDisposable, configuration);
154 KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime);
155 }
156 return OK;
157 }
158 catch (CompilationException e) {
159 messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e),
160 MessageUtil.psiElementToMessageLocation(e.getElement()));
161 return INTERNAL_ERROR;
162 }
163 }
164
165
166 /**
167 * Allow derived classes to add additional command line arguments
168 */
169 @NotNull
170 @Override
171 protected K2JVMCompilerArguments createArguments() {
172 return new K2JVMCompilerArguments();
173 }
174
175 @NotNull
176 private static List<File> getClasspath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) {
177 List<File> classpath = Lists.newArrayList();
178 if (!arguments.noJdk) {
179 classpath.addAll(PathUtil.getJdkClassesRoots());
180 }
181 if (!arguments.noStdlib) {
182 classpath.add(paths.getRuntimePath());
183 }
184 if (arguments.classpath != null) {
185 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.classpath)) {
186 classpath.add(new File(element));
187 }
188 }
189 return classpath;
190 }
191
192 @NotNull
193 private static List<File> getAnnotationsPath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) {
194 List<File> annotationsPath = Lists.newArrayList();
195 if (!arguments.noJdkAnnotations) {
196 annotationsPath.add(paths.getJdkAnnotationsPath());
197 }
198 if (arguments.annotations != null) {
199 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.annotations)) {
200 annotationsPath.add(new File(element));
201 }
202 }
203 return annotationsPath;
204 }
205
206 @Override
207 protected void checkArguments(@NotNull K2JVMCompilerArguments argument) {
208 super.checkArguments(argument);
209
210 if (!CompilerArgumentsUtil.checkOption(argument.inline)) {
211 throw new IllegalArgumentException(CompilerArgumentsUtil.getWrongInlineOptionErrorMessage(argument.inline));
212 }
213 }
214
215 }