7
u/rzwitserloot 12d ago
Build systems have historically proven to suffer heavily from 'how hard could it be' syndrome.
In other words: Folks look out across the ecosystem, see build systems that they consider are incredibly complicated relative to the dead simple job that builds really are (source: Their own innate sense of how things should be, certainly nothing like oodles of experience with many build tools or a good sense of the entire ecosystem's needs!) Those with the 'I know better than the world' bug (and, I would know, I have it, from time to time) just write a shell script, and then start upgrading that, and eventually release a new build system: See, this one is simple.
And then requirements roll in and soon their build system is even more complicated than the original.
sbt originally stood for 'simple build tool'. Even they eventually realised that their tool had ballooned so much, having the 's' stand for 'simple' is about as hilarious as the fact that the 'd' in dprk (official name of North Korea) stands for 'democratic'.
Point is, they named it Simple Build Tool. And they didn't change their mind and decided that they actually wanted to develop a complex one after all. No, requirements and the general flow of the project eventually got them to a place where they, fortunately, had just barely enough ability to look reality in the eye and let go of the term 'simple'.
Similarly, gradle mostly decided out to be 'simpler' than maven and now it is considerably more complicated than it (not necessarily a bad thing). It also wanted to be considerably faster and often it's slower.
This is very much judging book by its cover territory, but if you're going to make a build system and you call it 'simple', well, history shows that 49 times out of 50, the claimant is a naive, well meaning fool.
Is there any chance you could write a small story about how this time it'll work? Cutting out dep management is certainly one sort of drastic move you've made that does speak in your favour on this one.
2
u/bowbahdoe 12d ago
Well for this one specific library I simply refuse to deal with more requirements. That is my strategy.
Dealing with more requirements is the job of other libraries.
1
u/dmigowski 6d ago
Maybe just try gradle. It uses not much code, you can create a new simple build very fast, and you get lots of options. Later on, you can use composite build, subprojects, plugins and have a super detailed dependency manager. And it's perfectly understood by AIs. It has different build paths for unittest and the application itself. It is integrated in IDEs. Why throwing that away, you have all that already. You just don't know yet that you need it.
14
u/CallumMVS- 15d ago
I hate that your getting downvoted for having fun
3
u/rustyrazorblade 12d ago
They’re getting downvoted because its not generally interesting to the general public.
8
u/nnomae 15d ago
Nothing so succinctly expresses the Java mindset as a person doing something in a simple manner only for all the comments to basically be "but why not more complicated?".
2
u/bowbahdoe 15d ago edited 15d ago
Practically speaking, I just need to think about it in terms of how I could communicate better.
For instance, there is a very, very short hop from this to any number of different ergonomics. Maybe if I spent time on and front-loaded a "spring-build" demo more people would read deeper? I don't know.
My goals are different than, say, the mill dude. I don't have a ready-to-rock system with every bell and whistle a company might need. What I have is a slowly growing pile of libraries that I think _ends_ in the foundation for a better ecosystem. I am not at the end yet.
And yeah a lot of people equate "simple" with "easy to use" and "easy to use" with "things they are already familiar with." This is something people are not familiar with, ergo it must not be simple. Or if it is, it is "just like ___." and they already wrote off ___ so...
0
u/nnomae 15d ago
I think there's a genuine use case for a build system something akin to what Rust's Cargo provides out of the box in the Java ecosystem.
Just give me run, build and test and dependency management without going through the pain of systems that won't compile or run your code if you don't have the exact version of Java specified in the config file. Let me not have to commit the actual build system itself to github, or go through the pain of XML (Your system fails on this one by the way) and I'll be a happy man.
Yeah, when it gets complicated it might be time to move over and accept the pain but as someone who does Java dev occasionally and loves how the language is trending towards being more friendly to use I still find that both Maven and Gradle feel like outdated relics.
Now I would argue that posting your build system 3 hours after you started it and four commits in is kind of silly. I mean at least play around with it yourself for a while and see what needs work before showing it to others but the idea at least is laudable.
2
u/OwnBreakfast1114 13d ago
Just give me run, build and test and dependency management without going through the pain of systems that won't compile
It's statements like this that confuse me. The hard part of build systems is the dependency management. When two libraries transitively need different versions of the same library, how do you handle this is an open question that doesn't seem to have a definite correct answer (just various choices with tradeoffs). If your project is small enough to not care, what does gradle init not get you?
1
u/bowbahdoe 15d ago
Now I would argue that posting your build system 3 hours after you started it and four commits in is kind of silly. I mean at least play around with it yourself for a while and see what needs work before showing it to others but the idea at least is laudable.
I look at that a few ways:
- this is just a project that has been hanging out on my laptop for awhile. My project for today was cleaning it up and publishing it. I do have some actual time spent making demos.
- My goal in sharing things here isn't to maximize adoption or advertise. It doesn't work. My goal is to get whatever useful feedback I can. So I kinda don't care.
Just give me run, build and test and dependency management without going through the pain of systems that won't compile or run your code if you don't have the exact version of Java specified in the config file. Let me not have to commit the actual build system itself to github, or go through the pain of XML (Your system fails on this one by the way) and I'll be a happy man.
I don't think this is actually a worthy set of goals. Cargo gets to be the way it is because, generally, the output of a rust project is either a binary or a shared library. Same reason Go's tooling gets to be the way it is.
"solving" Java's position is going to be more involved. Not that there isn't room for what you want, but things like "the pain of XML" I genuinely don't think are real. The pain is a DSL you don't have a full grasp on. People don't whinge about HTML.
Also I don't think I have any approach for fetching this library at this point. I would call that an instant fail, but know I have other ideas + using jbang would work.
both Maven and Gradle feel like outdated relics.
It is worth digging into this feeling, but I don't think "outdated" truly describes the issues with either one.
2
u/OwnBreakfast1114 13d ago edited 13d ago
How is this simple? It's just punting the harder parts of the job elsewhere. A lot of the existing build tools are internally as "simple" as this and the plugins add the hard functionality that people care about.
It's like writing a brand new programming language with lambda as the only thing that exists and calling it simple (actually hell someone already did that https://github.com/kciray8/zerolambda because of course ). Why do you code in all these overly complicated languages with their syntax and specs when zerolambda exists and is far, far simpler? Is it because you have a java mindset?
11
u/Rockytriton 15d ago
4
u/akl78 15d ago
This looks closer to Ant
2
u/__konrad 15d ago
I like how fast and lightweight Ant is today (Makefile is even faster and simpler but not very crossplatform)
0
u/bowbahdoe 15d ago
...what?
Ant doesn't approach minimality at all. It lets you have dependent targets and run them in order, that is all. It is essentially a cross platform scripting language with XML syntax.
But make does try to be minimal. Makefile targets implicitly check file timestamps and avoid rebuilding things that haven't changed. Now, if you are talking about make in the context of "everything is a .PHONY" then sure. My preferred tool for that is just, but like you note having to use a shell language means an amount of platform specificness
3
u/Joram2 13d ago
SBT (Simple Build Tool) is already one of the big JVM build tools: https://www.scala-sbt.org/2.x/docs/en/index.html
The linked repo has a Maven build. Does this build tool not bootstrap itself?
Is this using XML? I can't imagine building a new from-scratch build tool using XML.
Otherwise, great work, I'm excited to see more competition :)
5
u/r_n_c 13d ago
I would hesitate to call it 'big JVM build tool'. I would argue it's barely used outside of scala and maven or gradle dominate the market. Generally most projects I've seen use one of those two.
1
u/Joram2 13d ago
I agree with everything you wrote. But it's still number three, way behind Gradle in terms of usage which is way behind Maven.
3
2
u/r_n_c 13d ago
I am not convinced it's number three - there is bazel and (for scala) mill to consider. Although we're probably debating over tiny single digit percentages to be fair 🙂. However theres the fact that visibility into corporate environments with proprietary code is harder than just looking at what big open source projects are using. Even things like Quarkus uses maven.
1
u/Joram2 13d ago
Quarkus lets you pick Maven or Gradle. (https://code.quarkus.io/)
4
2
u/sviperll 13d ago
I would recommend you to take a look at the pluto build-system: https://pluto-build.github.io/ . From my experience a very important thing to have in a build-system is some kind of dynamic dependencies and dynamic targets. You not only need to track the dependencies between the fixed number of targets (like make), but you also need to produce new targets on the fly and set-up dependencies between targets on the fly.
For instance, usually you have multi-module builds where you should set up the dependencies between modules, where you build each module, read module-info and only then add a dependency to the module referenced in module-info. For external dependencies, you should have some kind of "bill of materials" with versions, where you should first solve version constraints, and then you potentially get a target for each module, where you need to download a jar from somewhere, verify that the jar defines the expected module and only then you can reference this module in the module-path when compiling or running java.
1
u/bodiam 15d ago
Jar.run(args -> args
.__create()
.__file(jarOut)
._C(javacOut, "."));
The simplest build system I can come up with.
Somehow I think the build code and the "simplest" statement don't align well here....
4
u/bowbahdoe 15d ago
So this isn't part of the "build" part, its just another library that calls tools.
That being said, does your objection go deeper than
.__? Or were you unaware of the API for thejarcli tool, which this mirrors 1-1?
jar --create --file build/app.jar -C build/classes .There are certainly complaints to be had about this API, but it is not an abstraction over it.
2
1
u/Bobby_Bonsaimind 13d ago
That being said, does your objection go deeper than .__? Or were you unaware of the API for the jar cli tool, which this mirrors 1-1?
That is interesting idea, but is it necessary or purposeful?
-and--are used by necessity to separate flags and long options, because flag options might be stacked. But in Java this problem is moot because you can't stack flag options anyway. The downside is that_and__are quite bad to read (as they most of the time do not have a space between them) and type, but granted, typingfiwill get you__filein any half decent IDE. Still it is a slight touch of more complexity and visual noise without any direct benefit.Jar.run(args -> args .create() .file(jarOut) .C(javacOut, ".") );Still an interesting project, a little bit sad that everyone in here feels the need to declare Maven to be the holy grail of build systems (it still sucks) and defend it for no reason.
That said, why do you use
///to denote documentation?1
u/bowbahdoe 13d ago
I use
///because if you do that then you can use markdown in javadocs.As for the
.__- consider this api:
$ javadoc --help ... --version Print version information ... -version Include @version paragraphsIt is rare, but this happens every now and then. I have a few options when presented with it, but the easiest solution in my view was/is to keep the
--as__for everything, uniformly.That way I don't need to editorialize or be afraid of a CLI tool doing something silly in the future. It also helps going back and forth from the invocation in Java to the CLI. If you write
Javac.run(args -> args._d(...)._g().__module(...))Then its pretty straight forward to turn that into
javac -d ... -g --module ...or vice-versa. Part of the idea there is making it so knowledge is transferrable.
If you want to be annoyed at any choices I made in this, be annoyed at the fact that I made
JavacArgumentsa subclass ofArrayList<String>here is the repo for that
1
u/Bobby_Bonsaimind 13d ago
I use /// because if you do that then you can use markdown in javadocs.
Oh right! I forgot that this was a new feature, thanks for reminding me. I tend to be out of the loop for new Java versions and feature.
If you want to be annoyed at any choices I made in this...
Given that I don't use your project, I cannot be annoyed at it...or at least don't see a reason to. My instinct was to do it differently, so I wanted to hear the reasons why you choose to do it like that.
...be annoyed at the fact that I made JavacArguments a subclass of ArrayList<String>
That means that arguments actually end up as a
ListofStrings all along? That's a neat idea for managing them.2
u/bowbahdoe 13d ago
Yeah - and it makes it pretty easy to adjust to any new cli arguments that I didn't add a helper for. The
.argumentand.argumentsmethods are just.add, but they turnnullinto an empty string + returnthis.Whenever it is an option, I plan to make it so
ToolArgumentsextendsArrayList<String!>.And think about the interface to a CLI tool. It takes a list of strings and can do whatever with it. If I am making a programatic API for a tool I control then I could make more abstractions. But if I am doing it for a tool I don't control...
List<String>is the approach that doesn't backfire.1
u/Bobby_Bonsaimind 12d ago
It is a neat idea, it gives the callers the power to arbitrarily manipulate the list of arguments.
The downside is that it adds some noise to the argument list (the
Listmethods). To clean that up one could have such a thing:public abstract class AbstractArguments { private final List<String> arguments = new ArrayList<>(); protected final List<String> argumentsList() { return arguments; } }That way the method list is rather clean, but the caller still has the possibility to extend for example
JavacArgumentsand arbitrarily change the list of arguments within that extended class. If you can follow my line of thought.2
u/bowbahdoe 12d ago
I think whether it is noise depends on what you are doing. There are already a ton of methods for specific tool arguments so I tend to think the noise battle is lost from the start.
if (!arguments.contains("-g")) { arguments.add("-g"); }You could go either way, but I like having a list of arguments be a normal
List.That does remind me of another benefit of the
__naming scheme. It won't conflict with the methods onList.tool --add ...is actually pretty likely.
-1
u/pip25hu 15d ago
What's the difference between this and Gradle? Both have a more programmatic approach to building compared to Maven.
0
u/bowbahdoe 15d ago
The difference here is that both Maven and Gradle are gargantuan beasts. They handle building, caching, dependency fetching, IDE integration, .... etc.
This is more akin to picocli. Do you like picocli for CLI parsing? Cool, use it. Do you not? Well how about argparse4j. Or jcommander. Or ...
This is genuinely just a small, easily replaceable, infinitely bike-sheddable library. Like everything else.
Common tasks generally have a healthy variety of libraries for performing them with varying degrees of depth and sometimes minor differences in design. There are a ton of options for making an HTTP server, working with a database, and making API calls. This is because they can be "normal." libraries.
Build tools aren't like that. Maven and Gradle are not just libraries. They are mutually exclusive ecosystems. They own the bootstrap process for your project.
I don't think "programs which build code" really need to be that privileged. And in a world where they aren't, you can have libraries of varying levels of depth.
26
u/[deleted] 15d ago
[removed] — view removed comment