【问题标题】:FSC recompiles every timeFSC 每次都重新编译
【发布时间】:2010-09-27 12:20:24
【问题描述】:

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

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 从头开始​​编译项目时,我看到以下输出:

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:

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 的情况下表现得很愚蠢。我认为这个问题在某种程度上与继承有关,但仅此而已。

那么有什么问题呢?

【问题讨论】:

  • FSC 将编译所有内容,除非您向它传递标志告诉它进行传递依赖分析。你是如何在 Ant 中配置 Scala 编译任务的?

标签: scala compilation scalac


【解决方案1】:

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

如果您有一个包含class Tokens 的不同源文件,请考虑一下编译器可能会做什么。

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

【讨论】:

  • ahaha,那是 1 秒内的“宾果游戏”,但我错过了很多时间来准确地写出我的答案,所以你是第一个)当你有密封类时,java 约定也不合适。
【解决方案2】:

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

所以,首先,fsc 默认重新编译所有内容,句号。是ant,而不是fsc,因为文件名与类名匹配,所以将Hello.scala 排除在外。它不会将Tokens.scala 排除在外,因为没有编译名为Tokens 的类——因此,在没有Tokens.class 的情况下,它重新编译了Tokens.scala

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

现在,从 Scala 2.8 开始,人们可以修复 ant 任务来做一件更智能的事情。我从 blogtrader.net blogtrader.net 获取此信息,Caoyuan 是 Netbeans 名声的 Scala 插件。您在构建目标上定义 Scala 任务,如下所示:

<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>

更多详情请参考曹源的博客。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 2019-08-16
    • 2021-11-05
    相关资源
    最近更新 更多