Is it possible to include resource files when packaging my project using Mix/escript?

erlang
mix

#1

Hi everyone,

I was thinking of resources like images, XML files or documents in other text formats. Is there something similar to the resources folder in Java (“src/main/resources”)? The goal would be to add files to my package that can be accessed from code on runtime.

Or is this somehow a very un-Elixir-y way of thinking? Elixir is my first functional language - so what would be the “right” way to do it?

Cheers,
smon


Current file (module) path
Bundling binaries with releases
#2

Hey!

That is precisely what the /priv folder is for in your project root. It’ll get packaged up along with your application when you build a release. If you have a data.xml file in your /priv directory you can get to it in your code by doing

Path.join(:code.priv_dir(:my_app), "data.xml")

#3

Awesome!

Thank you very much. priv is an abbreviation of what exactly? “private”? Or am I missing some more obvious term it stands for?

Cheers,
smon


#4

Erlang OTP Design Principles User’s Guide at Directory Structure

priv - Used for application specific files. For example, C executables are placed here. The function code:priv_dir/1 should be used to access this directory.

Per Jose:

“priv” is like “OTP” where its name made sense at the beginning but today it has grown beyond that. All it matters now is that we put in the “priv” directory any artifact that you need in production alongside your code.

Elixir Lang Talk - What is Priv?


#5

I am unable to open a File.stream! for the file in my /priv folder when running my escript-build. Do I have to fallback to Erlang? Using a path generated the way you described only works when starting the application in iex.

Edit

From the Mix.Tasks.Escript.Build:

Note: escripts do not support projects and dependencies
that need to store or read artifacts from the priv directory.

Damn…


#6

I have it on good authority that http://elixir-lang.org/docs/master/elixir/Application.html#app_dir/1 is an option here.


#7

Edited my previous reply in light of new information.


#8

I am not quite sure if I understood correctly.

Path.join(:code.priv_dir(:my_app), "data.xml")

produced the path /path/to/my_app/my_app/priv/data.xml, where the first my_app corresponds the escript build file.

By replacing :code.priv_dir(:my_app) with app_dir(:my_app), I can get rid off the priv sub-folder, but that still does not allow me to open a valid file stream.


#9

Hi @smon and @benwilson512, I’d also like to know if there are options to access the /priv folder for a command line utility built with escript. Please update if you’ve found anything. Thank you in advance!


#10

Hey!

Sorry I did not check the forum for quite some time. The answer seems to be the thing I already mentioned:

I basically gave up on the idea of adding the file to the build file.


#11

To confirm: although priv is the appropriate place, we can’t load files from priv inside escripts. What I usually do is to load the file at compilation time and store it as a module attribute:

@external_resource "priv/foo/bar"
@bar_contents File.read! "priv/foo/bar"
def bar_contents, do: @bar_contents

#12

Thanks for the replies @smon and @josevalim! :grinning: