PJUllrich
In my mix.exs I used to be able to call other Modules in order to fetch some configurations for my application-env configuration. Somehow this is not possible anymore since a few weeks (or the update to Elixir 1.11 maybe)
Here is an example of calling a module MyApp.Config.application_env() from inside my mix.exs file:
./mix.exs
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :my_app
version: "0.2.0",
elixir: "~> 1.5",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps(),
test_paths: ["test", "lib"]
]
end
def application do
[
mod: {MyApp.Application, []},
extra_applications: [:logger, :runtime_tools],
env: MyApp.Config.application_env()
]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
# deps and aliases ....
./lib/config.ex
defmodule MyApp.Config do
def application_env do
[my_config: "foo", another_config: "bar"]
end
end
Since the update to Elixir 1.11 I cannot call this module anymore since the compiler complains like this:
** (UndefinedFunctionError) function MyApp.Config.application_env/0 is undefined (module MyApp.Config is not available)
MyApp.Config.application_env()
mix.exs:28: MyApp.MixProject.application/0
(mix 1.11.0) lib/mix/tasks/compile.app.ex:382: Mix.Tasks.Compile.App.project_apps/1
(mix 1.11.0) lib/mix/tasks/compile.all.ex:97: Mix.Tasks.Compile.All.load_apps/2
(mix 1.11.0) lib/mix/tasks/compile.all.ex:24: Mix.Tasks.Compile.All.run/1
(mix 1.11.0) lib/mix/task.ex:394: Mix.Task.run_task/3
(mix 1.11.0) lib/mix/tasks/compile.ex:119: Mix.Tasks.Compile.run/1
(mix 1.11.0) lib/mix/task.ex:394: Mix.Task.run_task/3
I tried require-ing and import-ing the MyApp.Config module, but nothing helped. The config.ex file is compiled and put into the _build/dev/ebin folder, but somehow it is not available during compile-time. I also tried to set it to an module attribute like this: @config MyApp.Config, but even this didn’t help.
I have the feeling that it is related to the latest Compilation time improvements in 1.11 which states:
This change allows us to mark
imports andrequires as “exports dependencies” instead of “compile time” dependencies
Does somebody know how to make my MyApp.Config module available at compile-time again?
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #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
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
NobbZ
When
mix.exsis evaluated your application is not available, as your application is built using the evaluation result of themix.exs.So by requiring your applications code within
mix.exsyou are creating a circular dependency that your application needs to be compiled in order to get compiled.PJUllrich
Hmm, that makes sense, but now I’m wondering why it worked before
PJUllrich
On another node: How can I then extract logic to set the
applicationenvoption to another module/script/config file? I need to set default values for many application environment variables and don’t want to do this in every application which uses this library. So, I cannot use theconfig/...files since these are overwritten by the implementing applications, I believe. The advice in this thread was to use theapplicationenvoption inmix.exs, which is why I use above setup. But I also don’t want to have 30defpfunctions in mymix.exsand therefore extracting them to another module. Do you know a better/different way of setting a multitude of default values in a library maybe?NobbZ
Try to refactor your library to not need to rely on those defaults…
If you insist on providing them, you could have a an extra file in the project root defining them and load it via
Code.eval_file/2.PJUllrich
Thanks for the hint!
I used Code.compile_file/2 now in order to compile the
MyApp.Config-module before setting theapplicationenvoption like this:hauleth
Out of interest - why? Why not other way around?
PJUllrich
At work, we have ~5 Phoenix micro-services which all share some common libraries like a Neuron API-Client or a Cachex request handler. These libraries (Neuron, Cachex) need to be configured, both locally and on our servers, for the
test,dev, andprodenvironments. We don’t want to copy&paste the same configuration to all our micro-services, which is why we bundled the libraries and their configuration in a library of our own. Since theconfig.exsof a library is ignored when the library is used in a project like one of our micro-services, we needed to put the shared configurations in theapplicationenvoption of our own library. We have ~30 private functions which return a configuration for a “sub-library” so we didn’t want to put all these functions into ourmix.exs, but in a separateConfig-Module.If you know a way to refactor this nicely, I would much appreciate to hear about it
hauleth
config.exsis ignored, but the:envin application is not. So if you have application that is using that, then you can configure it there. In general, it depends, as there is few possible solutions, depending on use case.