<![CDATA[haxe - ruby0x1.notes]]>https://notes.underscorediscovery.com/Ghost 0.11Tue, 02 Feb 2021 23:21:57 GMT60<![CDATA[Haxe Entry Point]]>A title with two meanings, what have we here!

Recently I wrote about Haxe from 1000ft, which looks a the way Haxe fits together, how it's flexibility makes it difficult to explain, and how an onlooker might better understand it.

This post is a follow up, and discusses what happens

]]>
https://notes.underscorediscovery.com/haxe-entry-point/5d5cba3d-2506-4d4c-ac78-abe860e0e3ebSat, 07 Mar 2015 08:03:56 GMTA title with two meanings, what have we here!

Recently I wrote about Haxe from 1000ft, which looks a the way Haxe fits together, how it's flexibility makes it difficult to explain, and how an onlooker might better understand it.

This post is a follow up, and discusses what happens if you were interested in using Haxe for something, and were curious about the entry point from a user perspective.

To tackle the basic usage and understanding of the Haxe environment, we will write an example command line tool using Haxe.

This is a continuation of a series on Haxe itself, which you can find all related and future posts under the “haxe” tag.

haxe.org

Here is part one.
This is part two.


User entry

When you install Haxe, it installs a few command line tools that include the compiler, haxe, the package manager, haxelib and some other tools that it needs.

Let's start at haxelib, the first step usually.

haxelib

haxelib is a tool that manages haxe libraries, which is where the name comes from. In python you would be familiar with pip or pypa, on ruby there are gems, node.js has npm - if you've used any package manager before you should be quite at home.

haxelib repository
haxelib has a central repository of libraries. Libraries are distributed in zip form and are easily installed/removed from your computer at your discretion. Libraries are submitted by third party developers and offer a diverse range of tools, frameworks, and more through a simple command line interface.

haxelib install
If you want to install a library, it's as simple as saying haxelib install hxcpp. That would install a library named ”hxcpp”, which you will need to develop against the Haxe C++ target.

haxelib run
A library is allowed to include a "run script", which is a small neko module (mentioned here before) that can do certain tasks - perhaps some post-install configuration or thats how you interact with the library. For example - flow - the build tool used by snowkit libraries - is used entirely via the haxelib run command. To run the script, you would call haxelib run flow, which would show it's options.

This varies by library, so you would usually want to check the docs or readme about the library before executing the command blindly.

haxelib config and versions
A lib would download and unzip into a location you can set or view by calling haxelib setup(set) or haxelib config(view). On OS X for example the default should be /usr/lib/haxe/lib/, and within that folder it would put all your libraries.

Libraries have versions, and are unpacked into a folder structure which looks like this: hxcpp/3,1,68/. To install a specific version, I would call haxelib install hxcpp 3.1.48, which would install that version alongside the existing ones.

switching library versions
To switch between multiple versions of the same library you use haxelib set. To switch to an older version of hxcpp, I would call haxelib set hxcpp 3.1.48, which would make that the active version that's used by subsequent builds.

To see which versions you have installed, you can run haxelib list which shows all library versions. If you wanted to know where exactly the current version is located, you would use haxelib path hxcpp (which also for some reason includes some additional lib definitions).

haxelib updates
To update to a newer version of a library (if there is one) you would run haxelib update hxcpp.

You can also try haxelib upgrade, which would check and ask about upgrading every installed library - but be aware that you should check what was updated against your projects. You don't want to accidentally update to an incompatible version without realizing. I find it easier to be intentional about it, so I can switch to a version that is compatible again later if needed.

dev libraries
Sometimes a library won't be uploaded to haxelib repository yet, or you might want to make your own folder into a haxelib library under a given name. To do this you can use the haxelib dev command, which would specify the dev version and which specific folder on your computer you want it to use to represent it.

haxelib dev mylibrary /Users/Sven/dev/mylibrary/ would "install" this folder as a haxelib called "mylibrary", allowing me to use -lib mylibrary when building haxe projects later.

You can also install a library from a zip package, maybe you manually downloaded hxcpp 3.1.39 at work and wanted to install it offline at home. To do this, you would use haxelib local file.zip, which would be the same as if it were downloaded. This is also useful for testing your own libraries while developing them.

Let's say I was editing hxcpp for something I was testing, I could make a local copy, and point to it with dev, haxelib dev hxcpp ~/dev/hxcpp/. This allows me to say which hxcpp is used for all projects. If I wanted to go back to using the stable version, I would just call haxelib dev hxcpp which would stop using the dev version again.

git haxelib repositories
Another great use case is installing a dev version directly from a git URL. This is useful as many libraries might not yet be ready for haxelib releases, due to active development. Or, sometimes libraries get stuck in limbo waiting for a new haxe release.

The usage would be the same as the dev command, except it would use git to pull down the repository. It would use git to update it as well, when running update/upgrade. Using hxcpp as a continued example, if you wanted to try the bleeding edge version, you could run haxelib git hxcpp https://github.com/HaxeFoundation/hxcpp.git which would pull down the latest git version for you. To switch back to stable, you would just run haxelib dev hxcpp as before.

other haxelib info
More information about haxelib can be found on the Haxe website or by running haxelib with no arguments.

hxml

Now that we know how to install and manage libraries, how do we use them?

The Haxe intro post mentions hxml briefly, but here we will consider it as step two, in getting started with Haxe.

hxml = haxe markup language
The meaning of hxml is a guess from my part (but it would make sense). It's a very simple markup file that acts as command line arguments to the Haxe compiler - and that's it.

Let's take the simplest example, the haxe -version command. That second bit, the argument, we can put that inside of a text file and split each argument up, one on each line.

# haxe_version_example.hxml
-version

It helps to use the hxml extension, because then people know what to do with the file.

