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