Possible to write build.gradle in pure Java..?

This is a very interesting idea. Java 8 definitely opens up new opportunities. Although I would love to see more features in Java to support DSL’s. It would be absolutely possible to make Java very DSL friendly if it were prioritized.

As long as you are not working on the DSL level.

I will think more about this and I’m looking forward to discussing this further.

Hopefully Buildship will provide a set of IDE integration features (completion, “javadoc”, debugging, et cetera) that will satisfy these needs.

I totally disagree with that. It states very clearly that a new task will be added to the script.

I am glad you like the idea. I thought about this for a while not related to Gradle but building JVM based less verbose static or dynamic languages like Scala, Groovy, Xtend, etc.
Those existing JVM-languages have one thing in common: they all target the JVM by adhering to the .class file standard.

My idea is to build a slew of new languages that can all be mapped to valid (and very readable) .java source files. I described in my first post how this should happen and how IDE integration would look like. Especially since Java8 such a mapping could be quite simple and still powerful.

In the end you would have different mappings that “show” .java code in a Python-like syntax or Scala-like syntax or Groovy-like syntax. The syntax wouldn’t be 100% since you don’t want the mapping to be over-complicated.

I think this would make especially sense on a team level where developers could choose what mapping-flavor they use in their IDE and they always have the chance to switch back to pure Java. Languages like Groovy have a problem with adoption. It is all nice and good but many people, especially teams, don’t like to do a full switch to something like Groovy.

The whole concept is actually more involved and I only scratched the surface…but I think you get my point. One would need to do further experimentation to see how this concept fairs in a real-world implementation.

I am not sure, but I think you misunderstand. There is the task keyword and the task method call.

The task keyword is achieved (if you want to call it that) by black compiler magic via DefinitionScriptTransformer. It’s not really valid Groovy and scares the hell out of every beginner who learns Groovy and then sees Gradle scripts that mess with his knowledge :smile:

In my opinion there should be ONE way to do this:

task.create(name: “someTask”, type: JavaExec) {}

Adding a task to the collection of tasks should be explicit. Groovy (and by consequence Gradle) allows you to do the same thing in many ways. Too many ways. But then I am also against having two ways to create a String in Java (String a = new String(“a”); AND String a = “a”;). That’s just unacceptable :wink:

It may be a matter of taste but the difference is not big at all using fluent API.
You can mimic the hierarchy style as

