If you ever come across this error, it can be a bit cryptic to understand.
Here’s some sample code that produces the error:
import haxe.macro.Expr; import haxe.macro.Context; import neko.Lib; class BuildInMacroTests { public static function main() { var s:MyModel = new MyModel(); MyMacro.doSomething( s ); } } class MyModel extends sys.db.Object // has a build macro { var id:Int; var name:String; } private class MyMacro { public static macro function doSomething(output : Expr) : Expr { return output; } }
I’m still not sure I have a full grasp on it, but here’s a few pointers:
- It’s not necessarily an enum – it can happen with a class or interface that has a “@:build” macro also.
- The basic sequence happens in this order:
- BuildInMacrosTest.main() is the entry point, so the compiler starts there and starts processing.
- When it hits “var s:MyModel”, it does a lookup of that type, realizes the class needs a build macro to run, and runs the build macro.
- When it hits “MyMacro.doSomething()”, it types the expression, and realizes that it is a macro call. To run the macro, it must find the macro class, load it into the macro context, and execute it.
- It finds the macro class, it’s in this file.
- It tries to load this module (hx file) into the macro context, so it goes through the whole process of typing it again.
- As it’s loading it into the macro context, it hits the “MyModel” build macro again, which it can’t do at macro time, so it spews out the error.
- The basic solutions:
- Wrap your build macro declarations in conditionals:
#if !macro @:build(MyMacro.build()) #end class Object { ... }
- Wrap anything that is not a macro in conditionals:
#if !macro class BuildInMacroTests {} class MyModel {} #else class MyMacro {} #end
- Keep your macros in seperate files:
BuildInMacroTests.hx: class BuildInMacroTests { public static function main() { var s:MyModel = new MyModel(); MyMacro.doSomething( s ); } } class MyModel extends sys.db.Object { var id:Int; var name:String; } MyMacro.hx: import haxe.macro.Expr; import haxe.macro.Context; class MyMacro { public static macro function doSomething(output : Expr) : Expr { return output; } }
- Wrap your build macro declarations in conditionals:
A combination of the 1st and 3rd solutions is probably usually the cleanest.
Good luck!
One reply on “You cannot use @:build inside a macro : make sure that your enum is not used in macro”
This helped me, thanks Jason!