using hxml files
To use the hxml file, you simply hand it to haxe as an argument:
haxe ./haxe_version_example.hxml

The results would be identical to the above haxe -version command. This seems silly for one command, but for large projects with many flags, defines, library dependencies and targets it would quickly become impractical to use the command line directly. hxml files solve this easily.

hxml in practice
Now we know where to put the hxml file, what do we put inside it? There's a LOT of options actually, if you run haxe -help you would see a small section of the possible commands to Haxe.

To continue on our path though (we are at step two), we will only look at a few useful pieces of hxml to move forward.

  • -main ClassName
    • The class where the literal entry point will be
    • The entry point is a static function main() { }
  • a target to build to
    • Could be one of many, in our example -neko
  • -lib libraryname
    • Specify a haxelib dependency
  • -D mydefine
    • Specify a conditional define for #if mydefine within code
  • --next
    • Split between subsequent sections of the same hxml
    • You could consider this as starting a new hxml, within the existing one. This allows multiple targets or steps to be executed in order.
  • -cmd
    • Runs an arbitrary command after previous commands complete.

Example: “haxelibcounter”

To further our journey, we will ground it in practice. To do this, we will write a simple tool to count the number of haxelib libraries using the knowledge above. Here's what we'll do :

  • Use a library to parse command line arguments
  • Use hxml to build our program into a neko binary
  • Turn this command line tool into a haxelib of it's own

Note: The code is in snippets below, but the entire code is embedded at the end for clarity, and is also at the github repo in full.

This seems trivial, but it's the basis of every haxe game, application, website or tool. We are going to be using the haxe neko target (more about that here) to generate a small, cross platform binary that haxelib will use to run our tool from a user perpsective, as we discussed above.

step one: dependencies
So to begin, if you were paying attention, we need our lib dependencies! We are going to need the library we want to use to parse arguments. For the sake of example I have used my own simple library called “arguable” which I use in my own tools to handle command line parameters. It's very simple in itself, so it might serve as an interesting place to poke at if you're curious.

First, we need it installed. From a command line, we run haxelib install arguable.

There - it shows us what was inside the library, it has no run.n file, so we can't use haxelib run arguable, and we can see it has a test/build.hxml file - if we wanted to build the test we could pass that file to haxe.

The rest doesn't matter for now,

step two: create a hxml file

To do this we create a blank file, and fill it Haxe command line arguments. We will name our file build.hxml, as I find this easy to spot as the method to (re)build something.

The minimum we would be doing is specifying an entry point (-main) and a target (-neko), but we are also using a library, adding a define, and running the tool while we develop (this gives us quick turn around time).

  • Specify the entry point:
    In the hxml file, we start with -main HaxelibCounter. This tells Haxe to look for a file called HaxeCounter.hx - and inside it look for a static function main {} so that it knows where to start.

  • Specify a target:
    Since we want to build to the neko target with haxe, the docs tell us that we use -neko file_to_create.n. Our exact usage is -neko run.n, we are using run.n, because we want to use this library from haxelib run.
    This file is platform independent - as long as you have neko, you can run it. This is why it's used for the haxelib run command, it works anywhere Haxe is installed. If you wanted to create a platform dependent binary/exe, you would use nekotools boot file.n and what you would get out of that is file or file.exe, depending on the platform.

  • Specify the dependency:
    -lib arguable will tell Haxe that we are using haxelib to depend on this library. What this does is tell Haxe where the code from arguable will be on your computer, via haxelib. This way, when you reference code from within an arguable package, it can find it (more on this below).

  • Specify a define:
    This is just an example, so we will make a define called haxelibcounter_verbose which we will use to output more information in a debug type of build.

  • Tell neko to run the file it just built:
    As mentioned above, the -cmd argument will execute something for us. We can add -cmd neko run.n, immediately running the results if any of the build.

