Skip to content

Link directly to a JAR #3377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ package dotc

import dotty.tools.dotc.core.Types.Type // Do not remove me #3383
import util.SourceFile
import ast.{tpd, untpd}
import dotty.tools.dotc.ast.tpd.{ Tree, TreeTraverser }
import dotty.tools.dotc.ast.{ tpd, untpd }
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.SymDenotations.ClassDenotation
import dotty.tools.dotc.core.Symbols._
Expand All @@ -26,17 +25,17 @@ class CompilationUnit(val source: SourceFile) {
object CompilationUnit {

/** Make a compilation unit for top class `clsd` with the contends of the `unpickled` */
def mkCompilationUnit(clsd: ClassDenotation, unpickled: Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = {
def mkCompilationUnit(clsd: ClassDenotation, unpickled: tpd.Tree, forceTrees: Boolean)(implicit ctx: Context): CompilationUnit = {
assert(!unpickled.isEmpty, unpickled)
val unit1 = new CompilationUnit(new SourceFile(clsd.symbol.sourceFile, Seq()))
val unit1 = new CompilationUnit(new SourceFile(clsd.symbol.associatedFile, Seq()))
unit1.tpdTree = unpickled
if (forceTrees)
force.traverse(unit1.tpdTree)
unit1
}

/** Force the tree to be loaded */
private object force extends TreeTraverser {
def traverse(tree: Tree)(implicit ctx: Context): Unit = traverseChildren(tree)
private object force extends tpd.TreeTraverser {
def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = traverseChildren(tree)
}
}
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class ScalaSettings extends Settings.SettingGroup {
val YoptPhases = PhasesSetting("-Yopt-phases", "Restrict the optimisation phases to execute under -optimise.")
val YoptFuel = IntSetting("-Yopt-fuel", "Maximum number of optimisations performed under -optimise.", -1)
val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying local optimisations to the .program") withAbbreviation "-optimize"
val XlinkOptimise = BooleanSetting("-Xlink-optimise", "Recompile library code with the application.").withAbbreviation("-Xlink-optimize")
val Xlink = BooleanSetting("-Xlink", "Recompile library code with the application.")

/** Dottydoc specific settings */
val siteRoot = StringSetting(
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
}

private def mayLoadTreesFromTasty(implicit ctx: Context): Boolean =
ctx.settings.YretainTrees.value || ctx.settings.XlinkOptimise.value || ctx.settings.tasty.value
ctx.settings.YretainTrees.value || ctx.settings.Xlink.value || ctx.settings.tasty.value
}

class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ object Symbols {

/** If this is either:
* - a top-level class and `-Yretain-trees` is set
* - a top-level class loaded from TASTY and `-Xlink-optimise` is set
* - a top-level class loaded from TASTY and `-Xlink` is set
* then return the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree.
* This will force the info of the class.
*/
Expand Down
14 changes: 12 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/LinkAll.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class LinkAll extends Phase {
}
}

if (ctx.settings.XlinkOptimise.value) allUnits(Set.empty, units.toSet, Set.empty)
if (doLink) allUnits(Set.empty, units.toSet, Set.empty)
else units
}

Expand Down Expand Up @@ -62,12 +62,22 @@ class LinkAll extends Phase {
else acc + topClass
}
}

private def doLink(implicit ctx: Context): Boolean = {
val link = ctx.settings.Xlink
if (link.value) {
val out = ctx.settings.outputDir
if (out.value.endsWith(".jar"))
ctx.error("With " + link.name + " the output directory " + out.name + " should be a .jar\n" + out.value)
true
} else false
}
}

object LinkAll {

private[LinkAll] def loadCompilationUnit(clsd: ClassDenotation)(implicit ctx: Context): Option[CompilationUnit] = {
assert(ctx.settings.XlinkOptimise.value)
assert(ctx.settings.Xlink.value)
val tree = clsd.symbol.asClass.tree
if (tree.isEmpty) None
else {
Expand Down
10 changes: 6 additions & 4 deletions compiler/test/dotty/tools/dotc/LinkTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dotty
package tools
package dotc

import dotty.tools.io.Jar

import java.io.{File => JFile}
import java.nio.file.{Files, Path, Paths}

Expand Down Expand Up @@ -44,7 +46,7 @@ class LinkTests extends ParallelTesting {

// Setup class paths
def mkLinkClassFlags(libPath: String) =
TestFlags(mkClassPath(libPath :: Jars.dottyTestDeps), mkClassPath(Jars.dottyTestDeps), basicDefaultOptions :+ "-Xlink-optimise")
TestFlags(mkClassPath(libPath :: Jars.dottyTestDeps), mkClassPath(Jars.dottyTestDeps), basicDefaultOptions :+ "-Xlink")
val strawmanClassPath = mkLinkClassFlags(defaultOutputDir + strawmanLibGroup + "/main/")
val customLibClassFlags = mkLinkClassFlags(defaultOutputDir + linkCustomLibGroup + "/custom-lib")

Expand All @@ -61,11 +63,11 @@ class LinkTests extends ParallelTesting {
for (check <- new JFile(sourceDir).listFiles().filter(_.toString.endsWith(checkExt))) {
val outDir = {
def path(str: String) = str.substring(linkDir.length, str.length - checkExt.length)
defaultOutputDir + testName + path(check.toString) + "/"
defaultOutputDir + testName + path(check.toString) + "/linked.jar"
}
val expectedClasses = scala.io.Source.fromFile(check).getLines().toSet
val actualClasses = Files.walk(Paths.get(outDir)).iterator().asScala.collect {
case f if f.toString.endsWith(".class") => f.toString.substring(outDir.length, f.toString.length - ".class".length)
val actualClasses = new Jar(outDir).iterator.collect {
case f if f.toString.endsWith(".class") => f.toString.substring(0, f.toString.length - ".class".length)
}.toSet
assertEquals(check.toString, expectedClasses, actualClasses)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/dotc/MissingCoreLibTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MissingCoreLibTests {
@Test def missingDottyLib: Unit = {
val classPath = mkClassPath(Jars.dottyCompiler :: Jars.dottyInterfaces :: Jars.dottyExtras) // missing Jars.dottyLib
val source = "../tests/neg/nolib/Foo.scala"
val options = Array("-classpath", classPath, source)
val options = Array("-classpath", classPath, "-d", "../out/", source)
val reporter = Main.process(options)
assertEquals(1, reporter.errorCount)
val errorMessage = reporter.allErrors.head.message
Expand Down
24 changes: 14 additions & 10 deletions compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1027,18 +1027,22 @@ trait ParallelTesting extends RunnerOrchestration { self =>
}

/** Create out directory for directory `d` */
private def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String): JFile = {
private def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String, flags: TestFlags): JFile = {
val targetDir = new JFile(outDir + s"${sourceDir.getName}/${d.getName}")
targetDir.mkdirs()
targetDir
jaredIfNeeded(targetDir, flags)
}

/** Create out directory for `file` */
private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String): JFile = {
private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String, flags: TestFlags): JFile = {
val uniqueSubdir = file.getName.substring(0, file.getName.lastIndexOf('.'))
val targetDir = new JFile(outDir + s"${sourceDir.getName}/$uniqueSubdir")
targetDir.mkdirs()
targetDir
jaredIfNeeded(targetDir, flags)
}

private def jaredIfNeeded(targetDir: JFile, flags: TestFlags): JFile = {
new JFile(targetDir + (if (flags.isLinkTest) "/linked.jar" else ""))
}

/** Make sure that directory string is as expected */
Expand Down Expand Up @@ -1073,7 +1077,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
testGroup.name,
Array(sourceFile),
flags,
createOutputDirsForFile(sourceFile, parent, outDir)
createOutputDirsForFile(sourceFile, parent, outDir, flags)
)
new CompilationTest(target)
}
Expand All @@ -1095,7 +1099,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
(parent ne null) && parent.exists && parent.isDirectory,
s"Source file: $f, didn't exist"
)
val tastySource = createOutputDirsForFile(sourceFile, parent, outDir)
val tastySource = createOutputDirsForFile(sourceFile, parent, outDir, flags)
val target = JointCompilationSource(
testGroup.name,
Array(sourceFile),
Expand Down Expand Up @@ -1180,8 +1184,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
val (dirs, files) = compilationTargets(sourceDir)

val targets =
files.map(f => JointCompilationSource(testGroup.name, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++
dirs.map(dir => SeparateCompilationSource(testGroup.name, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir)))
files.map(f => JointCompilationSource(testGroup.name, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir, flags))) ++
dirs.map(dir => SeparateCompilationSource(testGroup.name, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir, flags)))

// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
new CompilationTest(targets)
Expand Down Expand Up @@ -1217,7 +1221,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>

val targets =
files.map { f =>
val classpath = createOutputDirsForFile(f, sourceDir, outDir)
val classpath = createOutputDirsForFile(f, sourceDir, outDir, flags)
JointCompilationSource(testGroup.name, Array(f), flags.withClasspath(classpath.getPath), classpath, fromTasty = true)
}
// TODO add SeparateCompilationSource from tasty?
Expand All @@ -1240,7 +1244,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
val (_, files) = compilationTargets(sourceDir)

val targets = files.map { file =>
JointCompilationSource(testGroup.name, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir))
JointCompilationSource(testGroup.name, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir, flags))
}

// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
Expand Down
2 changes: 2 additions & 0 deletions compiler/test/dotty/tools/vulpix/TestFlags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ final case class TestFlags(
TestFlags(s"$defaultClassPath:$classPath", runClassPath, options)

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

def isLinkTest: Boolean = options.contains("-Xlink")
}

object TestFlags {
Expand Down