I am using sbt-thrift plugin 0.6 with SBT 0.12 and I need to change the resource directory, source directory, output directory and other settings in my build configuration.
It doesn't seem to work as mentioned in README.
Can someone tell me how to do this thing?
SBT 0.13 + sbt-thrift 0.7
NOTE Below is the same configuration for SBT 0.12 and sbt-thrift 0.6
I use SBT 0.13.1 and hence had to use sbt-thrift 0.7 from http://bigtoast.github.io/repo/com/github/bigtoast/sbt-thrift_2.10_0.13/0.7/.
project/plugins.sbt
resolvers += "bigtoast-github" at "http://bigtoast.github.com/repo/"
addSbtPlugin("com.github.bigtoast" % "sbt-thrift" % "0.7")
build.sbt
import com.github.bigtoast.sbtthrift.ThriftPlugin
seq(ThriftPlugin.thriftSettings: _*)
With the above build configuration, you may want to look at https://github.com/bigtoast/sbt-thrift/blob/master/src/main/scala/ThriftPlugin.scala for possible tasks and settings (I have not checked whether README.md's fully correct).
There's source-directory setting to set "Source directory for thrift files. Defaults to src/main/thrift".
> thrift:source-directory
[info] C:\dev\sandbox\thrift\src\main\thrift
To change the value use the following:
ThriftPlugin.thriftSourceDir := sourceDirectory.value / "my-own-source-dir"
and reload so the setting changes (react) accordingly:
> thrift:source-directory
[info] C:\dev\sandbox\thrift\src\my-own-source-dir\main\thrift
Please note that all the settings and tasks belong to the thrift config.
SBT 0.12 + sbt-thrift 0.6
project/plugins.sbt
resolvers += "bigtoast-github" at "http://bigtoast.github.com/repo/"
addSbtPlugin("com.github.bigtoast" % "sbt-thrift" % "0.6")
Since OP asked about multi-project build configuration, below is the definition of two projects with one configured with a custom value for thriftSourceDir.
project/MyBuild.scala
import sbt._
import Keys._
import com.github.bigtoast.sbtthrift.ThriftPlugin._
object MyBuild extends Build {
lazy val thriftS = Defaults.defaultSettings ++
thriftSettings ++
Seq(
thriftSourceDir <<= sourceDirectory(_ / "my-own-source-dir")
)
lazy val thriftP = Project("thriftProject",
file("."),
settings = thriftS
)
lazy val someP = Project("some-other-project",
file("some-other-project")
)
}
With the build configuration, sbt shell gives you the following:
> sbt-version
[info] 0.12.4
> projects
[info] In file:/Users/jacek/sandbox/so/thrift-0.12/
[info] some-other-project
[info] * thriftProject
> thrift:source-directory
[info] /Users/jacek/sandbox/so/thrift-0.12/src/my-own-source-dir/main/thrift
> thriftProject/thrift:source-directory
[info] /Users/jacek/sandbox/so/thrift-0.12/src/my-own-source-dir/main/thrift
> some-other-project/thrift:source-directory
[info] /Users/jacek/sandbox/so/thrift-0.12/some-other-project/src
Related
I'd like to create an SBT project with inheritance and shared dependencies.
With Maven's POM files, there is the idea of Project Inheritance where you can set a parent project. I'd like to do the same thing with SBT.
The xchange-stream library uses Maven's Project Inheritance to resolve subproject dependencies when compiled from the parent project.
Here is my idea of what the file structure would look like:
sbt-project/
project/
dependencies.scala # Contains dependencies common to all projects
build.sbt # Contains definition of parent project with references
# to subprojects
subproject1/
build.sbt # Contains `subproject3` as a dependency
subproject2/
build.sbt # Contains `subproject3` as a dependency
subproject3/
build.sbt # Is a dependency for `subproject1` and `subproject2`
Where project1 and project2 can include project3 in their dependencies lists like this:
libraryDependencies ++= "tld.organization" % "project3" % "1.0.0"
Such that when subproject1 or subproject2 are compiled by invoking sbt compile from within their subdirectories, or when the parent: sbt-project is compiled from the main sbt-project directory, then subproject3 will be compiled and published locally with SBT, or otherwise be made available to the projects that need it.
Also, how would shared dependencies be specified in sbt-project/build.sbt or anywhere in the sbt-project/project directory, such that they are useable within subproject1 and subproject2, when invoking sbt compile within those subdirectories?
The following examples don't help answer either of the above points:
jbruggem/sbt-multiproject-example:
Uses recursive build.sbt files, but doesn't share dependencies among child projects.
Defining Multi-project Builds with sbt: pbassiner/sbt-multi-project-example:
Uses a single build.sbt file for the projects in their subdirectories.
sachabarber/SBT_MultiProject_Demo:
Uses a single build.sbt file.
Such that when subproject1 or subproject2 are compiled by invoking sbt compile from within their subdirectories...
Maybe Maven is meant to be used together with the shell environment and cd command, but that's not how sbt works at least as of sbt 1.x in 2019.
The sbt way is to use sbt as an interactive shell, and start it at the top level. You can then either invoke compilation as subproject1/compile, or switch into it using project subproject1, and call compile in there.
house plugin
A feature similar to parent POM would be achieved by creating a custom plugin.
package com.example
import sbt._
import Keys._
object FooProjectPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
val commonsIo = "commons-io" % "commons-io" % "2.6"
override def buildSettings: Seq[Def.Setting[_]] = Seq(
organization := "com.example"
)
override def projectSettings: Seq[Def.Setting[_]] = Seq(
libraryDependencies += commonsIo
)
}
sbt-sriracha
It's not exactly what you are asking for, but I have an experimental plugin that allows you to switch between source dependency and binary dependency. See hot source dependencies using sbt-sriracha.
Using that you could create three individual sbt builds for project1, project2, and project3, all located inside $HOME/workspace directory.
ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version := "0.1.1-SNAPSHOT"
lazy val project3Ref = ProjectRef(workspaceDirectory / "project3", "project3")
lazy val project3Lib = "tld.organization" %% "project3" % "0.1.0"
lazy val project1 = (project in file("."))
.enablePlugins(FooProjectPlugin)
.sourceDependency(project3Ref, project3Lib)
.settings(
name := "project1"
)
With this setup, you can launch sbt -Dsbt.sourcemode=true and it will pick up project3 as a subproject.
You can use Mecha super-repo concept. Take a look on the setup and docs here: https://github.com/storm-enroute/mecha
The basic idea is that you can combine dependent sbt projects (with their own build.sbt) under single root super-repo sbt project:
/root
/project/plugins.sbt
repos.conf
/project1
/src/..
/project/plugins.sbt
build.sbt
/project2
/src/..
/project/plugins.sbt
build.sbt
Please, note that there is no build.sbt in the root folder!
Instead there is repos.conf file. It contains definition of the sub-repos and looks like the folowing:
root {
dir = "."
origin = ""
mirrors = []
}
project1 {
dir = "project1"
origin = "git#github.com:some_user/project1.git"
mirrors = []
}
project2 {
dir = "project2"
origin = "git#github.com:some_user/project2.git"
mirrors = []
}
Then you can specify the Inter-Project, source-level Dependencies within individual projects.
There are two approaches:
dependencies.conf file
or in the build source code
For more details, please, see the docs
I have a multi-project sbt where I use sbt-release plugin. Everything works fine if I run release in a sub-project
> project reporter
[info] Set current project to reporter (in build file:/source/storage-integ/)
> release
[info] Starting release process off commit: c069698baf8bb6fca611ab4e7e086398aab473c5
[info] Checking remote [origin] ...
But this doesn't work when I run "sbt reporter/release" from cli. Where as "sbt reporter/compile" or "sbt reporter/assembly" do work.
$ sbt reporter/release
[warn] Executing in batch mode.
[warn] For better performance, hit [ENTER] to switch to interactive mode, or
[warn] consider launching sbt without any commands, or explicitly passing 'shell'
[info] Loading global plugins from /home/vagrant/.sbt/0.13/plugins
[info] Loading project definition from /source/storage-integ/project
[info] Set current project to root (in build file:/source/storage-integ/)
[error] Expected ':' (if selecting a configuration)
[error] Not a valid key: release (similar: releaseVcs, rpmRelease, rpm-release)
[error] reporter/release
This looks very similar to another SO post. I tried adding releaseSettings to build.sbt as suggested but it throws error
build.sbt:62: error: not found: value releaseSettings
I tried import sbtrelease.Release._ but that throws
error: object Release is not a member of package sbtrelease
At this point I feel the solution mentioned is no longer valid. Also, I don't see any reference to releaseSettings in sbt-release readme. Any idea how to get this working?
sbt.version = 0.13.15 && sbt-release: "1.0.6"
The release settings should be only in your root project. So, in order to have that:
First, your build.sbt could be something like this
lazy val root: Project = project.in(file("."))
.settings(Releases.settings: _*)
.aggregate(module1, module2)
Then, your project/Releases.scala like:
object Releases {
// You need to custom these to reflect your actual procedure
private val releaseProcess = Def.setting {
Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
publishArtifacts,
setNextVersion,
commitNextVersion,
pushChanges
)
}
val settings = Seq(
releaseCommitMessage := s"Set version to ${(version in ThisBuild).value}",
releaseTagName := (version in ThisBuild).value,
releaseProcess := releaseProcess.value
)
}
By default you need a version.sbt with your current version. Lets say:
version in ThisBuild := "1.0.0-SNAPSHOT"
Then just:
sbt release
I'm attempting to use the sbt-aspectj plugin with the sbt native packager and am running into an issue where the associated -javaagent path to the aspectj load time weaver jar references an ivy cache location rather than something packaged.
That is, after running sbt stage, executing the staged application via bash -x target/universal/stage/bin/myapp/ results in this javaagent:
exec java -javaagent:/home/myuser/.ivy2/cache/org.aspectj/aspectjweaver/jars/aspectjweaver-1.8.10.jar -cp /home/myuser/myproject/target/universal/stage/lib/org.aspectj.aspectjweaver-1.8.10.jar:/home/myuser/myproject/target/universal/stage/lib/otherlibs.jar myorg.MyMainApp args
My target platform is Heroku where the artifacts are built before being effectively 'pushed' out to individual 'dynos' (very analogous to a docker setup). The issue here is that the resulting -javaagent path was valid on the machine in which the 'staged' deployable was built, but will not exist where it's ultimately run.
How can one configure the sbt-aspectj plugin to reference a packaged lib rather than one from the ivy cache?
Current configuration:
project/plugins.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.5")
build.sbt (selected parts):
import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
aspectjSettings,
javaOptions in Runtime ++= { AspectjKeys.weaverOptions in Aspectj }.value,
// see: https://github.com/sbt/sbt-native-packager/issues/598#issuecomment-111584866
javaOptions in Universal ++= { AspectjKeys.weaverOptions in Aspectj }.value
.map { "-J" + _ },
fork in run := true
)
Update
I've tried several approaches including pulling the relevant output for javaOptions from existing mappings, but the result is a cyclical dependency error thrown by sbt.
I have something that technically solves my problem but feels unsatisfactory. As of now, I'm including an aspectjweaver dependency directly and using the sbt-native-packager concept of bashScriptExtraDefines to append an appropriate javaagent:
updated build.sbt:
import com.typesafe.sbt.SbtAspectj._
lazy val root = (project in file(".")).settings(
aspectjSettings,
bashScriptExtraDefines += scriptClasspath.value
.filter(_.contains("aspectjweaver"))
.headOption
.map("addJava -javaagent:${lib_dir}/" + _)
.getOrElse(""),
fork in run := true
)
You can add the following settings in your sbt config:
.settings(
retrieveManaged := true,
libraryDependencies += "org.aspectj" % "aspectjweaver" % aspectJWeaverV)
AspectJ weaver JAR will be copied to ./lib_managed/jars/org.aspectj/aspectjweaver/aspectjweaver-[aspectJWeaverV].jar in your project root.
I actually solved this by using the sbt-javaagent plugin to adding agents to the runtime
Is it possible to build an sbt plugin in a multi-project setup and use that plugin in some other sub-project of the same multi-project?
For example:
root/
+ mySbtPlugin/
+ myProject/
+ project/
+ plugins.sbt // Uses `mySbtPlugin`
It is not possible since the only way to define plugins for a single or multi-module project is via project (meta)build. I was tricked again to have a solution for you when I set up the sandbox environment with the layout you described.
sbt allows project (meta)project to be in the root directory only. No other project directories are processed and become part of the build definition.
That's why your best (and only) bet is to have the multi-module build for myProject and mySbtPlugin to ease your development, and enable the plugin only for these project(s) you really want to (be careful with auto-plugins, though).
project/plugins.sbt
lazy val root = (project in file(".")) dependsOn sbtNonamePlugin
lazy val sbtNonamePlugin = ProjectRef(file("../sbt-noname"), "sbt-noname")
addSbtPlugin("pl.japila" % "sbt-noname" % "1.0")
build.sbt
lazy val `my-project`, `sbt-noname` = project
sbt-noname/build.sbt
sbtPlugin := true
name := "sbt-noname"
organization := "pl.japila"
version := "1.0"
sbt-noname/src/main/scala/sbtnoname/Plugin.scala
package sbtnoname
import sbt._
import plugins._
object Plugin extends AutoPlugin {
override def trigger = allRequirements
override val projectSettings: Seq[Setting[_]] = inConfig(Test)(baseNonameSettings)
lazy val sayHello = taskKey[Unit]("Say hello")
lazy val baseNonameSettings: Seq[sbt.Def.Setting[_]] = Seq(
sayHello := {
println("I'm the plugin to say hello")
}
)
}
With the files above, run sbt.
> about
[info] This is sbt 0.13.6-SNAPSHOT
[info] The current project is {file:/Users/jacek/sandbox/multi-plugin/}my-project 0.1-SNAPSHOT
[info] The current project is built against Scala 2.10.4
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, sbtnoname.Plugin, com.timushev.sbt.updates.UpdatesPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.4
> projects
[info] In file:/Users/jacek/sandbox/multi-plugin/
[info] * multi-plugin
[info] my-project
[info] sbt-noname
> plugins
In file:/Users/jacek/sandbox/multi-plugin/
sbt.plugins.IvyPlugin: enabled in multi-plugin, sbt-noname, my-project
sbt.plugins.JvmPlugin: enabled in multi-plugin, sbt-noname, my-project
sbt.plugins.CorePlugin: enabled in multi-plugin, sbt-noname, my-project
sbt.plugins.JUnitXmlReportPlugin: enabled in multi-plugin, sbt-noname, my-project
sbtnoname.Plugin: enabled in multi-plugin, sbt-noname, my-project
> my-project/test:sayHello
I'm the plugin to say hello
[success] Total time: 0 s, completed Jun 15, 2014 3:49:50 PM
Normally, when not using Git, you can just write:
addCompilerPlugin("something" % "blah" ...)
scalacOptions += "-P:blah:..."
This addCompilerPlugin takes a ModuleID. But here... I've tried adding:
lazy val root = project in file(".") dependsOn
uri("git://github.com/puffnfresh/wartremover.git#master")
to the project/plugins.sbt as well as:
lazy val wartRemover = RootProject(
uri("git://github.com/puffnfresh/wartremover.git#master"))
lazy val root = Project(...).settings(
...
scalacOptions += "-P:wartremover:...",
...
) depends on wartRemover
Both result in:
[error] (root/*:update) sbt.ResolveException: unresolved dependency:
org.brianmckenna#wartremover_2.10.3;0.5-SNAPSHOT: not found
tl;dr The project wartremover has not been published for Scala version 2.10.3. Downgrade yours with the following in build.sbt among the other necessary settings:
scalaVersion := "2.10.2"
Detailed procedure focusing on Scala 2.10.3
The following in build.sbt
addCompilerPlugin("org.brianmckenna" % "wartremover" % "0.5" cross CrossVersion.full)
adds org.brianmckenna:wartremover:0.5:plugin->default(compile) to libraryDependencies.
[sbt-0-13-2]> show libraryDependencies
[info] List(org.scala-lang:scala-library:2.10.3, org.brianmckenna:wartremover:0.5:plugin->default(compile))
So to use a RootProject that points at the project wartremover at GitHub I had to use the following in build.sbt (this is the complete file):
scalacOptions in root += "-P:wartremover:traverser:org.brianmckenna.wartremover.warts.Unsafe"
lazy val root = project in file(".") dependsOn wartRemover % "plugin->default(compile)"
lazy val wartRemover = RootProject(
uri("git://github.com/puffnfresh/wartremover.git#master"))
Since the project wartremover is not published for 2.10.3 I followed the steps below:
Show available projects
[root]> projects
[info] In file:/Users/jacek/sandbox/so/sbt-0.13.2/
[info] * root
[info] In git://github.com/puffnfresh/wartremover.git#master
[info] wartremover
Switch to wartremover and publishLocal it for scalaVersion set to 2.10.3.
[wartremover]> set scalaVersion := "2.10.3"
[info] Defining wartremover/*:scalaVersion
[info] The new value will be used by wartremover/*:allDependencies, wartremover/*:assemblyPackageScala::assemblyDefaultJarName and 12 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to wartremover (in build git://github.com/puffnfresh/wartremover.git#master)
[wartremover]> publishLocal
[info] Packaging /Users/jacek/.sbt/0.13/staging/d6dd3d2e3d818e69943a/wartremover/target/scala-2.10/wartremover_2.10.3-0.6-SNAPSHOT-sources.jar ...
[info] Updating {git://github.com/puffnfresh/wartremover.git#master}wartremover...
...
[info] published ivy to /Users/jacek/.ivy2/local/org.brianmckenna/wartremover_2.10.3/0.6-SNAPSHOT/ivys/ivy.xml
[success] Total time: 7 s, completed Jan 18, 2014 11:34:07 PM
Switch to the project root and do update. It should now work fine.
[wartremover]> project {file:/Users/jacek/sandbox/so/sbt-0.13.2/}
[info] Set current project to root (in build file:/Users/jacek/sandbox/so/sbt-0.13.2/)
[root]> update
[info] Updating {file:/Users/jacek/sandbox/so/sbt-0.13.2/}root...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[success] Total time: 0 s, completed Jan 18, 2014 11:36:24 PM
console should work fine now, too.
[root]> console
[info] Starting scala interpreter...
[info]
<console>:5: error: var is disabled
var value: scala.tools.nsc.interpreter.IMain = _
^
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
Type in expressions to have them evaluated.
Type :help for more information.
scala>
The error message worries me, though. I don't know the plugin and neither do I know how to get rid of it. It also happens when I follow the steps described in Compiler plugin when scalaVersion := "2.10.2" is set in build.sbt (so the compiler plugin's available in the repo).