Can I assembly one subproject from its directory with SBT? - scala

I defined multi-project SBT project. I declared all dependencies in my root project. When I run sbt assembly from root directory everything is okay.
How can I run sbt assembly from subproject directory? When I try to do this, SBT can't find dependencies that are declared in root build.sbt file.
For example, i do something like this in root build.sbt:
ThisBuild / organization := "org.example"
ThisBuild / version := "1.0"
ThisBuild / scalaVersion := "2.11.12"
...
lazy val commonSettings = Seq(
libraryDependecies ++= Seq(
"org.apache.spark" %% "spark-core" % sparkVersion
, "org.apache.spark" %% "spark-hive" % sparkVersion
, "org.apache.spark" %% "spark-sql" % sparkVersion
// other dependencies
).map(_% Provided) ++ Seq(
"org.postgresl" % "postgresql" % "42.2.24"
// other dependencies
)
)
lazy val root = (project in file("."))
.aggregate(subproject)
.settings(
name := "root"
)
lazy val subproject = (project in file("subproject"))
.setting(
commonSettings,
name := "subproject"
//...Other settings
)
val allProjects = ScopeFilter(
inProject(
subproject
)
)
build.sbt from subproject directory:
assembly / mainClass := Some("org.example.Main")
//other settings
When I run sbt assembly from root directory everything okay.
When I run it from subproject directory i get errors like that:
object apache is not a member of package org
import org.apache.spark.sql.expressions.UserDefinedFunction
Is it possible to compile jar files from subprojects directories?

You have to build from the directory in which main project is defined.
However you don't have to always build everything. You can pretty much do:
# in project root directory
sbt "subproject / assembly"
so there isn't even an issue.

Related

Is there a way to specify different Scala scapegoat versions for multi-project SBT build?

I was trying the following:
lazy val root = (project in file("."))
.settings(
libraryDependencies ++= commonDeps,
scapegoatVersion := "1.3.5"
)
lazy val foo = (project in file("foo"))
.settings(
libraryDependencies ++= Dependencies.fooDeps,
scalaVersion := "2.13.8",
scapegoatVersion := "1.4.12"
)
Each project's version resolved to 1.0.
I also tried ThisBuild / scapegoatVersion := <some-version> but it set the version for all projects.
Unfortunately, it is not possible because of a wrong reference to scapegoatVersion setting.
libraryDependencies ++= Seq(crossVersion(GroupId %% ArtifactId % (scapegoatVersion in ThisBuild).value % Provided)))
The problem is that it adds libraryDependencies to projectSettings or scope ThisProject but uses a broader scope ThisBuild to refer to scapegoatVersion.
Because of this it ignores your scapegoatVersion specified per project.
Your approach would work if the plugin did the following
libraryDependencies ++= Seq(crossVersion(
GroupId %% ArtifactId % (scapegoatVersion in ThisProject).value % Provided)
))
You could submit a PR to the project.

how to change the scalaPB default path of protobuf files?