Onward
This is our starting hxml file, for this project:
(# is a comment line, it's ignored by Haxe)

Writing the tool

Now we get to the code. We create a blank file, name it HaxelibCounter.hx, and put it in the same folder with the build.hxml. Inside the file, we need a class named HaxelibCounter, and we need a function within that class called static function main. This is the Haxe entry point.

class HaxelibCounter {

    static function main() {
        trace("This will do stuff soon!");
    } //main

} //HaxelibCount

First run

Now we have :

  • A file to build
  • A file to tell Haxe how to build it
  • And that will run the program when it's done

We can run our application using Haxe \o/
From within the same folder from a command line, run: haxe build.hxml

And you should see:

> haxe build.hxml
HaxelibCounter.hx:6: This will do stuff soon!

Importing code from the library

Now we need to reference some code from arguable. We do this using the import statement. Import statements must be before everything else in the file, so it goes right at the top of our class.

Class paths
The import statement basically checks a list of locations called the class path to see if the module you are looking for is in there. Our example: import arguable.ArgParser;

If you look at the haxelib install log above, you will notice that arguable/ArgParser.hx is actually just a file within a folder. This is no coincidence! A . within the import statement is stepping one depth lower into the class path. This is true for a folder (a package), or a Module (multiple types within one hx file) - more on that below.

By using -lib arguable, we add the location of that folder that haxelib is keeping track of - to the class path. Now, when some Haxe code says import arguable.ArgParser;, the modules within the class path are checked. Since a single file on disk can contain multiple types, the file that contains them is called a Module. hint: You can also look up the -cp command, it adds a package folder manually.

Since that's all we need to know about that for now,

What about packages?
A package is a folder within the class path. arguable. is the package, ArgParser is the module. import arguable.ArgParser; tells Haxe to look inside the arguable package folder(s) and find a module called ArgParser. Simple enough!

This brings up an important rule of understanding in Haxe:

  • Modules/Classes MUST start with a Capital Letter
  • packages/folders MUST start with lower case

This is how you tell the difference between game.Game and Game.game.
Small letter: package (reaching into a folder).
Capital letter: A haxe class (module).

In this obtuse example, Game.game is a static variable on the class called Game, and game.Game implies that the Game class is in a folder called game/. Ideally you wouldn't name things in such convoluted ways, but with this simple rule you can always tell the difference.

after import
So, we imported the ArgParser module which is a Haxe class, this gives us a shortcut name for arguable.ArgParser. We no longer have to explicitly say arguable.ArgParser every time we want to talk about that class in our code - we have now explained to Haxe which ArgParser we are referring to, later.

Using the ArgParser class

Hopefully the library you are using is documented, as that's usually where you check for how to use things. If not, you should probably file an issue for documentation with the developer as, well, that's a major issue.

arguable is a very simple library, so the documentation is housed in the readme file. To use it, we simply give it the list of system arguments from the haxe std api.

The Sys.args() function gives us the command line arguments to our haxe program on language targets that have access to Sys (neko does). Note again, Capital = Class. There is also a sys package, which contains various other useful modules but we are using the Top Level class called Sys.

Let's change our code to the following and run it again haxe build.hxml:

static function main() {

    var args = ArgParser.parse( Sys.args() );
    trace(args);

} //main

We get
HaxelibCounter.hx:10: { any => false, length => 0, valid => [], invalid => [] }

So far so good, we didn't give it any arguments, so that result makes sense.

Using our define

Since we are making a tool we might want to print a lot of information during development to help us understand what path the tool is taking. We made a define to allow us to turn this on and off easily, so it doesn't burden the user unless they need it.

The defines are used with #if define_name and allow opposites with ! (not). #if !neko. You can combine them with ( ), like #if (cpp && neko && !mydefine). The Haxe manual covers these further, that's all we need. Let's make a debug function to do some logging:

Now our code looks like this:

var args = ArgParser.parse( Sys.args() );  
debug('> found args $args');  

And without that define (commented out in the hxml) we don't see that output. This will come in handy.

Implementation details

What we really want to do in this example is:

  • If the user has no arguments provided, show the usage information.
  • If the user requested we show the count, do that.
  • Additionally, if the user asks, print the names while we are at it.

We can now use arguable to do the simple handling, and add the printing of the usage. We'll fill in the do_count function next :

do_count()
What we are doing next is pretty straight forward, we ask haxelib list for all installed libraries, we split that up one per line, and then print the total.

Some notes: I have intentionally specified the 'full name' for sys.io.Process. This is an alternative to using import, and is important when you might have to modules/classes with overlapping names. I like to keep haxe API names explicit, so myself and others can easily look them up.

and --show-names

The last bit of functionality, we can display the names since we already have the list.

To do that, we can add:

Let's run it again. You'll probably find it only ever returns the usage info! We need to pass the arguments via our hxml file for now. You can try it out by just removing or adding the arguments here:

-cmd neko run.n --count --show-names

Now my output says:

Tidying up

One thing you'll notice is the HaxelibCounter.hx:48: stuff, that comes from trace, which is really important for debugging effectively. But since our tool will be user facing, we want to remove that from the output. For this, Sys.println is available, which will print to the command line without any prefixes.

We can use a built in define for this: #if debug. Haxe has a -debug command line option which enables more debug related features, depending on the target. It also defines the debug conditional which we can use to swap between clean logging and debug logging. When we want to debug, we uncomment the #-debug line from inside our hxml (shown later) and in the code :

Turning this into a haxelib for haxelib run

We already know that a haxelib needs a json file - and optionally a run.n file (which we have!) so let's create the haxelib.json, which is pretty much copied from the template in the documentation:

Now we can tell haxelib that it exists. From the project folder, we tell it to use "this folder" (./):

haxelib dev haxelibcounter ./

Now, it should show up in haxelib list, and we can try haxelib run. I've left debug and verbose flags enabled, for testing:

Notice anything new?

haxelib run adds a needed argument

When running from haxelib the last argument is always the path at which the command is being run from! That's useful, because we often need to know that. What haxelib is doing is basically neko run.n path/that/this/is/running/from. Keep that in mind when writing tools, and how that affects your argument processing.

Let's try with arguments to haxelib run. This time I have disabled -debug and verbose logging, so what we get is the end result we were looking for (i've trimmed the output obviously):

The keen observer might notice the number went from 42 -> 43 haxelibs, that's because I added this one during!

Submitting to haxelib for other users


Please note : Don't submit this tutorial yourself. I have submitted it and you can install it from haxelib install haxelibcounter to mess around with it. But submitting a bunch of the same thing is of no real use to anyone.

First we add documentation. Since ours is really small we will just add it to the README.md file, but it's crucial.

Then, we need to make our project into a zip file, and name the zip file with the same version name for clarity. I called mine haxelibcounter-1.0.0.zip.

Since haxelib.json mentions the contributors, it will ask me for my user password (it read the file and knows who I am). Now I just run haxelib submit haxelibcounter-1.0.0.zip and it will upload it, and become available.

Conclusion

Hopefully this guide helps you further understand the underlying Haxe toolkit and it's eco system through a practical example. Once you start using big libraries and frameworks that abstract you away from the hxml and the command line - it can easily become unclear as to how things fit together.

My hope in writing this is that you are aware of how the Haxe part fits together without all that, so when you are writing tools, games, applications, websites or whatever else using Haxe (either manually, or through a framework) - you have a good understanding of what happens behind the scenes. The more you understand about the tools you're using, the better equipped you'll be to tackle any problem. You'll also probably start to see Haxe in situations you didn't before, because of it's versatility.

Follow and find me on Twitter if you have feedback or questions, and as always I really appreciate the amount of people that share these articles with others!


