Getting started with Haxe/C++
Haxe code can be transformed into C++ and then compiled using your system's C++ toolchain into a native executable.
Console applications
Before using Haxe to target C++, you first need to install the hxcpp library on your computer. From a terminal:
haxelib install hxcpp
Let's see our first HelloWorld example:
class Test { static function main() { trace("Hello World !"); } }
Put this class into a file named Test.hx and create the file compile.hxml in the same directory with the following content:
-cpp cpp -debug -main Test
The -debug switch is to make sure it traces (and may only be needed on a mac). To produce 64 bit binaries the file should define the HXCPP_M64 compile variable:
-cpp cpp -main Test -D HXCPP_M64
To compile this from terminal:
haxe compile.hxml
If an error occurs, it will be displayed. If everything went smoothly like it should, this will produce a folder named cpp with your application inside. You can now run your application from terminal:
cpp/Test-debug
The application will print the trace in the console and exit:
Hello World
C++ target troubleshooting
Cannot open program database
This happens on Windows when your code resides in a Dropbox synced folder.
fatal error C1033: cannot open program database 'vc100.pdb' Called from ? line 1 Called from BuildTool.hx line 1265 Called from BuildTool.hx line 554 Called from BuildTool.hx line 591 Called from BuildTool.hx line 710 Called from BuildTool.hx line 783 Uncaught exception - Error in building thread Error : Build failed
In this scenario dropbox starts to sync the pdb file, but then the compiler can't write it. Do NOT compile in Dropbox.
Quotation mark in PATH environment variable on Windows
Called from ? line 1 Called from BuildTool.hx line 1265 Called from BuildTool.hx line 554 Called from BuildTool.hx line 588 Called from Setup.hx line 84 Uncaught exception - Could not automatically setup MSVC Error : Build failed
The build tool fails on Win7+ when the PATH contains the quotation mark character ("). Removing the quotation mark (") characters from the PATH will fix the problem.
Graphical applications (ie. games) with NME
Building a game or application with NME is almost like writing for a single platform with a Flash-like display list. However, when you are ready to publish your application, you can choose between targets like iOS, webOS, Android, Windows, Mac, Linux and Flash Player.
Instead of using the lowest common denominator between platforms with a "universal" runtime, NME projects are compiled as SWF bytecode or C++ applications, using the Haxe language compiler and the standard C++ compiler toolchain for each platform.
NME includes an install tool that automatically handles the build, packaging and install process for each target, so you don't need to do it yourself. Cross-platform really is easy and native.
- NME has its own website with documentation, tutorials and a blog
- you can also follow NME creator here: Huge gamehaxe blog
- FlashDevelop 4 supports NME's specific workflow and lets you debug the Flash target like a regular AS3 project.
Code sample
This sample, taken from haxenme.org tutorials will display an image in the middle of the screen. Notice that:
- we're using the Flash API but in the nme.* package,
- assets management is abstracted to be identical on all platforms: the bitmap is actually embedded when targeting Flash.
package; import nme.display.Bitmap; import nme.display.Sprite; import nme.display.StageAlign; import nme.display.StageScaleMode; import nme.events.Event; import nme.Assets; import nme.Lib; class DisplayingABitmap extends Sprite { private var logo:Bitmap; public function new () { super (); addEventListener (Event.ADDED_TO_STAGE, this_onAddedToStage); } private function construct () { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; logo = new Bitmap (Assets.getBitmapData ("assets/nme.png")); resize (); addChild (logo); stage.addEventListener (Event.RESIZE, stage_onResize); } private function resize () { logo.x = (stage.stageWidth - logo.width) / 2; logo.y = (stage.stageHeight - logo.height) / 2; } private function stage_onResize (e):Void { resize (); } private function this_onAddedToStage (e):Void { construct (); } // Entry point public static function main () { Lib.current.addChild (new DisplayingABitmap ()); } }
Buiding
NME includes a custom build tool, mainly to handle the crossplatform assets management. The application isn't configured using a .HXML file but with a .NMML config file:
<?xml version="1.0" encoding="utf-8"?> <project> <app title="Displaying A Bitmap" main="DisplayingABitmap" package="org.haxenme.tutorial.displayingabitmap" version="1.0.0" company="NME" /> <window width="640" height="480" fps="30" orientation="portrait" resizable="true" /> <set name="BUILD_DIR" value="Export" /> <classpath name="Source" /> <haxelib name="nme" /> <assets path="Assets" rename="assets" include="*" exclude="nme.svg" /> <ndll name="std" /> <ndll name="regexp" /> <ndll name="zlib" /> <ndll name="nme" haxelib="nme" /> <icon name="Assets/nme.svg" /> </project>
Now to build the project, open the terminal and type one of these lines, depending on the desired target:
'nme' is a shortcut to 'haxelib run nme'
nme test sample.nmml flash nme test sample.nmml cpp nme test sample.nmml android nme test sample.nmml webos
IOS is a bit trickier as you can it is only possible to automate build & test for the simulator but not for the device; 'nme update' will just create a Xcode project that you will have to open & run in Xcode:
nme test sample.nmml ios -simulator nme update sample.nmml ios
Yep it's that simple to create a desktop or mobile application with the same codebase.