It's useful to be able to pass data to Flash code at compile-time rather than at runtime. So during your build process you can in some way configure the build - the obvious reason would be to turn on or off some debugging or instrumentation, but you could also configure features, pass in build numbers, set in initial languages etc. all depending on some build parameters or other.
The obvious way would be to in some way template the .as file you're compiling, like so:
package { public class MyConfigClass { public static const SOME_SETTING:Boolean={insert template value}; public function doSomething():void { if (SOME_SETTING) { // Do it! } } } }
The Flex command-line compiler provides an argument called -define, which works a little bit like the /D compiler directive in C/C++ (for any C/C++ coders out there!).
It lets you declare a value as part of the compilation command-line. That value gets evaluated as the compiler builds each class, effectively doing the templating step (above) for us, without having to copy any files around.
If we take our example above and alter it very slightly...
package { public class MyConfigClass { public static const SOME_SETTING:Boolean=CONFIG::someSetting; // Actual AS3 this time public function doSomething():void { if (SOME_SETTING) { // Do it! } } } }
mxmlc MyConfigClass.as -define+=CONFIG::someSetting,true
Bingo! Compile-time configuration, inserting the word 'true' directly into the sourcecode where the compiler finds 'CONFIG::someSetting'.
The CONFIG part of the tag is an arbitrary namespace, which you can set to whatever you like; the second part (someSetting) is a variable name.
Important: If you do put an entry such as CONFIG::myString in your source code, you must pass some value to it on the command-line, or your source code just won't compile!
The important thing to remember is that the compiler substitutes the value exactly as typed, and also that the compiler ignores the first set of quotes around the value (to allow the value to contain spaces).
So if we pass into this code:
public static const MY_STRING:String=CONFIG::myString; public static const MY_NUMBER:Number=CONFIG::myNumber;
-define+=CONFIG::myString,"Hello!" -define+=CONFIG::myNumber,"7"
public static const MY_STRING:String=Hello!; // Which won't compile! public static const MY_NUMBER:Number=7;
-define+=CONFIG::myString,"'Hello!'" -define+=CONFIG::myNumber,"7"
public static const MY_STRING:String='Hello!'; // Which will compile! public static const MY_NUMBER:Number=7;
You can also use the define feature to include or exclude blocks of code from the final .SWF at compile time, which is a brilliant feature and highly useful when you're writing debugging code.
You use a Boolean -define value to enable or disable a block of code.
Here's an example, picking which version of a function to use at compile time:
package { public class MyClass { CONFIG::isDebug public function doSomething():void { trace("This is a debug build!"); } CONFIG::isRelease public function doSomething():void { trace("This is a release build!"); } } }
mxmlc MyClass.as -define+=CONFIG::isDebug,true -define+=CONFIG::isRelease,false
mxmlc MyClass.as -define+=CONFIG::isDebug,false -define+=CONFIG::isRelease,true
However, it's worth bearing in mind that either of these versions will cause compilation errors:
This tries to include doSomething() twice:
mxmlc MyClass.as -define+=CONFIG::isDebug,true -define+=CONFIG::isRelease,true
mxmlc MyClass.as -define+=CONFIG::isDebug,false -define+=CONFIG::isRelease,false
Compile-time configuration is very useful. :-) You can read all about it
on this Flex documentation page.