How to get root project directory from a library

Hey,
I’m writing a library, in my library I want to get the root project(the actual project using my library) directory path.
I tried, File.cwd!() but I’m getting the root dir of the library.

Few things to know.
I’m calling File.cwd!() outside a function.
I’m using Mix dependency path to bring my library into the project (for testing purposes).

One more thing.
Using File.cwd!() inside a macro will get me the project path. but I don’t want to use a macro :slight_smile:

Thanks
Mazz

That implies that your call File.cwd!() is executed at compile time. That explains why you see the dependency directory.

In other words:

defmodule MyLibrary do
  @cwd File.cwd! # this is executed at compile time

  def foo do
    IO.puts("cwd at compile time: #{@cwd}")
    IO.puts("cwd at runtime: #{File.cwd!}")
  end
end
1 Like

What is “root project dir”? The source folder? It might not exist in a later phase of the applications life cycle…

Also the cwd might be anything. Totally depends on from which folder mix was called when compiling or from where release was actually started…

Under some very rare circumstances you do not even have a CWD.

Please be aware of those culprits, and try to avoid the usage in a compile time environment… Especially as those paths might not exist anymore at runtime…

4 Likes

From what you have written I assume that you want to distribute some file with your library/application and then read it in the user runtime. This is why there is priv/ directory and :code.priv_dir/1.

3 Likes

Forgot to write my use case :grimacing:.
I’m trying to read some Markdown files from the user project for example, read this file /lib/pages/index.md and compile it. But I don’t want the user to write some module to use a library module. (Don’t know if it’s make sense)

@NobbZ root dir for me is where the mix file is.

Compiling non-elixir stuff can be done with custom compilers. To my knowledge, you can safely use File.cwd from there.

Don’t read randomly from your users dir. Ask them to explicitely specify where to serach.

1 Like

Thanks @mat-hek I will take a look at it.

@NobbZ My solution right now is to read a config key with the value Path.expand("./") to get the absolute path.

Is that ok?

That seams to be okay, though I wouldn’t expand, but just rely on the fact that its correctly specified as a relative or absolute path.

Also I do hope, that you do not persist the users files into your modules, this will cause a lot of headache and not changing behaviour on change of the source files…

If it’s note the absolute path it will point to the relative path of the library.

What do you mean by persist the file into my module?

You said you compile the found file. To what? Do you generate new modules from it? Files? Something else?

I generate an HTML file inside the priv directory.

Then you can just ignore my words of warning.

Still I hope you do it in a way that ensures recompilation on change of the source files.

To be honest, implementing a “compiler” that can be added to the key with the same name in the project description is probably your best option.

3 Likes

Thank you.