2010-09-27 78 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

相關問題