diff --git a/bridges/scala-native/src/main/scala/bloop/scalanative/NativeBridge.scala b/bridges/scala-native/src/main/scala/bloop/scalanative/NativeBridge.scala index 0059241d50..b83e055196 100644 --- a/bridges/scala-native/src/main/scala/bloop/scalanative/NativeBridge.scala +++ b/bridges/scala-native/src/main/scala/bloop/scalanative/NativeBridge.scala @@ -15,7 +15,7 @@ object NativeBridge { if (workdir.isDirectory) Paths.delete(workdir) Files.createDirectories(workdir.underlying) - val classpath = project.classpath.map(_.underlying) + val classpath = project.compilationClasspath.map(_.underlying) val nativeLogger = NativeLogger(logger.debug _, logger.info _, logger.warn _, logger.error _) val config = setUpNativeConfig(project, config0) val nativeMode = config.mode match { @@ -66,7 +66,7 @@ object NativeBridge { if (config.nativelib.toString.nonEmpty) config.nativelib else { Discover - .nativelib(project.classpath.map(_.underlying)) + .nativelib(project.compilationClasspath.map(_.underlying)) .getOrElse(sys.error("Fatal: nativelib is missing and could not be found.")) } } diff --git a/bridges/scalajs-0.6/src/main/scala/bloop/scalajs/JsBridge.scala b/bridges/scalajs-0.6/src/main/scala/bloop/scalajs/JsBridge.scala index fb0580e3be..628ac3dbb2 100644 --- a/bridges/scalajs-0.6/src/main/scala/bloop/scalajs/JsBridge.scala +++ b/bridges/scalajs-0.6/src/main/scala/bloop/scalajs/JsBridge.scala @@ -57,7 +57,7 @@ object JsBridge { target: Path, logger: BloopLogger ): Unit = { - val classpath = project.classpath.map(_.underlying) + val classpath = project.compilationClasspath.map(_.underlying) val classpathIrFiles = classpath .filter(Files.isDirectory(_)) .flatMap(findIrFiles) diff --git a/bridges/scalajs-1.0/src/main/scala/bloop/scalajs/JsBridge.scala b/bridges/scalajs-1.0/src/main/scala/bloop/scalajs/JsBridge.scala index c8a6ada55f..9216a86489 100644 --- a/bridges/scalajs-1.0/src/main/scala/bloop/scalajs/JsBridge.scala +++ b/bridges/scalajs-1.0/src/main/scala/bloop/scalajs/JsBridge.scala @@ -59,7 +59,7 @@ object JsBridge { } val cache = new IRFileCache().newCache - val irClasspath = FileScalaJSIRContainer.fromClasspath(project.classpath.map(_.toFile)) + val irClasspath = FileScalaJSIRContainer.fromClasspath(project.compilationClasspath.map(_.toFile)) val irFiles = cache.cached(irClasspath) val moduleInitializers = mainClass match { diff --git a/config/src/main/scala/bloop/config/Config.scala b/config/src/main/scala/bloop/config/Config.scala index abf717e963..2a7ebc5487 100644 --- a/config/src/main/scala/bloop/config/Config.scala +++ b/config/src/main/scala/bloop/config/Config.scala @@ -183,6 +183,7 @@ object Config { classpath: List[Path], out: Path, classesDir: Path, + resources: Option[List[Path]], `scala`: Option[Scala], java: Option[Java], sbt: Option[Sbt], @@ -193,7 +194,7 @@ object Config { object Project { // FORMAT: OFF - private[bloop] val empty: Project = Project("", emptyPath, List(), List(), List(), emptyPath, emptyPath, None, None, None, None, None, None) + private[bloop] val empty: Project = Project("", emptyPath, List(), List(), List(), emptyPath, emptyPath, None, None, None, None, None, None, None) // FORMAT: ON def analysisFileName(projectName: String) = s"$projectName-analysis.bin" @@ -201,7 +202,7 @@ object Config { case class File(version: String, project: Project) object File { - final val LatestVersion = "1.1.0-M1" + final val LatestVersion = "1.1.0-M2" private[bloop] val empty = File(LatestVersion, Project.empty) @@ -237,6 +238,7 @@ object Config { List(scalaLibraryJar), outDir, classesDir, + Some(List(outDir.resolve("resource1.xml"))), Some( Scala( "org.scala-lang", diff --git a/config/src/main/scala/bloop/config/util/ConfigUtil.scala b/config/src/main/scala/bloop/config/util/ConfigUtil.scala new file mode 100644 index 0000000000..56487f742d --- /dev/null +++ b/config/src/main/scala/bloop/config/util/ConfigUtil.scala @@ -0,0 +1,26 @@ +package bloop.config.util + +import java.nio.file.{Path, Files} + +object ConfigUtil { + def pathsOutsideRoots(roots: Seq[Path], paths: Seq[Path]): Seq[Path] = { + paths.filterNot { path => + roots.exists { root => + var found: Boolean = false + val rootDirSize = root.toString.size + var currentTarget = (if (Files.isRegularFile(path)) path.getParent else path).toAbsolutePath + while (!found && + currentTarget != null && + // Use a heuristic to know if we should short-circuit and return false + currentTarget.toString.size >= rootDirSize) { + if (currentTarget == root) { + found = true + } + + currentTarget = currentTarget.getParent + } + found + } + } + } +} diff --git a/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala b/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala index 79febd1d8f..c0c06f9588 100644 --- a/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala +++ b/frontend/src/main/scala/bloop/bsp/BloopBspServices.scala @@ -498,7 +498,7 @@ final class BloopBspServices( bsp.ScalacOptionsItem( target = target, options = project.scalacOptions.toList, - classpath = project.classpath.map(e => bsp.Uri(e.toBspUri)).toList, + classpath = project.compilationClasspath.map(e => bsp.Uri(e.toBspUri)).toList, classDirectory = bsp.Uri(project.classesDir.toBspUri) ) }.toList diff --git a/frontend/src/main/scala/bloop/data/Project.scala b/frontend/src/main/scala/bloop/data/Project.scala index ff69aee506..71e65e426d 100644 --- a/frontend/src/main/scala/bloop/data/Project.scala +++ b/frontend/src/main/scala/bloop/data/Project.scala @@ -10,6 +10,7 @@ import xsbti.compile.{ClasspathOptions, CompileOrder} import bloop.ScalaInstance import bloop.bsp.ProjectUris import bloop.config.{Config, ConfigEncoderDecoders} +import bloop.engine.Dag import bloop.engine.tasks.toolchains.{JvmToolchain, ScalaJsToolchain, ScalaNativeToolchain} import ch.epfl.scala.{bsp => Bsp} @@ -19,6 +20,7 @@ final case class Project( dependencies: List[String], scalaInstance: Option[ScalaInstance], rawClasspath: List[AbsolutePath], + resources: List[AbsolutePath], compileSetup: Config.CompileSetup, classesDir: AbsolutePath, scalacOptions: List[String], @@ -33,11 +35,12 @@ final case class Project( resolution: Option[Config.Resolution], origin: Origin ) { + /** The bsp uri associated with this project. */ val bspUri: Bsp.Uri = Bsp.Uri(ProjectUris.toURI(baseDirectory, name)) /** This project's full classpath (classes directory and raw classpath) */ - val classpath: Array[AbsolutePath] = (classesDir :: rawClasspath).toArray + val compilationClasspath: Array[AbsolutePath] = (classesDir :: rawClasspath).toArray val classpathOptions: ClasspathOptions = { ClasspathOptions.of( @@ -63,6 +66,20 @@ final case class Project( case _ => false } } + + def fullClasspathFor(dag: Dag[Project]): Array[AbsolutePath] = { + val cp = compilationClasspath.toBuffer + // Add the resources right after the classes directory if found in the classpath + Dag.dfs(dag).foreach { p => + val index = cp.indexOf(p.classesDir) + // If there is an anomaly and the classes dir of a dependency is missing, add resource at end + if (index == -1) { + p.resources.foreach(r => cp.append(r)) + } + else cp.insertAll(index, p.resources) + } + cp.toArray + } } object Project { @@ -113,6 +130,7 @@ object Project { val analysisOut = scala .flatMap(_.analysis.map(AbsolutePath.apply)) .getOrElse(out.resolve(Config.Project.analysisFileName(project.name))) + val resources = project.resources.toList.flatten.map(AbsolutePath.apply) Project( project.name, @@ -120,6 +138,7 @@ object Project { project.dependencies, instance, project.classpath.map(AbsolutePath.apply), + resources, setup, AbsolutePath(project.classesDir), scala.map(_.options).getOrElse(Nil), diff --git a/frontend/src/main/scala/bloop/engine/tasks/CompilationTask.scala b/frontend/src/main/scala/bloop/engine/tasks/CompilationTask.scala index eef2d508f4..d45659c5c8 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/CompilationTask.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/CompilationTask.scala @@ -85,7 +85,7 @@ object CompilationTask { instance, compilerCache, sources.toArray, - project.classpath, + project.compilationClasspath, graphInputs.store, project.classesDir, project.out, diff --git a/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala b/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala index 14a0d09ba1..c73f31b160 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/Tasks.scala @@ -54,7 +54,7 @@ object Tasks { import state.logger project.scalaInstance match { case Some(instance) => - val classpath = project.classpath + val classpath = project.fullClasspathFor(state.build.getDagFor(project)) val entries = classpath.map(_.underlying.toFile).toSeq logger.debug(s"Setting up the console classpath with ${entries.mkString(", ")}")( DebugFilter.All) @@ -182,7 +182,7 @@ object Tasks { fqn: String, args: Array[String] ): Task[State] = { - val classpath = project.classpath + val classpath = project.fullClasspathFor(state.build.getDagFor(project)) val processConfig = Forker(javaEnv, classpath) val runTask = processConfig.runMain(cwd, fqn, args, state.logger, state.commonOptions) runTask.map { exitCode => diff --git a/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala b/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala index 85aaf2fc49..92d5aedb45 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/TestTask.scala @@ -3,7 +3,7 @@ package bloop.engine.tasks import bloop.cli.ExitStatus import bloop.config.Config import bloop.data.{Platform, Project} -import bloop.engine.{Feedback, State} +import bloop.engine.{Dag, Feedback, State} import bloop.engine.tasks.toolchains.ScalaJsToolchain import bloop.exec.Forker import bloop.io.AbsolutePath @@ -129,7 +129,8 @@ object TestTask { implicit val logContext: DebugFilter = DebugFilter.Test project.platform match { case Platform.Jvm(env, _, _) => - val forker = Forker(env, project.classpath) + val classpath = project.fullClasspathFor(state.build.getDagFor(project)) + val forker = Forker(env, classpath) val testLoader = forker.newClassLoader(Some(TestInternals.filteredLoader)) val frameworks = project.testFrameworks.flatMap(f => TestInternals.loadFramework(testLoader, f.names, logger)) diff --git a/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileGraph.scala b/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileGraph.scala index cc1c01c6d0..563779d418 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileGraph.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/compilation/CompileGraph.scala @@ -214,7 +214,7 @@ object CompileGraph { // Let's order the IRs exactly in the same order as provided in the classpath! // Required for symbol clashes in dependencies (`AppLoader` in guardian/frontend) - val indexDirs = project.classpath.iterator.filter(_.isDirectory).zipWithIndex.toMap + val indexDirs = project.compilationClasspath.iterator.filter(_.isDirectory).zipWithIndex.toMap val dependentStore = { val transitiveStores = results.flatMap(r => indexDirs.get(r.bundle.project.classesDir).iterator.map(i => i -> r.store)) diff --git a/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala b/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala index 0b8a49b793..75e786f3c3 100644 --- a/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala +++ b/frontend/src/test/scala/bloop/bsp/BspProtocolSpec.scala @@ -317,7 +317,7 @@ class BspProtocolSpec { Assert.assertEquals(obtainedUri, expectedUri) val obtainedOptions = stringifyOptions(opts.options, opts.classpath, opts.classDirectory) - val classpath = p.classpath.iterator.map(i => bsp.Uri(i.toBspUri)).toList + val classpath = p.compilationClasspath.iterator.map(i => bsp.Uri(i.toBspUri)).toList val classesDir = bsp.Uri(p.classesDir.toBspUri) val expectedOptions = stringifyOptions(p.scalacOptions.toList, classpath, classesDir) diff --git a/frontend/src/test/scala/bloop/engine/DagSpec.scala b/frontend/src/test/scala/bloop/engine/DagSpec.scala index 3d7c82d6a5..033d6ba59e 100644 --- a/frontend/src/test/scala/bloop/engine/DagSpec.scala +++ b/frontend/src/test/scala/bloop/engine/DagSpec.scala @@ -21,8 +21,8 @@ class DagSpec { // format: OFF def dummyOrigin = TestUtil.syntheticOriginFor(dummyPath) def dummyProject(name: String, dependencies: List[String]): Project = - Project(name, dummyPath, dependencies, Some(dummyInstance), Nil, compileOptions, dummyPath, Nil, - Nil, Nil, Nil, Config.TestOptions.empty, dummyPath, dummyPath, + Project(name, dummyPath, dependencies, Some(dummyInstance), Nil, Nil, compileOptions, + dummyPath, Nil, Nil, Nil, Nil, Config.TestOptions.empty, dummyPath, dummyPath, Project.defaultPlatform(logger), None, None, dummyOrigin) // format: ON diff --git a/frontend/src/test/scala/bloop/exec/ForkerSpec.scala b/frontend/src/test/scala/bloop/exec/ForkerSpec.scala index 11c7730cac..32f4ea4887 100644 --- a/frontend/src/test/scala/bloop/exec/ForkerSpec.scala +++ b/frontend/src/test/scala/bloop/exec/ForkerSpec.scala @@ -43,7 +43,7 @@ class ForkerSpec { val cwdPath = AbsolutePath(cwd) val project = TestUtil.getProject(TestUtil.RootProject, state) val env = JavaEnv.default - val classpath = project.classpath + val classpath = project.fullClasspathFor(state.build.getDagFor(project)) val config = Forker(env, classpath) val logger = new RecordingLogger val opts = state.commonOptions.copy(env = TestUtil.runAndTestProperties) diff --git a/frontend/src/test/scala/bloop/tasks/IntegrationTestSuite.scala b/frontend/src/test/scala/bloop/tasks/IntegrationTestSuite.scala index 945bfa63f4..89b1258e70 100644 --- a/frontend/src/test/scala/bloop/tasks/IntegrationTestSuite.scala +++ b/frontend/src/test/scala/bloop/tasks/IntegrationTestSuite.scala @@ -79,6 +79,7 @@ class IntegrationTestSuite(testDirectory: Path) { dependencies = previousProjects.map(_.name), scalaInstance = previousProjects.head.scalaInstance, rawClasspath = Nil, + resources = Nil, compileSetup = Config.CompileSetup.empty, classesDir = classesDir, scalacOptions = Nil, diff --git a/frontend/src/test/scala/bloop/tasks/JsTestSpec.scala b/frontend/src/test/scala/bloop/tasks/JsTestSpec.scala index ee0fa31b2b..4149131267 100644 --- a/frontend/src/test/scala/bloop/tasks/JsTestSpec.scala +++ b/frontend/src/test/scala/bloop/tasks/JsTestSpec.scala @@ -181,7 +181,8 @@ class JsTestSpec( @Test def testsAreDetected(): Unit = { // Load the project's classpath by filtering out unwanted FQNs to create the test loader - val classpathEntries = testProject.classpath.map(_.underlying.toUri.toURL) + val classpath = testProject.fullClasspathFor(testState.build.getDagFor(testProject)) + val classpathEntries = classpath.map(_.underlying.toUri.toURL) val testLoader = new URLClassLoader(classpathEntries, Some(TestInternals.filteredLoader).orNull) def frameworks(classLoader: ClassLoader): List[Framework] = { testProject.testFrameworks.flatMap(f => diff --git a/frontend/src/test/scala/bloop/tasks/JvmTestSpec.scala b/frontend/src/test/scala/bloop/tasks/JvmTestSpec.scala index 0472ff18fa..21a8bfc59c 100644 --- a/frontend/src/test/scala/bloop/tasks/JvmTestSpec.scala +++ b/frontend/src/test/scala/bloop/tasks/JvmTestSpec.scala @@ -82,7 +82,8 @@ class JvmTestSpec( private val processRunnerConfig: Forker = { val javaEnv = JavaEnv.default - val classpath = testProject.classpath + val classpath = testProject.fullClasspathFor(testState.build.getDagFor(testProject)) + val classpathEntries = classpath.map(_.underlying.toUri.toURL) Forker(javaEnv, classpath) } diff --git a/frontend/src/test/scala/bloop/tasks/TestResourcesSpec.scala b/frontend/src/test/scala/bloop/tasks/TestResourcesSpec.scala index b23e6d503e..0619fd810c 100644 --- a/frontend/src/test/scala/bloop/tasks/TestResourcesSpec.scala +++ b/frontend/src/test/scala/bloop/tasks/TestResourcesSpec.scala @@ -1,13 +1,11 @@ package bloop.tasks import org.junit.Test -import org.junit.Assert.assertEquals import org.junit.experimental.categories.Category import sbt.internal.util.EscHelpers.removeEscapeSequences import bloop.cli.Commands -import bloop.exec.JavaEnv import bloop.tasks.TestUtil.{loadTestProject, runAndCheck} @Category(Array(classOf[bloop.FastTests])) diff --git a/frontend/src/test/scala/bloop/tasks/TestUtil.scala b/frontend/src/test/scala/bloop/tasks/TestUtil.scala index 76ce8c160e..3c2f036ae3 100644 --- a/frontend/src/test/scala/bloop/tasks/TestUtil.scala +++ b/frontend/src/test/scala/bloop/tasks/TestUtil.scala @@ -289,6 +289,7 @@ object TestUtil { dependencies = dependencies.toList, scalaInstance = scalaInstance, rawClasspath = classpath, + resources = Nil, compileSetup = Config.CompileSetup.empty.copy(order = compileOrder), classesDir = AbsolutePath(target), scalacOptions = Nil, diff --git a/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala b/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala index 5ebe9857a4..ac926223cf 100644 --- a/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala +++ b/integrations/gradle-bloop/src/main/scala/bloop/integrations/gradle/model/BloopConverter.scala @@ -94,6 +94,7 @@ final class BloopConverter(parameters: BloopParameters) { classpath = classpath, out = project.getBuildDir.toPath, classesDir = classesDir, + resources = Some(getResources(sourceSet)), `scala` = scalaConfig, java = getJavaConfig(project, sourceSet), sbt = None, @@ -118,6 +119,9 @@ final class BloopConverter(parameters: BloopParameters) { private def getSources(sourceSet: SourceSet): List[Path] = sourceSet.getAllSource.getSrcDirs.asScala.map(_.toPath).toList + private def getResources(sourceSet: SourceSet): List[Path] = + sourceSet.getResources.getSrcDirs.asScala.map(_.toPath).toList + private def isProjectDependency( projectDependencies: List[ProjectDependency], resolvedArtifact: ResolvedArtifact diff --git a/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala b/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala index 864957247a..be86e6c886 100644 --- a/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala +++ b/integrations/maven-bloop/src/main/scala/bloop/integrations/maven/MojoImplementation.scala @@ -2,15 +2,19 @@ package bloop.integrations.maven import java.io.File import java.nio.file.{Files, Path} +import java.util import bloop.config.Config import org.apache.maven.execution.MavenSession +import org.apache.maven.model.Resource import org.apache.maven.plugin.logging.Log import org.apache.maven.plugin.{MavenPluginManager, Mojo, MojoExecution} import org.apache.maven.project.MavenProject import org.codehaus.plexus.util.xml.Xpp3Dom import scala_maven.AppLauncher +import scala.collection.mutable + object MojoImplementation { private val ScalaMavenGroupArtifact = "net.alchim31.maven:scala-maven-plugin" @@ -68,6 +72,13 @@ object MojoImplementation { private val DefaultTestOptions = Config.TestOptions(Nil, List(Config.TestArgument(List("-v", "-a"), Some(JUnitFramework)))) + def writeConfig( + asScala: mutable.Buffer[File], + getTestOutputDir: File, + strings: util.List[String], + launcher: AppLauncher, + str: String): Int = ??? + def writeCompileAndTestConfiguration(mojo: BloopMojo, session: MavenSession, log: Log): Unit = { import scala.collection.JavaConverters._ def abs(file: File): Path = file.toPath().toRealPath().toAbsolutePath() @@ -97,11 +108,13 @@ object MojoImplementation { val allScalaJars = mojo.getAllScalaJars().map(abs).toList val scalacArgs = mojo.getScalacArgs().asScala.toList - def writeConfig(sourceDirs0: Seq[File], - classesDir0: File, - classpath0: java.util.List[_], - launcher: AppLauncher, - configuration: String): Unit = { + def writeConfig( + sourceDirs0: Seq[File], + classesDir0: File, + classpath0: java.util.List[_], + resources0: java.util.List[Resource], + launcher: AppLauncher, + configuration: String): Unit = { val suffix = if (configuration == "compile") "" else s"-$configuration" val name = project.getArtifactId() + suffix val build = project.getBuild() @@ -131,7 +144,9 @@ object MojoImplementation { val mainClass = if (launcher.getMainClass().isEmpty) None else Some(launcher.getMainClass()) val platform = Some(Config.Platform.Jvm(Config.JvmConfig(javaHome, launcher.getJvmArgs().toList), mainClass)) val resolution = None - val project = Config.Project(name, baseDirectory, sourceDirs, dependencyNames, classpath, out, classesDir, `scala`, java, sbt, test, platform, resolution) + // Resources in Maven require + val resources = Some(resources0.asScala.toList.map(r => classesDir.resolve(r.getTargetPath))) + val project = Config.Project(name, baseDirectory, sourceDirs, dependencyNames, classpath, out, classesDir, resources, `scala`, java, sbt, test, platform, resolution) Config.File(Config.File.LatestVersion, project) } // FORMAT: ON @@ -142,16 +157,23 @@ object MojoImplementation { bloop.config.write(config, configTarget.toPath) } - writeConfig(mojo.getCompileSourceDirectories.asScala, - mojo.getCompileOutputDir, - project.getCompileClasspathElements(), - launcher, - "compile") - writeConfig(mojo.getTestSourceDirectories.asScala, - mojo.getTestOutputDir, - project.getTestClasspathElements(), - launcher, - "test") + writeConfig( + mojo.getCompileSourceDirectories.asScala, + mojo.getCompileOutputDir, + project.getCompileClasspathElements, + project.getResources, + launcher, + "compile" + ) + + writeConfig( + mojo.getTestSourceDirectories.asScala, + mojo.getTestOutputDir, + project.getTestClasspathElements, + project.getTestResources, + launcher, + "test" + ) } private def relativize(base: File, file: File): Option[String] = { diff --git a/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala b/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala index d92a8373ef..93b60a564b 100644 --- a/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala +++ b/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala @@ -4,8 +4,8 @@ import _root_.mill._ import _root_.mill.define._ import _root_.mill.scalalib._ import _root_.mill.eval.Evaluator - import ammonite.ops._ +import bloop.config.util.ConfigUtil object Bloop extends ExternalModule { @@ -33,8 +33,7 @@ object Bloop extends ExternalModule { val scalaConfig = module match { case s: ScalaModule => T.task { - val pluginOptions = s.scalacPluginClasspath().map { pathRef => - s"-Xplugin:${pathRef.path}" + val pluginOptions = s.scalacPluginClasspath().map { pathRef => s"-Xplugin:${pathRef.path}" } Some( @@ -88,12 +87,12 @@ object Bloop extends ExternalModule { def transitiveClasspath(m: JavaModule): Task[Seq[Path]] = T.task { m.moduleDeps.map(classes) ++ - m.resources().map(_.path) ++ m.unmanagedClasspath().map(_.path) ++ Task.traverse(m.moduleDeps)(transitiveClasspath)().flatten } val classpath = T.task(transitiveClasspath(module)() ++ ivyDepsClasspath()) + val resources = T.task(module.resources().map(_.path.toNIO).toList) val project = T.task { Config.Project( @@ -104,6 +103,7 @@ object Bloop extends ExternalModule { classpath = classpath().map(_.toNIO).toList, out = out(module).toNIO, classesDir = classes(module).toNIO, + resources = Some(resources()), `scala` = scalaConfig(), java = javaConfig(), sbt = None, diff --git a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala index c3a9443f3a..0d94709864 100644 --- a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala +++ b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala @@ -4,26 +4,9 @@ import java.nio.charset.StandardCharsets import java.nio.file.{Files, Path} import bloop.config.Config +import bloop.config.util.ConfigUtil import bloop.integration.sbt.Feedback -import sbt.{ - AutoPlugin, - ClasspathDep, - ClasspathDependency, - Compile, - ConfigKey, - Configuration, - Def, - File, - Global, - Keys, - LocalRootProject, - Logger, - ProjectRef, - ResolvedProject, - Test, - ThisBuild, - ThisProject -} +import sbt.{AutoPlugin, ClasspathDep, ClasspathDependency, Compile, ConfigKey, Configuration, Def, File, Global, Keys, LocalRootProject, Logger, ProjectRef, ResolvedProject, Test, ThisBuild, ThisProject} import xsbti.compile.CompileOrder object BloopPlugin extends AutoPlugin { @@ -51,14 +34,10 @@ object BloopKeys { "The classifiers that will be exported with `updateClassifiers`") val bloopProductDirectories: TaskKey[Seq[File]] = taskKey[Seq[File]]("Bloop product directories") - val bloopManagedResourceDirectories: SettingKey[Seq[File]] = - settingKey[Seq[File]]("Managed resource directories for bloop") val bloopClassDirectory: SettingKey[File] = settingKey[File]("Directory where to write the class files") val bloopTargetDir: SettingKey[File] = settingKey[File]("Target directory for the pertinent project and configuration") - val bloopResourceManaged: SettingKey[File] = - settingKey[File]("Resource managed for bloop") val bloopInternalClasspath: TaskKey[Seq[(File, File)]] = taskKey[Seq[(File, File)]]("Directory where to write the class files") val bloopInstall: TaskKey[Unit] = @@ -135,10 +114,8 @@ object BloopDefaults { lazy val configSettings: Seq[Def.Setting[_]] = List( BloopKeys.bloopProductDirectories := List(BloopKeys.bloopClassDirectory.value), - BloopKeys.bloopManagedResourceDirectories := managedResourceDirs.value, BloopKeys.bloopClassDirectory := generateBloopProductDirectories.value, BloopKeys.bloopInternalClasspath := bloopInternalDependencyClasspath.value, - BloopKeys.bloopResourceManaged := BloopKeys.bloopTargetDir.value / "resource_managed", BloopKeys.bloopGenerate := bloopGenerate.value, BloopKeys.bloopAnalysisOut := None ) ++ discoveredSbtPluginsSettings @@ -744,8 +721,6 @@ object BloopDefaults { // Force source generators on this task manually Keys.managedSources.value - // Copy the resources, so that they're available when running and testing - bloopCopyResourcesTask.value // format: OFF val config = { @@ -754,10 +729,11 @@ object BloopDefaults { val analysisOut = None val compileSetup = Config.CompileSetup(compileOrder, c.bootLibrary, c.compiler, c.extra, c.autoBoot, c.filterLibrary) val `scala` = Config.Scala(scalaOrg, scalaName, scalaVersion, scalacOptions, allScalaJars, analysisOut, Some(compileSetup)) + val resources = Some(bloopResourcesTask.value) val sbt = computeSbtMetadata.value.map(_.config) val project = Config.Project(projectName, baseDirectory, sources, dependenciesAndAggregates, - classpath, out, classesDir, Some(`scala`), Some(java), sbt, Some(testOptions), Some(platform), resolution) + classpath, out, classesDir, resources, Some(`scala`), Some(java), sbt, Some(testOptions), Some(platform), resolution) Config.File(Config.File.LatestVersion, project) } // format: ON @@ -866,37 +842,24 @@ object BloopDefaults { internalClasspath ++ externalClasspath } - def bloopCopyResourcesTask = Def.taskDyn { + def bloopResourcesTask = Def.taskDyn { val configKey = sbt.ConfigKey(Keys.configuration.value.name) Def.task { import sbt._ - val t = BloopKeys.bloopClassDirectory.value - val dirs = - Classpaths - .concatSettings( - Keys.unmanagedResourceDirectories.in(configKey), - BloopKeys.bloopManagedResourceDirectories.in(configKey)) - .value val s = Keys.streams.value - val cacheStore = bloop.integrations.sbt.Compat.generateCacheFile(s, "copy-resources-bloop") - val mappings = (sbt.PathFinder(Keys.resources.value) --- dirs) pair (sbt.Path - .rebase(dirs, t) | sbt.Path.flat(t)) - s.log.debug("Copy resource mappings: " + mappings.mkString("\n\t", "\n\t", "")) - sbt.Sync(cacheStore)(mappings) - mappings - } - } + val bloopClassDir = BloopKeys.bloopClassDirectory.value + val resourceDirs = Classpaths + .concatSettings( + Keys.unmanagedResourceDirectories.in(configKey), + Keys.managedResourceDirectories.in(configKey) + ) + .value + .map(_.toPath) - def managedResourceDirs: Def.Initialize[Seq[File]] = Def.settingDyn { - val configName = Keys.configuration.value.name - val configKey = sbt.ConfigKey(configName) - Def.setting { - val oldUnmanagedResourceDirs = Keys.managedResourceDirectories.in(configKey).value - val oldResourceDir = Keys.resourceManaged.in(configKey).value - val newResourceDir = - BloopKeys.bloopResourceManaged.in(configKey).value / Defaults.nameForSrc(configName) - oldUnmanagedResourceDirs.map { dir => if (dir == oldResourceDir) newResourceDir else dir - } + val allResourceFiles = Keys.resources.in(configKey).value + val additionalResources = + ConfigUtil.pathsOutsideRoots(resourceDirs, allResourceFiles.map(_.toPath)) + (resourceDirs ++ additionalResources).toList } } diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 6bfc49843a..5e74b8e1a8 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -267,7 +267,7 @@ object BuildImplementation { final val globalSettings: Seq[Def.Setting[_]] = Seq( Keys.cancelable := true, - BuildKeys.schemaVersion := "4.0", + BuildKeys.schemaVersion := "4.2", Keys.testOptions in Test += sbt.Tests.Argument("-oD"), Keys.onLoadMessage := Header.intro, Keys.onLoad := BuildDefaults.bloopOnLoad.value,