I have a build.sbt for a couple of packages in the same project.
When I do sbt compile, my protobuf files are under [packagename]/src/main/protobuf/*,
so it won't scan these files since they have that additional package name in the path.
How to change the default protobuf file path?
It is unclear from your question whether your sbt build is a single or multi-project build. You can tell that it is a multi-project build if you see lines like val someSubProject = project.in(file(...).
If your build.sbt is a single project build, you can add a line to customize where protos are being scanned:
Compile / PB.protoSources += file("pkgname/src/main/protobuf")
If you have a multi-project build with a project proj1, then it should already work in the way you expect:
val proj1 = project.in(file("proj1"))
.settings(
PB.targets in Compile := Seq(
scalapb.gen(javaConversions=true) -> (sourceManaged in Compile).value / "scalapb"
),
libraryDependencies ++= Seq(
"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",
)
)
then sbt-protoc will generate sources for the protos under proj1/src/main/protobuf. The sources will get compiled as poart of the proj1 project.
You can customize the path it looks for by setting Compile / PB.protoSources within that project's setting. For example, if you want it to generate source for protos that are in another top-level directory, you can do:
val proj1 = project.in(file("proj1"))
.settings(
PB.targets in Compile := Seq(
scalapb.gen(javaConversions=true) -> (sourceManaged in Compile).value / "scalapb"
),
Compile / PB.protoSources :=
Seq((ThisBuild / baseDirectory).value / "somewhere" / "protos"),
libraryDependencies ++= Seq(
"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",
)
)
I recommend using AkkaGrpcPlugin and a multi-project SBT configuration.
Put the .proto files in a separate project and make the others depend on it. This project just has a single directory <root>/grpc/src/main/protobuf containing the .proto files. When this project is compiled it will create all the stub files which can be picked up by other projects that depend on it.
Here is an outline build.sbt file:
lazy val top_level =
(project in file("."))
.aggregate(grpc, main)
lazy val grpc =
project
.in(file("grpc"))
.settings(
???
)
.enablePlugins(AkkaGrpcPlugin)
lazy val main =
project
.in(file("main"))
.settings(
???
)
.dependsOn(grpc)
And add this to plugins.sbt:
addSbtPlugin("com.lightbend.akka.grpc" % "sbt-akka-grpc" % "1.1.1")

IntelliJ: Symbol 'type org.scalatest.compatible.Assertion' is missing from the classpath

Writing scala tests, I am encountering an error:
Symbol 'type org.scalatest.compatible.Assertion' is missing from the classpath.
This symbol is required by 'type org.scalatest.Assertion'.
Make sure that type Assertion is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
A full rebuild may help if 'package.class' was compiled against an incompatible version of org.scalatest.compatible.
My build.sbt is very simple:
import sbt.Keys.libraryDependencies
ThisBuild / scalaVersion := "2.13.2"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / organization := "com.example"
ThisBuild / organizationName := "example"
lazy val root = (project in file("."))
.settings(
name := "myproj",
libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.9",
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.9" % "test",
libraryDependencies += "org.scalatest" %% "scalatest-funsuite" % "3.2.9" % "test",
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2",
)
This problem only occurs when I build my project within IntelliJ. Using sbt itself it compiles well.
sbt version in this project: 1.3.10
sbt script version: 1.3.6
Any idea of how to fix it in IntelliJ?
Most of the problems related to IntelliJ being broken I resolve by doing so:
sbt clean compile in terminal on root folder
View -> Tool Windows -> sbt and within tab Reload SBT project (right click on project)

SBT: How to include sbt files in upper directory to my build.sbt?

I have a many dependent sbt projects in one folder. They all have same values in Build.sbt, for example dependencies.
I want to move same values from all sbt files to separate file. But don't want to use multibuild. Just need to include some other sbt files from upper directory.
For example my directory structure can look like this:
MyRepository
|- Dependencies.sbt
|- MyProject1
|- src
|- Build.sbt
|- MyProject2
|- src
|- Build.sbt
In that example, how can I include Dependencies.sbt in Build.sbt?
Code is reused between .sbt files by creating a normal .scala file in project/. The code in project/ will be available for use in the .sbt files.
If I remember correctly the definitions in one .sbt are not visible to other .sbt files, at least on the older versions.
Basically, the solution is to use: Dependencies.scala and not Dependencies.sbt and define the common part's there.
Check the illustration, that can be found here,
You create project/Dependencies.scala to track dependencies in one place.
import sbt._
object Dependencies {
// Versions
lazy val akkaVersion = "2.3.8"
// Libraries
val akkaActor = "com.typesafe.akka" %% "akka-actor" % akkaVersion
val akkaCluster = "com.typesafe.akka" %% "akka-cluster" % akkaVersion
val specs2core = "org.specs2" %% "specs2-core" % "2.4.17"
// Projects
val backendDeps =
Seq(akkaActor, specs2core % Test)
}
The Dependencies object will be available in build.sbt.
You need to, import Dependencies._ in your build.sbt file.
import Dependencies._
ThisBuild / organization := "com.example"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.12.8"
lazy val backend = (project in file("backend"))
.settings(
name := "backend",
libraryDependencies ++= backendDeps
)

SBT Won´t update .classpath in a Play Scala project

I am creating a new Play Scala project within Eclipse + Scala IDE.
The original build.sbt file is:
name := """portal"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.1"
libraryDependencies ++= Seq(
jdbc,
cache,
ws
)
I've edited it to include some more dependencies:
libraryDependencies ++= Seq(
jdbc,
javaEbean,
cache,
ws,
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4",
"org.scalatestplus" %% "play" % "1.1.0" % "test"
)
I can't figure out why SBT won't include Ebean, postgresql, nor scalatest in my classpath. Any help?
It happened that I needed to run the command
activator eclipse
again, and refresh the IDE.