david

david

Specifying paths for static library assets used in macro (compile vs runtime && `/app/_build/prod/lib/` vs `/app/lib`)

TL;DR: How to ensure that file paths specified in a library when compiled in a macro reflect correct paths at release. /app/_build/prod/lib/library_name/priv/ when compiled vs /app/lib/library_name-version/priv/ when released.

Hi there,
Working on an avatar generation library:
Avatarex - Generate unique, reproducible avatars from hashed strings (*hat tip to @Eiji for help in the rewrite)

I’m a bit confused as to how to ensure that the image asset paths which are being generated at compile time, as part of a using macro, reflect where they’ll actually be at runtime.
So paths that are generated at compile time:
:avatarex |> :code.priv_dir() |> Path.join("sets") |> ...
corresponds to locations that exist during compilation:
/app/_build/prod/lib/avatarex/priv/sets/birdy/body/body_1.png
but are different from the paths that are used at runtime:
/app/lib/avatarex-0.2.0/priv/sets/birdy/body/body_1.png

I do need to be able to File.ls the /app/_build/prod/lib/avatarex/priv/sets/birdy/body/ path at compile time to then generate the list of available images in that directory, but then again at runtime they need to look in /app/lib/....

I thought this may also be related to me not understanding how /app/_build/prod/lib becomes /app/lib upon release.

Thanks,
David

Resources I’ve Reviewed:

Marked As Solved

Eiji

Eiji

Oh, I see the point. Since paths are not guaranteed to be the same across different environments and releases we were using :code.priv_dir/1 to get a proper path. However we are doing it at compile time in prod environment and paths were changed in release:thinking:

You should do 2 things:

  1. Rewrite the current compile-time paths to be relative to priv directory. Since contents of priv directory does not changes we can safely call File.ls!/1 on them.
  2. In runtime we need to rewrite relative urls to absolute urls
prod_priv_path = :code.priv_dir(:avatarex)
dir_path = Path.join(~w[sets body])
prod_full_path = Path.join(prod_priv_path, dir_path)
# in struct we store `dir_path`
# for File.ls!/1 we use prod_full_path

def construct(…) do
  release_priv_path = :code.priv_dir(:avatarex)
  images = Enum.map(images, fn {layer, path} -> {layer, Path.join(release_priv_dir, path)} end)
  # …
end

The problem is that images is not the only variable which stores path. You would need to remember when you would update the code.

Let me know if you have some questions.

Where Next?

Popular in Questions Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

Other popular topics Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement