Skip to content

Commit 68ec8f7

Browse files
committed
Support -d with .jar paths
1 parent 0f208ed commit 68ec8f7

File tree

9 files changed

+84
-34
lines changed

9 files changed

+84
-34
lines changed

compiler/src/dotty/tools/backend/jvm/GenBCode.scala

+22-13
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import dotty.tools.dotc.util.{DotClass, Positions}
3434
import tpd._
3535
import StdNames._
3636

37-
import dotty.tools.io.{AbstractFile, Directory, PlainDirectory}
37+
import dotty.tools.io._
3838

3939
class GenBCode extends Phase {
4040
def phaseName: String = "genBCode"
@@ -47,27 +47,36 @@ class GenBCode extends Phase {
4747
superCallsMap.put(sym, old + calls)
4848
}
4949

50-
def outputDir(implicit ctx: Context): AbstractFile =
51-
new PlainDirectory(ctx.settings.outputDir.value)
50+
def outputDir(implicit ctx: Context): AbstractFile = {
51+
val path = ctx.settings.outputDir.value
52+
if (path.isDirectory) new PlainDirectory(Directory(path))
53+
else new PlainFile(path)
54+
}
5255

53-
private[this] var classFileOutput: AbstractFile = _
56+
private[this] var classOutput: AbstractFile = _
5457

5558
def run(implicit ctx: Context): Unit = {
5659
new GenBCodePipeline(entryPoints.toList,
57-
new DottyBackendInterface(classFileOutput, superCallsMap.toMap)(ctx))(ctx).run(ctx.compilationUnit.tpdTree)
60+
new DottyBackendInterface(classOutput, superCallsMap.toMap)(ctx))(ctx).run(ctx.compilationUnit.tpdTree)
5861
entryPoints.clear()
5962
}
6063

6164
override def runOn(units: List[CompilationUnit])(implicit ctx: Context) = {
62-
val out = outputDir
63-
lazy val tmp = out.subdirectoryNamed("tmp-" + System.currentTimeMillis().toHexString)
64-
classFileOutput = if (ctx.settings.XlinkOptimise.value) tmp else out
65-
val res = super.runOn(units)
66-
if (ctx.settings.XlinkOptimise.value) {
67-
Jar.create(new File(out.fileNamed("linked.jar").file), new Directory(classFileOutput.file), mainClass = "")
68-
tmp.delete()
65+
val output = outputDir
66+
if (output.isDirectory) {
67+
classOutput = output
68+
val res = super.runOn(units)
69+
classOutput = null
70+
res
71+
} else {
72+
assert(output.hasExtension("jar"))
73+
classOutput = new PlainDirectory(Path(Path(output.file).parent + "/tmp-jar-" + System.currentTimeMillis().toHexString).createDirectory())
74+
val res = super.runOn(units)
75+
Jar.create(new File(ctx.settings.outputDir.value.jfile), new Directory(classOutput.file), mainClass = "")
76+
classOutput.delete()
77+
classOutput = null
78+
res
6979
}
70-
res
7180
}
7281
}
7382

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ScalaSettings extends Settings.SettingGroup {
1818
val javaextdirs = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs)
1919
val sourcepath = PathSetting("-sourcepath", "Specify location(s) of source files.", "") // Defaults.scalaSourcePath
2020
val classpath = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp"
21-
val outputDir = DirectorySetting("-d", "directory|jar", "destination for generated classfiles.", Directory(Path(".")))
21+
val outputDir = DirectoryJarSetting("-d", "directory|jar", "destination for generated classfiles.", Directory(Path(".")))
2222
val priorityclasspath = PathSetting("-priorityclasspath", "class path that takes precedence over all other paths (or testing only)", "")
2323

2424
/** Other settings */

