2010-09-27 83 views
3

即使没有必要,FSC每次都会重新编译我的.scala文件 - 我可以编译它两次而不需要在任何尝试之间编辑任何内容,并重新编译它们! 例如,我有2个文件FSC每次都会重新编译

Hello.scala

class Hello{ 
    print("hello") 
} 

而且Tokens.scala:

abstract class Token(val str: String, val start: Int, val end: Int) 
    {override def toString = getClass.getSimpleName + "(" + "[" + start + "-" + end + "]" + str + ")"} 
class InputToken(str: String, start: Int, end: Int) 
     extends Token(str, start, end) 
class ParsedToken(str: String, start: Int, end: Int, val invisible: Boolean) 
     extends Token(str, start, end) 

当我问蚂蚁从头开始编制项目我看到以下的输出:

ant compile 
init: 
    [mkdir] Created dir: D:\projects\Test\build\classes 
    [mkdir] Created dir: D:\projects\Test\build\test\classes 

compile: 
     [fsc] Base directory is `D:\projects\Test` 
     [fsc] Compiling source files: somepackage\Hello.scala, somepackage\Tokens.scala to D:\projects\Test\build\classes 

BUILD SUCCESSFUL 

比我不编辑任何东西,并要求蚂蚁再次编译:

ant compile 
init: 
    [mkdir] Created dir: D:\projects\Test\build\classes 
    [mkdir] Created dir: D:\projects\Test\build\test\classes 

compile: 
     [fsc] Base directory is `D:\projects\Test` 
     [fsc] Compiling source files: somepackage\Tokens.scala to D:\projects\Test\build\classes 

BUILD SUCCESSFUL 

正如您所看到的,fsc在Hello.scala(不重新编译)的情况下很智能,在Tokens.scala的情况下不起作用。我建议这个问题与继承有某种关系,但仅此而已。

那又怎么了?

+2

FSC将编译所有内容,除非您传递标志告诉它执行传递依赖性分析。你如何在Ant中配置Scala编译任务? – 2010-09-27 13:17:32

回答

4

我不喜欢发布很多人写的东西,但我认为这个问题值得一个更完整的答案,什么是严格要求。

所以,首先,fsc默认重新编译一切,句号。它是ant,而不是fsc,它将Hello.scala离开,因为文件名与类名匹配。它不会离开Tokens.scala,因为没有名为Tokens的类编译 - 所以,如果没有Tokens.class,它会重新编译Tokens.scala

这对Scala来说是错误的。 Scala在Java的一个基本方面有所不同,由于JVM的技术限制,trait中的更改需要重新编译每个使用它的类,对象或实例。

现在,人们可以修复ant任务,从Scala 2.8开始做更聪明的事情。我正在从曹禺的blogtrader.net获取这个信息,这是Scala插件的Netbeans名气。您可以定义在构建目标斯卡拉任务象下面这样:

<scalac srcdir="${src.dir}" 
     destdir="${build.classes.dir}" 
     classpathref="build.classpath" 
     force="yes" 
     addparams="-make:transitive -dependencyfile ${build.dir}/.scala_dependencies" 
     > 
    <src path="${basedir}/src1"/> 
    <!--include name="compile/**/*.scala"/--> 
    <!--exclude name="forget/**/*.scala"/--> 
</scalac> 

它告诉ant重新编译一切,ant根本就没有足够的智慧找出需要重新编译,或者不是。它还告诉Scala构建一个包含编译依赖项的文件,并使用传递依赖性算法找出需要重新编译或不需要的内容。

您还需要更改init目标以将构建目录包含在构建类路径中,因为Scala将需要重新编译其他类。它应该看起来像这样:

<path id="build.classpath"> 
    <pathelement location="${scala-library.jar}"/> 
    <pathelement location="${scala-compiler.jar}"/> 
    <pathelement location="${build.classes.dir}"/> 
</path> 

欲了解更多详情,请参阅草原的博客。

5

Tokens.scala被重新编译,因为没有匹配其基本名称的类文件。也就是说,它不会生成Tokens.class文件。当决定是否编译源文件时,fsc将查找具有相同基本名称的类文件,并且如果类文件不存在或源文件上的修改时间晚于类文件的修改时间,则源文件将被重建。如果可以的话,我建议你看看Simple Build Tool,它的连续编译模式可以准确地跟踪source-> classfile的映射,并且不会重新编译Tokens.scala

想要额外的笑,想想编译器如果有不同的源文件,其中有class Tokens

尽管scala允许任何源文件中的任意公共类/对象,但仍有相当多的工具假定您会遵循java约定,并且至少在文件中有一个类/对象与源文件基本名称。

+0

ahaha,那是在1秒内“宾果”,但我错过了很多时间准确地写我的答案,所以你是第一)还有,当你有密封类时,java约定是不合适的。 – Jeriho 2010-09-27 14:23:27

相关问题