addrummond

addrummond

Is it possible to detect if code is executing at compile time?

Can Elixir code detect whether it is executing at compile time? I would like to write something like the following macro:

defmacro foo() do
  quote do
    if is_compile_time? do
      one_thing()
    else
      another_thing()
    end
  end
end

It’s presumably obvious how the code that the macro expands to can execute at runtime. It can execute at compile time in a scenario such as the following:

defmodule Bar do
  def bar() do
    foo() # invoke the macro
  end
end

defmodule Amp do
  @attr Bar.bar() # code that 'foo' macro expands to is executed at compile time
end

I have tried examining __ENV__, but unless I’m missing something, it offers no reliable diagnostic for compile time vs. runtime. I wonder if there is any other way. For anyone familiar with Common Lisp, I suppose I am looking for something that works a bit like eval-when.

By the way, I am asking largely out of curiosity. I’m aware that in general one should not need to perform such a check :slight_smile:

Marked As Solved

hst337

hst337

compiling? = is_list(Process.get(:elixir_module_binaries))
But as @hauleth pointed out, difference between runtime and compile time is ephemeral. Compilation can happen in runtime, and anything can be called during compilation

Also Liked

kip

kip

ex_cldr Core Team

I use the following code in ex_cldr to detect if Elixir is compiling. The mechanism changed from Elixir 1.11, hence the conditional check:

  def compiling? do
    # TODO: When we depend on Elixir v1.11+ only, remove function_exported and elixir_compiler_pid
    process_alive?(:can_await_module_compilation?) ||
      process_alive?(:elixir_compiler_pid)
  end

  defp process_alive?(:can_await_module_compilation?) do
    Code.ensure_loaded?(Code) &&
      function_exported?(Code, :can_await_module_compilation?, 0) &&
      apply(Code, :can_await_module_compilation?, [])
  end

  defp process_alive?(name) do
    case Process.get(name) do
      nil -> false
      pid when is_pid(pid) -> true
    end
  end
josevalim

josevalim

Creator of Elixir

Please do not do this:

This is relying on internal compiler behaviour. Use the suggestions from @kip instead, which uses public APIs. :slight_smile:

dimitarvp

dimitarvp

That distinction doesn’t change anything he said though, you can still generate a module at runtime and compile it and for it what is happening will be “compile time”. You really should revise what you really want to achieve with this and consider other ways, this can very easily bite you in the rear in the most inopportune moment in the future.

hauleth

hauleth

The problem is that it is pretty hard to differentiate between “compile time” and “run time” as “compile time” is “run time with saving created modules to .beam files”.

You can check __CALLER__.function to detect whether macro was called within function body or outside of it.

mudasobwa

mudasobwa

Creator of Cure

BEAM does not create files on its own, Elixir and Erlang compiler do if run under some special conditions (e. g. from the command line.)

If you are compiling files manually, you are responsible for persisting them, if you wish. Here I do it, because Common Test needs tests to be available as beams.

Basically, it’s

{module, code} = Code.compile_file(file)
beam = Path.join(Path.dirname(file), to_string(module) <> ".beam")
:ok = File.write!(Path.join(Path.dirname(file), to_string(module) <> ".beam"), code)

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
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
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New

We're in Beta

About us Mission Statement