@@ -2,6 +2,7 @@ import sbt.Keys._
2
2
import sbt ._
3
3
import java .io .{ RandomAccessFile , File }
4
4
import java .nio .channels .FileLock
5
+ import scala .reflect .io .Path
5
6
6
7
object DottyBuild extends Build {
7
8
@@ -16,8 +17,6 @@ object DottyBuild extends Build {
16
17
// "-XX:+HeapDumpOnOutOfMemoryError", "-Xmx1g", "-Xss2m"
17
18
)
18
19
19
- var partestLock : FileLock = null
20
-
21
20
val defaults = Defaults .defaultSettings ++ Seq (
22
21
scalaVersion in Global := " 2.11.5" ,
23
22
version in Global := " 0.1-SNAPSHOT" ,
@@ -42,16 +41,16 @@ object DottyBuild extends Build {
42
41
// to get Scala 2.11
43
42
resolvers += Resolver .sonatypeRepo(" releases" ),
44
43
45
- // get reflect and xml onboard
46
- libraryDependencies ++= Seq (" org.scala-lang" % " scala-reflect" % scalaVersion.value,
47
- " org.scala-lang.modules" %% " scala-xml" % " 1.0.1" ,
48
- " me.d-d" % " scala-compiler" % " 2.11.5-20150506-175515-8fc7635b56" ,
44
+ // get libraries onboard
45
+ partestDeps := Seq (" me.d-d" % " scala-compiler" % " 2.11.5-20150506-175515-8fc7635b56" ,
46
+ " org.scala-lang" % " scala-reflect" % scalaVersion.value,
47
+ " org.scala-lang" % " scala-library" % scalaVersion.value % " test" ),
48
+ libraryDependencies ++= partestDeps.value,
49
+ libraryDependencies ++= Seq (" org.scala-lang.modules" %% " scala-xml" % " 1.0.1" ,
49
50
" org.scala-lang.modules" %% " scala-partest" % " 1.0.5" % " test" ,
51
+ " com.novocode" % " junit-interface" % " 0.11" % " test" ,
50
52
" jline" % " jline" % " 2.12" ),
51
53
52
- // get junit onboard
53
- libraryDependencies += " com.novocode" % " junit-interface" % " 0.11" % " test" ,
54
-
55
54
// scalac options
56
55
scalacOptions in Global ++= Seq (" -feature" , " -deprecation" , " -language:_" ),
57
56
@@ -62,14 +61,26 @@ object DottyBuild extends Build {
62
61
63
62
// enable verbose exception messages for JUnit
64
63
testOptions in Test += Tests .Argument (TestFrameworks .JUnit , " -a" , " -v" , " --run-listener=test.ContextEscapeDetector" ),
65
- testOptions in Test += Tests .Cleanup ({ () => if (partestLock != null ) partestLock.release }),
66
- // when this file is locked, running test generates the files for partest
67
- // otherwise it just executes the tests directly
64
+ testOptions in Test += Tests .Cleanup ({ () => partestLockFile.delete }),
65
+
68
66
lockPartestFile := {
69
- val partestLockFile = " ." + File .separator + " tests" + File .separator + " partest.lock"
70
- partestLock = new RandomAccessFile (partestLockFile, " rw" ).getChannel.tryLock
67
+ // When this file is present, running `test` generates the files for
68
+ // partest. Otherwise it just executes the tests directly.
69
+ val lockDir = partestLockFile.getParentFile
70
+ lockDir.mkdirs
71
+ // Cannot have concurrent partests as they write to the same directory.
72
+ if (lockDir.list.size > 0 )
73
+ throw new RuntimeException (" ERROR: sbt partest: another partest is already running, pid in lock file: " + lockDir.list.toList.mkString(" " ))
74
+ partestLockFile.createNewFile
75
+ partestLockFile.deleteOnExit
76
+ },
77
+ runPartestRunner <<= Def .taskDyn {
78
+ val jars = Seq ((packageBin in Compile ).value.getAbsolutePath) ++
79
+ getJarPaths(partestDeps.value, ivyPaths.value.ivyHome)
80
+ val dottyJars = " -dottyJars " + jars.length + " " + jars.mkString(" " )
81
+ // Provide the jars required on the classpath of run tests
82
+ runTask(Test , " dotty.partest.DPConsoleRunner" , dottyJars)
71
83
},
72
- runPartestRunner <<= runTask(Test , " dotty.partest.DPConsoleRunner" , " " ) dependsOn (test in Test ),
73
84
74
85
// Adjust classpath for running dotty
75
86
mainClass in (Compile , run) := Some (" dotty.tools.dotc.Main" ),
@@ -79,31 +90,31 @@ object DottyBuild extends Build {
79
90
80
91
// http://grokbase.com/t/gg/simple-build-tool/135ke5y90p/sbt-setting-jvm-boot-paramaters-for-scala
81
92
javaOptions <++= (managedClasspath in Runtime , packageBin in Compile ) map { (attList, bin) =>
82
- // put the Scala {library, reflect} in the classpath
83
- val path = for {
84
- file <- attList.map(_.data)
85
- path = file.getAbsolutePath
86
- } yield " -Xbootclasspath/p:" + path
87
- // dotty itself needs to be in the bootclasspath
88
- val fullpath = (" -Xbootclasspath/a:" + bin) :: path.toList
89
- // System.err.println("BOOTPATH: " + fullpath)
90
-
91
- val travis_build = // propagate if this is a travis build
92
- if (sys.props.isDefinedAt(TRAVIS_BUILD ))
93
- List (s " -D $TRAVIS_BUILD= ${sys.props(TRAVIS_BUILD )}" ) ::: travisMemLimit
94
- else
95
- List ()
96
-
97
- val tuning =
98
- if (sys.props.isDefinedAt(" Oshort" ))
99
- // Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222
100
- List (" -XX:+TieredCompilation" , " -XX:TieredStopAtLevel=1" )
93
+ // put the Scala {library, reflect} in the classpath
94
+ val path = for {
95
+ file <- attList.map(_.data)
96
+ path = file.getAbsolutePath
97
+ } yield " -Xbootclasspath/p:" + path
98
+ // dotty itself needs to be in the bootclasspath
99
+ val fullpath = (" -Xbootclasspath/a:" + bin) :: path.toList
100
+ // System.err.println("BOOTPATH: " + fullpath)
101
+
102
+ val travis_build = // propagate if this is a travis build
103
+ if (sys.props.isDefinedAt(TRAVIS_BUILD ))
104
+ List (s " -D $TRAVIS_BUILD= ${sys.props(TRAVIS_BUILD )}" ) ::: travisMemLimit
101
105
else
102
106
List ()
103
107
104
- tuning ::: agentOptions ::: travis_build ::: fullpath
108
+ val tuning =
109
+ if (sys.props.isDefinedAt(" Oshort" ))
110
+ // Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222
111
+ List (" -XX:+TieredCompilation" , " -XX:TieredStopAtLevel=1" )
112
+ else
113
+ List ()
114
+
115
+ (" -DpartestParentID=" + pid) :: tuning ::: agentOptions ::: travis_build ::: fullpath
105
116
}
106
- ) ++ addCommandAlias(" partest" , " ;lockPartestFile;runPartestRunner" )
117
+ ) ++ addCommandAlias(" partest" , " ;test:compile; lockPartestFile;test:test ;runPartestRunner" )
107
118
108
119
lazy val dotty = Project (id = " dotty" , base = file(" ." ), settings = defaults)
109
120
@@ -154,7 +165,23 @@ object DottyBuild extends Build {
154
165
lazy val benchmarks = Project (id = " dotty-bench" , settings = benchmarkSettings,
155
166
base = file(" bench" )) dependsOn(dotty % " compile->test" )
156
167
157
- lazy val lockPartestFile = TaskKey [Unit ](" lockPartestFile" , " Creates the file lock on ./tests/partest.lock" )
158
- lazy val runPartestRunner = TaskKey [Unit ](" runPartestRunner" , " Runs partests" )
159
-
168
+ // Partest tasks
169
+ lazy val lockPartestFile = TaskKey [Unit ](" lockPartestFile" , " Creates the lock file at ./tests/locks/partest-<pid>.lock" )
170
+ lazy val partestLockFile = new File (" ." + File .separator + " tests" + File .separator + " locks" + File .separator + s " partest- $pid.lock " )
171
+ def pid = java.lang.Long .parseLong(java.lang.management.ManagementFactory .getRuntimeMXBean().getName().split(" @" )(0 ))
172
+
173
+ lazy val runPartestRunner = TaskKey [Unit ](" runPartestRunner" , " Runs partest" )
174
+
175
+ lazy val partestDeps = SettingKey [Seq [ModuleID ]](" partestDeps" , " Finds jars for partest dependencies" )
176
+ def getJarPaths (modules : Seq [ModuleID ], ivyHome : Option [File ]): Seq [String ] = ivyHome match {
177
+ case Some (home) =>
178
+ modules.map({ module =>
179
+ val file = Path (home) / Path (" cache" ) /
180
+ Path (module.organization) / Path (module.name) / Path (" jars" ) /
181
+ Path (module.name + " -" + module.revision + " .jar" )
182
+ if (! file.isFile) throw new RuntimeException (" ERROR: sbt getJarPaths: dependency jar not found: " + file)
183
+ else file.jfile.getAbsolutePath
184
+ })
185
+ case None => throw new RuntimeException (" ERROR: sbt getJarPaths: ivyHome not defined" )
186
+ }
160
187
}
0 commit comments