How to exclude resources during packaging with SBT but not during testing - scala

I have a bunch of conf files in a project structure like this:
```
src / main / resources / live.conf
src / test / resources / test.conf
```
I want to excluded live.conf from the artifact that is build when I run sbt one-jar (using the one-jar plugin). I added this line which unfortunately also excludes test.conf when running sbt test:compile
excludeFilter in Runtime in unmanagedResources := "*.conf"
How can I exclude live.conf in the artifact jar but not for the tests?

This should help:
mappings in (Compile, packageBin) ~= { _.filter(!_._1.getName.endsWith(".conf")) }
packageBin is a task which produces your jar artifact and mappings denotes files wich are used for compilation and project packaging in Compile scope

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.

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.

How do I add additional file to class path which is not java or scala file using SBT configuration?

How do I add additional file to classpath which is not java or scala file using SBT configuration ?
My source folder is defined like this
javaSource in Compile := baseDirectory.value / "src"
I have jawr.properties in the root of my /src folder. I'd like this file to be copied to WEB-INF/classes of my packaged app. I tried changing filter to
includeFilter in (Compile, unmanagedSources) := "*.java" || "*.scala" || "jawr.properties",
But it fails on sbt compile because it tries to compile it as java file.
I'm on SBT 0.13.6
The philosophy of SBT is to work by convention (and not by configuration) as much as possible. So the most straightforward solution, in many cases, isn't to look for the correct setting to tell SBT where your files are... But rather to figure out where SBT already expects to find them. You can check this page of the "getting started with SBT" guide for the basics.
For resource files that needs to be packaged together with compiled classes, the default directory is src/main/resources (a convention borrowed from Maven, like most of SBT's default directory structure). Similarly, files in src/test/resources are added to the classpath but only during tests.
If, for some reason, you want to use non-standard directories, you will want to have a look at this page of the documentation. For resources, the key to modify is resourceDirectory:
// resources in `resources` instead of `src/main/resources` :
resourceDirectory in Compile := baseDirectory.value / "resources"
// test resources in `test-resources` instead of `src/test/resources` :
resourceDirectory in Test := baseDirectory.value / "test-resources"
You want it be an unmanaged resource (not source)
unmanagedResourceDirectories in Compile := Seq(baseDirectory.value / "src")
includeFilter in unmanagedResources := "jawr.properties"

How to exclude unnecessary unmanaged dependencies from packaging?

I want to create a standalone version of my application and was wondering how i could exclude
an unmanaged *.jar file to be packaged. It's the "mariaDB4j-2.0-SNAPSHOT.jar" file I solely
use in tests which is about 56MB huge.
I tried to put the jar file into a custom directory 'test/lib'. Unfortunately, this did not exclude mariaDB4j from packaging.
unmanagedBase <<= baseDirectory { base => base / "test/lib" }
unmanagedJars in Test <<= unmanagedBase map { base => (base ** "mariaDB4j-2.0-SNAPSHOT.jar").classpath }
Any thoughts on this?
Cheers
Oliver
I think you want to add to the testing classpath.
Two things:
You can check out what's on the classpath using show test:fullClasspath to make sure your jar is on there. Using inspect test:fullClasspath will show you what the dependencies used for testing are.
I think you can directly add your jar to the classpath via:
fullClasspath in Test += Attributed.blank(baseDirectory.value / "test/lib/mariaDB4j-2.0-SNAPSHOT")
Hope that helps!
This works, but it looks a little overstated. Changing the base directory of the unmanaged dependencies, include the file to the test's and exclude it from compile.
unmanagedBase <<= baseDirectory { base => base / "test/lib" }
unmanagedJars in Test <<= unmanagedBase map { base => (base ** "mariaDB4j-2.0-SNAPSHOT.jar").classpath }
excludeFilter in unmanagedJars in Compile := "mariaDB4j-2.0-SNAPSHOT.jar"
excludeFilter in unmanagedJars in Compile ~= { _ || "mariaDB4j-2.0-SNAPSHOT.jar" }
don't use unmanaged dependencies
if you want to keep the jar in your source repository just use a file based maven repository in your source tree with
resolvers += "Private Maven Repository" at file(".").toURI.toURL+"/repository"
then mvn install MariaDB4j locally and copy resulting stuff from maven cache to $yourproject/repository
and use the dependency like a regular managed dependency