If you would like something to try further, try listing the active version next to the name using --show-version or similar. You could also try compiling to a different target, but haxelib run only works with a run.n file and neko, and since we used sys api's, these won't be available on some targets.

All haxe related posts.


Full code listing:

All code is available directly here:
https://github.com/underscorediscovery/haxe-entry-point-example

build.hxml

HaxelibCounter.hx

]]>
<![CDATA[Haxe from 1000ft]]>I often run into people confused as to how to use Haxe or, where exactly it fits into a project pipeline.

For the newcomer, Haxe is a high level modern programming toolkit that compiles to a multitude of languages (c#, c++, java, js, python, php, etc). You can visit Haxe.

]]>
https://notes.underscorediscovery.com/haxe-from-1000ft/4b75c653-4e40-426b-8ba3-d5f1e9e7e776Wed, 18 Feb 2015 14:03:45 GMTI often run into people confused as to how to use Haxe or, where exactly it fits into a project pipeline.

For the newcomer, Haxe is a high level modern programming toolkit that compiles to a multitude of languages (c#, c++, java, js, python, php, etc). You can visit Haxe.org for a closer look - in the mean time, here is a broad strokes view of what Haxe is and can do.

haxe.org

This is part one.
Here is part two.


The versatility confusion matrix

Haxe is an extremely versatile toolkit for cross platform and cross target development (more on this soon). It is a tool that fits many uses which by nature makes it very hard to pinpoint it to a list of "What is it" or "What is it for". It's difficult to say - because you can do basically anything using it.

Let's take a language people don't get “confused” by (or do they?) and ask the same questions : What is C#? What can I use it for? What about C++? Or Java? Or JS? Or Python? Every single one of these languages are versatile, and let you :

  • write a console application
  • write a game / game engine
  • write a web page/app/backend
  • write a high level utility script

Since Haxe is a programming language, it does all of these things as well. Simple enough! Bonus: because Haxe becomes other languages (including the ones in our example), it can do everything those languages do as well.

The Haxe Toolkit

Now that we see that Haxe includes a programming language, what else does the Haxe Toolkit include? more details on haxe.org

  • The programming language
  • The (cross) compiler
  • The standard library

The programming language

As mentioned, it's a programming language. It's modern, it's high level, it's strictly typed and includes access to the underlying target languages and native platforms.

The cross compiler

What do you do with some code written in the Haxe programming language? Feed it to the compiler!

What does that compiler generate? Code in a target language and depending on the target, a binary of sorts. Let's look at a simple example.

Given App.hx as a Haxe class, let's see an example of how to get a target language file from a Haxe file:

  • haxe -main App -python app.py
  • haxe -main App -js app.js

Edit: I was reminded that although python has been available as a target for almost a year in repo, and is listed on the main home page, that it is in fact a 3.2 feature and is not available in 3.1.3 stable. It will be shipping sometime in the near future - Sorry for the lack of clarity on that!

This is covered in more detail later on, with more examples of real world uses and other targets. The compiler includes many other utilities as well :

noteable compiler utilities

There are so many to list, because of the wide number of targets, but I'll short list some of my favourite ones :

  • Insanely fast. Building complex projects in < 1s usually, which of course varies by the target language and the complexity of the output code, your disk write speeds, etc - but the compiler itself is so fast you'll often wonder if it worked because it blinked by.
  • Documentation xml output can be generated directly from Haxe itself, which will return the information about every type and all the documentation within the files for consumption. This data is pretty brutal, but can be coerced using the Haxe xml parser itself fairly easily into other data like JSON. From it, though, really useful and fully in depth documentation can be generated. Of couse the Haxe API itself uses it.
  • Code completion is handled by the compiler itself. You tell it a file location and the command line options, it will return xml information about the completion at that point. This allows third party plugins and tools to fully utilitize the features of the language in their interface, if they provide the capability to do so. Included in the compiler is a code completion cache server, which will stay running and cache types and classes for projects, ensuring that there is never delays in completion.

The standard library

When you're writing code in general, and especially cross platform code, it's really helpful (and often important) to have code that works the same across all targets.

This is what the standard library is for. There are a myriad of classes in there, way too many to list here, but let's pick a few for examples of the type of thing that are "built in" to the language and are often available on every target.

The full Haxe api listing is here

common cross platform examples

  • JSON
    • var object = haxe.Json.parse(str);
    • var string = haxe.Json.stringify(object,null,4);
  • Base64
    • var encoded = haxe.crypto.Base64.encode(source);
    • There is also CRC, md5, sha1, sha256 etc
  • XML
    • var xml = haxe.xml.Parser.parse(source, strict);
    • for(node in xml) var attribute = node.get('example');
  • Serialization
    • var str = haxe.Serializer.run(object);
    • var object = haxe.Unserializer.run(str);
  • Http
    • var data = haxe.Http.requestUrl('http://example.com');
    • available on cpp, cs, java, js, macro, neko, php, python

target specific utilities

On top of common tools and types and utilities, the standard library includes a lot of options for each target individually, allowing maximum use of the underlying language features.

Some easy examples : File/FileSystem access. These are only available on certain platforms where it makes sense. When compiling to other targets, these types are not available.

Also remember : these are all strongly typed API's.

python example
Say you were writing something for the python target, and you needed access to the python standard library.

import python.lib.Glob;  
...
var list:Array<String> = Glob.glob('path/');  

javascript example
If you're writing a web page, you might want access to the native api, like window or document:

js.Browser.window.alert('hello from haxe'); js.Browser.document.getElementById('id');

Maybe you wanted to create an element:

var element = new js.html.DivElement();  
    element.style.width = '99px';
js.Browser.document.appendChild(element);  

sys target example
A good number of platforms support the sys types.

var data = sys.io.File.getContent('path.txt');

In many of these cases you might want to use #if python of #if sys and so on, to prevent code from trying to compile for the wrong target and throw errors your way.

Using the generated code

As this is a large and open ended topic, I will only give a few simple examples for you to understand how to use the low level code output in another project or as part of a project. This is ALWAYS going to be dependent on the actual language output you are targeting. For example, C# can use dll's really easily, or C++ target can generate as a static library, etc. Each target usage differs based on where you will use it.

js example
JS is straight forward, you simply load it in an HTML file in the browser or in node.js or other interpreters.

There are two main use cases here, one is that your application boots itself up (using the regular static function main entry point in the -main class, and the second is that you're complimenting existing js code with some js code from Haxe.

In the first case, you would just include the generated js file as usual, with <script type="text/javascript" src="app.js"> </script> and the entry point will be called for you.

The second case would require you to call into or out of the Haxe code. This is a js specific problem, and is solved with js specific solutions. You would be able to for example, store a value in the global scope from Haxe, or call global stuff from Haxe that the non Haxe code exposes.

C# example

With Haxe code written say as a library for use in C# tools (like Unity, Mono, etc) you can directly generate a .dll file for immediate use as a reference. The code can also be included in the project manually, and the -D no-root flag will keep all the Haxe code in it's own namespace to avoid conflicts.

You can also use Haxe with Unity directly.

Java example

A good example of a Java use case would be an Android plugin. If you add the android.jar library to your class path in the hxml file or command line, you can compile immediately usable jar files from Haxe code that call the native android api's directly.
Here's an example class, written in Haxe, that opens a URL in the device default browser as a new Activity. This Haxe class is compiled into a .jar file, and is then usable in any android project thanks to the Haxe cross compiler, and the Haxe java backend.


Haxe is a low level toolkit

Most people encounter Haxe through a framework using the Haxe toolkit to deploy to multiple targets - this is because Haxe is designed to be a lower level set of tools to efficiently and adeptly handle cross platform development.

This also means that there are things you will need a framework in order to achieve them. To answer the question "how do I draw graphics with Haxe" is a bit of a misnomer, the toolkit (and the language) cannot answer this for you.

Let's look at js:

  • You could draw with Canvas/HTML5
  • You could draw with WebGL
  • You could draw with Processing.js, Pixi.js, phaser.js etc

Every single target has a plethora of options available for every specific need.

Thus, frameworks, bindings, native externs and cross target implementations are written by third party developers, to give you access to these things in your Haxe code.

Continuing with the js target example, how about JQuery? What about node.js? Pixi.js? Phaser? What about some audio for the js web target, like Howler.js.

All of these offer strongly typed, ready to use bindings for just one of the many targets.

Certain targets like C++ and C# are a bit more complicated due to the nature of different compilers and runtimes, but there are still many frameworks and bindings available to you for any number of things.

Notes about the backends

Often a target has it's own implementation of all of the backend details, and standard lib implementation specifics. These are an automatic dependency when targeting that platform, as they make all the generated code work, but the process is transparent to you provided you have them installed through haxelib. For example, haxelib install hxjava would install the java backend, hxcs and hxcpp are the C# and C++ backends respectively.

Notes about neko

Neko is a VM (Virtual Machine) that runs code written in the neko programming language. The neko language is not intended to be programmed manually, but rather is a generated language that allows running the code (often bytecode) across multiple platforms through the virtual machine. You can think along the lines of lua or other VM's that run bytecode interpreted at runtime.

So why do you see neko mentioned in Haxe discussions?

  • Neko is a Haxe target
    Haxe code can be compiled directly to neko bytecode, which can then be loaded into a neko VM. A good example: mod_neko which runs on Apache web server, can run Haxe code on the server side, much like you would install mod_php and run php files, mod_neko runs neko files. Lot's of frameworks and developers use neko on the server, and code their backend in Haxe. The haxelib server and site are all written in Haxe.
  • Neko bytecode is cross platform
    This makes it a great candidate for using Haxe to write cross platform command line utilities. The reason you see neko when Haxe is running, is because the Haxe toolkit includes neko (and its tools) and uses it for many things. Again, haxelib, the Haxe package manager, allows packages to include a run.n file, a neko file compiled from Haxe, that will run when a user calls haxelib run yourpackage. This is powerful because you only need one file, and it will run on every target that you support in your code, with full access to the standard library and more.

Neko is useful for these types of tools and includes features like nekotools -boot bytecode.n, which will generate a binary for a plaform (like a windows exe or mac binary), should you want to distribute the tool standalone. Neko also compiles really quickly, because Haxe is fast at compiling and the generated bytecode has no compile step.

Finally, because Haxe includes neko in the installer and is dependent on it, it's a reliable tool that many frameworks and developers lean on to do their bidding. If you're going to be using Haxe and writing tools, it's a great option for scripting user facing utilities that will have no dependencies and be cross platform.

notes about platform vs target

  • A platform is a host environment that runs code.
    • web/mac/windows/linux/ios/android
  • A target is a language target that haxe compiles to
    • c++/c#/java/js/python/etc

The important distinction is that a single language target can and will run on multiple platforms. For example, the c++ backend will run on iOS, Android, Mac, Windows, Linux, Blackberry, Tizen and quite a few others. It also supports custom toolchains for things like consoles and native cross compilers and makes it easy to compile the c++ using it's build tools, to any C++ supported platform.

JS output can run on node.js or other interpreter based platforms. Python can run on any platform with a python interpreter. PHP as well. The targets and platforms are not the same thing.

On the shoulders of a giant

Because Haxe is this flexible, because it's a low level toolkit, many frameworks are built on top of Haxe in order to achieve some goal. A few examples of these, some of which you have probably heard of:

  • NME (native media engine)
    • long standing media and game framework loosely based on flash API's
    • the original backbone of many frameworks and tools
  • OpenFL (Open Flash Library)
    • forked from NME originally to align closer to Flash API
    • general purpose framework based on Flash 2D API
    • many game frameworks built on top of it, HaxeFlixel, HaxePunk, etc
    • many tools built dependent on it like haxeui
  • UFront
    • large, powerful MVC web backend/frontend framework
    • compiles to php/neko
  • Flambe
    • Flash/WebGL/HTML5/Android/iOS 2D game engine using AIR
  • Nape physics
    • cross target high performance 2D physics engine

Frameworks determine workflow

Now that we are higher up, there are workflows determined by the higher level frameworks you'll probably be using, which means you might not have to call the Haxe command line directly much at all (if ever).

Integration with IDE's like Flash Develop, they supporting Haxe as a relatively first class part of the editor. The features and decisions Flash Develop makes are often informed by the IDE that implements them. For tools and frameworks, you'll find that a variety of options will exist under different circumstances that meet different needs in the eco system.

know your tools
Having frameworks built on frameworks using tools that are built into IDE's made by various third parties can lead to layers of indirection. The best approach is to pick a framework or tool or work directly with Haxe itself and try to understand the stack you are using to achieve your goals. There is no way around it, and this applies to any language/platform/programming tool. Try and know more about how things fit together to serve your needs.

platform and target considerations
Framework/tool specific choices can also lead to isolating a specific subset of targets, so of course you shouldn't assume that because Haxe can target so many languages, every framework automatically works on all of those options. A lot of times that doesn't even make sense (there is no concept of a console application on web or mobile etc).

These choices are expected and good, and are often goal oriented, man power based or related to logical reasoning.

A great example is Flambe, which targets swf/js Haxe targets primarily. It then leverages AIR for mobile/desktop and HTML5/WebGL for browsers. This maximizes the focus and provide something that does what it sets out to do well, while leveraging the power of the Haxe toolkit to achieve it.

Flambe uses npm (node package manager) to install, and has it's own command line utilities to build and run the games, including automatic asset updates while the game is running in the browser and lots more. This means a tight integration with the framework and the best possible options to be avaible to the end user, things that the Haxe toolkit couldn't (and shouldn't) provide.

If you wanted to jump to using another framework, it will probably (unless it is built on Flambe) have a completely different workflow. This is great, and normal/expected, and allows a rich set of tools across a variety of preferences, goals, target languages and platforms to cover a wide range of use cases.

Conclusion

As you'll notice the amount of use cases spirals rapidly when you consider that the output code can be used in a multitude of ways. This is a valuable and powerful thing about Haxe and what makes it quite hard to describe.

Hopefully this helps someone starting out with Haxe or explains why I choose it for everything I write, why I created http://snowkit.org and use Haxe for my games and engines.

You can view all my ramblings about Haxe here.

]]>
<![CDATA[haxe: compile time macros]]>Haxe is a really great language for me. It does cross platform in a sensible way - by compiling and generating code to a target language. The best part is that it's not just converting, it's properly compiling the code - so all errors are caught by the compiler itself

]]>
https://notes.underscorediscovery.com/haxe-compile-time-macros/05c4c7f6-bc2c-41be-b44f-5f18e7295a1aTue, 04 Nov 2014 11:05:45 GMTHaxe is a really great language for me. It does cross platform in a sensible way - by compiling and generating code to a target language. The best part is that it's not just converting, it's properly compiling the code - so all errors are caught by the compiler itself long before the generated code even gets there.

