How to build codebase against multiple versions of an SBT plugin? - scala

I've got some projects that I'd like to cross-build for multiple Scalas, which is straightforward, but also for multiple versions of Play! Framework, which is less straightforward because they come as an SBT plugin.
I've currently got it working by separating them into completely separate builds, with symlinks to share a common codebase project. Is this the best solution or can I do it in a single build?
I'm aware of the whole "SBT is recursive" thing so I know they are going to have to be separate build projects, but wondered if they could still live within the same aggregated build.
Minimal setup:
https://github.com/halfninja/play-multiversion-build
If this is the best way to go about it then I'll self-answer with this but I'm interested to hear from people with a more SBT-minded brain as it's stretching my comprehension.
I've also seen some builds use system properties to modify versions, which avoids needing separate directories with symlinks but is otherwise the same solution requiring separate builds.

Related

Cross-cutting "logical" scopes in multi-project sbt builds

Let's say I have a build with a handful of subprojects that are related but have some logical classification above the sorts of things that the build is normally aware of.
For example, I might have a collection of subprojects
Foo
Bar
Baz
Quux
Woof
Oink
I know that Woof and Bar are part of what I'd call the server component. Baz is a common dependency of both, and Foo, Quux, and Oink are on the client side. The whole build is an aggregate of the various subprojects, but sometimes I'd just like to "focus" on the server side, or the client side, or whatever.
On one hand, I've considered nested aggregated projects, but I'm not sure how well that works with sbt's other functionality.
On the other, I was thinking of making custom scopes that cut across the subprojects. I'd like to be able to configure related projects with similar keys, so it is handy to be able to say that I'd like to update a certain key for the group of related projects.
What's a good approach for this sort of thing? Am I thinking about it wrong?
Dealt with the similar situation.
My solution was to break things out into sub-projects all in sbt, and use dependsOn to link the sub-projects. The nice unintended consequence here is that sub-projects with dependsOn mimic Maven dependencies perfectly. If you publish one of these, it will magically have maven dependencies for the others. Tools like eclipse and intelli will generally also see these dependency chains rather easily.
This gives you the option of keeping things in the same SBT project or not, with almost no difference in the end. They just all tie together at the 'maven-style' dependency. Using a local maven repo here or a remote one works great. At this point, you're free to make a choice based on code-management and not dep-management, as to whether or not to break things into different SBT projects.
EDIT: so in the end, if you want to move a module out of the multi-project SBT thing, you just need to add regular maven deps to whatever code base is requesting the other
My opinion: Skip the sub-projects. Splitting a project is nice, when you publish them as independent projects. But multiple projects make also trouble: It is quite hard to get good and stable interfaces between multiple projects.
I would split a project into multiple projects as late as possible. Dependency management (especially cyclical dependencies), refactoring (especially moving of classes) and tool support in general (especially IDE integration) is much better with only one big project.
Things like measuring code coverage can also become surprisingly difficult, when the coverage spans multiple projects.
Custom scopes and six sub-projects: In my opinion this is totally over engineered. Stay with one project, get the whole thing running and split it later (if necessary).

Inherit .sbt files

I have many small Scala applications and I would like a central place to manage versions of common dependencies.
I know I can set up a Build.scala file and define multiple projects. I used to have that, but not all of these applications are related in that sense. They just happen to share a common software architecture.
How do I achieve this with SBT? Currently I'm managing multiple .sbt files that I batch update (like dependencies.sbt, common.sbt etc.).
My initial approach was to start writing a plugin, but I got stumped along the way with getting dependencies working within the plugin.
I wanted to collect plugin settings and build settings. But I never got one plugin to depend on a set of other plugins.
Anyone tried this before, how do I manage central application profiles (both plugins and settings)?
Do you mean different applications? You can then just put your settings into global.sbt. You can look for more detailed description here

How best to structure and build Clojure apps with plugins?

