diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index 0d0145f36bd..49cc2a7e9fb 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -129,6 +129,14 @@ open class K2JVMCompiler : CLICompiler() { JvmMetadataVersion.skipCheck = true } + if (arguments.includeRuntime) { + configuration.put(JVMConfigurationKeys.INCLUDE_RUNTIME, true) + } + val friendPaths = arguments.friendPaths?.toList() + if (friendPaths != null) { + configuration.put(JVMConfigurationKeys.FRIEND_PATHS, friendPaths) + } + putAdvancedOptions(configuration, arguments) messageSeverityCollector.report(CompilerMessageSeverity.LOGGING, "Configuring the compilation environment", CompilerMessageLocation.NO_LOCATION) @@ -137,51 +145,47 @@ open class K2JVMCompiler : CLICompiler() { val destination = arguments.destination - val jar: File? - val outputDir: File? - if (destination != null) { - val isJar = destination.endsWith(".jar") - jar = if (isJar) File(destination) else null - outputDir = if (isJar) null else File(destination) - } - else { - jar = null - outputDir = null - } - val environment: KotlinCoreEnvironment - - val friendPaths = arguments.friendPaths?.toList() ?: emptyList() - if (arguments.module != null) { val sanitizedCollector = FilteringMessageCollector(messageSeverityCollector, `in`(CompilerMessageSeverity.VERBOSE)) val moduleScript = CompileEnvironmentUtil.loadModuleDescriptions(arguments.module, sanitizedCollector) - if (outputDir != null) { - messageSeverityCollector.report(CompilerMessageSeverity.WARNING, "The '-d' option with a directory destination is ignored because '-module' is specified", CompilerMessageLocation.NO_LOCATION) + if (destination != null) { + messageSeverityCollector.report( + CompilerMessageSeverity.WARNING, + "The '-d' option with a directory destination is ignored because '-module' is specified", + CompilerMessageLocation.NO_LOCATION + ) } - val directory = File(arguments.module).absoluteFile.parentFile + val moduleFile = File(arguments.module) + val directory = moduleFile.absoluteFile.parentFile - val compilerConfiguration = KotlinToJVMBytecodeCompiler.createCompilerConfiguration(configuration, moduleScript.modules, directory) - compilerConfiguration.put(JVMConfigurationKeys.MODULE_XML_FILE_PATH, arguments.module) - - environment = createCoreEnvironment(rootDisposable, compilerConfiguration) + KotlinToJVMBytecodeCompiler.configureSourceRoots(configuration, moduleScript.modules, directory) + configuration.put(JVMConfigurationKeys.MODULE_XML_FILE, moduleFile) + val environment = createCoreEnvironment(rootDisposable, configuration) if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) return COMPILATION_ERROR - KotlinToJVMBytecodeCompiler.compileModules(environment, configuration, moduleScript.modules, directory, jar, friendPaths, arguments.includeRuntime) + KotlinToJVMBytecodeCompiler.compileModules(environment, directory) } else if (arguments.script) { val scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size) - environment = createCoreEnvironment(rootDisposable, configuration) - + val environment = createCoreEnvironment(rootDisposable, configuration) if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) return COMPILATION_ERROR - return KotlinToJVMBytecodeCompiler.compileAndExecuteScript(configuration, paths, environment, scriptArgs) + return KotlinToJVMBytecodeCompiler.compileAndExecuteScript(environment, paths, scriptArgs) } else { - environment = createCoreEnvironment(rootDisposable, configuration) + if (destination != null) { + if (destination.endsWith(".jar")) { + configuration.put(JVMConfigurationKeys.OUTPUT_JAR, File(destination)) + } + else { + configuration.put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(destination)) + } + } + val environment = createCoreEnvironment(rootDisposable, configuration) if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) return COMPILATION_ERROR if (environment.getSourceFiles().isEmpty()) { @@ -192,13 +196,13 @@ open class K2JVMCompiler : CLICompiler() { return COMPILATION_ERROR } - KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, friendPaths, arguments.includeRuntime) + KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment) } if (arguments.reportPerf) { - reportGCTime(environment.configuration) - reportCompilationTime(environment.configuration) - PerformanceCounter.report { s -> reportPerf(environment.configuration, s) } + reportGCTime(configuration) + reportCompilationTime(configuration) + PerformanceCounter.report { s -> reportPerf(configuration, s) } } return OK } @@ -206,7 +210,6 @@ open class K2JVMCompiler : CLICompiler() { messageSeverityCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element)) return INTERNAL_ERROR } - } private fun createCoreEnvironment(rootDisposable: Disposable, configuration: CompilerConfiguration): KotlinCoreEnvironment { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CompileEnvironmentUtil.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CompileEnvironmentUtil.java index dbce98a82fc..cfc63c9d4d3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CompileEnvironmentUtil.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CompileEnvironmentUtil.java @@ -57,7 +57,7 @@ import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.N import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR; public class CompileEnvironmentUtil { - private static Logger LOG = Logger.getInstance(CompileEnvironmentUtil.class); + private static final Logger LOG = Logger.getInstance(CompileEnvironmentUtil.class); @NotNull public static ModuleScriptData loadModuleDescriptions(String moduleDefinitionFile, MessageCollector messageCollector) { @@ -162,9 +162,9 @@ public class CompileEnvironmentUtil { if (vFile == null) { String message = "Source file or directory not found: " + sourceRootPath; - String moduleFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE_PATH); + File moduleFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE); if (moduleFilePath != null) { - String moduleFileContent = FileUtil.loadFile(new File(moduleFilePath)); + String moduleFileContent = FileUtil.loadFile(moduleFilePath); LOG.warn(message + "\n\nmodule file path: " + moduleFilePath + "\ncontent:\n" + moduleFileContent); diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index 57132c8248e..741e979d0d8 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -74,53 +74,45 @@ object KotlinToJVMBytecodeCompiler { private fun writeOutput( configuration: CompilerConfiguration, outputFiles: OutputFileCollection, - outputDir: File?, - jarPath: File?, - jarRuntime: Boolean, mainClass: FqName? ) { + val jarPath = configuration.get(JVMConfigurationKeys.OUTPUT_JAR) if (jarPath != null) { - CompileEnvironmentUtil.writeToJar(jarPath, jarRuntime, mainClass, outputFiles) - } - else { - val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) - outputFiles.writeAll(outputDir ?: File("."), messageCollector) + val includeRuntime = configuration.get(JVMConfigurationKeys.INCLUDE_RUNTIME, false) + CompileEnvironmentUtil.writeToJar(jarPath, includeRuntime, mainClass, outputFiles) + return } + + val outputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) ?: File(".") + val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) + outputFiles.writeAll(outputDir, messageCollector) } - private fun createOutputFilesFlushingCallbackIfPossible( - configuration: CompilerConfiguration, - outputDir: File?, - jarPath: File? - ): GenerationStateEventCallback { - if (jarPath != null) return GenerationStateEventCallback.DO_NOTHING - + private fun createOutputFilesFlushingCallbackIfPossible(configuration: CompilerConfiguration): GenerationStateEventCallback { + if (configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY) == null) { + return GenerationStateEventCallback.DO_NOTHING + } return GenerationStateEventCallback { state -> val currentOutput = SimpleOutputFileCollection(state.factory.currentOutput) - writeOutput(configuration, currentOutput, outputDir, jarPath = null, jarRuntime = false, mainClass = null) + writeOutput(configuration, currentOutput, mainClass = null) state.factory.releaseGeneratedOutput() } } - fun compileModules( - environment: KotlinCoreEnvironment, - configuration: CompilerConfiguration, - chunk: List, - directory: File, - jarPath: File?, - friendPaths: List, - jarRuntime: Boolean - ): Boolean { + fun compileModules(environment: KotlinCoreEnvironment, directory: File): Boolean { val outputFiles = hashMapOf() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project) + val projectConfiguration = environment.configuration + val chunk = projectConfiguration.getNotNull(JVMConfigurationKeys.MODULES) for (module in chunk) { moduleVisibilityManager.addModule(module) } + val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS) for (path in friendPaths) { moduleVisibilityManager.addFriendPath(path) } @@ -133,28 +125,31 @@ object KotlinToJVMBytecodeCompiler { result.throwIfError() - val generationStates = ArrayList() + val moduleConfigurations = ArrayList(chunk.size) + val generationStates = ArrayList(chunk.size) for (module in chunk) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() val ktFiles = CompileEnvironmentUtil.getKtFiles( - environment.project, getAbsolutePaths(directory, module), configuration + environment.project, getAbsolutePaths(directory, module), projectConfiguration ) { path -> throw IllegalStateException("Should have been checked before: $path") } if (!checkKotlinPackageUsage(environment, ktFiles)) return false - val onIndependentPartCompilationEnd = - createOutputFilesFlushingCallbackIfPossible(configuration, File(module.getOutputDirectory()), jarPath) + val moduleConfiguration = projectConfiguration.copy().apply { + put(JVMConfigurationKeys.OUTPUT_DIRECTORY, File(module.getOutputDirectory())) + } - val generationState = generate(environment, result, ktFiles, module, onIndependentPartCompilationEnd) + val generationState = generate(environment, moduleConfiguration, result, ktFiles, module) outputFiles.put(module, generationState.factory) + moduleConfigurations.add(moduleConfiguration) generationStates.add(generationState) } try { - for (module in chunk) { + for ((module, configuration) in chunk.zip(moduleConfigurations)) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - writeOutput(configuration, outputFiles[module]!!, File(module.getOutputDirectory()), jarPath, jarRuntime, null) + writeOutput(configuration, outputFiles[module]!!, null) } return true } @@ -165,13 +160,7 @@ object KotlinToJVMBytecodeCompiler { } } - fun createCompilerConfiguration( - base: CompilerConfiguration, - chunk: List, - directory: File - ): CompilerConfiguration { - val configuration = base.copy() - + fun configureSourceRoots(configuration: CompilerConfiguration, chunk: List, directory: File) { for (module in chunk) { configuration.addKotlinSourceRoots(getAbsolutePaths(directory, module)) } @@ -189,8 +178,6 @@ object KotlinToJVMBytecodeCompiler { } configuration.addAll(JVMConfigurationKeys.MODULES, chunk) - - return configuration } private fun findMainClass(generationState: GenerationState, files: List): FqName? { @@ -205,28 +192,22 @@ object KotlinToJVMBytecodeCompiler { .singleOrNull { it != null } } - fun compileBunchOfSources( - environment: KotlinCoreEnvironment, - jar: File?, - outputDir: File?, - friendPaths: List, - includeRuntime: Boolean - ): Boolean { + fun compileBunchOfSources(environment: KotlinCoreEnvironment): Boolean { val moduleVisibilityManager = ModuleVisibilityManager.SERVICE.getInstance(environment.project) + val friendPaths = environment.configuration.getList(JVMConfigurationKeys.FRIEND_PATHS) for (path in friendPaths) { moduleVisibilityManager.addFriendPath(path) } if (!checkKotlinPackageUsage(environment, environment.getSourceFiles())) return false - val onIndependentPartCompilationEnd = createOutputFilesFlushingCallbackIfPossible(environment.configuration, outputDir, jar) - val generationState = analyzeAndGenerate(environment, onIndependentPartCompilationEnd) ?: return false + val generationState = analyzeAndGenerate(environment) ?: return false val mainClass = findMainClass(generationState, environment.getSourceFiles()) try { - writeOutput(environment.configuration, generationState.factory, outputDir, jar, includeRuntime, mainClass) + writeOutput(environment.configuration, generationState.factory, mainClass) return true } finally { @@ -234,13 +215,8 @@ object KotlinToJVMBytecodeCompiler { } } - fun compileAndExecuteScript( - configuration: CompilerConfiguration, - paths: KotlinPaths, - environment: KotlinCoreEnvironment, - scriptArgs: List - ): ExitCode { - val scriptClass = compileScript(configuration, paths, environment) ?: return ExitCode.COMPILATION_ERROR + fun compileAndExecuteScript(environment: KotlinCoreEnvironment, paths: KotlinPaths, scriptArgs: List): ExitCode { + val scriptClass = compileScript(environment, paths) ?: return ExitCode.COMPILATION_ERROR val scriptConstructor = getScriptConstructor(scriptClass) try { @@ -280,18 +256,13 @@ object KotlinToJVMBytecodeCompiler { private fun getScriptConstructor(scriptClass: Class<*>): Constructor<*> = scriptClass.getConstructor(Array::class.java) - fun compileScript( - configuration: CompilerConfiguration, - paths: KotlinPaths, - environment: KotlinCoreEnvironment - ): Class<*>? { - val state = analyzeAndGenerate(environment, GenerationStateEventCallback.DO_NOTHING) ?: return null + fun compileScript(environment: KotlinCoreEnvironment, paths: KotlinPaths): Class<*>? { + val state = analyzeAndGenerate(environment) ?: return null - val classLoader: GeneratedClassLoader try { val classPaths = arrayListOf(paths.runtimePath.toURI().toURL()) - configuration.jvmClasspathRoots.mapTo(classPaths) { it.toURI().toURL() } - classLoader = GeneratedClassLoader(state.factory, URLClassLoader(classPaths.toTypedArray(), null)) + environment.configuration.jvmClasspathRoots.mapTo(classPaths) { it.toURI().toURL() } + val classLoader = GeneratedClassLoader(state.factory, URLClassLoader(classPaths.toTypedArray(), null)) val script = environment.getSourceFiles()[0].script ?: error("Script must be parsed") return classLoader.loadClass(script.fqName.asString()) @@ -301,17 +272,14 @@ object KotlinToJVMBytecodeCompiler { } } - fun analyzeAndGenerate( - environment: KotlinCoreEnvironment, - onIndependentPartCompilationEnd: GenerationStateEventCallback - ): GenerationState? { + fun analyzeAndGenerate(environment: KotlinCoreEnvironment): GenerationState? { val result = analyze(environment, null) ?: return null if (!result.shouldGenerateCode) return null result.throwIfError() - return generate(environment, result, environment.getSourceFiles(), null, onIndependentPartCompilationEnd) + return generate(environment, environment.configuration, result, environment.getSourceFiles(), null) } private fun analyze(environment: KotlinCoreEnvironment, targetDescription: String?): AnalysisResult? { @@ -365,10 +333,10 @@ object KotlinToJVMBytecodeCompiler { private fun generate( environment: KotlinCoreEnvironment, + configuration: CompilerConfiguration, result: AnalysisResult, sourceFiles: List, - module: Module?, - onIndependentPartCompilationEnd: GenerationStateEventCallback + module: Module? ): GenerationState { val generationState = GenerationState( environment.project, @@ -376,12 +344,12 @@ object KotlinToJVMBytecodeCompiler { result.moduleDescriptor, result.bindingContext, sourceFiles, - environment.configuration, + configuration, GenerationState.GenerateClassFilter.GENERATE_ALL, module?.let(::TargetId), module?.let { it.getModuleName() }, module?.let { File(it.getOutputDirectory()) }, - onIndependentPartCompilationEnd + createOutputFilesFlushingCallbackIfPossible(configuration) ) ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index 0d0f66cc329..c94e3276021 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -19,12 +19,20 @@ package org.jetbrains.kotlin.config; import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents; import org.jetbrains.kotlin.modules.Module; +import java.io.File; import java.util.List; public class JVMConfigurationKeys { private JVMConfigurationKeys() { } + public static final CompilerConfigurationKey OUTPUT_DIRECTORY = + CompilerConfigurationKey.create("output directory"); + public static final CompilerConfigurationKey OUTPUT_JAR = + CompilerConfigurationKey.create("output .jar"); + public static final CompilerConfigurationKey INCLUDE_RUNTIME = + CompilerConfigurationKey.create("include runtime to the resulting .jar"); + public static final CompilerConfigurationKey DISABLE_CALL_ASSERTIONS = CompilerConfigurationKey.create("disable not-null call assertions"); public static final CompilerConfigurationKey DISABLE_PARAM_ASSERTIONS = @@ -41,7 +49,7 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey INCREMENTAL_COMPILATION_COMPONENTS = CompilerConfigurationKey.create("incremental cache provider"); - public static final CompilerConfigurationKey MODULE_XML_FILE_PATH = + public static final CompilerConfigurationKey MODULE_XML_FILE = CompilerConfigurationKey.create("path to module.xml"); public static final CompilerConfigurationKey DECLARATIONS_JSON_PATH = @@ -50,6 +58,9 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey> MODULES = CompilerConfigurationKey.create("module data"); + public static final CompilerConfigurationKey> FRIEND_PATHS = + CompilerConfigurationKey.create("friend module paths"); + public static final CompilerConfigurationKey MODULE_NAME = CompilerConfigurationKey.create("module name"); } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/StdlibTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/StdlibTest.java index b2b865947e2..e62fd2d59ae 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/StdlibTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/StdlibTest.java @@ -28,7 +28,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.codegen.state.GenerationState; -import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.ContentRootsKt; import org.jetbrains.kotlin.descriptors.ClassDescriptor; @@ -64,8 +63,7 @@ public class StdlibTest extends KotlinTestWithEnvironment { } public void testStdlib() throws ClassNotFoundException { - GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate( - getEnvironment(), GenerationStateEventCallback.Companion.getDO_NOTHING()); + GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(getEnvironment()); if (state == null) { fail("There were compilation errors"); } diff --git a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.java b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.java index 4c22556c7b9..297f27a1cec 100644 --- a/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.java +++ b/compiler/tests/org/jetbrains/kotlin/scripts/ScriptTest.java @@ -86,7 +86,7 @@ public class ScriptTest { KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); try { - return KotlinToJVMBytecodeCompiler.INSTANCE.compileScript(configuration, paths, environment); + return KotlinToJVMBytecodeCompiler.INSTANCE.compileScript(environment, paths); } catch (CompilationException e) { messageCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(e), diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java index ff544822a29..ff0273b49c1 100644 --- a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/ExecuteKotlinScriptMojo.java @@ -43,7 +43,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler; import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot; import org.jetbrains.kotlin.codegen.GeneratedClassLoader; import org.jetbrains.kotlin.codegen.state.GenerationState; -import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback; import org.jetbrains.kotlin.config.CommonConfigurationKeys; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.JVMConfigurationKeys; @@ -181,7 +180,7 @@ public class ExecuteKotlinScriptMojo extends AbstractMojo { KotlinCoreEnvironment environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); - GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(environment, GenerationStateEventCallback.Companion.getDO_NOTHING()); + GenerationState state = KotlinToJVMBytecodeCompiler.INSTANCE.analyzeAndGenerate(environment); if (state == null) { throw new ScriptExecutionException(scriptFile, "compile error");