One of its most powerful features is the macro system which allows you to run haxe code at compile time, to augment and empower your existing haxe code. It sounds crazy - so let's dig in.

haxe.org


In this post, the example output code will be shown using javascript for simplicity - just one of the many language targets that it supports - c++, c#, php, java, python, js.

Haxe in Haxe at compile time

Haxe manages to get macros right, it uses it's own language at compile time to alter the compilation state. This means you can inject expressions, code, remove code, throw errors and generally make code do things not usually possible, that are specific to your code base or target. And even better, you have during this compilation phase the full power of the language behind you to do so.

In luxe for example - there is a concept available for using a Component/Entity system. Sometimes, a user would accidentally try and use the entity parent property in the contstructor of the Component, long before it was assigned. This wasn't their fault, it's just the nature of the way the system works and that was something that would have to be learnt. But not with macros around!

One of the first macros I decided to write was based on this problem - I made an @:autoBuild macro happen on every descendent of Component - which at compile time, has a look at the expressions within the constructor of the given component. If it finds you touching the field named entity - it throws a neat and clearly marked error message to warn you. This saves oodles of time on things being null and obscure crashes, and gives a massive boost to usability when you can design for that explicitly.

The exact code is actually not complete right now - but the ability to do this type of thing is far more helpful than it first seems.

