Embedding data files at compile time

I’ve got some external data that I was hoping to embed in my Application as a compile time string.
I got it working by making a module attribute (evaluated at compile time) that does a File.read of the priv directory.

My issue is that it seems to be difficult to get the compiler to notice changes to this file as even mix compile --force doesn’t always update things.

Any other techniques for this that might work?

Thanks!

1 Like

Have you tried using the @external_resource module attribute?

3 Likes

Awesome thanks! I will check that out! :slight_smile:

1 Like

You can even watch a whole folder if you’d like. There’s a good example of that in the docs:

https://hexdocs.pm/mix/1.14/Mix.Tasks.Compile.Elixir.html#module-__mix_recompile__-0

3 Likes

In case it helps anyone else, I ended up using the directory watcher version to automatically embed a directory of lua scripts into my app like this:

defmodule MyApp.Examples do
  paths = Path.join([:code.priv_dir(:my_app), "lua", "*.lua"]) |> Path.wildcard()
  @paths_hash :erlang.md5(paths)


  scripts_by_name =
    for path <- paths do
    @external_resource path
    script = File.read!(path)
    name = Path.basename(path)
    {name, script}
  end
  |> Map.new()

  @scripts_by_name scripts_by_name

  def get(name), do: @scripts_by_name[name]

  def __mix_recompile__?() do
      Path.join([:code.priv_dir(:my_app), "lua", "*.lua"]) |> Path.wildcard() |> :erlang.md5() != @paths_hash
  end
end
4 Likes