Monday, March 18, 2013

Yet another build system? Please?

Problem: Most gradle/ant builds turn into groovy/XML soup

Problem: Gradle/Ant projects can lack a good idea of "where to start" to build something. What properties do I need to define? What order of tasks? What do the tasks depend on (db, etc)?

Problem: Maven is a PITA and inflexible, and the advocates are tyrannical

Problem: Maven still ends up with a massive huge xml file

Problem: Maven won't do simple, literal directory-of-jars

Problem: Maven's internet connection dependence

Problem: If maven dep-resolve fails you (IBM Websphere, another reason to hate you), you're basically screwed.

------------------------

What are the good parts that have been invented:

- (Ant) a general set of plugins for templating/replacement, files, building code, etc etc.

- (Ant) decent IDE support

- (Maven) maven repository: the failed dependency resolution is a rare case. Generally, this thing is a very good thing for code sharing and library use/reuse. Gotta leverage this massive body of work and mindshare.

- (Maven) standard project structure: although src/main/java isn't my favorite thing (three levels down? really?), the overall maven project structure provides acceptable structure that people are used to now.

- (Maven) standard project structure for WARs: again, I am not too excited about the file structure, but it'll do.

- (Maven) standard jar naming <artifact>-<version>.jar, a great thing indeed

- (Maven) binary / javadoc / source jars

- (Gradle) groovy scripting for those things you need scripting

-----------------------

What I want from a build system
-  leverage the structuring standards of Maven that have made unfamiliar projects more straightforward to interpret
- leverage Maven repos and dependency maps, but add flexibility fallbacks for literal jars, and only do dependency resolution when new projects are setup or new libraries/dependencies added (one-off or one-time tasks)
- this is a new feature for java builds: a single file download that specifies where to download the rest of the project (sourcecode, etc). The build system will connect to sftp/ftp/git/subversion/whatever to get the code, then do dep resolve. Kind of like .rpms for linux. Great way to do starting points for projects, especially ones without a fancy site or github...
- use some of the nice features that make Ruby on Rails so good: convention over configuration, and folder structure as configuration. Maven failed at this since you end up with a huge POM xml. 
  - Why not have a naming convention for mulitple source folders: as long as they match /src-* and are at the project root, then they are an additional source folder. 
  - /info dir has the project info. 
  - /lib for various libraries. In the /lib, you can have .jar files for inline/literal inclusion, or an empty file named <artifact>;<version> that triggers dependency resolution. Nice instant  visual indication of the libraries used to build a project. Subdirs for main for main build, test for test build and execute, etc.
  - /tasks is a dir with more subdirs <taskname>, and each of those has their own gradle/ant script that can be invoked

Need to add a quick jar? drop it in the /lib/main dir. Need to add a quick set of dependencies from another project that you know works? Copy-paste the dependency files into the lib dir. Source tree getting a bit thick in the /src/main/java folder? spin off some more src-* source directories. Maybe even tasks can become drag-and-drop or copy/paste with sufficient automation/decoupling. 

Web resources, ears, subprojects, project relationships, etc: all to be determined. 

Another key aspect should be IDE support and multiple IDE usage. perhaps a separate directory tree for ide-specific settings. Ant/Gradle/Maven xmls can be autogenerated for IDE import/usage if need be. 


Project structure:
/root of project
/liblibraries and dependencies
/lib/mainlibs and deps for main compile
/lib/testlibs and deps for unit test exec
/srcmaven-style primary source dir, with /main/java, /tast/java, /main/resource, etc
/src-more maven-style source dirs, such as a service impl, etc
/tasknonstandard task scripts