Current section

Files

Jump to
double_down lib double_down facade compile_helper.ex
Raw

lib/double_down/facade/compile_helper.ex

defmodule DoubleDown.Facade.CompileHelper do
@moduledoc false
# Helper for ensuring behaviour modules are compiled and their .beam
# files are on disk before BehaviourFacade facades that depend on them.
#
# This is only needed when the behaviour and facade are compiled in the
# same batch (e.g. both in test/support/). In normal usage the behaviour
# would be in lib/ or a dependency, compiled in a prior batch.
@doc false
@spec ensure_compiled!(Path.t()) :: :ok
def ensure_compiled!(source_path) do
# Compile the file — returns [{module, binary}, ...]
compiled = Code.compile_file(source_path)
# Write each beam binary to the build output directory so
# Code.Typespec.fetch_callbacks/1 can find them.
for {module, binary} <- compiled do
beam_path = beam_output_path(module)
File.mkdir_p!(Path.dirname(beam_path))
File.write!(beam_path, binary)
# Load the binary so the code server also has it
:code.load_binary(module, String.to_charlist(beam_path), binary)
end
:ok
end
defp beam_output_path(module) do
# Use the first code path entry that looks like a build directory
ebin_dir =
:code.get_path()
|> Enum.map(&to_string/1)
|> Enum.find(&String.contains?(&1, "_build"))
if ebin_dir do
Path.join(ebin_dir, "#{module}.beam")
else
# Fallback: write to a temp directory and add it to the code path
tmp = Path.join(System.tmp_dir!(), "double_down_beams")
File.mkdir_p!(tmp)
:code.add_patha(String.to_charlist(tmp))
Path.join(tmp, "#{module}.beam")
end
end
end