thojanssens1
defmodule Bar do
@after_compile __MODULE__
defmacro __before_compile__(_env) do
IO.inspect("#{__MODULE__}.__before_compile__")
end
def __after_compile__(_env, _bytecode) do
IO.inspect("#{__MODULE__}.__after_compile__")
end
end
defmodule Foo do
require Bar
@before_compile Bar
@after_compile __MODULE__
def __after_compile__(_env, _bytecode) do
IO.inspect("#{__MODULE__}.__after_compile__")
end
end
Will print:
“Elixir.Bar.after_compile”
“Elixir.Bar.before_compile”
“Elixir.Foo.after_compile”
[Bar, Foo]
Why is after_compile called before before_compile for the Bar module?
Trending in Questions
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
Hello,
I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind.
However, when I launch mix phx.server, I get an error...
New
Hi everyone,
I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding.
I sta...
New
I’m working on a small exercise involving update_in/3, and I came up with this solution:
data = %{
name: "Periodic Table",
category:...
New
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication):
toke...
New
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New
** (ArgumentError) expected :max_attempts to be a positive integer, got: {:@, [line: 10, column: 19], [{:max_attempts, [line: 10, column:...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex











Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
ityonemo
Because you are compiling Foo after Bar.
NobbZ
Baris compiled, you see its output ofBar.__after_compile__Foois going to get compiled, it callsBar.__before_compile__, you see the outputBar.__before_compile__, because__MODULE__isBarin that context. You wan’t to checkenv.modto see the callers module.Foogets actuially compiled, its after compile gets called and you see itsFoo.__after_compile__.thojanssens1
Thank you! Can I ask something more as you seem to have good knowledge of macros?
Why does it say Baz is already compiled, when I’m executing
__using__? As to my understanding,__using__is run on compile time, so the file should not be compiled yet?LostKobrakai
Baz is already compiled when used in MyApp. MyApp is not yet compiled. In macros it’s important to be aware if you‘re working in the context of the macro (
__MODULE__is the module with the macro definition) or if you‘re working on the AST of the macros result, which is effectively becoming part of the module calling the macro (__MODULE__refers to the module calling the macro).thojanssens1
So if I understand right, if a module A calls
__using__of a module B, then__using__macro of B will be executed after B is compiled.Then if I try to register an attribute on another module:
But again:
So Bar is already compiled, but how can I tell that it should not compile before registering the attributes in the
__using__macro of Baz?I tried
require MyAppintoBar, which I thought means “wait forMyAppto be compiled before the compilation ofBar”, then I am sure thatBarwill not be compiled yet, but obviously got it all wrong again.LostKobrakai
In your example there’s no compile time relationship between MyApp(/Baz) and Bar, so they’re compiled in parallel. I’m not sure though why exactly it doesn’t work with
require MyAppadded.But I guess more important would be to know why you want to do that. Why should calling
use Bazregister a module attribute on a third module?thojanssens1
These were indeed all examples with Foo/Bar/Baz placeholders because I did not want to bloat the problem with application-specific details. But here is what I try to do:
I want my library to receive options at compile time, e.g. the user can pass option
otp_app: :my_apptoTheLibrarysomehow. Often this is done withusebut I don’t need to inject anything in a user’s module.Then in some module of the library, I need to use those options in a
__before_compile__/1macro (because based on those options, I want to generate some functions into that module in the library).I could not find a way for
__before_compile__to get access to the option; keep having the blah-blah-blah-already-compiled.I do not know what is the best way for the user to pass the option to the library.
LostKobrakai
As the option is already compile time only you can just as easily use the app env for configuration and the value will be available everywhere without intruducing compile time dependencies just to pass along configuration values.
NobbZ
Again, you need to look into the callers environment. Macros get passed
__CALLER__as a magic variable, so you probably want toModule.register_attribute(__CALLER__.mod, :attr, [])or in this case even more appropriate, as you do not make it accumulating or persistent:Or instead of the empty list use any other default value you prefer.
Beeing aware of the current context you are in is important for macros.
Perhaps give Metaprogramming Elixir by @chrismccord a read? I only skimmed about the first quarter of it, but it helped me to understand macros enough for my usecase.
ityonemo
compile-time output:
If it’s clearer, this is effectively equivalent: