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

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).

Related

Assemble transitive closure of a main file in scala sbt project

I'm working on a scala sbt project, and I am at a point where I want to assemble the whole thing to share a .jar-file with others, so that they can use it on their side. For my local testing, I'm doing so using the sbt-assembly plugin, that works nicely.
When sharing, I would though prefer to only share the parts that are important for the other party (the project has huge components that irrelevant at the current point, and I'd prefer not to share these for various reasons). Concretely, they will be executing one particular main file, so it would be enough to pack everything that this file depends on.
Is there a way to accomplish this? I'd also be interested in doing this on the code level (i.e., create a copy of the project that only contains dependencies of that main file), but also while assembling or even modifying the jar file after assembly is okay. I did not find the tools to achieve any of these.
As I said, I'm dealing with a scala sbt project, and I'm working with IntelliJ IDEA; I'd also be happy with an IDE tool that does the job.

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

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.

Multiple Xtext DSLs in single Eclipse project

I would like to know if there is a way to organize multiple DSLs inside a single Eclipse project. More specifically, I would like to organize all five Xtext projects of a DSL in some top-level "project folder".
The background is that we manage complexity and enable reuse by making smaller reusable DSLs, e.g. one reusable for expressions and other one for more domain-specific or application-specific aspects. However, each Xtext DSL results in 5 projects, causing a lot of clutter in the Package Explorer when multiple DSLs are involved. A strongly related question has been asked before:
Xtext: define 2 DSL's in one project
The answer there is that multiple DSLs are not needed inside the project for that specific use-case. My use-case is different because I want to be able to easily view the different DSLs and potentially co-develop them.
We are using Xtext in an environment managed by Gradle. We are using the Gradle Eclipse plugin, which creates a lot of Eclipse project files everywhere. As a result, when choosing to "Open Project from File System" in Eclipse, I not only get the option to import the five projects related to the DSL, but also the option of opening the parent folder as a project. This means I can have each DSL (all its five projects) organized neatly in a "project folder". This is exactly what I want! ...
BUT ...
it does not actually work. The figure below shows my package explorer with the five projects of my ExperimentDSL included in the bottom. This DSL works. On top, it shows the folder structure I get when including the project file generated by Gradle, resulting in a "project folder" that can potentially contain multiple DSLs.
As you can see, GenerateExperimentDSL is flagged red and refuses to run. It seems Eclipse somehow treats it as a Java project, but I do not know how to change this or and if this would help solve my problem. Secondly, I would not know how to set up such a project by hand, since the project file in this failing case was generated by Gradle.
Long story short, does anyone know how to get this kind of folder structure to work so that I can keep all my DSLs in the workspace without clutter?
What you try to do is currently not possible. Have a look at the concept of WorkingSets in Eclipse that let you achieve something similar

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.

Structure for big GWT project

Context
big project with multi maven module or single maven module structure
Question
did you finally use multi-maven-module or single-maven-module structure?
Details
If you've worked on a big project that had long development duration and contains lots of functionality(i.e. not a trivial project), did you choose to split the project into multiple maven modules or went with the single-module approach?
For example, having a multi-module structure, crashes when running maven commands like mvn gwt:eclipse(see http://bit.ly/gs4Rmo). I guess this would have worked well with single module GWT project. And there could be other commands like the above that has issues with multi-module structure.
However, the multi-module structure could bring the benefits of a faster development, i.e. if you separate the "server" from "client" module, you could compile the business logic(server) separately and package it into resulting web archive. Compiling the GWT code, takes about 20 seconds, so if you only modify the server package, it could save you lots of time in the long run.
Which other cases like the one above did you encounter when working with a multi-module/single module project?
Thank you!
A few notes:
On development server you don't have to compile the code "by hand": dev server compiles the code automatically and reloads it. Just keep dev server running, change some code and then reload the page in browser. (this is only true if you change existing classes and don't change project structure)
Multiple maven modules have nothing to do with multiple GWT modules.
You would want to have multiple GWT modules (= multiple entry points) if you have code that executes in different environments: for example you have web and mobile sites that have quite different code bases. Then you would split the project into three modules: web, mobile and common. Then you'd reference common in both web and mobile.
Another case for multiple GWT modules would be if you, for some reason, want to have a multiple host (entry) HTML pages. There are rare cases when you'd want this, for example when you need to do redirects when integrating OpenID. The other case would be that you already have existing Web pages where you are only adding GWT to add some functionality.
Don't split the GWT project into multiple modules just to reduce download size: use Code Splitting instead.
If your main gripe is long gwt compile times then read: How do I speed up the gwt compiler?
We started with multiple modules and eventually merged into a single module. The main reason for this was maintenance of modules is a huge overhead. Each module had a pom to build the UI, RPC layer and backend services. So with 30 modules we had 90 maven projects to manage.
Merging the modules turned 90 maven projects into 3 with one parent level pom.
This considerably lowers maintenance overhead and improves build times. GWT's compiler is notoriously slow so having a single compile parsing source files once instead of multiple times makes things much faster.
On the flip side, a single module means the compiler slurps everything up into memory at once. This could make split points intolerably slow to find if you insert any in your code. Therefore if you intend to split, it may be worth considering where you're putting those points and arrange your project accordingly.