compiler/src/dotty/tools/dotc/config/Settings.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object Settings {
2222
val ListTag = ClassTag(classOf[List[_]])
2323
val VersionTag = ClassTag(classOf[ScalaVersion])
2424
val OptionTag = ClassTag(classOf[Option[_]])
25-
val DirectoryTag = ClassTag(classOf[Directory])
25+
val DirectoryJarTag = ClassTag(classOf[Path])
2626

2727
class SettingsState(initialValues: Seq[Any]) {
2828
private[this] var values = ArrayBuffer(initialValues: _*)
@@ -161,9 +161,10 @@ object Settings {
161161
case Success(v) => update(v, args)
162162
case Failure(ex) => fail(ex.getMessage, args)
163163
}
164-
case (DirectoryTag, arg :: args) =>
164+
case (DirectoryJarTag, arg :: args) =>
165165
val path = Path(arg)
166166
if (path.isDirectory) update(Directory(path), args)
167+
else if (path.extension == "jar") update(path, args)
167168
else fail(s"'$arg' does not exist or is not a directory", args)
168169
case (_, Nil) =>
169170
missingArg
@@ -286,7 +287,7 @@ object Settings {
286287
def OptionSetting[T: ClassTag](name: String, descr: String): Setting[Option[T]] =
287288
publish(Setting(name, descr, None, propertyClass = Some(implicitly[ClassTag[T]].runtimeClass)))
288289

289-
def DirectorySetting(name: String, helpArg: String, descr: String, default: Directory): Setting[Directory] =
290+
def DirectoryJarSetting(name: String, helpArg: String, descr: String, default: Directory): Setting[Path] =
290291
publish(Setting(name, descr, default, helpArg))
291292
}
292293
}

compiler/src/dotty/tools/dotc/transform/LinkAll.scala

+11-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class LinkAll extends Phase {
3434
}
3535
}
3636

37-
if (ctx.settings.XlinkOptimise.value) allUnits(Set.empty, units.toSet, Set.empty)
37+
if (doLink) allUnits(Set.empty, units.toSet, Set.empty)
3838
else units
3939
}
4040

@@ -62,6 +62,16 @@ class LinkAll extends Phase {
6262
else acc + topClass
6363
}
6464
}
65+
66+
private def doLink(implicit ctx: Context): Boolean = {
67+
val link = ctx.settings.XlinkOptimise
68+
if (link.value) {
69+
val out = ctx.settings.outputDir
70+
if (out.value.extension != "jar")
71+
ctx.error("With " + link.name + " the output directory " + out.name + " should be a .jar\n" + out.value)
72+
true
73+
} else false
74+
}
6575
}
6676

