#Compile time configuration of Elixir libraries

1 messages · Page 1 of 1 (latest)

calm swallow
#

I have achieved a horrible kludge. I have compile time configured a setting into the Elixir MIME library.

src/config/config.ex

defmodule MyConfig do
  # Path to package's directory
  project_dir = Path.expand("../../../../../packages/mime", __DIR__)
  # Path to Elixir's ebin directory
  ebins_dir = Path.expand("../../../elixir/ebin", __DIR__)
  # Path to custom configuration file
  custom_config = Path.expand("../../priv/config.erl", __DIR__)

  System.cmd(
    System.find_executable("elixir"),
    [
      # I copied most of these from https://github.com/gleam-lang/gleam/blob/abdf034c4b694127402b5340e149006bb414b99e/compiler-core/src/build/project_compiler.rs#L483
      "-pa",
      ebins_dir,
      "-S",
      "mix",
      "compile",
      "--force",
      "--no-deps-check",
      "--no-load-deps",
      "--no-protocol-consolidation",

      # Handy flag: pass custom configuration to compilation
      "--erl-config",
      custom_config
    ],
    env: [{"MIX_ENV", "prod"}],
    cd: project_dir
  )
end

priv/config.erl

{mime, [{types, #{<<"a">> => [<<"b">>]}}]}.

% Corresponds to:
% config :mime, :types, %{"a" => ["b"]}

Now we can test it:

➜  elixir_config_test git:(trunk) ✗ gleam build
Downloading packages
 Downloaded 3 packages in 0.01s
  Compiling gleam_stdlib
  Compiling gleeunit
  Compiling mime
  Compiling elixir_config_test
   Compiled in 2.19s
➜  elixir_config_test git:(trunk) ✗ gleam shell
   Compiled in 0.01s
    Running Erlang shell
Erlang/OTP 27 [erts-15.0] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]

Eshell V15.0 (press Ctrl+G to abort, type help(). for help)
1> 'Elixir.MIME':compiled_custom_types().
#{<<97>> => [<<98>>]}

Hooray!

Downside: MIME is compiled twice, first by Gleam and then by us.

CC @sick sequoia, thanks for the nerdsnipe. 🙂

#

This kludge is too good to not be shared, gotta write about it on my blog

calm swallow
#

looking at the code, I guess this part

  # Path to Elixir's ebin directory
  ebins_dir = Path.expand("../../../elixir/ebin", __DIR__)

should actually be

  # Path to all ebin directories
  ebins_dir = Path.expand("../../../*/ebin", __DIR__)
calm swallow
#

I think this --erl-config could be used by Gleam to compile the config into deps directly 🙂

#

Also a module is not needed in the .ex file, can just put everything on top level. I'll write a blog post with the updated details

sick sequoia
#

good lord

#

am I understanding right that it's a macro that shells out to the elixir compiler and recompiles the project with mix, including the custom config?

#

ah not the whole project, just the MIME dependency, as each package has it's own ebins dir I suppose?

calm swallow
#

Yeah you'd have to make it into a function to run for all the dependencies you have

#

It's not a macro really, just Elixir code. Compiling Elixir = running Elixir