SBT Native Packager change output location of ZIP - scala

This is my build.sbt:
name := "DB-Services"
version := "0.1"
scalaVersion := "2.12.12"
lazy val root = (project in file(".")).enablePlugins(UniversalPlugin,JavaServerAppPackaging)
artifactName := { (_, _, _) => "DB-Services.zip"}
Universal / mappings ++= directory(target.value)
Currently sbt package generates DB-Services.zip inside of target/scala-2.12. However I need this ZIP to be generated inside target folder instead. But the problem is that the mapping I provided above does not work and the ZIP continues to be generated inside target/scala-2.12.
What changes should I do in my build.sbt so that the ZIP is generated in target folder? (I cannot generate the ZIP in any other location due to limitations with our CICD)
(PS: This answer does not work, so please do not mark this as duplicate)

Universal / target := (Compile / target).value
Works for me. How I found this:
There is a useful tool in SBT to dive into settings and tasks: inspect
I ran inspect root/Universal/packageBin (root/Universal/packageBin is how we build an artifact), it returned:
...
[info] Dependencies:
[info] Universal / packageBin / validatePackage
[info] Universal / packageBin / mappings
[info] Universal / packageName
[info] Universal / target
[info] Universal / packageBin / universalArchiveOptions
[info] Universal / topLevelDirectory
...
Universal / target looked interesting, so I ran: inspect Universal / target , it returned:
...
[info] Description:
[info] Main directory for files generated by the build.
...
We can find that Compile / target returns a path to the target directory in a same way (or just a read docs).

Related

How do I make sbt include non-Java sources to published artifact?

How do I make sbt include non-Java sources to published artifact ?
I'm using Kotlin plugin and can't figure out how to force sbt to include .kt file into published source jar. It only includes .java files.
A lot of people online suggest adding following code to sbt script but it doesn't help
mappings in (Compile, packageSrc) ++= {
val base = (sourceManaged in Compile).value
val files = (managedSources in Compile).value
files.map { f => (f, f.relativeTo(base).get.getPath) }
},
I also tried
includeFilter in (Compile, packageSrc) := "*.scala" || "*.java" || "*.kt",
Here is output of some variables in sbt console
sbt:collections> show unmanagedSourceDirectories
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/scala
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/java
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/kotlin
sbt:collections> show unmanagedSources
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/java/com/walkmind/extensions/collections/TestSomething.java
which plugin you use for kotlin?
https://github.com/pfn/kotlin-plugin has the option kotlinSource to configure where the source directory is located.
sbt packageBin compiled kotlin files and include them to output jar.
build.sbt
// define kotlin source directory
kotlinSource in Compile := baseDirectory.value / "src/main/kotlin",
src/main/kotlin/org.test
package org.test
fun main(args: Array<String>) {
println("Hello World!")
}
console
sbt compile
sbt packageBin
target/scala-2.13
jar include MainKt.class
and folder org/test contains MainKt.class too.
would this solve your problem?
I found a workaround for this in my project https://github.com/makiftutuncu/e. I made following: https://github.com/makiftutuncu/e/blob/master/project/Settings.scala#L105
Basically, I added following setting in SBT to properly generate sources artifact:
// Include Kotlin files in sources
packageConfiguration in Compile := {
val old = (packageConfiguration in Compile in packageSrc).value
val newSources = (sourceDirectories in Compile).value.flatMap(_ ** "*.kt" get)
new Package.Configuration(
old.sources ++ newSources.map(f => f -> f.getName),
old.jar,
old.options
)
}
For the documentation artifact, I added Gradle build to my Kotlin module. I set it up as shown here https://github.com/makiftutuncu/e/blob/master/e-kotlin/build.gradle.kts. This way, I make Gradle build generate the Dokka documentation. And finally, added following setting in SBT to run Gradle while building docs:
// Delegate doc generation to Gradle and Dokka
doc in Compile := {
import sys.process._
Process(Seq("./gradlew", "dokkaJavadoc"), baseDirectory.value).!
target.value / "api"
}
I admit, this is a lot of work just to get 2 artifacts but it did the trick for me. 🤷🏻 Hope this helps.

Publish SBT project with sub-projects as a single Maven artifact

I have an SBT project for a Scala library. The implementation is spread across multiple SBT sub-projects but I would like to publish the library as a single JAR. I've constructed the following example:
val subProject = project
val myLibrary = project
.in(file("."))
.dependsOn(subProject)
The project myLibrary it the main project which depends on all other sub-projects. If I run sbt myLibrary/package, I get a JAR files with just the class files, sources and rendered documentation of the sources in project myLibrary. I found the following workaround to include the files from the other sub-projects, by adding settings like the following to myLibrary:
val myLibrary = project
.in(file("."))
.dependsOn(subProject)
.settings(
Compile / packageBin / mappings ++= (subProject / Compile / packageBin / mappings).value,
Compile / packageSrc / mappings ++= (subProject / Compile / packageSrc / mappings).value,
Compile / packageDoc / mappings ++= (subProject / Compile / packageDoc / mappings).value)
What is the intended way to produce the same result?
You can take a look at sbt-assembly plugin which creates fat jar (includes all the dependencies) of your project.