6777
object LinkAll {

compiler/src/dotty/tools/repl/ReplDriver.scala

+5-2
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,11 @@ class ReplDriver(settings: Array[String],
108108
val outDir: AbstractFile = {
109109
if (rootCtx.settings.outputDir.isDefault(rootCtx))
110110
new VirtualDirectory("(memory)", None)
111-
else
112-
new PlainDirectory(rootCtx.settings.outputDir.value(rootCtx))
111+
else {
112+
val path = rootCtx.settings.outputDir.value(rootCtx)
113+
assert(path.isDirectory)
114+
new PlainDirectory(Directory(path))
115+
}
113116
}
114117
compiler = new ReplCompiler(outDir)
115118
rendering = new Rendering(compiler, classLoader)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dotty
2+
package tools
3+
package dotc
4+
5+
import java.io.{File => JFile}
6+
7+
import org.junit.Assert._
8+
import org.junit.Test
9+
import vulpix.TestConfiguration.mkClassPath
10+
11+
class JarOutputTests {
12+
13+
@Test def jarOutput: Unit = {
14+
val classPath = mkClassPath(Jars.dottyTestDeps)
15+
val source = "../tests/neg/nolib/Foo.scala"
16+
val out = new JFile("../out/jaredFoo.jar")
17+
if (out.exists()) out.delete()
18+
val options = Array("-classpath", classPath, "-d", out.toString, source)
19+
val reporter = Main.process(options)
20+
assertEquals(0, reporter.errorCount)
21+
assertTrue(out.exists())
22+
}
23+
24+
}

compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class MissingCoreLibTests {
1212
@Test def missingDottyLib: Unit = {
1313
val classPath = mkClassPath(Jars.dottyCompiler :: Jars.dottyInterfaces :: Jars.dottyExtras) // missing Jars.dottyLib
1414
val source = "../tests/neg/nolib/Foo.scala"
15-
val options = Array("-classpath", classPath, source)
15+
val options = Array("-classpath", classPath, "-d", "../out/", source)
1616
val reporter = Main.process(options)
1717
assertEquals(1, reporter.errorCount)
1818
val errorMessage = reporter.allErrors.head.message

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

+15-12
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
5252
def outDir: JFile
5353
def flags: TestFlags
5454

55-
def runClassPath: String = {
56-
val out = outDir.getAbsolutePath + (if (flags.isLinkedOptimised) "/linked.jar" else "")
57-
out + ":" + flags.runClassPath
58-
}
55+
def runClassPath: String = outDir.getAbsolutePath + ":" + flags.runClassPath
5956

6057
def title: String = self match {
6158
case self: JointCompilationSource =>
@@ -1008,18 +1005,22 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10081005
}
10091006

10101007
/** Create out directory for directory `d` */
1011-
private def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String): JFile = {
1008+
private def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String, flags: TestFlags): JFile = {
10121009
val targetDir = new JFile(outDir + s"${sourceDir.getName}/${d.getName}")
10131010
targetDir.mkdirs()
1014-
targetDir
1011+
jaredIfNeeded(targetDir, flags)
10151012
}
10161013

10171014
/** Create out directory for `file` */
1018-
private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String): JFile = {
1015+
private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String, flags: TestFlags): JFile = {
10191016
val uniqueSubdir = file.getName.substring(0, file.getName.lastIndexOf('.'))
10201017
val targetDir = new JFile(outDir + s"${sourceDir.getName}/$uniqueSubdir")
10211018
targetDir.mkdirs()
1022-
targetDir
1019+
jaredIfNeeded(targetDir, flags)
1020+
}
1021+
1022+
private def jaredIfNeeded(targetDir: JFile, flags: TestFlags): JFile = {
1023+
new JFile(targetDir + (if (flags.isLinkTest) "/linked.jar" else ""))
10231024
}
10241025

10251026
/** Make sure that directory string is as expected */
@@ -1081,7 +1082,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10811082
callingMethod,
10821083
Array(sourceFile),
10831084
flags,
1084-
createOutputDirsForFile(sourceFile, parent, outDir)
1085+
createOutputDirsForFile(sourceFile, parent, outDir, flags)
10851086
)
10861087
new CompilationTest(target)
10871088
}
@@ -1161,9 +1162,11 @@ trait ParallelTesting extends RunnerOrchestration { self =>
11611162

11621163
val (dirs, files) = compilationTargets(sourceDir)
11631164

1165+
def createOutputDirsFor(f: JFile): JFile = createOutputDirsForFile(f, sourceDir, outDir, flags)
1166+
11641167
val targets =
1165-
files.map(f => JointCompilationSource(callingMethod, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++
1166-
dirs.map(dir => SeparateCompilationSource(callingMethod, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir)))
1168+
files.map(f => JointCompilationSource(callingMethod, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir, flags))) ++
1169+
dirs.map(dir => SeparateCompilationSource(callingMethod, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir, flags)))
11671170

11681171
// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
11691172
new CompilationTest(targets)
@@ -1182,7 +1185,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
11821185
val (_, files) = compilationTargets(sourceDir)
11831186

11841187
val targets = files.map { file =>
1185-
JointCompilationSource(callingMethod, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir))
1188+
JointCompilationSource(callingMethod, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir, flags))
11861189
}
11871190

11881191
// Create a CompilationTest and let the user decide whether to execute a pos or a neg test

compiler/test/dotty/tools/vulpix/TestFlags.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ final case class TestFlags(
1313

1414
def all: Array[String] = Array("-classpath", defaultClassPath) ++ options
1515

16-
def isLinkedOptimised: Boolean = options.contains("-Xlink-optimise")
16+
def isLinkTest: Boolean = options.contains("-Xlink-optimise")
1717
}
1818

1919
object TestFlags {

0 commit comments

Comments
 (0)