# Compilation directives priority and macro

**URL:** https://community.haxe.org/t/compilation-directives-priority-and-macro/3452
**Category:** Haxe
**Created:** [February 7, 2022, 6:24pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452 "2022-02-07T18:24:49Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![filt3rek](https://community.haxe.org/user_avatar/community.haxe.org/filt3rek/32/2613_2.png) [@filt3rek](https://community.haxe.org/u/filt3rek)
#### Post date: [February 7, 2022, 6:24pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/1 "2022-02-07T18:24:49Z")

</div>

Hej folks !

Sorry, again with macro misundertanding… 😛  
I can’t really understand if it’s normal, when I build for js target I get this error : `Class<Logger> has no field _log (Suggestion: log)` : [Try Haxe !](https://try.haxe.org/#71741B30)

```haxe
class Logger {
#if sys
  static function _log(){}
#end
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
#if sys
	return macro @:privateAccess Logger._log();
#else
  	return macro null;
#end
  }
}

```

Same here : [Try Haxe !](https://try.haxe.org/#835611a1)

```haxe
class Logger {
#if sys
  static function _log(){}
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
		return macro @:privateAccess Logger._log();
  }
#else
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
  	return macro null;
  }
#end
}

```

And a last one : [Try Haxe !](https://try.haxe.org/#C459AE3b) here no errors, so If I understand well, the “non-macro” function “log” is prior to the macro one right ?..

```haxe
class Logger {
#if sys
  static function _log(){}
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
		return macro @:privateAccess Logger._log();
  }
#else
  public static function log( ?a ){}
#end
}

```

Can anybody explain me please what’s going on the 2 firsts examples ? Compiler doesn’t take care of # directives, but I thought it was prior to anything.  
So the only way to “separate” between targets is to play with `Context.defined( "sys" )` ? : [Try Haxe !](https://try.haxe.org/#E17848CF)

```haxe
class Logger {
#if sys
  static function _log(){}
#end
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
    if( haxe.macro.Context.defined( "sys" ) ){
		return macro @:privateAccess Logger._log();
    }else{
		return macro null;
    }
  }
}

```

And I imagine it’s slower than with # ?..

And at the end, how would be the best way to have a function that on sys targets do something and no-sys, just be “bypassed” by compiler (best without even be treated at macro time…) ?

---

<div class="post-metadata">

### Author: ![tobil4sk](https://community.haxe.org/user_avatar/community.haxe.org/tobil4sk/32/1458_2.png) [@tobil4sk](https://community.haxe.org/u/tobil4sk)
#### Post date: [February 7, 2022, 7:01pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/2 "2022-02-07T19:01:01Z")

</div>

The macro context always has “sys” defined as true, regardless of whether the final target you are compiling to is a sys target (which javascript is not). So the macro code generates the call to the \_log function, but compilation later fails because Javascript does not have this function defined.

The last example is probably what you want to have, where you are checking if specifically the final (non-macro) context for has “sys” defined. You are not trying to see if the macro context has “sys” features, but rather if the final javascript context once all macros are run has them. Also, it shouldn’t really be slower to use `haxe.macro.Context.defined("sys")` in a macro, because both that and the #if block happen at compile time and call on the same functionality in the compiler.

---

<div class="post-metadata">

### Author: ![filt3rek](https://community.haxe.org/user_avatar/community.haxe.org/filt3rek/32/2613_2.png) [@filt3rek](https://community.haxe.org/u/filt3rek)
#### Post date: [February 7, 2022, 7:14pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/3 "2022-02-07T19:14:28Z")

</div>

Thanks for your answer @tobil4sk

I’m happy to read that both # directive and `Context.defined()` call the same functionality, I was thinking directives are something “lighter” I don’t know how to say… anyway.  
And yes that was what I was also thinking that macro context defined “sys”, it’s ok.

What about something like that ? [Try Haxe !](https://try.haxe.org/#8E274b1C)

```haxe
class Logger {
#if sys
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
		return macro trace( 1 );
  }
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
  	return macro trace( 2 );
  }
#end
}

```

I we remove the directives, the compiler sees that this is duplicated, not here.

And I’m sorry, I put stupid examples sometimes because I try things and want to understand well how does it work…

---

<div class="post-metadata">

### Author: ![tobil4sk](https://community.haxe.org/user_avatar/community.haxe.org/tobil4sk/32/1458_2.png) [@tobil4sk](https://community.haxe.org/u/tobil4sk)
#### Post date: [February 7, 2022, 7:36pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/4 "2022-02-07T19:36:22Z")

</div>

In this case you would probably want to decide whether to generate “trace( 1 );” or “trace( 2 );” within a single macro function and use an if statement to branch between the two, as you did in the last example of your previous post. There you have no way of telling the compiler which log you actually want, as they are both defined in the same context with the same name.

---

<div class="post-metadata">

### Author: ![filt3rek](https://community.haxe.org/user_avatar/community.haxe.org/filt3rek/32/2613_2.png) [@filt3rek](https://community.haxe.org/u/filt3rek)
#### Post date: [February 7, 2022, 7:41pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/5 "2022-02-07T19:41:20Z")

</div>

Yes my last example is not linkd to the others, it just seems to me like a kind of bug because if your remove just the directives, the compiler complains that log is duplicated field, but with the directives, it give the error : `Class<Logger> has no field log` instead of telling `Duplicate class field declaration : Logger.log`, strange isn’t it ?

---

<div class="post-metadata">

### Author: ![tobil4sk](https://community.haxe.org/user_avatar/community.haxe.org/tobil4sk/32/1458_2.png) [@tobil4sk](https://community.haxe.org/u/tobil4sk)
#### Post date: [February 7, 2022, 7:53pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/6 "2022-02-07T19:53:28Z")

</div>

With the directives there are never any duplicate fields, because in the macro context it only uses the one defined in the #if sys block, and in the Javascript context only the one in the #else block, so never both at once.

---

<div class="post-metadata">

### Author: ![filt3rek](https://community.haxe.org/user_avatar/community.haxe.org/filt3rek/32/2613_2.png) [@filt3rek](https://community.haxe.org/u/filt3rek)
#### Post date: [February 7, 2022, 7:59pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/7 "2022-02-07T19:59:08Z")

</div>

@tobil4sk I mean my last example, there is only one `#if sys`, so it should throw “Duplicate fields” no ? :

```haxe
class Logger {
#if sys
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
		return macro trace( 1 );
  }
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
  	return macro trace( 2 );
  }
#end
}

```

Or maybe I don’t understand what you are talking about … ?

---

<div class="post-metadata">

### Author: ![tobil4sk](https://community.haxe.org/user_avatar/community.haxe.org/tobil4sk/32/1458_2.png) [@tobil4sk](https://community.haxe.org/u/tobil4sk)
#### Post date: [February 7, 2022, 8:07pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/8 "2022-02-07T20:07:53Z")

</div>

Ah yes sorry I misunderstood what you were saying, that is weird. It would seem that now the “sys” block is completely preventing either of them from being recognised, even if there is only one… So maybe the diagnosis was wrong.

This seems to fail, which doesn’t make sense with the theory I gave.

> **[Try Haxe !](https://try.haxe.org/#4d61C0B8)**
>
> Haxe is an amazing multiplatform programming language. Check it out !

```haxe
class Logger {
#if sys
  static function _log(){}
  public static macro function log( exprs : Array<haxe.macro.Expr> ){
		return macro @:privateAccess Logger._log();
  }
#else
#end
}

```

Perhaps the #if sys block should not be around the “macro” function?

---

<div class="post-metadata">

### Author: ![filt3rek](https://community.haxe.org/user_avatar/community.haxe.org/filt3rek/32/2613_2.png) [@filt3rek](https://community.haxe.org/u/filt3rek)
#### Post date: [February 8, 2022, 12:52am UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/9 "2022-02-08T00:52:47Z")

</div>

So if I understand well, `sys` is defined inside the macro function and here we must use ̀Context.defined()` to get the real output target, and outside the macro function, the compilation directive just follow the output target right ?  
I don’t know if my explanation is understandable…

---

<div class="post-metadata">

### Author: ![tobil4sk](https://community.haxe.org/user_avatar/community.haxe.org/tobil4sk/32/1458_2.png) [@tobil4sk](https://community.haxe.org/u/tobil4sk)
#### Post date: [February 8, 2022, 10:47pm UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/10 "2022-02-08T22:47:27Z")

</div>

Yes, `Context.defined()` gives values for the actual target (so Javascript in this case).

As I understand it, when compiling files for the macro, then #if blocks will use the values for the macro target. However, after this, the #if blocks are evaluated again independently with the values of the “real” target for final compilation. (For reasons like this, it is better to completely separate macro and non-macro code into different files to avoid confusion)

Additionally, it would seem that any macro function has to be defined both in the macro context and the final context, so if we have:

```haxe
public static macro function log( exprs : Array<haxe.macro.Expr> ) { ... }

```

this function must be accessible in both the macro and javascript contexts. (so for example, it cannot be behind a `#if sys` block, where it would only be visible in the macro context)

---

<div class="post-metadata">

### Author: ![filt3rek](https://community.haxe.org/user_avatar/community.haxe.org/filt3rek/32/2613_2.png) [@filt3rek](https://community.haxe.org/u/filt3rek)
#### Post date: [February 9, 2022, 8:06am UTC](https://community.haxe.org/t/compilation-directives-priority-and-macro/3452/11 "2022-02-09T08:06:01Z")

</div>

Yes it’s something like that, but IMHO, functions with “macro” keyword have only to be defined in no-macro context if not they are just not seen and then when we are inside this function it’s macro context that “begins”
