Add plugins under a same project in sbt - scala

I'm trying to build a Scala project aggregated by multiple projects, one of which is an sbt plugin. I would like to use this plugin in another subproject under the same parent project, but I don't quite understand how to do this.
My "build.sbt" in the project root is like this:
lazy val plugin = project
.in(file("sbt-Something"))
.dependsOn(lib)
.settings(common: _*)
.settings(name := "My plugin",
sbtPlugin := true)
lazy val examples = project
.in(file("examples"))
.dependsOn(lib, plugin)
.settings(common: _*)
.settings(name := "Examples")
How to add the plugin as a plugin to project examples?

I don't think you can have a plugin at the same "level" that project which is using it.
If you think of it, the plugin must be available before the compilation of the project that is using it. This is because it may, for example modify the build settings, which would influence the way the project is built.
If you want to keep your plugin within your project you can do so by declaring a project in the project/project directory.
$YOUR_PROJECT_ROOT/project/build.sbt
lazy val plugin = project
.in(file("sbt-plugin"))
.dependsOn(lib)
.settings(name := "My plugin", sbtPlugin := true)
lazy val lib = project.in(file("lib"))
lazy val root = project.in(file(".")).dependsOn(plugin)
Then you can put your code to sbt-plugin directory, and your shared library code to the lib folder.
In your normal build you can reference the shared library and the plugin.
$YOUR_PROJECT_ROOT/build.sbt
val lib = ProjectRef(file("project/lib"), "lib")
val root = project.in(file(".")).dependsOn(lib).enablePlugins(MyPlugin)
Please note that maybe it would be better to keep the shared library as a separate project, because I think this setup may be a bit tricky. For example if you change something in the shared library the main project should recompile and should use new code. The plugin however will only use new code after issuing the reload command on the project.
If you want to share settings between the projects you can check answers to How to share version values between project/plugins.sbt and project/Build.scala?

Related

Mutli-projects build with gradle like sbt

I'm basically a scala developer and i have project in scala - sbt recently i've started using kotlin and trying to some parts of my code in to kotlin. I need help in understanding gradle build system.
db-service
queue-service
business-logic
processor-code depends on projects on db-service, queue-service and business logic
another project "X" depends on queue-service and some other service.
Usually in sbt this is something very straight forward you can use ProjectRef to include these projects as dependencies.
How do i achieve the same with gradle? Thanks in advance
//Update
sample build.sbt
lazy val buildSettings = Seq(
scalaVersion := "2.12",
fork in Test := true,
fork in IntegrationTest := true,
...
)
lazy val root = Project("processor-code", file("."))
.settings(buildSettings: _*)
.settings(
libraryDependencies ++= //Deps
)
.dependsOn(db-service, queue-service, utilities)
.aggregate(db-service, queue-service, utilities)
lazy val db-service = ...
lazy val queue-service = Project("queue-service", file(".")).settings()...
lazy val utilities = ProjectRef(file("../utilities"), "utilities")
i have tried including the project in settings.gradle
include 'project'
project(":project").projectDir = "../myProject"
and added
implementation(project(":project"))
however, it doesn't seem working show error plugin already on classpath, then i've also tried creating a submodule and it seemed like it was working but when i was trying to run it throws a initialization exception
i've understood that we can configure a project in the following scenario
Root project: (contains common build.gradle)
| - subproject A
| - subproject B
| - myapp
now myapp easily can depend on subprojects
My scenario (no common build.gradle, each project will have its own build.gradle)
| Independent project A
| Independent project B
| my app
While it's true that you can only depend on other sub-projects, technically, that's still possible with Gradle.
Since project A is a Gradle project, you could pack it with gradle jar command. Then you could move the produced JAR to wherever you want, but probably to your my app project.
Now it's possible to launch an arbitrary command from Gradle using project.exec {}
What's more, you can even write your own Kotlin/Groovy function inside Gradle to do that for you.
That's what SBT is doing for you, actually.

sbt auto-plugins - disable them but for one sub project

Switching sbt-assembly from 0.11.2 to 0.13.0, I suddenly find myself in a situation where calling sbt assembly does not just invoke the task in the sub-project that explicitly added assemblySettings, but it tries to run it for each and every sub project.
So, if I have
lazy val root = project(...).aggregate(core, app)
lazy val core = project(...)
lazy val app = project(...).dependsOn(core)
How can I disable the assembly task for all but the root project? With other plugins such as sbt-buildinfo this problem doesn't occur because you have to explicitly enable the plugin per sub-project.
The goal is to be able to run sbt assembly so it will do that just for the root project.
Found the answer in a closed issue. You have to add the following line to your common settings:
aggregate in assembly := false

How to share resources between projects in SBT

