Gradle and ./configure

I am evaluating Gradle and its ability to cope with specific requirements of my C++ project. What I want to do (among other things), is to let user ./configure the build (equivalents of e.g. --prefix, --with-foo, --without-bar, etc., but also e.g. path to the repository containing dependencies). What I do not want is manually edit some configuration file and/or build script every time I want to change project build configuration, nor pass gazzilion of command line arguments every time I type ./gradlew build.

What I have previously done in Boost.Build was separate configure target, which produced automatically generated config-file. All other targets depended on that config-file and used it to get configuration values. So I typed bjam configure <lots of configuration values> only once, which produced the config-file. Then I needed only to type bjam with no arguments, which built all the real targets.

Is there some similar approach possible with Gradle?

Note: ./configure step (as in “configure-make-make install”) should not be confused with Gradle’s configuration phase - those are two completely different things (and the name clash makes it hard to google for it).

Note: I have asked this same quesiton on StackOverflow some time ago, but without any success, so I am asking the same thing right at the source.

You could declare one or more GradleBuild tasks within your build.gradle. You can configure command line args via the startParameter

@Lance_Java: That was well hidden bit of documentation I have actually read before, not realizing it might be helpful - thanks for pointing that out. I took a closer look at that and this is my first naive approach:

  • configure.gradle script: effectively ./configure step
    • very simple build script using file settings.template located in project’s root directory for creating settings.gradle script by employng task filter and its expand
    • the settings.gradle file generated by this build should contain usual multiproject definitions (such as e.g. include 'lib/foo') and also definitions of various variables used throughout the make.gradle and possibly its children
  • make.gradle script: effectively make step (probably also make install, but I am not as far, yet):
    • the first line of this script will say apply from: settings.gradle, which makes it dependent on successful execution of configure step
  • build.gradle script:
    • defining one task build(type: GradleBuild) task, referring the configuration generating task in configure.gradle
    • defining a few task build(type: GradleBuild) tasks, referring tasks from make.gradle (make, clean, install, test, doc, …)

This is more-less me dumping contents of my head, I still need to look up a few things (I am quite new to Gradle, so I do not know how exactly the above would be implemented). Any comments would be highly appreciated, though. These are issues which came to my mind so far:

  • Will it be possible to do partial builds this way? (e.g. I want to rebuild only single subproject and its dependants instead of building everything.)
  • A bit “stronger brother” of clean task (e.g. clean-all) will be needed in order to be able to clean also auto-generated settings.gradle file. This should probably be defined in build.gradle and it should call clean tasks from both configure.gradle as well as make.gradle.
  • Will apply from: settings.gradle work as expected? Would it interfere with the configure script in some unwanted way? Will it be better to split this into two files (one containing the definitions of subprojects and the other one containing generated variable values)?

Edit: I have originally confused settings.gradle and configure.gradle, so I have corrected that. Using settings.gradle might not be the best choice afterall.

Edit: It proves to be more difficult than it originally looked like (I am definitely missing something basic here). I have renamed my original build.gradle to make.gradle:

allprojects {
  apply plugin: 'cpp'
  group = 'tld.example.gradlecpp'
  version = '0.1'
  buildDir = "${rootDir}/build/$name"
  binaries.all {
    // cppCompiler.define "GRADLECPP_FOO_INDIRECT"  // remove #include directive using #ifdef to see how intelligent Gradle really is :)
  }
}

The new build.gradle contains just this:

task make(type: GradleBuild) {
    buildFile = "${rootDir}/make.gradle"
    tasks = ['build']
    startParameter.searchUpwards = false
}

However, when I invoke gradle (./gradlew make), it will completely ignore anything I said in allprojects of make.gradle (e.g. buildDir is ignored and the default location is used instead, subprojects will complain about non-existent property binaries because apply plugin: 'cpp' has been ignored, etc.). I am stuck here, can anyone point me at my mistake, please?