Haxe: Cross-platform Development’s Best-kept Secret
The modern, cross-platform programming language Haxe is well-known in some circles, yet many developers have never heard of it. Since it first appeared in 2005, it’s been battle-tested by its loyal—if rather quiet—following.
In this article, Toptal Freelance Software Engineer Kevin Bloch explores the Haxe ecosystem and how to transpile some sample code.
The modern, cross-platform programming language Haxe is well-known in some circles, yet many developers have never heard of it. Since it first appeared in 2005, it’s been battle-tested by its loyal—if rather quiet—following.
In this article, Toptal Freelance Software Engineer Kevin Bloch explores the Haxe ecosystem and how to transpile some sample code.
Kevin has 20+ years among full-stack, desktop, and indie game development. He lately specializes in PostgreSQL, JavaScript, Perl, and Haxe.
The modern programming language Haxe is well-known in some circles, yet many reading this will never have heard of it. Don’t let its niche status fool you, though. Since it first appeared in 2005, it’s been battle-tested by its loyal—if rather quiet—following. It boasts a pragmatic and mature combination of features for development in business, gaming, and even academic contexts.
Disney, Hasbro, and the BBC are using Haxe, so why haven’t more developers heard of it? Perhaps its versatility means that there isn’t one, single “killer app” for the Haxe programming language.
Or perhaps it’s because one of its earliest killer apps—a migration path away from the dying Flash platform—is a bit niche in some ways. The venerable casual games market has been scrambling the past few years under the shadow of Adobe’s uncertainty, and now it’s finally clear that anything Flash-based will officially have to move by 2020.
Business software engineers and web developers—in fact, many game developers, too—might hear “Flash” and immediately tune out. Hence the Haxe Foundation taking the FlashDevelop IDE and rebranding it more as a Haxe IDE, HaxeDevelop.
But it can be hard to shake off an association—especially when it continues to be quite relevant. For example, FlowPlay, whose social games have 75 million users, picked Haxe over Unity and HTML5 for their recent two-year transition of 1.4 million lines of code away from Flash. (More details are available in the case study.)
Maybe it’s difficult for the Haxe Foundation to be able to highlight use cases like this, while still appealing to developers of non-game software. But don’t let that deter you from a little exploration.
What’s the Big Deal with Haxe?
The Debian project describes Haxe as a “universal programming language.” There are several aspects to that.
In general, the Haxe language means reusing (good) code. By that I mean: You can reuse Haxe code on many platforms, you can integrate it with existing Haxe and non-Haxe code, and as for good, the Haxe language makes available many tried-and-true paradigms, such as type safety.
Continuing along the versatility theme, this translates into several major categories of use cases—Flash migration aside, of course.
Developing a cross-platform app or game from scratch. Haxe can target desktop, mobile, and web platforms all from a single-language source base. Cross-platform programming languages are nothing new, and there are specialty solutions for cross-platform desktop and mobile apps and games. But Haxe does something a little more special in the sense that it can target not just multiple platforms, but multiple paradigms, e.g. HTML5 and native binaries.
One language “to rule them all.” Pardon the Tolkien reference, but just like Node.js hailed an era of using the same language on the front and back end of a website, any project with something resembling a client-server architecture can use Haxe for both halves.
For example, the web app FontStruct uses Haxe both for drawing on an HTML5 canvas on the front end and via Java2D on the back end. (But as mentioned, this approach is optional—Haxe plays nicely with existing non-Haxe code as well, because it’s designed not to tie you down.) Keeping app, game, business, and even rendering logic consistent across all contexts, platforms, and output languages is much easier this way.
Fleeing from JavaScript to type safety. Wait, isn’t this what TypeScript is for? Yes, if you want to stay limited to JavaScript output. The Haxe language, in contrast, can also transpile to Java, C++, C#, Python, and Lua, among others.
Meanwhile, the Haxe programming language is easy enough to learn coming from JavaScript—its syntax doesn’t mean a huge paradigm shift like, say, that of Rebol, the benefits of such a shift notwithstanding. Haxe core developer Dr. Andy Li wrote a more in-depth comparison between TypeScript and Haxe that’s still relevant today, although both languages continue to evolve.
Pretty fast workflow for a compiler. This is a more recently added piece (although Neko was an option before it): HashLink is a cross-platform virtual machine (VM) that seems to strike a balance between being extremely quick to compile to, yet also performant enough at runtime for things like 3D gaming. But even on the web side, Haxe can outperform TypeScript both at compile time and at run time.
An exciting frontier. Haxe itself is open-source and has an active community, with new language features being added all the time. Its own best-kept sub-secret might just be its compile-time macro system, which itself has many interesting use cases, letting you meta-program to your heart’s content. (I mention a few examples below.)
Who Else Is Using Haxe?
For starters, game developers, of course: Madden NFL Mobile, Evoland II, Double Kick Heroes…these and hundreds of other published games were developed using Haxe. But Haxe is also making waves outside the gaming sphere:
- Back in 2014, TiVo used Haxe to increase performance on their TiVo Premiere boxes by over 30%.
- Massive Interactive, whose clients include DAZN and Telecine for Haxe-based “smart TV” systems (both with large userbases) has been using Haxe for years. Their UI architect Philippe Elsass noted to me that in his experience working with large web projects, Haxe tends to be simpler to use than TypeScript and about an order of magnitude faster to compile.
- Synolia uses the Haxe language for their online customization tool Heidi, which is used by major French brands Carrefour and La Fnac, and also Nickelodeon. According to Synolia, the Haxe toolkit allowed them to efficiently manage the transition from Flash to HTML5, while also being able to take on new business development opportunities in the mobile sphere. Heidi being a SaaS application, the Haxe toolkit allowed them to share common source code among the app’s different layers and services.
- Multinational enterprise Docler Holding became a strategic partner of the Haxe Foundation in 2017.
What’s the Haxe Ecosystem Like?
When it comes to gaming and Haxe, it’s a wide, wide world in terms of open-source frameworks and libraries. From independent indie teams to successful studios with international clients, Haxe users are sharing code all over the place:
- Flambe is used by brands like Disney, Coca-Cola, and Toyota to develop HTML5 games.
- Heaps is the high-performance game framework behind recent 3D strategy hit Northgard.
- Powering millions of mobile gameplays, rapid development library awe6 is perhaps a hidden gem within a hidden gem.
- Kha, which can target the XBox One, Nintendo Switch, and PlayStation 4 besides desktop and mobile, has over 20 game engines built on top of it. This includes Armory, which has full Blender integration and recently itself became open-source.
- Originally modeled after the old Flixel library for Flash, HaxeFlixel is the popular choice behind games like the sleeper hit Defender’s Quest.
- Gamua’s Starling, the framework used for the Facebook port of Angry Birds a few years back, now has an open-source Haxe port.
- OpenFL, based on the Flash API, will also soon be a way to target multiple consoles—namely the PlayStation 4, the PlayStation Vita, the XBox One and the Nintendo Switch—without additional licensing fees. HaxeFlixel and Starling are both built on top of OpenFL, but some games are developed on OpenFL directly, like the award-winning Papers, Please.
- The Native Media Engine, NME, from which OpenFL was forked many years ago, is still releasing major versions, too.
- Maybe you saw when HaxePunk (descended from FlashPunk) was featured on GitHub’s Release Radar blog.
- The highly optimized Nape Physics Engine is great for any 2D game engine or simulator needing more sophisticated physics.
Granted, the game development scene is a more visible part of the Haxe language ecosystem. (Perhaps this is thanks to the nature of game jams like Ludum Dare?) But the business and even enterprise sides are showing through, too. For example:
- Modular app framework hexMachina supports domain-specific language (DSL) usage and model-view-controller (MVC) architecture, among many other features.
- UI layout engine HaxeUI is actively evolving and has corporate support. Products like 3DVista and Kaizen for Pharma have shipped production apps with it.
- It’s not the only one, but the thx.core library and its relatives provide general-purpose extensions to Haxe, much like Lodash does for JavaScript.
- Speaking of JavaScript, Haxe projects that target it may benefit from leveraging Haxe Modular, which helped both Telecine and FlowPlay to scale their enormous projects while keeping them fast-loading on the client side.
- Haxe’s ecosystem also continues to evolve to interface with current technologies; e.g. there’s now a GraphQL library.
- Lastly, the exemplary Tinkerbell leverages Haxe’s macro system for all sorts of useful tasks. It has frameworks for web routing, unit testing, and embedding SQL, as well as libraries for everything from templating and CSS selector parsing to async/await and lower-learning-curve reactive state handling.
These are just highlights of some of the directions users of the Haxe language have taken it so far. Haxe.org maintains a full list of libraries sorted by popularity which you can also browse by tag. But it’s also worth highlighting a couple projects the Haxe Foundation itself maintains:
- For the DevOps angle, there’s the official Haxe Docker repo.
- Stability-wise, even with a major version update, Haxe 4 will have some compatibility help for those with projects dependent on Haxe 3.
That all sounds nice, but what’s it like to get a development environment going on your system?
Haxe Quick Start
Whether for Win, Mac, or Linux, the first step is to download Haxe. The installer there will provide a few different things:
-
The Haxe compiler itself, which should let you run
haxe
from your terminal or command prompt. - The Haxe standard library, allowing for low-level basics, but also some higher-level, general purpose support. For example, XML, ZIP processing, and MySQL access are all facilitated here.
-
The Haxelib package manager, which allows you to install new packages via the
haxelib
command. (Note: It’s also worth checking out lix for more advanced package management than Haxelib provides, especially if you’re considering using Haxe in a professional context.) - Neko, a virtual machine target that allows for quick and efficient recompilation and debugging.
(That said, there’s more than one way to get set up. If you already have npm
installed, for example, OpenFL’s installation instructions have the option of installing Haxe via Yeoman commands. Homebrew and Chocolatey provide similar paths, too.)
Anyway, once you have Haxe, you could use it from the command line by itself, but developers often opt for using an IDE. FlashDevelop/HaxeDevelop is still mainly supported under Windows only. Most other options are cross-platform (Win/Mac/Linux):
- VSCode’s Haxe plugin is well-supported.
- IntelliJ IDEA also has a Haxe plugin.
- The games framework Kha has its own IDE called Kode Studio (Win/Mac/Linux).
- Sublime Text and Atom both have Haxe plugins, as do many other editors, some of which are platform-specific.
For the purposes of this quick-start guide, we’ll go with VSCode. It may be simplest to get the Haxe Extension Pack via Ctrl+P and ext install haxe-extension-pack
, but if you’re a minimalist you may just want to ext install vshaxe
for the basic Haxe plugin itself, and pick and choose whichever other parts of the pack you might want.
Creating a Haxe Project
Since the Haxe language can transpile to many targets, managing how this is done for each one is made easier using a build file. However, to get started, all we need is a single Haxe class file with a .hx
extension.
As for the code we’ll put in it, let’s take the Array Comprehension example from try.haxe.org and put it in a file called Test.hx
:
class Test {
static function main() {
var a = [for (i in 0...10) i];
trace(a); // [0,1,2,3,4,5,6,7,8,9]
var i = 0;
var b = [while(i < 10) i++];
trace(b); // [0,1,2,3,4,5,6,7,8,9]
}
}
Now, from Test.hx
’s location, you can run Haxe in interpretation mode, i.e. without transpiling at all, to see the output of those two trace()
calls:
$ haxe -main Test --interp
Test.hx:4: [0,1,2,3,4,5,6,7,8,9]
Test.hx:8: [0,1,2,3,4,5,6,7,8,9]
Great, it works!
Transpiling Haxe Code to JavaScript
Suppose you want to share this with the world via some JavaScript on a web page of yours. That’s built into Haxe, and as easy as:
$ haxe -main Test -js haxe-test.js
If you have Node.js installed, you can check the output from the command line like so:
$ node my-cool-test.js
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Otherwise, the code in haxe-test.js
is ready to go—if you were to include it in a web page, you’d see the output in your web browser’s developer console upon load.
Transpiling and Compiling to a Native Binary
Let’s say you also want a native binary for the desktop you’re developing on. To do this, we’re going to transpile to the C++ target, so we can then use C++ (assuming you have it installed) to compile the .cpp
output to a native binary. For that, we’ll need hxcpp
, so we’ll need to install it:
$ haxelib install hxcpp
After that, we can do transpilation and compilation both at once with this command:
$ haxe -main Test -cpp bin
And then our binary is ready to run:
$ bin/Test
Test.hx:4: [0,1,2,3,4,5,6,7,8,9]
Test.hx:8: [0,1,2,3,4,5,6,7,8,9]
(On Windows, this would be bin\Test.exe
instead.)
Creating a Haxe Build File (.hxml)
Despite the suggestive extension, .hxml
files aren’t XML—unlike the .hxproj
files used by HaxeDevelop and FlashDevelop, but I won’t be covering that in this article. Here’s what a build-all.hxml
would look like to accomplish the transpiling we did above:
-main Test # tells Haxe our main class is Test (case-sensitive)
--each # all of the above commands will be applied to each target
-js haxe-test.js # our first transpilation target
--next # no other options, time to move to the next target
-cpp bin # our second transpilation (and compilation) target
Note the difference in prefixes: -main
, -js
, and -cpp
are each parameters you would pass to haxe
directly, while --each
and --next
(two hyphens) are up a meta-level, telling the compiler what to do with the other parameters.
You can now hit both JavaScript and native targets simply by running haxe build-all.hxml
.
If you wanted to transpile to JavaScript and then immediately run the result using Node, you could run haxe run-js.hxml
, where run-js.hxml
looks like this:
-main Test
-js haxe-test.js
-cmd node haxe-test.js
Similarly, a “build and run” for the native binary would look like this (on Linux, that is—a variation would be needed for Windows):
-main Test
-cpp bin
-cmd bin/Test
What about VSCode? That part is simple: The extension you installed will automatically pick up on these .hxml
files, giving you auto-generated build tasks (without a tasks.json
) in a drop-down, letting you choose which build file to use.
Note: Be careful if you have multiple VSCode windows open, though—as of this writing, this can cause problems with building via Ctrl+B. (You can still use the command line, no problem.)
Haxe 4
If you followed the above setup, you may have noticed that the download page included links to both 3.x and 4.x branches of the Haxe installer.
The cutting-edge version 4 of the Haxe compiler brings with it many new features. In one case, this is also a testament to the power of its macro system: The Haxe compiler used to lack support for short lambda functions, so the slambda library implemented support for them via macros. As of version 4, support is built into the compiler, and the library is being deprecated.
So what else is Haxe 4 bringing to the table?
Not necessarily too many attention-grabbers. Instead, Haxe 4 has many smaller improvements. After all, Haxe itself is fairly mature technology, developed by a smaller and more focused team, perhaps, than similar projects—and it’s maybe a bit of a stretch to call any one project similar to Haxe.
Many of its most interesting features have already been present for a while now. For example, I mentioned above that Haxe provides a fast workflow via Neko or HashLink. But since 2016, it’s also featured a compilation server. This means that for non-VM targets, recompiling a project that depends on a large library will be much faster due to in-memory caching—which can also be leveraged by Haxe IDEs for code completion.
But Haxe 4, in particular, will see:
- Macro execution being 4x faster.
- PHP5 support being dropped.
- Some syntactic updates done that TypeScript users will probably welcome, even if they’re slightly different between the two languages. Namely, arrow functions and the new function type syntax.
Haxe Tutorials
While you can always dive right into Haxe’s standard API or syntax documentation, there are some more beginner-friendly Haxe materials available as well.
If you prefer getting oriented with videos, the Haxe US Summit 2018 in Seattle has its workshops up alongside those from other years, to gain more of an insider’s view.
But sometimes what might get you started more easily is a more specific tutorial. Like a start-to-finish tutorial on how to build a dungeon crawler game in HaxeFlixel. There’s also a series of HaxeFlixel tutorials that explain more of what’s happening behind the scenes as they go. On the 3D end, there’s a Haxe tutorial on getting started with Armory.
Or maybe you just want a Haxe tutorial on the fast processing of XML—this is one among many tutorials that are now a few years old, but still quite relevant. As I mentioned earlier, while there are a lot of frontiers, many of the basics of developing in Haxe are stable at this point, so tutorials don’t necessarily go stale very quickly. (Where they do, it’s usually from a dependency on a specific library, not on the Haxe core itself.)
As you can see, you can take the Haxe language—or it can take you—in many different directions. I hope you’ve enjoyed this introduction to the diverse and fascinating world of Haxe, and I look forward to hearing what you end up doing with Haxe’s technology!
Further Reading on the Toptal Blog:
Understanding the basics
Is Haxe newer than TypeScript?
Haxe is actually a bit older than TypeScript, and while it doesn’t have the same corporate weight behind it, its language and transpiler are both quite mature.
Which targets can Haxe compile and transpile to?
The Haxe compiler can target JavaScript, Java, C++, C#, PHP, Python, ActionScript 3, Flash, and Lua, plus the HashLink and Neko virtual machines. In turn, Haxe’s output can then run on Windows, Linux, macOS, iOS, Android, PlayStation 4, PlayStation Vita, Nintendo Switch, and XBox One.
Is Haxe only for game development?
No. While Haxe’s vibrant gamedev ecosystem includes frameworks like OpenFL, HaxeFlixel, Heaps, Kha, Flambe, Armory, Kha, awe6, NME, and HaxePunk, it’s also useful in production for business applications and web sites.
Bergerac, France
Member since January 31, 2017
About the author
Kevin has 20+ years among full-stack, desktop, and indie game development. He lately specializes in PostgreSQL, JavaScript, Perl, and Haxe.