I found a solution to this, but it is only viable within specific parameters (and apologies in advance if I’m misrepresenting any of this due to my limited understanding).
To clarify, the application itself did not REQUIRE compile-time configuration: it is completely functional when this configuration is supplied at run-time. The motivation here came from the desire to expose the application configuration in the generated documentation. I wanted something like this:
@moduledoc """
Here is a nice chart:
#{ Application.get_env(:my_app, :stuff) |> ChartGenerator() }
"""
The trick here is that there is some wiggle room between build-time and compile-time. The config/config.exs
is read during build-time, and per the docs, your dependencies and its structs are not available during build-time. However, it turns out that they are available shortly thereafter (i.e. during compile-time). Instead of storing this information inside of the Application
config, I instead stored it in its own .exs
file – I put it in the config/
directory so it would get included with builds and I accessed it using Code.eval_file/2
I could include this “config”-like stuff at runtime and pass it as an argument where it needed to go (instead of Application.get_env(:my_app, :stuff)
):
def start(_type, _args) do
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(
[
{MyDep, [stuff: Code.eval_file("config/stuff.exs") |> elem(0)]}
]
opts)
end
Likewise, I could also read it inside my @moduledoc
blocks where I wanted the documentation to reflect the up-to-date information from that file:
@moduledoc """
Here is a nice chart:
#{ Code.eval_file("config/stuff.exs") |> elem(0) |> ChartGenerator() }
"""
Using Application.compile_env/3
wouldn’t work because the dependencies weren’t compiled yet (the dep’s structs were not yet available). Application.get_env/3
returned nil
inside a @moduledoc
tag (I guess because the runtime.exs
hadn’t been parsed yet?).
So the lesson is that there is a bit more subtlety in how the app is compiled… maybe config/config.exs
should instead be named config/build.exs
and Application.compile_env/3
should be named Application.build_env/3
? Or maybe I am still missing pieces to how this all fits together.