Compiler Configuration with Macros
Macros can be used during the compilation process to generate custom code. Macros can also be used to perform some pre-compilation tasks.
These compiler configuration macros can be used with the haxe --macro commandline parameter.
An example is to force the inclusion of all the files defined in a given package and its sub packages :
haxe --macro include('my.package') ....
Please use single-quotes for string constants since some OS (such as Windows) remove double-quotes.
The previous example is actually a shortcut for the following :
haxe --macro haxe.macro.Compiler.include('my.package') ....
And here's the code for the actual method :
/**
Include for compilation all classes defined in the given package excluding the ones referenced in the ignore list.
**/
public static function include( pack : String, ?rec = true, ?ignore : Array<String>, ?classPaths : Array<String> ) {
var skip = if(null == ignore) {
function(c) return false;
} else {
function(c) return Lambda.has(ignore, c);
}
if(null == classPaths)
classPaths = Context.getClassPath();
// normalize class path
for( i in 0...classPaths.length ) {
var cp = StringTools.replace(classPaths[i], "\\", "/");
if(StringTools.endsWith(cp, "/"))
cp = cp.substr(0, -1);
classPaths[i] = cp;
}
var prefix = pack == '' ? '' : pack + '.';
for( cp in classPaths ) {
var path = pack == '' ? cp : cp + "/" + pack.split(".").join("/");
if( !sys.FileSystem.exists(path) || !sys.FileSystem.isDirectory(path) )
continue;
for( file in sys.FileSystem.readDirectory(path) ) {
if( StringTools.endsWith(file, ".hx") ) {
var cl = prefix + file.substr(0, file.length - 3);
if( skip(cl) )
continue;
Context.getModule(cl);
} else if( rec && sys.FileSystem.isDirectory(path + "/" + file) && !skip(prefix + file) )
include(prefix + file, true, ignore, classPaths);
}
}
}
As you can see, there's no black magic going here. You can use any of the haxe.macro.Compiler methods or write your own custom versions.
So far the possibilities include :
- including files to make sure they are compiled
- excluding some classes from being generated
- patching types by removing some declared fields or changing their type
- adding metadata either before/class is defined or at end of compilation (with Context
onGeneratemethod) - defining a custom Javascript code generator (see below)
Much more possibilities will be added when there is a need for it.
Custom JS Generator
You can write your own custom JS generator in Haxe : the generator will take care of creating the .js file(s) and generating the class structure/registration. You cannot however customize the way the Haxe expressions are generated.
See 'haxe/std/haxe/macro/ExampleJSGenerator.hx' for a reference implementation.
In order to use it, simply add the following commandline parameter to haxe compilation :
--macro haxe.macro.DefaultJSGenerator.use()