complex code rejection

Because you can alter the expressions in the macros at compile time, you can reject code from ever existing in the output. This is possible through #if loglevel > 1 using Haxe already - but what if the condition was far more complex? What if the condition was based on where the code is being built - like in a continuous integration server? What about environment variables? Or git commit revisions? Basically - any condition you can program - a macro can do. Since a macro is just haxe code, it has the full capability of the Haxe language and compiler to do it's bidding at compile time.

log code rejection

One simple example is logging code, using log levels to define what level of logging is present in a build. I like really dense detailed logs because I can write a parser for them and visualize them in ways that aid debugging complex systems quickly. This can add a large toll on a code base if the log code ends up in the output, because every logged string has to be stored and allocated and adds to the final build size output and sometimes runtime cost.

The macro rejecting the expression means the final code does not include the logging at all. Haxe already has a concept like this built in as a build flag --no-traces, which removes trace() calls - the built in debugging print command - but the concept applies not only to logging but more expensive and intricate systems like profiling and instrumentation.

profiling and instrumentation

Haxe macros let me add instrumentation code to my hearts content without it ever affecting runtime release builds, something I have been wanting an elegant solution for for quite some time. The next section is an even better option - what about deep profiling all functions automatically? Or each block, or each expression of each block?

complex code injection

Since you can emit code expressions from a macro, you can inject code as well. You can construct entire classes and types dynamically - at compile time.

