binki
binki

Reputation: 8316

How do I get haxe to generate externs?

I am writing haxe code which I want to compile to an arbitrary target as a module and then use the results from another module compiled for this same target. I don’t want to handle this the “Haxe way” (which is to fully inline all libraries at compiletime). Instead I want to be able to write distinct Haxe modules and reference them with full type safety without inlining between the modules. The natural way to do this would be to have both source Haxe files and a separate directory of “headers” filled with extern describing the public API of my module, with these externs somehow automatically generated so that they don’t need to be manually maintained.

I cannot figure out how to get Haxe to emit externs. It would make sense to me if haxe-externs were an actual “target platform” so that I could do something like:

$ haxe ClassName -hxe externsoutdir

It would make less sense but still be acceptable if one of the -D flags like -D dump (which seems to sort of get one part of the way there) or some imaginary, nonexistent -D dump-externs existed. Then you could generate externs while compiling to your favorite target:

$ haxe ClassName -js outfile.js -D shallow-expose -D dump-externs=externsoutdir

The idea is to take a class definition like this:

@:expose
class ClassName {
    function quack() {
    trace('quack');
    }
}

and emit something like this in a separate directory:

extern class ClassName {
    function quack():Void;
}

so that I can consume it from another module like this:

@:expose
class MyClassName extends ClassName {
    override function quack() {
    super.quack();
    trace('…and again I say “quack”');
    }
}

$ haxe -cp path\to\externsoutdir MyClassName -js outfile.js -D shallow-expose

It would only make sense to generate externs for things decorated with @:expose or some other decorator.

I will figure out how to wrap the emitted modules to load each other correctly. That’s easy. The hard part is generating the extern definitions—shouldn’t Haxe already have a way to do this?

Is there already some tool or built-in way I’m missing to do this? When Googling, all I see are projects that supposedly help with generating externs for existing JavaScript libraries. But that’s not my use case…

Upvotes: 1

Views: 707

Answers (1)

Jeff Ward
Jeff Ward

Reputation: 19196

Update: --gen-hx-classes was removed sometime aroudn Haxe 4.0.0-rc3. Apparently the functionality still exists secretly as -D gen-hx-classes, but beware, if you rely on this, it seems like its going away.


I believe --gen-hx-classes option might be what you're looking for. Oddly I don't see it in the compiler flags list.

I use it in a modular JavaScript build system that is similar to what you're talking about.

I believe it creates a directory of .hx files that are externs for every class generated by the build (including those from the Haxe standard library.) Actually, getting duplicates of the classes in the standard library may be a problem you will face.

You may also need to use @:keep (or the related macro) to ensure dead code elimination doesn't remove things the other build will need.

You might also need to exclude a class from one or the other builds, e.g. --macro 'exclude("haxe.io.Input")' (or, excludeFile is actually more performant for a whole list of exclusions.)

Upvotes: 2

Related Questions