Skip to content
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

Support multiple separate build targets #3126

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 7 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import $file.project.settings, settings.{
ScalaCliSbtModule,
ScalaCliScalafixModule,
localRepoResourcePath,
moduleConfigFileName,
platformExecutableJarExtension,
workspaceDirName,
projectFileName,
Expand Down Expand Up @@ -474,6 +475,7 @@ trait Core extends ScalaCliCrossSbtModule
| def workspaceDirName = "$workspaceDirName"
| def projectFileName = "$projectFileName"
| def jvmPropertiesFileName = "$jvmPropertiesFileName"
| def moduleConfigFileName = "$moduleConfigFileName"
| def scalacArgumentsFileName = "scalac.args.txt"
| def maxScalacArgumentsCount = 5000
|
Expand Down Expand Up @@ -701,7 +703,8 @@ trait Build extends ScalaCliCrossSbtModule
Deps.scalaJsEnvNodeJs,
Deps.scalaJsTestAdapter,
Deps.swoval,
Deps.zipInputStream
Deps.zipInputStream,
Deps.tomlScala
)

def repositoriesTask =
Expand Down Expand Up @@ -738,6 +741,8 @@ trait Build extends ScalaCliCrossSbtModule
| def defaultScalaVersion = "${Scala.defaultUser}"
| def defaultScala212Version = "${Scala.scala212}"
| def defaultScala213Version = "${Scala.scala213}"
|
| def moduleConfigFileName = "$moduleConfigFileName"
|}
|""".stripMargin
if (!os.isFile(dest) || os.read(dest) != code)
Expand Down Expand Up @@ -1032,6 +1037,7 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
)}"
| def cs = "${settings.cs().replace("\\", "\\\\")}"
| def workspaceDirName = "$workspaceDirName"
| def moduleConfigFileName = "$moduleConfigFileName"
| def libsodiumVersion = "${deps.libsodiumVersion}"
| def dockerArchLinuxImage = "${TestDeps.archLinuxImage}"
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ object EitherCps:
case Left(e) => throw EitherFailure(e, cps)
case Right(v) => v

def failure[E](using
cps: EitherCps[_ >: E]
)(e: E) = // Adding a context bounds breaks incremental compilation
throw EitherFailure(e, cps)

final class Helper[E]():
def apply[V](op: EitherCps[E] ?=> V): Either[E, V] =
val cps = new EitherCps[E]
Expand Down
13 changes: 7 additions & 6 deletions modules/build/src/main/scala/scala/build/Bloop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import java.io.{File, IOException}

import scala.annotation.tailrec
import scala.build.EitherCps.{either, value}
import scala.build.bsp.buildtargets.ProjectName
import scala.build.errors.{BuildException, ModuleFormatError}
import scala.build.internal.CsLoggerUtil._
import scala.build.internal.CsLoggerUtil.*
import scala.concurrent.duration.FiniteDuration
import scala.jdk.CollectionConverters._
import scala.jdk.CollectionConverters.*

object Bloop {

Expand All @@ -30,7 +31,7 @@ object Bloop {
}

def compile(
projectName: String,
projectName: ProjectName,
buildServer: BuildServer,
logger: Logger,
buildTargetsTimeout: FiniteDuration
Expand All @@ -39,16 +40,16 @@ object Bloop {
logger.debug("Listing BSP build targets")
val results = buildServer.workspaceBuildTargets()
.get(buildTargetsTimeout.length, buildTargetsTimeout.unit)
val buildTargetOpt = results.getTargets.asScala.find(_.getDisplayName == projectName)
val buildTargetOpt = results.getTargets.asScala.find(_.getDisplayName == projectName.name)

val buildTarget = buildTargetOpt.getOrElse {
throw new Exception(
s"Expected to find project '$projectName' in build targets (only got ${results.getTargets
s"Expected to find project '${projectName.name}' in build targets (only got ${results.getTargets
.asScala.map("'" + _.getDisplayName + "'").mkString(", ")})"
)
}

logger.debug(s"Compiling $projectName with Bloop")
logger.debug(s"Compiling ${projectName.name} with Bloop")
val compileRes = buildServer.buildTargetCompile(
new bsp4j.CompileParams(List(buildTarget.getId).asJava)
).get()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package scala.build

import ch.epfl.scala.bsp4j

import scala.build.bsp.buildtargets.ProjectName
import scala.build.options.Scope

trait BloopBuildClient extends bsp4j.BuildClient {
def setProjectParams(newParams: Seq[String]): Unit
def setGeneratedSources(scope: Scope, newGeneratedSources: Seq[GeneratedSource]): Unit
def setGeneratedSources(projectName: ProjectName, newGeneratedSources: Seq[GeneratedSource]): Unit
def diagnostics: Option[Seq[(Either[String, os.Path], bsp4j.Diagnostic)]]
def clear(): Unit
}
Expand Down
58 changes: 32 additions & 26 deletions modules/build/src/main/scala/scala/build/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.util.concurrent.{ScheduledExecutorService, ScheduledFuture}
import scala.annotation.tailrec
import scala.build.EitherCps.{either, value}
import scala.build.Ops.*
import scala.build.bsp.buildtargets.ProjectName
import scala.build.compiler.{ScalaCompiler, ScalaCompilerMaker}
import scala.build.errors.*
import scala.build.input.VirtualScript.VirtualScriptNameRegex
Expand All @@ -29,7 +30,7 @@ import scala.util.control.NonFatal
import scala.util.{Properties, Try}

trait Build {
def inputs: Inputs
def inputs: ModuleInputs
def options: BuildOptions
def scope: Scope
def outputOpt: Option[os.Path]
Expand All @@ -42,7 +43,7 @@ trait Build {
object Build {

final case class Successful(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions,
scalaParams: Option[ScalaParameters],
scope: Scope,
Expand Down Expand Up @@ -170,7 +171,7 @@ object Build {
}

final case class Failed(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions,
scope: Scope,
sources: Sources,
Expand All @@ -184,7 +185,7 @@ object Build {
}

final case class Cancelled(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions,
scope: Scope,
reason: String
Expand All @@ -199,9 +200,9 @@ object Build {
* Using only the command-line options not the ones from the sources.
*/
def updateInputs(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions
): Inputs = {
): ModuleInputs = {

// If some options are manually overridden, append a hash of the options to the project name
// Using options, not options0 - only the command-line options are taken into account. No hash is
Expand All @@ -212,11 +213,11 @@ object Build {
}

private def allInputs(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions,
logger: Logger
)(using ScalaCliInvokeData) =
CrossSources.forInputs(
CrossSources.forModuleInputs(
inputs,
Sources.defaultPreprocessors(
options.archiveCache,
Expand All @@ -229,7 +230,7 @@ object Build {
)

private def build(
inputs: Inputs,
inputs: ModuleInputs,
crossSources: CrossSources,
options: BuildOptions,
logger: Logger,
Expand All @@ -244,7 +245,7 @@ object Build {
val sharedOptions = crossSources.sharedOptions(options)
val crossOptions = sharedOptions.crossOptions

def doPostProcess(build: Build, inputs: Inputs, scope: Scope): Unit = build match {
def doPostProcess(build: Build, inputs: ModuleInputs, scope: Scope): Unit = build match {
case build: Build.Successful =>
for (sv <- build.project.scalaCompiler.map(_.scalaVersion))
postProcess(
Expand Down Expand Up @@ -422,7 +423,7 @@ object Build {
}

private def build(
inputs: Inputs,
inputs: ModuleInputs,
sources: Sources,
generatedSources: Seq[GeneratedSource],
options: BuildOptions,
Expand Down Expand Up @@ -474,23 +475,28 @@ object Build {
}
}

def projectRootDir(root: os.Path, projectName: String): os.Path =
root / Constants.workspaceDirName / projectName
def classesRootDir(root: os.Path, projectName: String): os.Path =
def projectRootDir(root: os.Path, projectName: ProjectName): os.Path =
root / Constants.workspaceDirName / projectName.name
def classesRootDir(root: os.Path, projectName: ProjectName): os.Path =
projectRootDir(root, projectName) / "classes"
def classesDir(root: os.Path, projectName: String, scope: Scope, suffix: String = ""): os.Path =
def classesDir(
root: os.Path,
projectName: ProjectName,
scope: Scope,
suffix: String = ""
): os.Path =
classesRootDir(root, projectName) / s"${scope.name}$suffix"

def resourcesRegistry(
root: os.Path,
projectName: String,
projectName: ProjectName,
scope: Scope
): os.Path =
root / Constants.workspaceDirName / projectName / s"resources-${scope.name}"
root / Constants.workspaceDirName / projectName.name / s"resources-${scope.name}"

def scalaNativeSupported(
options: BuildOptions,
inputs: Inputs,
inputs: ModuleInputs,
logger: Logger
): Either[BuildException, Option[ScalaNativeCompatibilityError]] =
either {
Expand Down Expand Up @@ -548,7 +554,7 @@ object Build {
}

def build(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions,
compilerMaker: ScalaCompilerMaker,
docCompilerMakerOpt: Option[ScalaCompilerMaker],
Expand Down Expand Up @@ -628,7 +634,7 @@ object Build {
}

def watch(
inputs: Inputs,
inputs: ModuleInputs,
options: BuildOptions,
compilerMaker: ScalaCompilerMaker,
docCompilerMakerOpt: Option[ScalaCompilerMaker],
Expand Down Expand Up @@ -832,7 +838,7 @@ object Build {
* a bloop [[Project]]
*/
def buildProject(
inputs: Inputs,
inputs: ModuleInputs,
sources: Sources,
generatedSources: Seq[GeneratedSource],
options: BuildOptions,
Expand Down Expand Up @@ -997,7 +1003,7 @@ object Build {
}

def prepareBuild(
inputs: Inputs,
inputs: ModuleInputs,
sources: Sources,
generatedSources: Seq[GeneratedSource],
options: BuildOptions,
Expand Down Expand Up @@ -1078,7 +1084,7 @@ object Build {
}

def buildOnce(
inputs: Inputs,
inputs: ModuleInputs,
sources: Sources,
generatedSources: Seq[GeneratedSource],
options: BuildOptions,
Expand Down Expand Up @@ -1110,7 +1116,7 @@ object Build {
}

buildClient.clear()
buildClient.setGeneratedSources(scope, generatedSources)
buildClient.setGeneratedSources(inputs.scopeProjectName(scope), generatedSources)

val partial = partialOpt.getOrElse {
options.notForBloopOptions.packageOptions.packageTypeOpt.exists(_.sourceBased)
Expand Down Expand Up @@ -1248,7 +1254,7 @@ object Build {
else path.toString

private def jmhBuild(
inputs: Inputs,
inputs: ModuleInputs,
build: Build.Successful,
logger: Logger,
javaCommand: String,
Expand All @@ -1257,7 +1263,7 @@ object Build {
buildTests: Boolean,
actionableDiagnostics: Option[Boolean]
)(using ScalaCliInvokeData): Either[BuildException, Option[Build]] = either {
val jmhProjectName = inputs.projectName + "_jmh"
val jmhProjectName = inputs.projectName.name + "_jmh"
val jmhOutputDir = inputs.workspace / Constants.workspaceDirName / jmhProjectName
os.remove.all(jmhOutputDir)
val jmhSourceDir = jmhOutputDir / "sources"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.io.File
import java.net.URI
import java.nio.file.Paths

import scala.build.bsp.buildtargets.ProjectName
import scala.build.errors.Severity
import scala.build.internal.WrapperParams
import scala.build.internals.ConsoleUtils.ScalaCliConsole
Expand All @@ -17,7 +18,7 @@ import scala.jdk.CollectionConverters.*
class ConsoleBloopBuildClient(
logger: Logger,
keepDiagnostics: Boolean = false,
generatedSources: mutable.Map[Scope, Seq[GeneratedSource]] = mutable.Map()
generatedSources: mutable.Map[ProjectName, Seq[GeneratedSource]] = mutable.Map()
) extends BloopBuildClient {
import ConsoleBloopBuildClient._
private var projectParams = Seq.empty[String]
Expand All @@ -32,8 +33,8 @@ class ConsoleBloopBuildClient(

private val diagnostics0 = new mutable.ListBuffer[(Either[String, os.Path], bsp4j.Diagnostic)]

def setGeneratedSources(scope: Scope, newGeneratedSources: Seq[GeneratedSource]) =
generatedSources(scope) = newGeneratedSources
def setGeneratedSources(projectName: ProjectName, newGeneratedSources: Seq[GeneratedSource]) =
generatedSources(projectName) = newGeneratedSources
def setProjectParams(newParams: Seq[String]): Unit = {
projectParams = newParams
}
Expand Down
10 changes: 5 additions & 5 deletions modules/build/src/main/scala/scala/build/CrossSources.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ final case class CrossSources(

object CrossSources {

private def withinTestSubDirectory(p: ScopePath, inputs: Inputs): Boolean =
private def withinTestSubDirectory(p: ScopePath, inputs: ModuleInputs): Boolean =
p.root.exists { path =>
val fullPath = path / p.subPath
inputs.elements.exists {
Expand All @@ -155,14 +155,14 @@ object CrossSources {
/** @return
* a CrossSources and Inputs which contains element processed from using directives
*/
def forInputs(
inputs: Inputs,
def forModuleInputs(
inputs: ModuleInputs,
preprocessors: Seq[Preprocessor],
logger: Logger,
suppressWarningOptions: SuppressWarningOptions,
exclude: Seq[Positioned[String]] = Nil,
maybeRecoverOnError: BuildException => Option[BuildException] = e => Some(e)
)(using ScalaCliInvokeData): Either[BuildException, (CrossSources, Inputs)] = either {
)(using ScalaCliInvokeData): Either[BuildException, (CrossSources, ModuleInputs)] = either {

def preprocessSources(elems: Seq[SingleElement])
: Either[BuildException, Seq[PreprocessedSource]] =
Expand Down Expand Up @@ -379,7 +379,7 @@ object CrossSources {
* the resource directories that should be added to the classpath
*/
private def resolveResourceDirs(
allInputs: Inputs,
allInputs: ModuleInputs,
preprocessedSources: Seq[PreprocessedSource]
): Seq[WithBuildRequirements[os.Path]] = {
val fromInputs = allInputs.elements
Expand Down
Loading
Loading