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 org.jetbrains.annotations.NotNull; 023 import org.jetbrains.jet.cli.common.CLICompiler; 024 import org.jetbrains.jet.cli.common.CLIConfigurationKeys; 025 import org.jetbrains.jet.cli.common.ExitCode; 026 import org.jetbrains.jet.cli.common.arguments.CompilerArgumentsUtil; 027 import org.jetbrains.jet.cli.common.arguments.K2JVMCompilerArguments; 028 import org.jetbrains.jet.cli.common.messages.*; 029 import org.jetbrains.jet.cli.common.modules.ModuleScriptData; 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.codegen.optimization.OptimizationUtils; 038 import org.jetbrains.jet.config.CommonConfigurationKeys; 039 import org.jetbrains.jet.config.CompilerConfiguration; 040 import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; 041 import org.jetbrains.jet.utils.KotlinPaths; 042 import org.jetbrains.jet.utils.KotlinPathsFromHomeDir; 043 import org.jetbrains.jet.utils.PathUtil; 044 045 import java.io.File; 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.freeArgs.isEmpty() && 088 !arguments.version 089 ) { 090 ReplFromTerminal.run(rootDisposable, configuration); 091 return ExitCode.OK; 092 } 093 else if (arguments.module != null) { 094 } 095 else if (arguments.script) { 096 configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, arguments.freeArgs.get(0)); 097 } 098 else { 099 configuration.addAll(CommonConfigurationKeys.SOURCE_ROOTS_KEY, arguments.freeArgs); 100 } 101 102 configuration.put(JVMConfigurationKeys.SCRIPT_PARAMETERS, arguments.script 103 ? CommandLineScriptUtils.scriptParameters() 104 : Collections.<AnalyzerScriptParameter>emptyList()); 105 106 configuration.put(JVMConfigurationKeys.GENERATE_NOT_NULL_ASSERTIONS, arguments.notNullAssertions); 107 configuration.put(JVMConfigurationKeys.GENERATE_NOT_NULL_PARAMETER_ASSERTIONS, arguments.notNullParamAssertions); 108 configuration.put(JVMConfigurationKeys.ENABLE_INLINE, 109 CompilerArgumentsUtil.optionToBooleanFlag(arguments.inline, InlineCodegenUtil.DEFAULT_INLINE_FLAG)); 110 configuration.put(JVMConfigurationKeys.ENABLE_OPTIMIZATION, 111 CompilerArgumentsUtil.optionToBooleanFlag(arguments.optimize, OptimizationUtils.DEFAULT_OPTIMIZATION_FLAG)); 112 113 configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector); 114 115 messageCollector.report(CompilerMessageSeverity.LOGGING, "Configuring the compilation environment", 116 CompilerMessageLocation.NO_LOCATION); 117 try { 118 configureEnvironment(configuration, arguments); 119 120 String destination = arguments.destination; 121 122 File jar; 123 File outputDir; 124 if (destination != null) { 125 boolean isJar = destination.endsWith(".jar"); 126 jar = isJar ? new File(destination) : null; 127 outputDir = isJar ? null : new File(destination); 128 } 129 else { 130 jar = null; 131 outputDir = null; 132 } 133 134 if (arguments.module != null) { 135 MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector, in(CompilerMessageSeverity.VERBOSE)); 136 ModuleScriptData moduleScript = CompileEnvironmentUtil.loadModuleDescriptions( 137 paths, arguments.module, sanitizedCollector); 138 if (moduleScript.getIncrementalCacheDir() != null) { 139 configuration.put(JVMConfigurationKeys.INCREMENTAL_CACHE_BASE_DIR, new File(moduleScript.getIncrementalCacheDir())); 140 } 141 142 if (outputDir != null) { 143 messageCollector.report(CompilerMessageSeverity.WARNING, 144 "The '-d' option with a directory destination is ignored because '-module' is specified", 145 CompilerMessageLocation.NO_LOCATION); 146 } 147 148 File directory = new File(arguments.module).getAbsoluteFile().getParentFile(); 149 KotlinToJVMBytecodeCompiler.compileModules( 150 configuration, moduleScript.getModules(), directory, jar, arguments.includeRuntime 151 ); 152 } 153 else if (arguments.script) { 154 List<String> scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size()); 155 JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(rootDisposable, configuration); 156 KotlinToJVMBytecodeCompiler.compileAndExecuteScript(paths, environment, scriptArgs); 157 } 158 else { 159 JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(rootDisposable, configuration); 160 KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime); 161 } 162 return OK; 163 } 164 catch (CompilationException e) { 165 messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e), 166 MessageUtil.psiElementToMessageLocation(e.getElement())); 167 return INTERNAL_ERROR; 168 } 169 } 170 171 172 /** 173 * Allow derived classes to add additional command line arguments 174 */ 175 @NotNull 176 @Override 177 protected K2JVMCompilerArguments createArguments() { 178 return new K2JVMCompilerArguments(); 179 } 180 181 @NotNull 182 private static List<File> getClasspath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { 183 List<File> classpath = Lists.newArrayList(); 184 if (!arguments.noJdk) { 185 classpath.addAll(PathUtil.getJdkClassesRoots()); 186 } 187 if (!arguments.noStdlib) { 188 classpath.add(paths.getRuntimePath()); 189 } 190 if (arguments.classpath != null) { 191 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.classpath)) { 192 classpath.add(new File(element)); 193 } 194 } 195 return classpath; 196 } 197 198 @NotNull 199 private static List<File> getAnnotationsPath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { 200 List<File> annotationsPath = Lists.newArrayList(); 201 if (!arguments.noJdkAnnotations) { 202 annotationsPath.add(paths.getJdkAnnotationsPath()); 203 } 204 if (arguments.annotations != null) { 205 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.annotations)) { 206 annotationsPath.add(new File(element)); 207 } 208 } 209 return annotationsPath; 210 } 211 212 @Override 213 protected void checkArguments(@NotNull K2JVMCompilerArguments argument) { 214 super.checkArguments(argument); 215 216 if (!CompilerArgumentsUtil.checkOption(argument.inline)) { 217 throw new IllegalArgumentException(CompilerArgumentsUtil.getWrongCheckOptionErrorMessage("inline", argument.inline)); 218 } 219 220 if (!CompilerArgumentsUtil.checkOption(argument.optimize)) { 221 throw new IllegalArgumentException(CompilerArgumentsUtil.getWrongCheckOptionErrorMessage("optimize", argument.optimize)); 222 } 223 } 224 225 }