55 lines
1.6 KiB
Elixir
55 lines
1.6 KiB
Elixir
|
|
defmodule CCPrecompiler.UniversalBinary do
|
||
|
|
@moduledoc """
|
||
|
|
Build a universal binary on macOS
|
||
|
|
|
||
|
|
## Example
|
||
|
|
|
||
|
|
"macos-universal" => {
|
||
|
|
:script, "", {CCPrecompiler.UniversalBinary, []}
|
||
|
|
}
|
||
|
|
|
||
|
|
"""
|
||
|
|
|
||
|
|
@behaviour CCPrecompiler.CompilationScript
|
||
|
|
|
||
|
|
@impl CCPrecompiler.CompilationScript
|
||
|
|
def compile(_app, _version, _nif_version, _target, args, _custom_args) do
|
||
|
|
config = Mix.Project.config()
|
||
|
|
app_priv = Path.join(Mix.Project.app_path(config), "priv")
|
||
|
|
make_precompiler_filename = config[:make_precompiler_filename] || "nif"
|
||
|
|
nif_file = "#{make_precompiler_filename}.so"
|
||
|
|
|
||
|
|
compiled_bin = Path.join(app_priv, nif_file)
|
||
|
|
x86_64_bin = Path.join(app_priv, "#{make_precompiler_filename}_x86_64.so")
|
||
|
|
aarch64_bin = Path.join(app_priv, "#{make_precompiler_filename}_aarch64.so")
|
||
|
|
|
||
|
|
File.rm(compiled_bin)
|
||
|
|
|
||
|
|
# first we compile `x86_64-apple-darwin`
|
||
|
|
:ok = System.put_env("CC", "gcc -arch x86_64")
|
||
|
|
System.put_env("CXX", "gcc -arch x86_64")
|
||
|
|
System.put_env("CPP", "g++ -arch x86_64")
|
||
|
|
ElixirMake.Compiler.compile(args)
|
||
|
|
File.rename!(compiled_bin, x86_64_bin)
|
||
|
|
|
||
|
|
# then we compile `aarch64-apple-darwin`
|
||
|
|
System.put_env("CC", "gcc -arch arm64")
|
||
|
|
System.put_env("CXX", "gcc -arch arm64")
|
||
|
|
System.put_env("CPP", "g++ -arch arm64")
|
||
|
|
ElixirMake.Compiler.compile(args)
|
||
|
|
File.rename!(compiled_bin, aarch64_bin)
|
||
|
|
|
||
|
|
{_, exit_status} =
|
||
|
|
System.cmd("lipo", ["-create", "-output", compiled_bin, x86_64_bin, aarch64_bin])
|
||
|
|
|
||
|
|
File.rm!(x86_64_bin)
|
||
|
|
File.rm!(aarch64_bin)
|
||
|
|
|
||
|
|
if exit_status == 0 do
|
||
|
|
:ok
|
||
|
|
else
|
||
|
|
Mix.raise("Failed to create universal binary")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|