Hi, In my previous post, I talked about a RPC version of the Flex compiler API, i.e. instead of invoking the Flex compiler in the same JVM process as the caller, the RPC version makes network calls to a server dedicated to compiling Flex applications, modules and libraries. After working on the prototype a little more in the past several weeks, I finally have something for you to try - I call it the HellFire Compiler (yes, I give my work a name because ‘a RPC version of the Flex compiler’ is a mouthful).
There are three pieces in the HellFire Compiler:
- A special version of flex-compiler-oem.jar. It is simply an implementation of the Flex Compiler API that makes network calls to a compiler daemon.
- hfcd (HellFire Compiler Daemon). Users run hfcd as an independent, separate process (as a background job or in a Terminal window). hfcd uses the original flex-compiler-oem.jar to compile Flex applications.
- An Eclipse/FB plugin. This is usually installed in FB. It retrieves from hfcd information about the compilations, e.g. compile time, link time, memory usage, etc.
Installation
So how do you go about configuring Flex Builder 3 to use the HellFire Compiler? First, we take care of hfcd…
- Download and unzip hfcd_3.0.0.477.zip.
- Download flex_sdk_3.0.0.477.zip and (do not unzip) and put it in the hfcd_3.0.0.477 directory.
- Run ‘ant’ in the hfcd_3.0.0.477 directory.
- You can now run hfcd in server/bin.
Please check out the screenshot below. It shows the expected results after step 3 and 4.
Now, we configure FB3 to use the RPC version of flex-compiler-oem.jar.
1. Run ‘Adobe Flex Builder 3′. Click ‘Preferences –> Flex –> Installed Flex SDKs’.
2. Click ‘Add’.
3. Click ‘Browse…’ and select ‘client’ in the hfcd_3.0.0.477 directory.
4. You should see ‘HellFire Compiler’ as the Flex SDK name. Click ‘OK’.
5. Select ‘HellFire Compiler’ as the default SDK. You can choose not to do this. But each Flex project must be individually configured to use the ‘HellFire Compiler’ sdk.
6. Click ‘OK’. Flex Builder 3 now uses the HellFire compiler to compile your opened projects. You should make sure hfcd is running before clicking ‘OK’.
Now, let’s install the Eclipse/FB plugin.
1. Click ‘Help –> Software Updates –> Find and Install…’.
2. Click ‘Search for new features to install’.
3. Click ‘New Local Site…’ and select ’site’ in the hfcd_3.0.0.477 directory.
4. The local site name is ‘hfcd_3.0.0.477/site’. You may change it to whatever you want.
5. Click ‘Finish’. Eclipse now reads site.xml in order to find out what are available.
6. Select ‘HellFire Compiler 3.0.0.477′ and click ‘Next’.
7. Read and accept the license agreement.
8. You may change the installation directory. I would not. Click ‘Finish’.
9. The plugin is not digitally signed, but it’s okay. Click ‘Install All’.
10. Click ‘Yes’ when you are asked to restart Flex Builder.
11. You should now see the ‘HellFire Compiler’ view in FB.
12. Click ‘Project –> Clean’ and start a build immediately. You will see in the ‘HellFire Compiler’ view what hfcd has compiled and the applications/libraries compile/link time.
The software will expire on August 1st, 2008. But I’ll likely have an update available before the expiration.
Note that this software has not reached production quality yet. If you see any issues, please email hfcd@stopcoding.org
Uninstallation
1. Run ‘Adobe Flex Builder 3′. Click ‘Preferences –> Flex –> Installed Flex SDKs’.
2. Select ‘HellFire Compiler’. Click ‘remove’ and ‘OK’.
3. Click ‘Help –> Software Updates –> Manage Configuration’.
4. Right-click ‘HellFire Compiler’. Select ‘Uninstall’. Restart Flex Builder.
What’s next?
There are several areas I would like to explore
- With hfcd, the compiler and the other FB features are separated and it’s possible to give the VM for hfcd specific VM args that boost the performance of the compiler. For example, I’ve seen consistent 30% performance improvement when hfcd uses the ‘-server’ VM mode. It may be true or maybe I forgot to blink my eyes. I don’t know. Also, it’s interesting to see how aggressive the VM grows the heap in ‘-server’ VM mode.
- Running hfcd on a second machine. When I was with Adobe, there was a desktop under my desk (I don’t know why I put a *desktop* computer *under* my desk) that I occasionally used for testing purposes. It was faster than my laptop too! So in theory, if you run hfcd on such a machine, it could shorten the FB build time…. I’m going to see if Eclipse can help me synchronize files and remap paths….
- Suppose that there are two independent projects in your workspace, i.e. no project references. In theory, Eclipse/FB could compile the projects in parallel. If so, it would make the out-of-process solution even more compelling.
- The Eclipse/FB plugin currently only retrieves compile time and link time. But there is nothing to prevent the plugin from retrieving compiler reports (e.g. dependency info, usage info), bytecode disassembler output, etc.
