SBT doesn't compile tests located in custom test source folders

I have 3 test source folders in my project. I have added the following key to build.sbt (version of SBT: 1.2.1):
sourceDirectories in Test := baseDirectory { base =>
Seq(
base / "src/test/common/scala",
base / "src/test/unit/scala",
base / "src/test/functional/scala"
)
}.value
SBT correctly recognized the folders:
sbt test:sourceDirectories
...
[info] Set current project to service (in build file:/myprojectfolder/)
[info] * /myprojectfolder/src/test/common/scala
[info] * /myprojectfolder/src/test/unit/scala
[info] * /myprojectfolder/src/test/functional/scala
but test:compile doesn't produce any test classes in target/scala-2.11/test-classes and in result test task doesn't run any tests.
I'm using ScalaTest 3.0.5 although that doesn't seem relevant.
Any ideas why SBT ignores test scala sources during compilation?
Thank you manuzhang for useful comments. Indeed the following change did the trick:
instead of
sourceDirectories in Test := baseDirectory { base =>
Seq(
base / "src/test/common/scala",
base / "src/test/unit/scala",
base / "src/test/functional/scala"
)
}.value
I used
unmanagedSourceDirectories in Test := baseDirectory { base =>
Seq(
base / "src/test/common/scala",
base / "src/test/unit/scala",
base / "src/test/functional/scala"
)
}.value

Scala source external to SBT project folder

When creating an SBT scala project in ItelliJ, it wants me to put all source code in the src/main/scala folder of the project folder. However, I want to put the source code somewhere else independent or particular projects, build-tools, IDEs, etc.
How do I tell it to get the source from arbitrary locations?
You can use the following settings to change the location where SBT looks for your Scala sources:
// Change Scala source directory. Default is:
// scalaSource in Compile := baseDirectory.value / "src" / "main" / "scala"
scalaSource in Compile := file("<Path to your sources...>")
// Change Scala test source directory. Default is:
// scalaSource in Test := baseDirectory.value / "src" / "test" / "scala"
scalaSource in Test := file("<Path to your test sources...>")
For further information (including how to specify other source, library and resource directories), refer to the official SBT documentation for customizing paths.

webappResources in package := Seq(baseDirectory.value ....) throws Error parsing expression

I try to configure sbt (version 0.9.0) to use webapp/dist as the webappResource directory when running package task in sbt, and webapp/app as the webappResource directory when running the container:start command, following this description:
How to have different webapp resources for container:start and package tasks in SBT
But it throws the following error:
error: eof expected but 'package' found.
webappResources in package := Seq(baseDirectory.value / "webapp" / "dist")
^
[error] Error parsing expression.
I guess that package is a reserved word also in sbt conf file, any other way to override setting in package task?
The reason for doing this is that I use gulp to manage webclient. Gulp runs the project from app folder, and compiles (minification etc.) the webclient project into dist folder. When I develop, I use the webapp/app folder as declared below:
webappResources in Compile := Seq(baseDirectory.value / "webapp" / "app")
When I create a release, I first build (minification etc.) the webapp client into webapp/dist using gulp. Then I want to package webapp/dist content into the final war.
But I am not able to override the setting above to use webapp/dist, when using the package task.
I have also tried to create my own configuration like this:
webappResources in Compile := Seq(baseDirectory.value / "src" / "main" / "webapp" / "app")
lazy val ReleaseWarConfig = config("release-war") extend (Compile)
val root = (project in file(".")).
configs(ReleaseWarConfig).
settings(inConfig(ReleaseWarConfig)(webSettings): _*).
settings(
webappResources in Compile := Seq(baseDirectory.value/"src"/"main"/"webapp"/"dist")
)
// I have also tried webappResources in ReleaseConfig instead of Compile ..
But it still uses the webapp/app directory instead of webapp/dist directory.
Any help would be very much appreciated !!!!
What is the directory layout of your project? It sounds like you have your Web application resources directory at [myproject]/webapp/dist/, meaning you have WEB-INF/ and WEB-INF/web.xml (and various other optional resources) under [myproject]/webapp/dist/ as well. Is this correct?
To set the location of your Web application resources directory to [myproject]/webapp/dist/, add the following setting to your sbt configuration:
build.sbt:
webappSrc in webapp <<= (baseDirectory in Compile) map { _ / "webapp" / "dist" }
You can read more about this setting in the readme.