Let's take the profiling example one step further and devise a conceptual macro for automatically profiling every block expression within a given class. Notice below I have tagged my class for a "build" macro - I want this class to be handled by my Profiling macro apply function at compile time. Since I only care about the update function right now in this example - let's tag that code for profiling only using custom metadata @:profiling. Note that @:build is from haxe, the custom one is ours.

Also take note that I separated logic into blocks { } of expressions - because I can use this to my advantage in the macros at compile time.

@:build(luxe.macros.Profiling.apply())
class Player {

    @:profiling
    function update(dt:Float) {
        {
            //update_ai
            ...
        }
        {
            //update_stats
            ...
        }
    }
}

automatic injection

Now I have everything I need - my macro will run at compile time on the class I am interested in measuring, my macro will check all methods in the class for @:profiling - if it finds it, it will look for each root block { } expression and automatically insert a start and end measurement at runtime so the final code would in pseudo code look like

profiler.start('update_ai') {

    //update ai
    ...

} profiler.end('update_ai').

For now - I won't be posting the code (this system is not even finished being coded heh) but the important thing is to understand the potential from macros and their ability to empower the code base for the development process to be quicker, more friendly, more streamlined in the output and more expressive.

continuing

This of course has down sides, code is being executed at compile time. While haxe compiler is incredibly fast - you can slow it to a crawl by a single compile time macro. If your macro introduces network latency for pinging a server or something - you will be waiting for that too.

The other thing to consider is that macros are quite complex and are the most advanced feature in haxe - so it often appears unapproachably difficult. Often this is not the case, and patience and examples will get you using them in no time. Haxe 3 made massive strides in simplifying their usage - they still have some things that are fairly difficult to wrap your head around that WILL take time to get used to.

This is not something you can fast track - the easiest way I have found is to learn by doing. That's why I am making this post, to hopefully inspire you to think of really simple, really easy macros that help you get your feet wet.

Simple concrete example

Most times a unique build id is useful in determining which version or specific build is being executed on a test machine or users machine for debugging purposes. To that end, our simple example will generate a unique-ish static string value for a build id. Since this code happens at compile time, a far more complex algorithm can be used to ensure uniqueness if required, but for the most part this code will do fine.

// MIT License
//https://github.com/underscorediscovery/haxe-macro-examples | notes.underscorediscovery.com

import haxe.macro.Expr;  
import haxe.macro.Context;

import haxe.crypto.Md5;  
import haxe.Timer.stamp;  
import Math.random;

class BuildID {

        /** Generate a unique enough string */
    public static function unique_id() : String {
        return Md5.encode(Std.string( stamp()*random() ));
    }

        /** Generates a unique string id at compile time only */
    macro public static function get() {
        return macro $v{ unique_id() };
    }

} //BuildID

Take note of the functions here - one is for generating a string ID at runtime - a regular public static function. You can use this any time from your program. Then, there is a macro function, these are compile time functions and can use the macro context to spit out expressions. I won't dig too much into the specifics of the expressions themselves - but $v{ } generates an expression from a value if it's a primitive type. Our case is a string but this is covered in the Haxe manual if you wanted more insight.

Let's look at what the using code would look like, and the resulting output target javascript code. This class is stand alone and can be used with the Haxe compiler to have a look at the results yourself, using the older documentation here as the new manual is still working on these introductions.

Basically to use this example at home, run haxe build.hxml from the compile_time_buildid/ folder of the repo.

// MIT License
//https://github.com/underscorediscovery/haxe-macro-examples | notes.underscorediscovery.com

class TestID {

    public static var build_id : String = BuildID.get();

    public function new() {
        trace( build_id );
        trace( 'running build ${build_id}' );
    }

        //called automatically as the entry point
    static function main() {
        new TestID();
    }

}

resulting output

There - now we have a unique value for the ID. The ... represents some haxe specifics that aren't useful in this example but notice how the build id is hardcoded into the output source file. This value will change with every build you run.

(function () { "use strict";
var TestID = function() {  
    console.log(TestID.build_id);
    console.log("running build " + TestID.build_id);
};
TestID.main = function() {  
    new TestID();
};
...
TestID.build_id = "cf30a1a97db5628b91535dfd3a972ea6";  
TestID.main();  
})();

even more hardcoded

Notice console.log(TestID.buildid); and the line below it? This is printing the value of a variable called build_id. It's a fixed value because its hardcoded into the file, but then why do we even need the variable access when we could replace every mention of TestID.build_id with the exact id string? Haxe allows this too, using inline static access.

Let's change :
public static var build_id : String = BuildID.get();
to
public inline static var build_id : String = BuildID.get();

For strings this is not that great, since it will generate a lot more strings, but for numbers, constants and the like it can really cut out a lot of code and even optimize the output significantly by doing away with superflous values at compile time.

Now that we have changed it to inline, this is the output - every mention of the variable build_id is gone and is now hardcoded into the file directly.

(function () { "use strict";
var TestID = function() {  
    console.log("10e594bd858844cb16a1577c61309b49");
    console.log("running build " + "10e594bd858844cb16a1577c61309b49");
};
TestID.main = function() {  
    new TestID();
};
...
TestID.main();  
})();

code example

The complete code for the above can be found here for convenience :

Github Repository

Links and tutorials

The official Haxe manual
Getting better all the time, this is the definitive guide though quite meaty and requires a good couple of passes before things make sense. Learn from simple examples and practicing, use the manual as a reference.

Andi Li: Everything in Haxe is an expression
This guide is a really helpful understanding that everything is an expression in haxe. This makes macros make a lot more sense for me.