Hi Clement,
This Hellfire compiler looks very interesting.
I will do some tests on flex-mojos, I hope it works =D
VELO
shweeeet!
Dear Clement,
I couldn’t find your email, so I will write you here.
I was hired by company X to implement a runtime builder for mxml. Thats means — ability to load an mxml document in a flex app and render it on the fly.
I have been reading through your code. If you can give me any tips that can lead me off the wrong path, please do.
Basically I see now to main paths for me:
1 - port all your java and javacc stuff to actionscript, so that I will run it as *is*.
2 - write a fresh parser in actionscript by hand and only refer to your code as reference.
Also, I haven’t figured out how to treat bits of actionscript in the mxml — I don’t have runtime compiling feature (eval) in actioscript.
I’m not sure which way is best.
Thanks,
Boris
Hi Clement,
I did some tests.
1st I wanna ask a favor, hellfire.compiler.client.ConfigurationStub. Can you implement a toString() like what was done on flex2.tools.oem.internal.OEMConfiguration?
Now, about results. I try, and got two exceptions, both at client side and at same time:
[ERROR] java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
at hellfire.tools.IOToolkit.readInt(IOToolkit.java:387)
at hellfire.tools.ClientHandler.readInt(ClientHandler.java:299)
at hellfire.tools.ClientHandler.receive(ClientHandler.java:532)
at hellfire.compiler.client.ApplicationStub.getReport(ApplicationStub.java:540)
at flex2.tools.oem.Application.getReport(Application.java:329)
at info.rvin.mojo.flexmojo.compiler.AbstractFlexCompilerMojo.tearDown(AbstractFlexCompilerMojo.java:1316)
at info.rvin.mojo.flexmojo.compiler.ApplicationMojo.tearDown(ApplicationMojo.java:126)
at info.rvin.mojo.flexmojo.AbstractIrvinMojo.execute(AbstractIrvinMojo.java:145)
and
java.lang.NegativeArraySizeException
at hellfire.compiler.CompilerReport.setFrameCount(ReportToolkit.java:453)
at hellfire.compiler.ReportToolkit.readReport(ReportToolkit.java:105)
at hellfire.compiler.ReportToolkit.readReport(ReportToolkit.java:51)
at hellfire.compiler.client.ApplicationStub.getReport(ApplicationStub.java:541)
at flex2.tools.oem.Application.getReport(Application.java:329)
at info.rvin.mojo.flexmojo.compiler.AbstractFlexCompilerMojo.tearDown(AbstractFlexCompilerMojo.java:1316)
at info.rvin.mojo.flexmojo.compiler.ApplicationMojo.tearDown(ApplicationMojo.java:126)
at info.rvin.mojo.flexmojo.AbstractIrvinMojo.execute(AbstractIrvinMojo.java:145)
Is there any additional data that I can give to you to help to track this down?
Nothing was show on server side.
Fell free to mail me if you want.
VELO
Hi Velo, I added toString() and also fixed the exceptions. I’ve just updated the zip file. Thanks for testing.
Hi Boris,
Porting the entire compiler to AS3 is going to be extremely challenging. I would not recommend that.
Writing an MXML ‘interpreter’ in AS3 is comparatively easier than porting the Flex compiler. But…
1. If you have and binding expressions in your MXML document, you’ll need an AS3-based AS3 compiler in your app.
2. If your MXML document uses mx.controls.Button but you don’t use it in your app, your MXML document will not render due to the missing class. You could dynamically load Button (in a SWF) before rendering your MXML document. But how do you find out what Button depends on? Well, you need to load catalog.xml. The situation can get out of hand pretty easily.
I’m not suggesting that such a MXML ‘interpreter’ in AS3 is not doable. It’s doable, but it’ prudent to keep the implementation of this ‘interpreter’ simple. e.g.
1. no AS3 scripts. XML elements only.
2. all dependent classes are linked into your Flex app.
This AS3-based MXML ‘interpreter’ idea is not new and I know some customers are attempting to implement it. I suggest you ping flexcoders to see if you can find them and ask them to talk about their experience on this topic.
Now that there is this hfcd thing, your last option could be an AS3-based Flex Compiler API implementation that connects to hfcd via sockets or HTTP tunneling.
Cool, it works =D
VELO
[...] Some days ago Clement Worg released his HelfFire compiler. [...]
http://blog.flex-mojos.info/2008/06/20/using-hellfire-compiler-under-flex-mojos/
Now I need to document compilation times…. to see how fast it goes.
VELO
Hi Clement,
This is great news. I am trying out the flex-mojos integration with hellfire, which VELO has done, but am getting an exception that looks like the one VELO mentions above. But the stacktrace is different.
Here it is:
[ERROR] java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
at hellfire.tools.IOToolkit.readInt(IOToolkit.java:387)
at hellfire.tools.ClientHandler.readInt(ClientHandler.java:299)
at hellfire.tools.ClientHandler.receive(ClientHandler.java:532)
at hellfire.compiler.client.ConfigurationStub.setSWFMetaData(ConfigurationStub.java:1316)
at info.rvin.mojo.flexmojo.compiler.AbstractFlexCompilerMojo.configure(AbstractFlexCompilerMojo.java:998)
at info.rvin.mojo.flexmojo.compiler.AbstractFlexCompilerMojo.setUp(AbstractFlexCompilerMojo.java:773)
at info.rvin.mojo.flexmojo.compiler.ApplicationMojo.setUp(ApplicationMojo.java:117)
at info.rvin.mojo.flexmojo.AbstractIrvinMojo.execute(AbstractIrvinMojo.java:143)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:447)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:539)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:480)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:459)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:311)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:278)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:143)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:333)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:126)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:282)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
The exception is deep down in hellfire, so even though flex-mojos is present in the stacktrace, I start here
Can you help with this?
Hi Clement,
About this Tech Per exception.
AFIK, you have 3 releases on HFCD so far, right?
The first one.
The second, with toString and something else.
And the last, with metadata implemented, right?
According with our tests, this exception only occurs on release 3. On release 2 “all” works fine (only metadata blows).
I wanna ask you one more thing, can you version HFCD?
Will be easier to report problems if you do so.
VELO
Is it possible that Tech Per is using the 2nd release of flex-compiler-oem.jar and the 3rd release of hfcd.jar?
There is a build number in the readme.txt file. Is that good enough? Do you want the build number in the jar manifest as well?
One more note, minimum JDK requirement is 1.5.
Jus to recap the fixes I’ve done so far:
1. added Configuration.toString(), per VELO.
2. fixed a read timeout exception in Application.getReport().
3. fixed Configuratoion.setSWFMetaData() - missing impl.
4. changed the default ports to 50207 and 50208.
The current build is 329 (it’s included in readme.txt).
Forgot to mention in the installation instructions. Minimum JDK requirement is JDK 1.5.
Hi Clement,
Nice recap. And good stuff with the build number.
To solve my problem with the SocketTimeoutException, I tried using the flex-compiler-oem.jar that comes with the latest hellfire build# 329 in combination with the flex-mojos compiler. This just throws me another exception:
java.lang.ClassCastException: java.lang.String
at hellfire.compiler.client.ConfigurationStub.setSWFMetaData(ConfigurationStub.java:1319)
at info.rvin.mojo.flexmojo.compiler.AbstractFlexCompilerMojo.configure(AbstractFlexCompilerMojo.java:993)
at info.rvin.mojo.flexmojo.compiler.AbstractFlexCompilerMojo.setUp(AbstractFlexCompilerMojo.java:773)
at info.rvin.mojo.flexmojo.compiler.ApplicationMojo.setUp(ApplicationMojo.java:117)
at info.rvin.mojo.flexmojo.AbstractIrvinMojo.execute(AbstractIrvinMojo.java:143)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:447)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:539)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:480)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:459)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:311)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:278)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:143)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:333)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:126)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:282)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
I am using Java5.
Is it correct, that the server ports changed to 50207 and 50208 with build 329?
I reckon the exception above could be a problem with flex-mojos, but, given that the exception is thrown at setSWFMetaData(ConfigurationStub.java:1319) inside the hellfire compiler, I thought I would go to you first
Can you help with that one?
Configuration.setSWFMetaData(Configuration.DATE, obj) where obj should be an instance of java.util.Date, not java.lang.String.
The following is from the javadoc of the compiler api:
* The valid fields and types of value are specified below:
*
* CONTRIBUTOR java.lang.String
* CREATOR java.lang.String
* DATE java.util.Date
* DESCRIPTION java.util.Map
* TITLE java.util.Map
* LANGUAGE java.lang.String
* PUBLISHER java.lang.String
Thanks Clement. I will digg into the sources of flex-mojos then, to fix the issue there.
[...] Configuring Flex Builder to use the HellFire compiler (from Stop Coding!) [...]
Clement,
“Running hfcd on a second machine…”
Is it possible to actually run this on a separate machine (i.e. desktop under the desk) as you mentioned with this version. If so, where do you specify the location of the server. Am I dumb and missing something?
Mike
Hi Mike,
RE: “running hfcd on a 2nd machine…”
I’m working on it. ETA: mid-July.
[...] flex-mojos have the ability to delegate flex compilation to an external compile server, the hellfire compiler, done by Clement Wong, a former Adobe employee it seems. This would enable fast builds for single [...]
[...] this plugin has a good, thriving community, with actual ongoing development. I was trying out the hellfire compiler with flex-mojos one day and could not get it to work. I checked out the sources and found a bug in [...]
Any update to comment 19 and the mid-July ETA ?
The trial version of hfcd has expired… is there any way around this (i.e. a new version)? If not, any ETA for it?
[...] Coding! - The Unofficial Flex Compiler Blog」より、「Hellfire Compiler」(とその設定方法)。 [...]