FSC每次都重新编译 [英] FSC recompiles every time
问题描述
FSC每次都重新编译我的.scala文件,即使没有必要 - 我可以编译它两次,而不需要在尝试之间编辑任何东西,它会重新编译它们!
例如,我有2个文件
Hello.scala
class Hello {
print(hello)
}
和Tokens.scala:
抽象类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)
类ParsedToken(str:String,start:Int,end:Int,val invisible:Boolean)
extends Token str,start,end)
当我要求ant从头开始编译项目时, / p>
ant compile
init:
[mkdir]创建目录:D:\projects\Test\\ \\build\classes
[mkdir]创建目录:D:\projects\Test\build\test\classes
编译:
[fsc] Base目录是`D:\projects\Test`
[fsc]编译源文件:somepackage\Hello.scala,somepackage\Tokens.scala到D:\projects\Test\build\类
BUILD SUCCESSFUL
比我不编辑任何东西,再次编译:
ant compile
init:
[mkdir]创建dir:D:\projects \Test\build\classes
[mkdir]创建目录:D:\projects\Test\build\test\classes
编译:
[fsc]基本目录是`D:\projects\Test`
[fsc]将源文件:somepackage\Tokens.scala编译为D:\projects\Test\build\classes
BUILD SUCCESSFUL
正如你所看到的, scala(没有重新编译),并在Tokens.scala的情况下行为蠢。我建议问题是与继承有关,但这是所有。
那么是什么问题?
我不喜欢张贴他人写的东西,但我认为这个问题是一个更完整的答案,严格要求。
因此,首先, fsc
默认重新编译所有内容,period。它是 ant
,而不是 fsc
,它留下 Hello.scala
out,因为文件名匹配类名。它不会离开 Tokens.scala
,因为没有类 Tokens
编译 - 所以,在没有 Tokens.class
,它重新编译 Tokens.scala
。
这是与Scala做错了。 Scala与Java的一个基本方面不同之处在于,由于JVM的技术限制, trait
中的更改需要重新编译每个使用它的类,对象或实例化。 / p>
现在,可以修复 ant
任务,从Scala 2.8开始做一个更聪明的事情。我从 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>
详情请参阅Caoyuan的博客。
FSC recompiles my .scala files every time even there is no need - I can compile it twice without editing anything between attempts and it recompiles them! For example, I have 2 files
Hello.scala
class Hello{
print("hello")
}
And 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)
When I ask ant to compile project from scratch I see following output:
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
Than I don't edit anything and ask ant compile again:
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
As you can see, fsc acts smart in case of Hello.scala (no recompilation) and acts dumb in case of Tokens.scala. I suggest that the problem is somehow related with inheritance but that is all.
So what is wrong?
I don't like much posting stuff written by others, but I think this question merits a more complete answer that what was strictly asked.
So, first of all, fsc
recompiles everything by default, period. It is ant
, not fsc
, which is leaving Hello.scala
out, because the file name matches the class name. It is not leaving Tokens.scala
out because there is no class called Tokens
compiled -- so, in the absence of a Tokens.class
, it recompiled Tokens.scala
.
That is the wrong thing to do with Scala. Scala differs in one fundamental aspect from Java in that, because of technical limitations on JVM, a change in a trait
requires recompilation of every class, object or instantiation that uses it.
Now, one can fix the ant
task to do a smarter thing starting with Scala 2.8. I'm taking this information from blogtrader.net by Caoyuan, of Scala plugin for Netbeans fame. You define the Scala task on the build target like below:
<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>
It tells ant
to recompile everything, as ant
simply isn't smart enough to figure out what needs to be recompiled or not. It also tells Scala to build a file containing compilation dependencies, and use a transitive dependency algorithm to figure out what needs to be recompiled or not.
You also need to change the init target to include the build directory in the build classpath, as Scala will need that to recompile other classes. It should look like this:
<path id="build.classpath">
<pathelement location="${scala-library.jar}"/>
<pathelement location="${scala-compiler.jar}"/>
<pathelement location="${build.classes.dir}"/>
</path>
For more details, please refer to Caoyuan's blog.
这篇关于FSC每次都重新编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!