How can I make the compile task in SBT depend on a java source-processor library (spring-boot-configuration-processor) - scala

How do I configure my compile task to depend on the spring-boot-configuration-processor library?
The official documentation gives an example using Gradle's dependsOn function for the compileJava task:
...
dependencies {
optional "org.springframework.boot:spring-boot-configuration-processor"
}
compileJava.dependsOn(processResources)
}
Can someone show me how a similar task could be created for an SBT build file? Can this even work with Scala source code?
EDIT:
The spring-boot-annotation-processor reads metadata on Classes annotated with #ConfigurationProperties and generates meta-data to help with IDE code completion and documentation reading. i.e. Saves you from manually typing out well formed JSON docs that describe each of your configuration properties.
To answer #Haspemulator the library generates resources from source code.

sourceGenerators in Compile <+= Def.task {
run processor code
return list of generated files
}

Related

gradle include scala version in jar artifact name using kotlin DSL

How can I rename the produced jar by the gradle scala plugin using gradle build task to include the scala version name? I believe this property is called: archivesBaseName. It is made available from the java plugin (https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:archivesBaseName).
NOTE: I would want to accomplish this task using the kotlin DSL.
For the shadow jar:
id("com.github.johnrengelman.shadow") version "5.2.0" apply false
val shadowJar: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar by tasks
shadowJar.apply {
archiveBaseName.set("${project.name}_2.12-all")
}
tasks {
build {
dependsOn(shadowJar)
}
already works fine, but I would want to change the regular output as well.
I.e.:
archivesBaseName = "asdf"//"${project.name}_${sparkVersion}_${scalaVersionShort}"
usually works. But I have not figured out how to get this to work in the Kotlin DSL
base.archivesBaseName = "gradle"
https://chromium.googlesource.com/external/github.com/gradle/gradle/+/cf6d0508131b0ff9d6354b3d46f83bcf5ca8f8a4/build.gradle.kts#45
gets the job done

Using SBT to drive a build Java+Scala build that includes SWIG and C++ compilation

I am about to write the build configuration for a (mostly) SWIG'd wrap of a C++ library to be callable from Scala. Due to the presence of 3rd party dependencies on the Scala side, as well vast community support, I'd like to use sbt to automate the build.
However, I am a bit at a loss as to automating the swig and c++ compilation steps. Does anyone have experience with mixed-language build configurations driven by sbt and can offer advice about this?
So far I have found about the sbt-sh plugin, but I'd rather avoid shelling out directly if possible. I have also considered using cmake as the driver (since cmake does have a swig-driver plugin), and have a java/scala-only build step fired off cmake after it has completed the swig and c++ build steps.
SBT has its own syntax for executing external processes. You can leverage this + path finding + source generation.
A rough example:
lazy val invokeSwig = taskKey[Seq[File]]("invoke swig")
invokeSwig := {
s"swig -java example.i -outdir ${target.value}" !
val pathFinder = target.value ** "*.java"
pathFinder.get
}
target in invokeSwig := target.value / "swig"
sourceGenerators in Compile <+= invokeSwig
Note: I am using sbt v0.13.9, but this should work in other versions too.
You'd have to do some additional work for the native components. This includes compiling them as well as ensuring that they are available during run.
Unfortunately, I don't think you can get around doing some shell scripting since swig is a command line tool. (I have not found any java wrappers.)
SBT has the concept of source generators. A source generator is nothing more than a function/task writing (and returning) some files. If you do this, then SBT will first execute all source generators before starting to compile the (rest of the) code.
Just make sure to get swig to output its files to sourceManaged in Compile, then the generated source files are available on the classpath during compilation.
def runSwig: Seq[File] = {
import sys.process._
Seq("swig" , "param1", "param2", "..." ).!
// Somehow determine which files have been written by swig.
// I would make swig output its files to a temp directory and copy them to the source managed directory manually.
}
sourceGenerators in Compile += Def.task {
runSwig
}
I'm not sure about C++ code though. In my own project I'm using docker to cross compile to various platforms. If your native code doesn't change often, I won't recommend recompiling the native code every time SBT is compiling your java/scala code.

Where should javah fit into an SBT build?

javah is used to generate C headers from #native methods. It operates on compiled class files, so it requires a classpath as an argument. For this reason, it seems sensible to make a javah task depend on fullClasspathin Compile.
The issue I am facing is that the generated headers are needed in order to build a native library, and the native library needs to be a resource. But, because it is a resource, it will be included in fullClasspath in Compile, which leads to a circular dependency.
Does SBT have a classpath key that includes all .class files but excludes resources?
I just discovered sbt-jni, a very interesting new SBT plugin which simplifies working with JNI from SBT.
When reading some source code, I stumbled over
this line
, which seems to refer to the problem you are facing. If I understand it correctly, the work-around in sbt-jni is to combine dependencyClasspath in Compile, compile in Compile, and classDirectory in Compile instead of using fullClasspath in Compile. I'm not sure if this will exactly result in a classpath that includes all .class files, but maybe something like that works for you as well.

How do I use shared configurations across SBT (Play) multi-projects?

I have several SBT 0.13 / Play 2.2 projects (websites). They are all multi-module as they share some common functionality. This makes their project configuration files both complex and almost identical, but not quite.
I would like to be able to share as much as possible of these configuration files across the projects (frequent play updates makes keeping 5+ websites up to date a royal pain, not to mention all the almost-identical-but-evolving dependency lists across the projects).
build.properties and plugins.sbt are identical across projects and can be overwritten by a simple script. Great.
Build.scala is trickier - I would like to introduce a shared base class like so:
abstract class MyBuildBase extends Build { ... }
that in Build.scala do:
object ApplicationBuild extends MyBuildBuild { ... }
In order for this to make any sense at all, MyBuildBase.scala needs to be shared across projects. This can be done with svn:external, which operates on directories. Which means I need to somehow make this shared directory accessible when Build.scala is compiled (otherwise sbt complains loudly).
Reading http://www.scala-sbt.org/0.13.0/docs/Detailed-Topics/Classpaths.html and http://www.scala-sbt.org/0.13.0/docs/Getting-Started/Full-Def.html it seems like this should be possible.
However, it is exceptionally unclear to me what to actually put in the project/project/Build.scala file to actually achieve this - I can't find an example of "an sbt build file that's intended to build an sbt build file and include some extra source files in the build".
Any suggestions?
What you probably want to do is create a plugin, or shared library.
You can make an sbt project with a build like follows:
build.sbt
sbtPlugin := true
organization := "you"
name := "common-build"
version := "1.0"
Then create in src/main/scala your abstract class "MyBuildBase". Release this project as an sbt plugin.
Then in your other projects, you can use this as a library/plugin. In project/plugins.sbt add:
addSbtPlugin("you" % "common-build" % "1.0")
And this will resolve your common build library when building your build.
If you need more information, look up more about sbt plugins and ignore the part about making something that extends a Plugin. Plugins are just libraries versioned with sbt's version number and your own. You should be able to put whatever code you want in there to share between builds.
Note: in 2016, Build.scala is deprecated for Build.sbt.
Here is the new (Dec. 2016) multi-module with App Scala sbt template by Michael Lewis.
Usage
sbt new lewismj/sbt-template.g8
You can then run:
sbt compile
sbt publish-local
sbt assembly
It is based on Scala SBT template (Library)
This giter8 template will write SBT build files for a Scala library.

Using SBT 0.10.0 to generate source code with ANTLR3

How would I use the simple build tool (sbt) 0.10.0 to generate any kind of source code based on an ANTLR3 grammar?
I guess I have to use a plugin for something like this, if I want to use the generated code within the same project or a subproject of the same parent project. Are there any existing plugins for SBT 0.10? ...or maybe another solution without using a plugin?
You won't need to use a plugin.
First you will need to define antlr as a dependency. Then you will need to define your source generation task according to this page:
https://github.com/harrah/xsbt/wiki/Common-Tasks
Your task definition is going to look something like this:
sourceGenerators in Compile <+= sourceManaged in Compile map { dir =>
<code to generate source from grammar files>
}
Where the code to generate your source will create a new org.antlr.Tool object with your files as an argument to the constructor. Once you have created a Tool object, then invoke the process method, and your source should be generated.