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 kotlin.modules.Module; 024 import org.jetbrains.annotations.NotNull; 025 import org.jetbrains.jet.cli.common.CLICompiler; 026 import org.jetbrains.jet.cli.common.CLIConfigurationKeys; 027 import org.jetbrains.jet.cli.common.ExitCode; 028 import org.jetbrains.jet.cli.common.arguments.CompilerArgumentsUtil; 029 import org.jetbrains.jet.cli.common.arguments.K2JVMCompilerArguments; 030 import org.jetbrains.jet.cli.common.messages.*; 031 import org.jetbrains.jet.cli.jvm.compiler.*; 032 import org.jetbrains.jet.cli.jvm.repl.ReplFromTerminal; 033 import org.jetbrains.jet.codegen.CompilationException; 034 import org.jetbrains.jet.codegen.inline.InlineCodegenUtil; 035 import org.jetbrains.jet.config.CommonConfigurationKeys; 036 import org.jetbrains.jet.config.CompilerConfiguration; 037 import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; 038 import org.jetbrains.jet.utils.KotlinPaths; 039 import org.jetbrains.jet.utils.KotlinPathsFromHomeDir; 040 import org.jetbrains.jet.utils.PathUtil; 041 042 import java.io.File; 043 import java.util.Arrays; 044 import java.util.Collections; 045 import java.util.List; 046 047 import static com.google.common.base.Predicates.in; 048 import static org.jetbrains.jet.cli.common.ExitCode.INTERNAL_ERROR; 049 import static org.jetbrains.jet.cli.common.ExitCode.OK; 050 051 @SuppressWarnings("UseOfSystemOutOrSystemErr") 052 public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> { 053 054 public static void main(String... args) { 055 doMain(new K2JVMCompiler(), args); 056 } 057 058 @Override 059 @NotNull 060 protected ExitCode doExecute( 061 @NotNull K2JVMCompilerArguments arguments, 062 @NotNull MessageCollector messageCollector, 063 @NotNull Disposable rootDisposable 064 ) { 065 KotlinPaths paths = arguments.kotlinHome != null 066 ? new KotlinPathsFromHomeDir(new File(arguments.kotlinHome)) 067 : PathUtil.getKotlinPathsForCompiler(); 068 069 messageCollector.report(CompilerMessageSeverity.LOGGING, 070 "Using Kotlin home directory " + paths.getHomePath(), CompilerMessageLocation.NO_LOCATION); 071 072 CompilerConfiguration configuration = new CompilerConfiguration(); 073 074 try { 075 configuration.addAll(JVMConfigurationKeys.CLASSPATH_KEY, getClasspath(paths, arguments)); 076 configuration.addAll(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, getAnnotationsPath(paths, arguments)); 077 } 078 catch (Throwable t) { 079 MessageCollectorUtil.reportException(messageCollector, t); 080 return INTERNAL_ERROR; 081 } 082 083 if (!arguments.script && 084 arguments.module == null && 085 arguments.src == null && 086 arguments.freeArgs.isEmpty() 087 ) { 088 ReplFromTerminal.run(rootDisposable, configuration); 089 return ExitCode.OK; 090 } 091 else if (arguments.module != null) { 092 } 093 else if (arguments.script) { 094 configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, arguments.freeArgs.get(0)); 095 } 096 else { 097 if (arguments.src != null) { 098 List<String> sourcePathsSplitByPathSeparator 099 = Arrays.asList(arguments.src.split(StringUtil.escapeToRegexp(File.pathSeparator))); 100 configuration.addAll(CommonConfigurationKeys.SOURCE_ROOTS_KEY, sourcePathsSplitByPathSeparator); 101 } 102 for (String freeArg : arguments.freeArgs) { 103 configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, freeArg); 104 } 105 } 106 107 configuration.put(JVMConfigurationKeys.SCRIPT_PARAMETERS, arguments.script 108 ? CommandLineScriptUtils.scriptParameters() 109 : Collections.<AnalyzerScriptParameter>emptyList()); 110 111 configuration.put(JVMConfigurationKeys.GENERATE_NOT_NULL_ASSERTIONS, arguments.notNullAssertions); 112 configuration.put(JVMConfigurationKeys.GENERATE_NOT_NULL_PARAMETER_ASSERTIONS, arguments.notNullParamAssertions); 113 configuration.put(JVMConfigurationKeys.ENABLE_INLINE, 114 CompilerArgumentsUtil.optionToBooleanFlag(arguments.inline, InlineCodegenUtil.DEFAULT_INLINE_FLAG)); 115 116 configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector); 117 118 messageCollector.report(CompilerMessageSeverity.LOGGING, "Configuring the compilation environment", 119 CompilerMessageLocation.NO_LOCATION); 120 try { 121 configureEnvironment(configuration, arguments); 122 123 File jar = arguments.jar != null ? new File(arguments.jar) : null; 124 File outputDir = arguments.outputDir != null ? new File(arguments.outputDir) : null; 125 126 if (arguments.module != null) { 127 MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector, in(CompilerMessageSeverity.VERBOSE)); 128 List<Module> modules = CompileEnvironmentUtil.loadModuleDescriptions(paths, arguments.module, sanitizedCollector); 129 130 if (outputDir != null) { 131 messageCollector.report(CompilerMessageSeverity.WARNING, "The '-output' option is ignored because '-module' is specified", 132 CompilerMessageLocation.NO_LOCATION); 133 } 134 135 File directory = new File(arguments.module).getAbsoluteFile().getParentFile(); 136 KotlinToJVMBytecodeCompiler.compileModules(configuration, modules, 137 directory, jar, 138 arguments.includeRuntime); 139 } 140 else if (arguments.script) { 141 List<String> scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size()); 142 JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(rootDisposable, configuration); 143 KotlinToJVMBytecodeCompiler.compileAndExecuteScript(paths, environment, scriptArgs); 144 } 145 else { 146 JetCoreEnvironment environment = JetCoreEnvironment.createForProduction(rootDisposable, configuration); 147 KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime); 148 } 149 return OK; 150 } 151 catch (CompilationException e) { 152 messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e), 153 MessageUtil.psiElementToMessageLocation(e.getElement())); 154 return INTERNAL_ERROR; 155 } 156 } 157 158 159 /** 160 * Allow derived classes to add additional command line arguments 161 */ 162 @NotNull 163 @Override 164 protected K2JVMCompilerArguments createArguments() { 165 return new K2JVMCompilerArguments(); 166 } 167 168 @NotNull 169 private static List<File> getClasspath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { 170 List<File> classpath = Lists.newArrayList(); 171 if (!arguments.noJdk) { 172 classpath.addAll(PathUtil.getJdkClassesRoots()); 173 } 174 if (!arguments.noStdlib) { 175 classpath.add(paths.getRuntimePath()); 176 } 177 if (arguments.classpath != null) { 178 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.classpath)) { 179 classpath.add(new File(element)); 180 } 181 } 182 return classpath; 183 } 184 185 @NotNull 186 private static List<File> getAnnotationsPath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { 187 List<File> annotationsPath = Lists.newArrayList(); 188 if (!arguments.noJdkAnnotations) { 189 annotationsPath.add(paths.getJdkAnnotationsPath()); 190 } 191 if (arguments.annotations != null) { 192 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.annotations)) { 193 annotationsPath.add(new File(element)); 194 } 195 } 196 return annotationsPath; 197 } 198 199 @Override 200 protected void checkArguments(@NotNull K2JVMCompilerArguments argument) { 201 super.checkArguments(argument); 202 203 if (!CompilerArgumentsUtil.checkOption(argument.inline)) { 204 throw new IllegalArgumentException(CompilerArgumentsUtil.getWrongInlineOptionErrorMessage(argument.inline)); 205 } 206 } 207 208 }