Mojoler.Build (mojoler v0.1.0)

Copy Markdown View Source

Decides whether a native build is required and publishes .so files by rename.

The rename is the publication step. A failed mojo build never reaches it, so the previous libraries stay in place.

Summary

Types

What the compiler should do with the current fingerprint and load state.

Functions

Returns whether any name in names was marked loaded.

Returns the sha256 fingerprint of the native inputs.

Returns whether dir contains every product library.

Moves lib*.so from staging to dest.

Returns the directory that contains this project's mix.exs.

Types

decision()

@type decision() :: :noop | :loaded | :build

What the compiler should do with the current fingerprint and load state.

  • :noop — the fingerprint matches and every library file is present
  • :loaded — a rebuild is required, but this VM has already mapped a library
  • :build — compile into a staging directory, then publish

Examples

iex> Mojoler.Build.decide(true, true, true)
:noop

Functions

any_loaded?(names)

@spec any_loaded?([Mojoler.Nif.library()]) :: boolean()

Returns whether any name in names was marked loaded.

names are basenames such as "libpoc.so". An empty list is false.

Examples

iex> Mojoler.Build.any_loaded?([])
false
iex> Mojoler.Nif.mark!("doctest-any-loaded")
:ok
iex> Mojoler.Build.any_loaded?(["doctest-any-loaded.so"])
true

decide(fingerprint_match?, loaded?, outputs_exist?)

@spec decide(boolean(), boolean(), boolean()) :: decision()

Chooses the next compile step.

fingerprint_match? is true when priv/native/FINGERPRINT equals the current fingerprint. loaded? is true when this VM has marked any product library. outputs_exist? is true when every expected .so is a regular file. None of the arguments is optional.

Examples

iex> Mojoler.Build.decide(true, true, true)
:noop

iex> Mojoler.Build.decide(false, true, true)
:loaded

iex> Mojoler.Build.decide(false, false, false)
:build

iex> Mojoler.Build.decide(true, false, false)
:build

fingerprint(root)

@spec fingerprint(Path.t()) :: String.t()

Returns the sha256 fingerprint of the native inputs.

root is the project directory. The script hashes Mojo sources, the ABI tools, the build scripts, erl_nif.h, the Mojo version, the compiler triple, and the link flags. There is no optional argument.

Returns

A 64-character hex string.

Examples

iex> fp = Mojoler.Build.fingerprint(Mojoler.Build.root())
iex> byte_size(fp) == 64
true

outputs_present?(dir)

@spec outputs_present?(Path.t()) :: boolean()

Returns whether dir contains every product library.

The expected names are libpoc.so, libtwice.so, libterm.so, libown.so, libsched.so, libdsl_arith.so, libdsl_bytes.so, and libdsl_box.so.

Examples

iex> Mojoler.Build.outputs_present?(Path.join(Mojoler.Build.root(), "priv/native"))
true

publish!(staging, dest)

@spec publish!(Path.t(), Path.t()) :: :ok | {:error, String.t()}

Moves lib*.so from staging to dest.

staging and dest are directories. When this VM has already loaded one of those libraries, nothing is renamed.

Also copies link-inputs.txt when that file is present in staging.

Returns

  • :ok after the renames
  • {:error, message} when a listed library is already loaded

File.rename!/2 raises File.Error when the rename itself fails.

Examples

iex> parent = Path.join(System.tmp_dir!(), "mojoler-doctest-34")
iex> staging = Path.join(parent, "staging")
iex> dest = Path.join(parent, "dest")
iex> File.mkdir_p!(staging)
:ok
iex> Mojoler.Build.publish!(staging, dest)
:ok
iex> is_list(File.rm_rf!(parent))
true

root()

@spec root() :: Path.t()

Returns the directory that contains this project's mix.exs.

Examples

iex> File.regular?(Path.join(Mojoler.Build.root(), "mix.exs"))
true