Greetings, all,

I am ready to plunge into the autoconfig system for Hackystat. I want to sketch out my plan of action for you all in case you discover any things I should do differently.

Motivation:

Currently in Hackystat Version 7, the build system contains a file called "modules.build.xml", which contains direct references to targets defined in the local.build.xml files associated with each of the Hackystat modules. There are several problems with the current approach:

(1) Anyone attempting to invoke the Hackystat Ant-based build system must have downloaded copies of _all_ Hackystat modules. This makes it impossible to create and distribute configurations containing only a subset of all available modules.

(2) Third parties cannot add their own private modules and build a Hackystat configuration without manually editing the modules.build.xml file (the changes of which must be re-added to each subsequent Hackystat release).

(3) Editing and maintaining modules.build.xml by hand is a pain.

Solution:

Auto-generate the modules.build.xml file locally by discovering the locally available set of Hackystat modules and using information contained in their local.build.xml file to write the modules.build.xml file. Thus, the modules.build.xml file will not exist in the SVN repository; it must be generated locally. Whenever the Hackystat Ant build system is invoked, it will always do two things immediately: (a) check that a modules.build.xml file exists, and (b) check that the modules.build.xml file is up to date (i.e. has a creation date more recent than all of the local.build.xml files associated with locally available hackystat modules. If (a) is not true, then the build fails with a message to autogenerate the modules.build.xml file. If (b) is not true, then a warning is generated that the modules.build.xml file is out of date, but the build proceeds.

To auto-generate the modules.build.xml file, we need to do the following:
(A) find all the local.build.xml files
(B) parse each local.build.xml file to determine:
    (a) what the name of the module is
    (b) what module(s) this module depends upon
(C) generate the modules.build.xml file contents

(A) is quite simple; we can do this within Ant in a couple of lines of code.

(B) is not that difficult either. Take a look at the following excerpt of hackyCore_Build/local.build.xml:

<project name="hackyCore_Kernel.local" default="hackyCore_Kernel.default">
     :
 <property name="hackyCore_Kernel.required.modules" value="hackyCore_Build"/>
     :

To get (a), the name of the module, we can use the "name" attribute of the <project> element, and get the substring up to the first occurrence of a ".".

To get (b), the dependent modules, I propose that we require that each local.build.xml include a special property called <module_name>.required.modules. This property's value is a (possibly empty) comma-separated list of module names. So, after discovering the module name by parsing the name attribute of the <project> element, we can next parse all of the <property> elements that are children of the <project> element, looking for a property with the appropriate name.

Once we have the list of all modules in the system and, for each module, the list of all modules it depends on, we do a topographic sort of the resulting tree to get the sequence in which the module targets must be called (i.e. build, kernel, statistics, report, common, telemetry....).

Once we have this list, we can now write out the modules.build.xml file.

There's another feature we can build into this system: at the end of the modules.build.xml file, we can provide "default" definitions for all of the targets that should be provided in the local.build.xml files. These default targets will call <fail> with a message indicating that the module's local.build.xml file failed to provide a definition for this target. Since the local.build.xml files are imported before these definitions, the default targets would only be defined when missing from their local.build.xml file. What's nice about this is that if a local.build.xml file fails to provide an implementation of, say, LOCC, that would only cause a failure if LOCC is actually invoked. (Without these default definitions, the build would not even start: Ant would fail immediately with a message indicating an undefined target.)

Comments? Improvements?

Cheers,
Philip

Reply via email to