The project I'm working on at work is a webapp on the Lift Framework. We're using xsbt web plugin as well. There's a "core" project, which contains the vast majority of the functionality; my current goal is to create two "distribution" projects that add a different set of classpath resources to the "core" project. The problem is that I either 1) can't get the "distribution" projects to run, or 2) Get them to run, but the required resource doesn't seem to be there.
What I've tried
Here's an abridged version of my project/Build.scala:
lazy val core = Project("Core", file("core"))
.settings( /*some dependencies, resolvers, webSettings */ )
lazy val app1 = Project("App1", file("app1"))
.aggregate(core)
.settings( /*the same settings as core */ )
lazy val app2 = Project("App2", file("app2"))
.aggregate(core)
.settings( /*the same settings as core*/ )
Then in the directory structure for both app1 and app2, I have a file at src/main/resources/aFileINeed. The core application is using the class.getResource approach to load the file from the classpath.
Problems
If I try to run one of the distribution projects, using container:start, it does not detect the required file in the classpath. Also, it claims that src/main/webapp is not an existing directory (that folder is included in the core project, as it is required by the xsbt web plugin).
How can I get these projects to "merge" their resources? I expected that using aggregate or dependsOn in the Build.scala project definition would handle that for me, but it apparently doesn't.
This is what I'm doing. I create a global 'resources' directory in the root of the project, and then the following variable:
lazy val globalResources = file("resources")
And then in every project's settings:
unmanagedResourceDirectories in Runtime += globalResources
For projects that use the xsbt-web-plugin or some other library that imports it you'll have to use the stronger
unmanagedResourceDirectories in Compile += globalResources
Beware that using this solution your projects will potentially have muliple resource directories and AFAIK if you define the same file twice compile:copy-resources is going to be angry at you.

How can depend on a PlayProject in GitHub?

I want to have a Play 2.0 project depend on another Play 2.0 project and I want it to checkout and build that project when it builds.
I know how I could do this if the dependent project was not a PlayProject, but a standard library. I could use something like this.
val libDep = RootProject(uri("git://github.com/ChazInc/play2-authenticitytoken.git"))
val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
// settings here
).dependsOn(libDep)
That won't work for me with the play project since I need the special build logic I get for free from a PlayProject for the dependency. I see that PlayProject can take a file argument, but it doesn't take a URI arguement like RootProject.
In order to use a git project directly, the project in question must have a project folder with Build.scala and/or plugins.sbt at the root level of the project. It sucks for Play modules, but that's the way it currently is.

Custom SBT Build file to not compile views in Play 2.0

I have a Play 1.2.4 app that I'm trying to migrate to Play 2.0.2. I currently have a structure in Play 1.2.4 like this:
Website depends on Frontend
Catalog depends on Frontend
Frontend depends on (a routes file being defined when compiling views)
Where Frontend contains a bunch of views that are used by both Website and Catalog. This decision was made because Catalog is really lightweight and is used for quick development of Frontend. While Website has a lot more code in it and takes longer to code/compile/test.
I cannot setup these projects as subprojects like is decribed here http://www.playframework.org/documentation/2.0/SBTSubProjects because there is a circular dependency. The views use Asset.of which requires the routes file to be defined. But the Website and Catalog each define a routes file and Play 2.0 does not support routes files from dependencies (this is supposed to come in Play 2.1). And in the Catalog the views are referenced in the controllers.
I was thinking that if I could change my build logic for Frontend to not try to compile the views, but instead just publish an artifact containing them then I could have Website and Catalog add those artifacts to the views it defines and build them together. This would break the circular dependency I have.
Has anyone else done this before? I'm too much of a beginner with SBT to even know if this is possible. Could anyone tell me how I could modify the Build.scala file to stop compiling the views but export them instead? Would it make sense for me to make this an SBT plugin? Of if you know of any code that shows how to do this another could you post a link to the code?
I used the play new to create two projects. The LDAPInterface was an interface to LDAP that we wanted to use across several applications. The Second Project was the Access manger. In the AccessManager\project\build.scala file, we structured it this way in order to use the LDAPInterface project. In eclipse, we just included the LDAPInterface in the project dependency section so we could debug. You could always compile a jar file and include that, but ... not as good if you want to drill down on project dependencies within eclipse. If we used play.Project it recognized it as a web project. If we just used Project it seemed to think it was a console application.
import sbt._
import Keys._
import play.Project._
object LDAPInterface {
lazy val depProject = RootProject(file("../LDAPInterface"))
}
object ApplicationBuild extends Build {
val appName = "AccessManager"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
//Add your project dependencies here,
javaCore,
javaJdbc,
javaEbean
)
// lazy val root = Project(id = "AccessManager",
// base = file(".")
//).dependsOn(LDAPInterface.depProject)
lazy val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
).dependsOn(LDAPInterface.depProject)
}