Accessing values in project/Dependencies.scala file in scala code in subproject - scala

I have a multimodule scala project with the following structure -
-A/
-B/
-project/ (root project)
-build.sbt (this has build definition for all the subprojects)
I have an object declared in the project/ folder (lets call this object Dependencies) which contains various constants . Is it possible to access a variable declared in project/Dependencies.scala in scala code inside a subproject(A or B) without creating a dependency of any of the subprojects on the root project.
Please let me know if I need to clarify further.

If you want to make some code from your build definition available for the code in the project, you can use sbt-buildinfo plugin. It's mostly adapted for setting/task keys, but you can use it for any other values defined in your build too.
The way it works is very simple: it uses sourceGenerators to generate a piece of Scala code (with the values from the build) that will be available to the rest of your project sources. So if you don't want to use sbt-buildinfo, you can also generate sources directly. See sbt documentation on Generating files.

Related

Unit testing SBT code within the local project

I have an SBT project, within which I have defined a source generator that parses some DB migration scripts in order to make the current DB version available to the application at compile-time.
For example, I might have the following resources:
subproject1/src/main/resources/db/migration/
|- V1__Baseline.sql
|- V2__AddCustomerTable.sql
|- V2_1__Refactor.sql
And I would require my source generator to create a scala object with the field val version = "2.1".
The SBT project is structured as:
project/
|- build.sbt
|- SchemaVersionParser.scala
Where SchemaVersionParser defines the utility functions that are used by build.sbt in order to parse the resources and generate the appropriate file.
Now since this is a key component of my app, I'd like to ensure that the functions in SchemaVersionParser which extract and sort the versions are unit tested.
Is there any supported means of unit testing SBT code residing locally in the one project? I know I can do this if I create a separate SBT plugin, however it'd be nice if I could avoid this.
SBT build definitions are SBT projects. So put test code in project/src/test/scala should be able to access SchemaVersionParser, and to launch the tests you just do sbt test in project directory.

How to setup SBT dependency for scala code that is located in same directory as Build.scala

Our project features a kind of adhoc "plugin" that reads csv files and stuffs the contents into a database.
This code is defined in /project/DataMigrate.scala
We had our own poorly implemented version of a CSV parser that isn't up to the task anymore so I tried to add this https://github.com/tototoshi/scala-csv to the libraryDependencies in /project/Build.scala but that did not make it importable from DataMigrate.scala. I also tried putting the library dependency in /project/build.sbt as I read something about "Build definition of a build definition", but that did not seem to help either.
Is it at all possible to add dependencies for code that lives in /project?
SBT is recursive, so just as you can define dependencies and settings of the actual project in [something].sbt or project/[something].scala you can define dependencies and settings of the projects project (any ad hoc plugins etc) in project/[something].sbt or project/project/[something].scala

Importing functions from outside a project in scala [sbt]

I have a scala sbt project of this format -
ProjectDirectory/
ProjectDirectory/build.sbt
ProjectDirectory/project
ProjectDirectory/src
ProjectDirectory/src/main/scala/MyMainFile.scala
ProjectDirectory/src/main/scala/MySupportingFile.scala
ProjectDirectory/target
Currently,to use the (utility) functions defined in MySupportingFile.scala inside MyMainFile.scala, I'm importing them and using them.
But, as our code grew we have moved to multiple projects few of which might need the functions inside MySupportingFile.scala.
How do I move MySupportingFile.scala outisde of this project and make it as library project and use it in all new projects that needs it.
You need to create a new project for MySupportingFile.scala in the same way this project was created. I.e.
SupportProject/
SupportProject/build.sbt
SupportProject/src/main/scala/MySupportingFile.scala
target subfolder will be created automatically when the project is compiled. Then build this project, publish it with publishLocal (depending on SBT version, it can be publish-local), and add dependency to this project in ProjectDirectory/build.sbt as usual:
libraryDependencies += supportProjectGroupId %% supportProjectName % supportProjectVersion

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.