Air NativeProcess and bash file to compile haXe nme project

Last week I’ve made some test with haXe nme and box2d. The result is awesome : beautiful perf and a quick export on the target required! When I tried to run box2d from flash on a iPhone there was really bad performance : 10 dynamics objects – 5 fps. With haXe nme, more than 80 dynamics objects and 30 fps… that the power of native app. And for the fun I had an html5 box2d export, but not running smoothly.
At the moment, what I’m really missing is a powerful IDE for writing code and don’t use the console (even if it works great). FlashDevelop is the best one, but runs only on windows. Sadly, FDT supports haXe but not the nme. However it seems that JetBrains are working on a plugin for haXe and nme! But right now, I use Sublime Text 2 with the haXe plugin.

Anyway, I thought it would be cool to have a simple utilitarian app to create nmml files and compile projects with options (targets, mode, …). An Air application seemed to be an elegant way. Let’s go for a proof of concept on this last part :

The problem was how to run terminal command line with Air? The NativeProcess class provides command line integration and general launching capabilities. The NativeProcess class lets an AIR application execute native processes on the host operating system.
So it means that if I write a simple bash file, I’m able to run it with AIR!

Here we go for a simple version, my file name is nme.sh :

#!/bin/bash
nme test \"SimpleBox2DExample.nmml\" flash

Make sure to save the file with a chmod which allows you to execute it.
The Flex code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx">
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->	
	</fx:Declarations>
 
 
	<fx:Script>
		<![CDATA[
 
			public var process:NativeProcess;
 
			protected function compile(mEvt:MouseEvent):void
			{
				trace(NativeProcess.isSupported);
 
				var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
				nativeProcessStartupInfo.workingDirectory = new File("/Users/Aymeric/Desktop/Simple Box2D Example/"); 
				nativeProcessStartupInfo.executable = new File("/Users/Aymeric/Desktop/Simple Box2D Example/nme.sh");
 
				process = new NativeProcess();
				process.start(nativeProcessStartupInfo);
				process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
				process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onErrorData);
				process.addEventListener(NativeProcessExitEvent.EXIT, onExit);
				process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError);
				process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
			}
 
			public function onOutputData(event:ProgressEvent):void {
				trace("Got: ", process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable)); 
			}
 
			public function onErrorData(event:ProgressEvent):void {
				trace("ERROR -", process.standardError.readUTFBytes(process.standardError.bytesAvailable)); 
			}
 
			public function onExit(event:NativeProcessExitEvent):void {
				trace("Process exited with ", event.exitCode);
			}
 
			public function onIOError(event:IOErrorEvent):void {
				trace(event.toString());
			}
 
		]]>
	</fx:Script>
 
	<s:Button label="Compile" click="compile(event)" />
 
</s:WindowedApplication>

If you run that script, your haXe nme project will compile from Air and open the flash player!
However this is not very dynamic… we can do better, let’s use some parameters :

#!/bin/bash
 
if [ $2 = "html5" ]
	then
	nme $1 \"SimpleBox2DExample.nmml\" $2
fi
 
nme test \"SimpleBox2DExample.nmml\" flash

That was our new bash file. $1 is the first argument given by our nativeProcessStartupInfo. The Air code :

var processArgs:Vector.<String> = new Vector.<String>();
processArgs[0] = "test";
processArgs[1] = "html5";
nativeProcessStartupInfo.arguments = processArgs;

Now if you run your app and click on the compile button, it will run your code in the browser thanks to html5 and open the flash player. You should be able to use all the nme’s Command-Line Tools.

If you’re familiar with bash script, you may be able to create a good dynamic script. I’m not.

Does it mean that we need to create ourselves the bash file? No, the app can generate one :

var file:File = File.desktopDirectory.resolvePath("test.sh");
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeUTFBytes("#!/bin/bash\nnme test \"SimpleBox2DExample.nmml\" flash");
stream.close();

Thanks to the File API we are able to create a file, and later update it.
So everything is running fine, and I’m able to run my generated bash script? Well, there is one last problem : you can’t execute this file, so you get an error : Error #3219: The NativeProcess could not be started. ‘launch path not accessible’.

Google, my friend, show me this thread : http://forums.adobe.com/thread/721724 but it doesn’t work for me. And I can’t find other result. As far as I know, it seems to be not possible to create a file from air and change its chmod.
Anyway, if your file is already created, you could update it through Air.

That’s it for this proof of concept, an other thing for the todo list ? Maybe.

Ho! And since I was blasted by box2d mobile perf with the nme, we started to work with Dav Kert for a Citrus Engine haXe nme release : stay tuned on the github.

3 thoughts on “Air NativeProcess and bash file to compile haXe nme project

  1. I currently use Sublime Text 2 with the haXe plugin. The problem I’ve had is with debugging. I haven’t figured out a good workflow for that. If you ever have time i would like to hear about your workflow process using sublime in perhaps a future blog post.

    Thanks for the article.

Leave a Reply

Your email address will not be published. Required fields are marked *