Getting compiler arguments at runtime
Posted in Uncategorized on March 29th, 2011 by adminHave you ever wondered how runtime shared libraries get into Flex? No? Well, neither did I. Lets face it, it’s not the hottest or most common thing to arise in the world of Actionscript development.
Today, however, I did have a need to understand the process. I’ve been tasked with building a system for a large game we are developing, which needs to load modules and RSLs. In a Flex application, this process is hidden as part of it’s initialisation – the SystemManager class handles this magic. Pass in the RSL URLs (try saying that quickly ten times) to the compiler, and it’s loads ‘em. Great for Flex, but not so great for us building Actionscript only projects.
My initial research focussed on the mx.managers.SystemManager which is ‘possibly the most important class in Flex’. This has the responsibility of booting up any Flex application. It is the factory class called from any Application subclass (subclass being very important, but more later).
If you look at the SystemManager class, you’ll notice that it has an info() method that returns an empty Object. If you look at other parts of the class, you’ll see it referring to data in the info Object (e.g. info()['rsls']). The odd thing is, is that the object info returns is always empty – return {}; – so whats going on?
It turns out that SystemManager is actually a base class that has subclasses automagically generated by the compiler. If you use the -keep compiler argument in a Flex project, you’ll see these generated classes. SystemManager implements IFlexModuleFactory, whose methods (including info()) are actually the ones generated. In the generated class you’ll see that the info() object now has references to some of the compiler arguments.
So, how do we retrieve this info() info in a non-Flex project?
After a little more research and experimentation I discovered it’s fairly simple. Firstly we need to create a factory which implements IFlexModuleFactory. In it’s most basic form, we only need to add a listen to an Event.COMPLETE from the loaderInfo, which then creates and adds the main application class. Also, this factory must extend Movieclip.
1 2 3 4 5 6 7 8 9 10 11 12 | public function Factory() { super(); stop(); loaderInfo.addEventListener(Event.COMPLETE, onComplete); } private function onComplete(event:Event):void { nextFrame(); addChild(create() as DisplayObject); } |
Simple enough. Since a subclass of this will be generated, we need do nothing with any of the other methods.
Now we need to use this factory. Following a similar method to creating a preloader we will use the Frame metadata. However, we can’t exactly follow this. In a seemingly odd move, we have to add the metadata to a superclass of the main application class, not the application class itself. I guess this is because in the flex world, a main application class extends mx.core.Application which has the metadata in it.
Therefore, we create a class that extends Sprite which acts as the application superclass, then extend this to create the actual application class
package { import flash.display.Sprite; [Frame(factoryClass="factory.Factory")] public class ApplicationBase extends Sprite { public function ApplicationBase() { super(); } } }
I”ve created a simple project which demonstrates this. I’ve added a -runtime-shared-libraries compilier argument which you can see in the factory as info()['rsls'].
Of course, it isn’t just RSLs you can access, a quick look through the source of SystemManager will reveal others. I’m sure there are many other uses, and at the very least it gives an interesting insight into what the mxmlc compiler does.