I think (see below) that I would like to structure a Clojure project as multiple modules, with ordered dependencies - just like Maven lets me do with multi-modules projects.
But I can't see how to do this with Leiningen - all I can see is the checkouts fix described in the FAQ which doesn't seem to be as powerful.
Will lein do this? Should I be using Gradle instead? Or is this kind of thing not needed?
Some more context: I am wondering how to architect a modular application that supports plugins (which I imagine means jars dumped on the classpath). And am wondering to what extent I can structure that as a core + plugins (I am thinking I should be able to do something with Clojure's dynamic code loading and not have to go with Java/OSGi). So I guess the driving motivation for a single project comes from wanting some way of packaging everything (the core + default plugins) as a single blob that is easy for the end user, but which can also be divided up (and which is built and tested in fragments, testing the logical independence of each module). More general advice about this is welcome
Update
A possible solution that wasn't mentioned below is using a Maven plugin - I assume that supports everything Maven does, but compiles Clojure, so will work with nested modules, etc.
First, it does not seem like Leiningen supports a module hierarchy like Maven does. The checkouts are the next closest thing it has. It should be sufficient though to develop a modular application in Clojure though.
For the project structure, I would have an API project, a "core" project, the plugins themselves, and a separate packaging project. The core and the plugins should only depend on the API. Which build tool you use to create the packaging project is up to you. Gradle would probably be more effective at handling the packaging, however having the "checkout" functionality Leiningen offers could make development of the system as a whole easier.
I would take a look at the code for Leiningen and Noir to figure out how to effectively handle this.
For dynamically loading the plugins, I would start with looking how Noir handles it in two of their files:
server.clj has namespace loading for all files under a particular namespace. Under the hood it uses tools.namespace, but you can easily see how it's used to require every namespace under a particular base. This is how Leiningen handles custom tasks as well - the base definition for the task should be in the leiningen.$task namespace.
core.clj has what I would use for plugin registration. In summary, use a map under an atom and add plugins to that map. I would advice wrapping the registration with a macro to keep your code cleaner.
What I listed above should be sufficient if you don't need to handle adding plugins at run time. If you don't have every plugin on the classpath during start-up, I would recommend utilizing pomegranite to add entries to the classpath. You can see an example in classpath.clj.

Eclipse : Using same output folder for different projects

Following is a question that is posted on http://dev.eclipse.org in April 2003. The original question is:
Hi all,
in eclipse i have created several java
projects representing different
modules for one web application. i'd
like to configure one output folder
for all of these projects. Any time i
build a subproject the content of the
output folder is deleted, so i loose
the classes of all other subprojects.
I think there must be a switch or
something like that to tell eclipse
not to clear the content of the output
folder when it builds a project - but
i just can't find it.
Thanks for your help!
Alex
I am trying to see if I could get a definitve answer for this question. I have tried to find out to see if this question has already been addressed and I was not able to find any except for the following answer:
Window-->Preferences-->Java-->Compiler-->Build Path
The above answer did not help me much.
Hmm... I think this approach will bring more trouble than it's worth. Sure it's a priori a quick and dirty fix to integrating your projects together but you are only pushing the problem forward. It is good practice to keep your modules as isolated as possible from each-other, trying to merge the compiled code in a single location is working against the way the IDE was designed and will only bring trouble.
I would recommend that you look into maven to build and package your modules. Then referencing them is just a matter of adding a declaration in the project that requires it and you are integrated. Of course you will need to learn it but it provides a good base of conventions that when followed yield almost effortless integration. Plus reusing some modules in another project becomes trivial so you gain in all fronts.
To answer the other question in the thread when they wish to make a tree of related projects it is possible though somewhat clumsy. Eclipse will always present projects as a flat list, however the folders can be arranged in a tree nonetheless. Just specify a custom location when creating a project or import the project from the sub-folder. Again here Maven can help a lot with it's concept of modules.
As eugener mentioned in his comment, there are plugins for maven that will make most of these tasks trivial. You may find all you are looking for just by exploring the gui, this said, reading the maven literature will give you good insight on how it works and what it can do for you.

How do you manage growing eclipse configurations?

I use eclipse for quite a lot of work, including:
multiple "utility" projects that include code that most of my java work makes use of
various plugin-related projects that I sync and use periodically (eg: the Git plugin)
plugin projects I'm actually developing
the occasional pydev / non-java project
etc...
It is becoming quite difficult to keep all these things straight, particularly since I never need to use them all at once. I've tried using Mylyn (and I'm trying it again) but in the past it has caused eclipse to run extremely slow, and I am notoriously horrible at remembering to tell mylyn that I've switched tasks, so it tends to learn very odd (and largely useless) sets of resources.
I've considered using multiple workspaces, but that is problematic when multiple projects need to exist in multiple workspaces, and when I need to synchronize the eclipse metadata directories across workspaces.
What is the best way to manage complex working environments in eclipse? Other development environments aren't a viable option because there aren't any sane alternatives when it comes to developing eclipse plugins (and that is a requirement).
(I think a very similar question was asked a month or two ago, but I haven't been able to find it...)
It isn't quite clear to me what your need is. But have you tried using working sets in the Package Explorer?
Open the Package Explorer view, open its menu, and Select Working Set. That lets you give a name to a subset of all the projects loaded in your workspace.
Switch working sets using the package Explorer menu. Use working sets to limit the scope of Search, errors, problems, etc.
Define as many working sets as you need to group your projects. A project can be part of any number of working sets.
Here's a screencast about working sets -- this does look like the right answer.
http://www.peterfriese.de/eclipse-working-sets-part-i/
You want to use "Working Sets".
I would recommend using different workspaces, and then adding the common projects to each workspace (you can specify the location of the project to be outside of the workspace). I believe this will work, but I haven't tried it, so I can't be sure.
As #JesperE and #Dennis S suggested, working sets will help you organize your projects, but they may not make eclipse run any faster, since the projects will all still be loaded into the workspace.