How to create multiple executable jars under same project, same src with sbt assembly - scala

I have one project and project directory looks like this:
aProject/
build.sbt
project/Build.scala
src/main/scala/
packageA/MainA.scala
packageB/MainB.scala
I want to package 2 fat jars, one containing packageA.MainA and the other containing packageB.MainB. How can I do this with sbt-assembly?

Related

Fat jar with dependencies of imported jars

I am rebuilding a decompiled fat jar. The fat jar embeds the dependencies of the compiled jar. The fat jar I have decompiled also includes jar files that are not imports of the code of the main compiled jar. I assume then that these jar files are dependencies of the jar files that are imported by the code.
I have included under Projects / project / Libraries (an Ant project) all the jar files (directly imported jars and those I assume are dependencies of the latter) and built the project to create a fat jar, but the jars which I assume are dependencies of the imported jars are still not being bundled. Is there any way I can include these in the fat jar?

sbt package: exclude Python files in JAR file

I'd like to figure out how to excluded the Python files from the JAR file generated by the sbt package command.
The Delta lake project uses SBT version 0.13.18 and the JAR file is built with sbt package.
The directory structure is as follows:
python/
delta/
testing/
utils.py
tests/
test_sql.py
src/
main/
...scala files
build.sbt
run-tests.py
It follows the standard SBT project structure with a couple of Python files added in.
The Python files are included in the JAR file when sbt package is run and I'd like to figure out how to exclude all the Python files.
Here's what I tried adding to the build.sbt file:
mappings in (Compile, packageBin) ~= { _.filter(!_._1.getName.endsWith("py")) } per this answer
excludeFilter in Compile := "*.py" per this answer
Neither of these worked.
Haven't tested it, but I think something like this when you make a fat jar.
assemblyMergeStrategry in assembly := {
case PathList(parts # _*) if parts.last.endsWith(".py") => MergeStrategy.discard
case _ => MergeStrategy.first // or whatever you currently have for your other merges
}

sbt how to specify dependency to a sibling project

I have a main sbt project which depends on two sbt subprojects, 'util', and 'common'. In addition the common project depends on the util project. In the build.sbt of the common project, how should I specify the dependency to the sibling project util, so that I can compile the common project independently?
Many thanks.
Azad

How to include jars under lib in multi-project sbt setup?

I have a project that is similar to the sbt-multi-project-example one. The only difference is that I have two already compiled jar dependencies inside a lib/ folder on root folder.
On a single-project sbt setup it automatically collects those jars and use them to compile my project, but in this case it is not being collected by the sub-projects.
Only one of my sub-projects require those jars.
Where should I put those jars and how should I setup build.sbt to recognize them?
Put the jars in a lib/ folder in the sub-project that requires them.

Control dependency loading ambiguity on SBT multi-project

I have an SBT Scala multi-project with the following structure:
multiprojectRoot
project/SharedProjectBuildCode.scala
project1
src/sourceFiles
project1-build.sbt
project2
src/sourceFiles
project2-build.sbt
projectN
src/sourceFiles
projectN-build.sbt
multiprojectRoot/project/SharedProjectBuildCode.scala: contains multi-project definitions that use dependsOn to create dependencies on local projects. For example:
lazy val project2 = Project(
...
).dependsOn(project1)
multiprojectRoot/project2/project2-build.sbt: Contains the settings and dependencies for a given project. For example:
name := "project2"
libraryDependencies ++= Seq(
...
"my.company" % "project1" % "1.0"
)
First dependency to project1 is declared with dependsOn on SharedProjectBuildCode.scala file and the second is created on standalone project2-build.sbt build definition file.
So, project2 definition contains either:
an ambiguous dependency to project1 or
a double dependency to project1
We want to keep this project structure, because is the best for our current workflow:
Independent .sbt files serve standalone deployment purposes for each project on our continuous delivery server.
Multi-project .scala file with dependsOn is used to facilitate development, allowing us to avoid things such as continuous publishLocal.
We need to have control for such dependency ambiguities someway. Can you help me?
I think you should have in SharedProjectBuildCode.scala
lazy val root = Project(id = "Main-Project",
base = file(".")) aggregate(project1, project2,..)
lazy val project2 = Project(id = "project2",
base = file("project1")).dependsOn(project1)
...
And don't need to add as dependency in build.sbt anymore.
I was able to control which dependency set loaded on each use case by using the rules of build files loading provided by SBT.
When you load SBT from a given root directory, it looks for *.sbt files on the root directory and also for *.scala on the root/project directory. If you have a multi-project build, then it also reads the definitions of .sbt files that are encountered on child projects, but it will not use project/.scala files on child projects:
.sbt build definition
Multi-project builds
So, I changed my multi-project build the following way:
multiprojectRoot
project/SharedProjectBuildCode.scala
project1
src/sourceFiles
project/DeploymentOnlyCode.scala
project1-build.sbt
project2
src/sourceFiles
project/DeploymentOnlyCode.scala
project2-build.sbt
projectN
src/sourceFiles
project/DeploymentOnlyCode.scala
projectN-build.sbt
This way, depending on the use case I run SBT from the multi-project root or a project internal directory:
Development: SBT is run from multiprojectRoot directory. It takes the advantages of having a multi-project build (such as using dependsOn and avoiding publishLocal).
Production: SBT is run from within a concrete project directory, such as multiprojectRoot/project2. It allows the project to be built as stand-alone, having all dependencies as explicit external (useful for declaring a sequence of dependencies on production, continuous integration server).
Now, a project has 3 instances of code that aggregates their attributes for a final build:
multiprojectRoot/project/SharedProjectBuildCode.scala: Contains local dependencies and other code relevant for multi-project build.
multiprojectRoot/project1/project1-build.sbt: Contains project build attributes, common for multi-project and standalone build of a project, such as name or dependencies that are always external. The same should be done for other multi-project projects of the same level, to be explicitly treated as external dependency artifacts.
multiprojectRoot/project1/project/DeploymentOnlyCode.scala: Contains build attributes that will only be taken into consideration for stand-alone build. The same can be done on other sub-projects, if these require to define deployment specific attributes.
This also gives maximum control on how a project is built, whether is a releasable artifact or not, and handle source code relevant only for a given project, as a complete and independent piece.