public Android android {
    return Android.of(AndroidConfig.of()
	    .and("flavor1", Flavor.of()
	        .packageName("com.example.flavor1" + substring)
	    .and("flavor2", Flavor.of()

Or you can embrace a more regular style (much more readable/maintenable in my sense) that all Java developper will understand and edit quite easily :

AndroiConf defaultConf() {
    return AndroidConfig.of().minVersion(8).versionCode(10);

Flavor flavor1() {
    return Flavor.of("com.example.flavor1" + substring).version(20);
Flavor flavor2() {
     return Flavor.of("com.example.flavor2").minSdkVersion(10);
Android android() {
    return Android.of(defaultConf()).and(flavor1()).and(flavor2());

Or more compact with the help of Lombok:

Android android() {
    val defaultConf = AndroidConf.of()
    val flavor1 = Flavor.of("com.example.flavor1" + substring)
    val flavor2 = Flavor.of("com.example.flavor2")
    return Android.of(defaultConf).and("flavor1", flavor1).and("flavor2", flavor2);

Not sure that the least scripts are less concise and readable than Groovy one, but probably easier to edit thanks to the full force of IDE (javadoc, code completion, code navigation,…)

Look at what you can do with Jerkar Project for example.

Your examples are showing established patterns to model DSL’s in Java. For me in the context of builds they are significantly less readable and full of noise compared to a proper DSL. I’m not in favor of such an approach.

1 Like

What do you mean exactly by “in build context” ?
In most situation the people maintaining the build file are the same that code the project. So maintaining a Java build file has a very low margin cost on Java project cause it is just another Java class to maintain among dozens, hundreds or thousands.

Using a ‘foreign’ language and use dedicated tooling to avoid Java noise only on the build file seems really overkill to me.
If a team really fell Java too noisy (and it is arguable) then it might write the entire project in Groovy, … so Groovy would make sense to write the build script :smiley: (as I would expect to use Javascript for building Javascript projects, Scala for Scala, Ruby for ruby,…)

Beside, the above Java DSL is not so ugly when displayed in an IDE with syntax color, and Javadoc behind a hover/click on each DSL element.

The “build context” you are meaning, is it a context where people who maintain the build script are not the ones who develops the project ? A context where the build is supposed to be read by non Java developer ? It might happen but in my experience it is rarely the case.

I mean a DSL for the domain of builds. Which is a complex domain. Which is also multi-language domain, e.g. we have more and more C/C++ projects being build with Gradle.

Often this is not the case.

I think we are talking about very different things here. There is the role of Java in implementing your business logic (Gradle is written in Java). We are very happy with it. Then there is the role of using Java as the foundation for your specification language for your build. It is a completely different domain. It is not plain Java vs plain Groovy. It is the suitability to create an (internal) DSL on top of it. We are also talking here about things like AST transforms. For example with the buildscript block in Gradle you can add dependencies to your build script itself in the same file where you define your build.

In my opinion those days are gone. Modern software stacks are multi-language. You want one build system for all of with which you can model a coherent, highly automated and integrated build process. That is a key reason why many organizations are using Gradle.

It still is a very different experience. To give you an example from another domain. The DSL is a key reason why I found Spock by far the best mocking and testing framework out there. You are so much more productive with Spock because of that.

Obviously it would not be hard to implement Java based build scripts with Gradle. But we think it is better to solve the current short coming when it comes to tooling than to switch/offer a plain Java based build script language.

I have a lot of trouble getting used to the Gradle DSL. This is not becasue it’s base syntax is difficult, in fact, it is probably more concise and easier than anything possible in Maven POMs. The real reason of my difficulty is that I am knee-deep into basically programming Groovy/DSL - just because it is possible, and maybe trying to mimic maven and ant features in some ways.

The only improvement is probably not by starting to code in Java, but by allowing the existing ecosystem of tools within the plugins and base DSL to mature. Also what helps a lot is just letting go of the old ways, and trying to settle in with the new style. Still I am missing how simple it was to keep part of my configuration outside the project. Gradle allows to do the same (init.gradle), but unfortunately, you switch from the Project context to the Gradle context in doing so.

I don’t. I just prefer on build tool to build everything for me (as far that it is possible). This is all a matter of personal preference, but I do not want to be caught in a programming-language-must-be-the-build-tool trap. If the latter was the case, Maven would not have existed in the form it is today. Nor would have the Make set of build tools. Then there is the question of how many people like to use SBT to build Scala …

The fact that Gradle is based on a Groovy DSL should be irrelvant to the programming language(s) you are using to development your applications.

I always feel very restricted when using Gradle. It does the job if you do everything by convention and don’t need a lot of special things during your build. So if your build works with the Gradle build files being almost empty (full convention) you are blessed and Gradle is a blessing. If you need to be very flexible you end up coding in Groovy with a special taste of being tied to Gradle. It’s horrible to debug. I don’t think the makers of Gradle will ever understand.
I am curious how it was decided to use Groovy as Gradle DSL historically? The project/scope Gradle has today (with people expecting deep and perfect IDE integration) I wonder if they would have every chosen Groovy. Using Java as far as IDE integration and coding support or debugging goes can never be touched by Groovy even if they optimize it for another decade. A huge part of this is the nature of statically typed vs. dynamically typed.

1 Like

Well, as you said that’s a matter of taste.
But for project using Java on sever side and modern html5 stack (i.e es6/reactjs/webpack/…) you’ll hardly convince both team to use same build tool :slight_smile:

That is one of the main criticisms yielded against Maven. It works well if you play strictly by the rule book, but if you need somet5hing more flexible it is going to be painful. I am a bit surprised that you feel restricted. Given your comments I would think deflated would be more appropriate. However, moving on, the mantra with Gradle tends to be that once the build file becomes complex, you might have enough to farm it off to a plugin (or at least to the buildSrc folder). This leads me nicely to your next statement.

This is nothing new to build tools that use an internal DSL (i.e. a DSL based upon a programming language). Cons & SCons had this issue way before Gradle was even an embrio. So do contemporary build tools like Kobalt, Leiningen & SBT. The coice is usually between a restrictive DSL (Make & family, Maven, Ant etc.) or a more flexible one. In both cases, build tools are usually extendable via plugins, but the effort required to extend may vary. Gradle is excellent in the aspect of allowing quick experimentation, only extending later, where as something like Maven always requires one to write the neew plugin from the start, without easy experimenting with the build file. (Well, there a limited possibilities, but not nearly as flexible and quick as in Gradle).

Why was XML chosen as the build script style for both Ant & Maven? Most probably because XML was cool in those days in the Java world. Java pretty much supported XML from the beginning (at least from what I can remember, and not having used Java in the 90s). People understood XML. Wind the years forward and I am not going to give the correct answer here (I’ll leave that to @adammurdoch), but it was a time when Groovy was the most expressive and readable way to script the JVM. (It probably still is, but that is up for debate). Choices are made upon technology available and technology known.

END NOTE: There is a modified joke that goes: There are two kinds of build tools, those that people don’t get used and those that they complain about. The mere fact that opinions are being offered up here, is an indication that Gradle is being used bychoice even though people are finding shortcomings in Gradle that relates to the context they are working in and their own personal preferences (we sometimes refer the the latter as signature skills). ONe should not see Gradle as the end-all build-tool, but merely as an evolution in build-tools. It, with its mates like Kobalt & Leiningen, are a next-generation of build-tools beyond that of Maven. They also allow the software communities of the world to experiment with new ideas and new forms of expression and as such learn new ways of doing things. This will also lead into another generation of build tools, which would probably be here within the next 10 years. Exactly what they will look like we do not know. (If we knew we would already be using them).

1 Like

As a relative newcomer to Gradle (about a month and a half), I rather vehemently disagree with this. Admittedly my use-case is a bit different than most, I suppose. I am working on a replacement for a system that used nmake and an ancient proprietary version control system to build thousands of small projects (some java-based and some not) that were deployed in RPMs. RPMs are not a “native” container type in the Java based ecosystem.

My initial effort was attempted using Maven which I knew and had a love-hate relationship with. Although the Maven RPM plugin support is somewhat ahead of what the Gradle RPM plugin offers, I found it almost impossible to use the Maven plugin. At every corner, another obstacle was found, and another hacky workaround demanded by Maven’s heavy convention demands, requiring dozens of new lines of xml. When I showed what I had wrought, of which I was initially proud, to my teammates, I became embarrassed. Clearly, my work could not be possibly extended to thousands of small projects in any acceptable timeframe.

Once I made the choice to switch to Gradle, everything got better. My build scripts for individual gradle projects are maybe two orders of magnitude smaller than those for Maven. (True, I wrote plugins for Gradle which accounts for part of the script reduction, but plugin creation would have been much more difficult in Maven). Yes, I had (and still have) my groovy learning curve, and yes, I even agree with you that sometimes having one way to express something rather than five is a better way to go, but I’m getting used to it. Yes I hate that there are similar looking constructs that behave differently, and I’ve even complained about that here, but eventually, you get there. Things that had me scratching my head for hours if not days are now solved in minutes.

I have learned to live with the limited Eclipse support as well (improvements will be appreciated), but I long ago learned to live without Eclipse debugging and stepping though code in general, even when I am writing java, and I rarely use it. That is probably the main cause of our disagreement.

It was very easy to express my typical use cases in gradle plugins, and if I need to write more plugins, these will be easy as well. I just created a new plugin this morning in about fifteen minutes. When I demoed this system to my teammates they were extremely impressed and my embarrassment is gone.

1 Like

I think that once a build script goes beyond a very basic set of tasks and configurations, moving code into buildSrc and implementing them like regular code, outside of the DSL, or even in a separate plugin, makes the most sense. If you end up having a huge set of logic written inlined in the task and model definitions, it’ll be painful pretty much whatever tool you use.

I think Kotlin support makes this topic pretty much moot. This should address all of OPs issues.

1 Like

@Carsten_Schmied I agree strongly with you. I write almost all my build scripts in Java, using my own iwant build system, which you may find interesting. There is a simple example of using it, too: iwant-demo. (Sorry for advertising another tool here, but I think this is relevant to the topic.)

@mark_vieira Kotlin is progress compared to the Groovy black box insanity. But I am still not really satisfied.

@wipu thanks, I will look into it. At least this thread delivered some alternatives in pure Java. Somebody else suggested using http://jerkar.github.io
It is pretty good. I will some find out if your iwant is even better :wink:

@Carsten_Schmied You are welcome. Don’t hesitate to ask for help, contact info can be found on the webpage.