Mark Knol: custom autocompletion with macros
An example of using macros to populate code for the compiler so it can code complete things that it wouldn't be able to otherwise.

Mark Weber: lots of simple macro snippet examples
A simple and useful reference for getting some ideas and introduction to the concepts behind the macro code, the different macro contexts and their uses.

Dan Korostelev writes about macros for tolerant JSON code
A look at "Using haxe macros as syntax-tolerant, position-aware json parser" with example code.

Lot's of these blogs and links include many great posts about haxe, and there are many more online if you search.


Good luck - and I hope to post more about haxe macros specifically in the near future as well.

]]>
<![CDATA[announcing snõwkit]]> 
I have spent my spare time in the last ~year and a half or something creating a set of libraries, all the while gathering like minded developers to foster a new collective for the Haxe programming toolkit.

The most important of these is a cross platform game engine called

]]>
https://notes.underscorediscovery.com/announcing-snowkit/6abc9d71-8705-4198-bb72-8c454c4f34c5Tue, 30 Sep 2014 18:30:00 GMT 
I have spent my spare time in the last ~year and a half or something creating a set of libraries, all the while gathering like minded developers to foster a new collective for the Haxe programming toolkit.

The most important of these is a cross platform game engine called luxe, for deploying games to Mac, Windows, Linux, Android, iOS and WebGL from the same code.

Haxe is a powerful tool for me with an important role in cross platform development and I wanted to help empower the Haxe eco system in the best way I know how - show, don't tell.

snowkit logo

Find out more below.


What is snowkit?

snowkit is a collective. It is a group of libraries, tools and developers with a common set of goals toward a high quality eco system for Haxe.

You can read about the full goals and ideals behind the community and libraries on the snowkit website.

What is Haxe?

Haxe is an expressive, beautiful modern programming language
that compiles its own code into other languages. learn more on the haxe website

haxe

Alpha release

The first set of libraries are releasing today in alpha status including a high level game engine, a lower level platform framework, and a build toolchain for Haxe. These currently focus on deploying to Mac, Windows, Linux, Android, iOS and WebGL.

As the first set of libraries continue in development toward an initial release, I am excited to announce and release the alpha versions of the main libraries for you to start using.

As with any alpha, there are work in progress features, potential bugs, and possibly undocumented areas but with your help in testing and contributing a stable release cycle can be met.

Aside from alpha status, the libraries are considered fairly stable and are being used in production already - and have been used daily for months by a good handful of developers. I prefer to work from a solid base line and test prior to release and the best way to do that is to use it.

Also, be aware that it is alpha and has the potential to change slightly. With every change though it will be clearly documented on migrating, but it would be advisable to stay close to the latest commits anyway during alpha to eliminate issues quickly.

Once the last few features are reached for each library, the first official versioned release will start at beta-1. Until that time development continues on the github repos under the alpha tags with no release cycle - for simplicity.

There are many exciting things to announce in the same breath - but for now, here are :

the first snowkit libs

 

flõw

The very first tool is a project based build tool called flow. It was created brand new to serve the Haxe eco system.

flow

You give flow a small json-like project file, and it can generate complete applications through a selection of tools like file copying and templating, building haxe code, building through hxcpp and packaging a final application file for web or native targets.

It leans on the existing Haxe eco system using haxelib directly, and only enhances the build process.

flow was created as a truly agnostic, a no dependency build toolchain to bolster the Haxe workflow. It includes project templates for Flash Develop, and a Sublime Text plugin for code completion and project management.

snõw

snow

The first large library to use flow is called snow. I created snow because I needed a light weight, minimal code, portable native framework to power my game engine. Originally, I created a minimal wrapper of the nme (native media engine) native code, which I called lime (light media engine), but the need for a truly light weight, no dependency framework I still required. snow is made from scratch, completely separated, to be exactly what I had intended.

snow is a very low level framework that gives you audio, input, windowing, and openGL access across Mac, Windows, Linux, Android, iOS and WebGL with the same consistent code. On native targets it also exposes multiple windows, direct access to OpenAL from haxe, and much more. snow can run headless, with or without a loop, and has access to assets and other utilities like OS level file change notifications, file drop events, and leverages the power of SDL on all native platforms. It is a very portable and explicitly flexible framework.

luxe

luxe

The second largest library to use both snow and flow, is luxe. luxe is a cross platform rapid development game engine for building applications and games on Mac, Windows, Linux, Android, iOS and WebGL.

With a write once, deploy anywhere approach and a bottom up design strategy, luxe is a high level engine making it really easy to use - BUT it does not get in your way if you want to get deeper.

It is designed for you to subvert it's structure to suit your needs, more like a toolbox, with a set of comprehensive building blocks for creating games and apps without making assumptions on the application domain code. It doesn't impose much structure at all.

With a hand crafted API and a large set of tools on hand, it is intended to be the starting point of building more game specific libraries and modules for it - and for various types of users. With tools like stackable, transient and modal state machines, events systems, collision classes, tilemap helpers and tons more, plus a flexible rendering engine with a shader driven pipeline at heart, luxe is intended for expressive coding in a self controlled way.

luxedesign

Here is a short video of some of the things you will find made in luxe already.

Finding more information

Each library has it's own comprehensive documentation and guides, you can view the links to them on the snowkit libs page.

For specific posts about the reasoning and history of snow, flow and luxe, these will be posted on the http://snowkit.org website in due time. Please subscribe to the hashtag and the rss feed, as that will be the direct feed of the community.

future

There are lots of exciting things to announce, and a lot of efforts underway by various members of the snowkit community toward an even greater Haxe eco system, and I look forward to seeing what we can do as a community.

For a brief look at the history and reasoning, here is a post about why I made snowkit.

]]>