Can sbt dynamically use a generated subproject's build.sbt - sbt

My main project needs to generate a sub-project with its own build.sbt and then compile and use the sub-project. If the sub-project was pre-generated, I could reference it from the main build.sbt with RootProject. But if the sub-project is not yet generated, any attempt to use a value of lazy val sub = RootProject(subBaseDir) fails.
Is it possible to load the sub-project that does not exist at the moment of sbt start, so some tasks of the main project depended of the sub-project?

Yes, it should be possible in SBT 0.13.13 using its new feature called "Synthetic subprojects". You won't have a build.sbt file for such synthetic projects, since they're, well, completely synthetic. But otherwise they're completely functional projects, and you should be able to set up the dependencies between tasks of current project and its derived projects.
Disclaimer: I haven't tried this new feature myself yet.

Related

qmake subdirs optional target/sub project

I wondering if there is such a thing like optional targets or sub project in qmake, the Qt build tool.
Project
In my test example I have a subdirs project which contains another two projects, one shared library and one basic application. The application depends on the library which works great. Additionally I have one additional compiler (invoking lrelease) and one additional target (invoking lupdate), which also works like a charm (the shared library provides them as pri file for multiple projects).
After a complete build in release mode, the Windows deployment tool (namely windeployqt.exe) is called and deploys the target with all required shared libraries and plugins to my deployment directory.
Last component I wish to add is the creation of an installer using the Qt Installer Framework, which in fact should be easily done one the executables are located. Thus I want to create another sub project which contains all the installer stuff and provides the qmake steps to create one. But the project should not be build all the time but only when I want to, preferably over the create menu of Qt Creator.
Question
Is there any way to make a qmake subdirs sub project fully optional, so it will not be built using the default build all?
You can add a check around it:
enableOptional {
message(optional enabled)
SUBDIRS += YourSubDir
}
And call qmake with
qmake CONFIG+=enableOptional yourProject.pro
The qmake documentation states that one should use the test function requires(condition) to skip building a whole project. Using this one may add a new build configuration, namely bundle as example, which defines a configuration variable as #Jeffrey pointed out in his answer.
I managed to get it working with the following qmake project definition:
requires(BUNDLE_INSTALLER)
TEMPLATE = aux
QMAKE_POST_LINK = ...
Once you define the variable, over a new build configuration for proper working with Qt Creator (example), the steps listed under QMAKE_POST_LINK are performed. So I may bundle the installer, if I want to.

How do you compose sbt projects into a single build?

A question about composing sbt projects:
I forked a library project (https://github.com/allenai/pipeline) and wish to hack on it vis-a-vis my project that uses it. If I put them in the same multi-project build ― really my preferred option over publishing locally and consuming ― sbt will not read the project dir of the nested fork (where .scala files and plugin definitions originally reside).
E.g. I try, in build.sbt:
lazy val pipeline = (project in file("pipeline"))
lazy val githubCruncher = (project in file("."))
.dependsOn(pipeline)
And I get errors indicating directory pipeline/project is being ignored; the build.sbt itself of the nested project is being read, but sbt does not find what is defined alongside to it in its sibling project directory (and hence fails to load build definition).
So, must I squash the two projects into a single build.sbt or can I somehow elegantly compose the two without that? I am asking because this has also been a problem on other projects I work on where I ended up squashing each and every build definition minutia into one big monolith ― even though I'd prefer distributing some of the sub-projects as independent projects aside my own dev configuration.
According to my experience looks like everything inside the project directory of a project being pulled into a multi-project build ― needs to move to project under the root of the multi-project build, whereas the build.sbt of the pulled-in project does not have to be squashed ― a reference to it from from the top level build.sbt will work (unless that reference is followed by definitions for it right there in the top level build.sbt).
Sbt plugins coming from the pulled-in project then become applied to the unified multi-project build, and need to be disabled with disablePlugins for other sub-projects, if or where appropriate or desireable.

How to use an SBT plugin in the plugin's own project?

I'm making first steps with an SBT plugin.
object WoahPlugin extends Plugin {
override lazy val settings = commands += thingCommand
lazy val thingCommand = Command.command("thing") {state: State =>
println("this is the thing~!")
state
}
}
After defining a command, I want to try it out. Do I need to build the plugin and define a new project that uses it in order to try it out? Or can I open an SBT session in the plugin's project and import it directly?
tl;dr You can't have a plugin project and be able to test it out without another project that uses it.
A plugin enhances a build definition of a project so you set up a plugin that expands the project with capabilities you want - additional settings and tasks. See Plugins in the official documentation of sbt.
You set up plugins in meta-project under project directory, by convention usually in project/plugins.sbt (but any project/*.sbt file would do).
If you need to test a plugin you've got two notable choices that all boil down to having a separate project for the plugin and another to use it - the choice is about the place where the test project is as compared to the plugin project under test.
Plugin project in project metaproject
You can have the sources of the plugin under project/src/main/scala so they belong to their own project, but because of the directory they live in project, they automatically become part of the metaproject for another project one level up.
With the plugin's sources inside the meta-project project you can define a plugin dependency in project/plugins.sbt and have the plugin installed (given the recent changes to sbt since 0.13.5 it doesn't necessarily mean the plugin's enabled).
Plugin project anywhere
The plugin project is a sbt project and as such can be referenced from another sbt project using ProjectRef. If it's a git:// or file:// project, you declare the dependency on the plugin project using dependsOn and the project reference with ProjectRef.
See Can multi-projects from GIT be used as SBT dependencies? and How can sbt pull dependency artifacts from git?.

What is the reason to add Local Maven Repository to sbt?

I keep seeing sbt projects with the following resolvers setting in their build definition:
resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
It's also described in the official documentation of sbt in Resolvers section.
My limited knowledge of using sbt and build management tools in general lets me however consider it as a kind of anti-pattern.
The reason is that if a project declares a dependency on a library in the Local Maven Repository it somehow got downloaded there in the first place so it's available somewhere outside the local maven repository. If it is, why not using the original repository as the source?
If the dependency is not in a public repository, and is a dependency of a project, the project can use dependsOn to declare it without the additional repository in resolvers.
Please advice as I may be missing something obvious that makes the resolvers setting indispensable.
One obvious reason would be if one of your dependencies is a local project built with maven.
One scenario:
You have a project x which you build with sbt
X depends on y. Y is built with maven.
There is a bug in y which you need to fix/test, and you want to regression test x before you check it in.
You build a snapshot of y, and then you can test x before you commit the change to y.

RootProject and ProjectRef

I have been trying to find more information on RootProject and ProjectRef, but looks like it is not mentioned at all in sbt documentation.
I understand that if you are referencing a root project you should use RootProject and ProjectRef when you are referencing a sub-project. However it is not clear how the behavior will be different between them. Can somebody please help explain?
Also the fact that it is not documented, does it mean that RootProject and ProjectRef are not the recommended way to reference other sbt projects?
Thanks.
A single sbt build has a single project/ directory for .scala build definitions and plugin definitions. There can be multiple subprojects within that build with their own .sbt files, but not their own project/*.scala files.
When you want to include other, separate builds directly instead of using their published binaries, you use "source dependencies". This is what RootProject and ProjectRef declare. ProjectRef is the most general: you specify the location of the build (a URI) and the ID of the project in the build (a String) that you want to depend on. RootProject is a convenience that selects the root project for the build at the URI you specify.
Source dependencies do have an overhead: startup time, memory usage, and command line usability. If the group of projects don't need to be separate, it is best to use a single build with standard subprojects.

Resources