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.K2JVMCompilerArguments; 027 import org.jetbrains.jet.cli.common.messages.*; 028 import org.jetbrains.jet.cli.common.modules.ModuleScriptData; 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.config.Services; 035 import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; 036 import org.jetbrains.jet.lang.resolve.kotlin.incremental.cache.IncrementalCacheProvider; 037 import org.jetbrains.jet.utils.KotlinPaths; 038 import org.jetbrains.jet.utils.KotlinPathsFromHomeDir; 039 import org.jetbrains.jet.utils.PathUtil; 040 041 import java.io.File; 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.*; 047 048 @SuppressWarnings("UseOfSystemOutOrSystemErr") 049 public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> { 050 051 public static void main(String... args) { 052 doMain(new K2JVMCompiler(), args); 053 } 054 055 @Override 056 @NotNull 057 protected ExitCode doExecute( 058 @NotNull K2JVMCompilerArguments arguments, 059 @NotNull Services services, 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 configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector); 072 073 IncrementalCacheProvider incrementalCacheProvider = services.get(IncrementalCacheProvider.class); 074 if (incrementalCacheProvider != null) { 075 configuration.put(JVMConfigurationKeys.INCREMENTAL_CACHE_PROVIDER, incrementalCacheProvider); 076 } 077 078 try { 079 configuration.addAll(JVMConfigurationKeys.CLASSPATH_KEY, getClasspath(paths, arguments)); 080 configuration.addAll(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, getAnnotationsPath(paths, arguments)); 081 } 082 catch (Throwable t) { 083 MessageCollectorUtil.reportException(messageCollector, t); 084 return INTERNAL_ERROR; 085 } 086 087 if (!arguments.script && 088 arguments.module == null && 089 arguments.freeArgs.isEmpty() && 090 !arguments.version 091 ) { 092 ReplFromTerminal.run(rootDisposable, configuration); 093 return ExitCode.OK; 094 } 095 else if (arguments.module != null) { 096 } 097 else if (arguments.script) { 098 if (arguments.freeArgs.isEmpty()) { 099 messageCollector.report(CompilerMessageSeverity.ERROR, "Specify script source path to evaluate", 100 CompilerMessageLocation.NO_LOCATION); 101 return COMPILATION_ERROR; 102 } 103 configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, arguments.freeArgs.get(0)); 104 } 105 else { 106 CompileEnvironmentUtil.addSourceFilesCheckingForDuplicates(configuration, arguments.freeArgs); 107 } 108 109 configuration.put(JVMConfigurationKeys.SCRIPT_PARAMETERS, arguments.script 110 ? CommandLineScriptUtils.scriptParameters() 111 : Collections.<AnalyzerScriptParameter>emptyList()); 112 113 putAdvancedOptions(configuration, arguments); 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 139 if (outputDir != null) { 140 messageCollector.report(CompilerMessageSeverity.WARNING, 141 "The '-d' option with a directory destination is ignored because '-module' is specified", 142 CompilerMessageLocation.NO_LOCATION); 143 } 144 145 File directory = new File(arguments.module).getAbsoluteFile().getParentFile(); 146 KotlinToJVMBytecodeCompiler.compileModules( 147 configuration, moduleScript.getModules(), directory, jar, arguments.includeRuntime 148 ); 149 } 150 else if (arguments.script) { 151 List<String> scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size()); 152 JetCoreEnvironment environment = 153 JetCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); 154 KotlinToJVMBytecodeCompiler.compileAndExecuteScript(paths, environment, scriptArgs); 155 } 156 else { 157 JetCoreEnvironment environment = 158 JetCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); 159 KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime); 160 } 161 return OK; 162 } 163 catch (CompilationException e) { 164 messageCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), 165 MessageUtil.psiElementToMessageLocation(e.getElement())); 166 return INTERNAL_ERROR; 167 } 168 } 169 170 private static void putAdvancedOptions(@NotNull CompilerConfiguration configuration, @NotNull K2JVMCompilerArguments arguments) { 171 configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions); 172 configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions); 173 configuration.put(JVMConfigurationKeys.DISABLE_INLINE, arguments.noInline); 174 configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize); 175 } 176 177 /** 178 * Allow derived classes to add additional command line arguments 179 */ 180 @NotNull 181 @Override 182 protected K2JVMCompilerArguments createArguments() { 183 return new K2JVMCompilerArguments(); 184 } 185 186 @NotNull 187 private static List<File> getClasspath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { 188 List<File> classpath = Lists.newArrayList(); 189 if (!arguments.noJdk) { 190 classpath.addAll(PathUtil.getJdkClassesRoots()); 191 } 192 if (!arguments.noStdlib) { 193 classpath.add(paths.getRuntimePath()); 194 } 195 if (arguments.classpath != null) { 196 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.classpath)) { 197 classpath.add(new File(element)); 198 } 199 } 200 return classpath; 201 } 202 203 @NotNull 204 private static List<File> getAnnotationsPath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { 205 List<File> annotationsPath = Lists.newArrayList(); 206 if (!arguments.noJdkAnnotations) { 207 annotationsPath.add(paths.getJdkAnnotationsPath()); 208 } 209 if (arguments.annotations != null) { 210 for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.annotations)) { 211 annotationsPath.add(new File(element)); 212 } 213 } 214 return annotationsPath; 215 } 216 }