mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-01-29 02:09:30 +08:00
Fix vendoring OTP for Windows app (#1039)
This commit is contained in:
parent
8bb8160605
commit
fe53c6a852
2 changed files with 66 additions and 75 deletions
|
@ -30,9 +30,9 @@ defmodule AppBuilder.Windows do
|
|||
app_icon_path = Path.join(tmp_dir, "app_icon.ico")
|
||||
copy_image(logo_path, app_icon_path)
|
||||
|
||||
erts_dir = Path.join([tmp_dir, "rel", "erts-#{:erlang.system_info(:version)}"])
|
||||
erl_exe = Path.join([tmp_dir, "rel", "erts-#{release.erts_version}", "bin", "erl.exe"])
|
||||
rcedit_path = ensure_rcedit()
|
||||
cmd!(rcedit_path, ["--set-icon", app_icon_path, Path.join([erts_dir, "bin", "erl.exe"])])
|
||||
cmd!(rcedit_path, ["--set-icon", app_icon_path, erl_exe])
|
||||
|
||||
File.write!(Path.join(tmp_dir, "#{app_name}.vbs"), launcher_vbs(release, options))
|
||||
nsi_path = Path.join(tmp_dir, "#{app_name}.nsi")
|
||||
|
@ -157,7 +157,7 @@ defmodule AppBuilder.Windows do
|
|||
' It's ok for either to fail because we run them asynchronously.
|
||||
|
||||
Set env = shell.Environment("Process")
|
||||
env("PATH") = ".\rel\erts-<%= :erlang.system_info(:version) %>\bin;" & env("PATH")
|
||||
env("PATH") = ".\rel\erts-<%= release.erts_version %>\bin;" & env("PATH")
|
||||
|
||||
' > bin/release rpc "mod.windows_connected(url)"
|
||||
'
|
||||
|
|
|
@ -7,86 +7,49 @@ defmodule Standalone do
|
|||
"""
|
||||
@spec copy_otp(Mix.Release.t(), otp_version :: String.t()) :: Mix.Release.t()
|
||||
def copy_otp(release, otp_version) do
|
||||
expected_otp_version = otp_version()
|
||||
ensure_otp_version(otp_version)
|
||||
{erts_source, otp_bin_dir, otp_lib_dir} = otp_dirs()
|
||||
|
||||
if otp_version != expected_otp_version do
|
||||
raise "expected OTP #{expected_otp_version}, got: #{otp_version}"
|
||||
end
|
||||
# 1. copy erts/bin
|
||||
release_erts_bin_dir = Path.join(release.path, "erts-#{release.erts_version}/bin")
|
||||
File.mkdir_p!(release_erts_bin_dir)
|
||||
|
||||
{erts_source, erts_bin_dir, erts_lib_dir, _erts_version} = erts_data()
|
||||
cp_r!(Path.join(erts_source, "bin"), release_erts_bin_dir)
|
||||
|
||||
erts_destination_source = Path.join(release.path, "vendor/bin")
|
||||
File.mkdir_p!(erts_destination_source)
|
||||
File.rm(Path.join(release_erts_bin_dir, "erl"))
|
||||
File.rm(Path.join(release_erts_bin_dir, "erl.ini"))
|
||||
|
||||
erts_source
|
||||
|> Path.join("bin")
|
||||
|> File.cp_r!(erts_destination_source, fn _, _ -> false end)
|
||||
File.write!(Path.join(release_erts_bin_dir, "erl"), ~S"""
|
||||
#!/bin/sh
|
||||
SELF=$(readlink "$0" || true)
|
||||
if [ -z "$SELF" ]; then SELF="$0"; fi
|
||||
BINDIR="$(cd "$(dirname "$SELF")" && pwd -P)"
|
||||
ROOTDIR="${ERL_ROOTDIR:-"$(dirname "$(dirname "$BINDIR")")"}"
|
||||
EMU=beam
|
||||
PROGNAME=$(echo "$0" | sed 's/.*\///')
|
||||
export EMU
|
||||
export ROOTDIR
|
||||
export BINDIR
|
||||
export PROGNAME
|
||||
exec "$BINDIR/erlexec" ${1+"$@"}
|
||||
""")
|
||||
|
||||
_ = File.rm(Path.join(erts_destination_source, "erl"))
|
||||
_ = File.rm(Path.join(erts_destination_source, "erl.ini"))
|
||||
make_executable(Path.join(release_erts_bin_dir, "erl"))
|
||||
|
||||
if os() == :macos do
|
||||
erts_destination_source
|
||||
|> Path.join("erl")
|
||||
|> File.write!(~S"""
|
||||
#!/bin/sh
|
||||
SELF=$(readlink "$0" || true)
|
||||
if [ -z "$SELF" ]; then SELF="$0"; fi
|
||||
BINDIR="$(cd "$(dirname "$SELF")" && pwd -P)"
|
||||
ROOTDIR="${ERL_ROOTDIR:-"$(dirname "$(dirname "$BINDIR")")"}"
|
||||
EMU=beam
|
||||
PROGNAME=$(echo "$0" | sed 's/.*\///')
|
||||
export EMU
|
||||
export ROOTDIR
|
||||
export BINDIR
|
||||
export PROGNAME
|
||||
exec "$BINDIR/erlexec" ${1+"$@"}
|
||||
""")
|
||||
# 2. copy lib
|
||||
release_lib_dir = Path.join(release.path, "lib")
|
||||
cp_r!(otp_lib_dir, release_lib_dir)
|
||||
|
||||
executable!(Path.join(erts_destination_source, "erl"))
|
||||
end
|
||||
# 3. copy boot files
|
||||
release_bin_dir = Path.join(release.path, "bin")
|
||||
|
||||
# Copy lib
|
||||
erts_destination_lib = Path.join(release.path, "lib")
|
||||
File.mkdir_p!(erts_destination_lib)
|
||||
|
||||
erts_lib_dir
|
||||
|> File.cp_r!(erts_destination_lib, fn _, _ -> false end)
|
||||
|
||||
# copy *.boot files to <resource_path>/bin
|
||||
erts_destination_bin = Path.join(release.path, "bin")
|
||||
|
||||
boot_files =
|
||||
erts_bin_dir
|
||||
|> Path.join("*.boot")
|
||||
|> Path.wildcard()
|
||||
|> Enum.map(&(String.split(&1, "/") |> List.last()))
|
||||
|
||||
File.mkdir_p!(erts_destination_bin)
|
||||
|
||||
for boot_file <- boot_files do
|
||||
erts_bin_dir |> Path.join(boot_file) |> File.cp!(Path.join(erts_destination_bin, boot_file))
|
||||
for file <- Path.wildcard(Path.join(otp_bin_dir, "*.boot")) do
|
||||
File.cp!(file, Path.join(release_bin_dir, Path.basename(file)))
|
||||
end
|
||||
|
||||
%{release | erts_source: erts_source}
|
||||
end
|
||||
|
||||
# From https://github.com/fishcakez/dialyze/blob/6698ae582c77940ee10b4babe4adeff22f1b7779/lib/mix/tasks/dialyze.ex#L168
|
||||
defp otp_version do
|
||||
major = :erlang.system_info(:otp_release) |> List.to_string()
|
||||
vsn_file = Path.join([:code.root_dir(), "releases", major, "OTP_VERSION"])
|
||||
|
||||
try do
|
||||
{:ok, contents} = File.read(vsn_file)
|
||||
String.split(contents, "\n", trim: true)
|
||||
else
|
||||
[full] -> full
|
||||
_ -> major
|
||||
catch
|
||||
:error, _ -> major
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Copies Elixir into the release.
|
||||
"""
|
||||
|
@ -104,7 +67,7 @@ defmodule Standalone do
|
|||
["elixir.bat", "elixirc.bat", "mix.bat", "iex.bat"]
|
||||
end
|
||||
|
||||
Enum.map(filenames, &executable!(Path.join(standalone_destination, "bin/#{&1}")))
|
||||
Enum.map(filenames, &make_executable(Path.join(standalone_destination, "bin/#{&1}")))
|
||||
|
||||
release
|
||||
end
|
||||
|
@ -121,11 +84,12 @@ defmodule Standalone do
|
|||
:zip.unzip(String.to_charlist(path), cwd: destination)
|
||||
end
|
||||
|
||||
defp erts_data do
|
||||
defp otp_dirs do
|
||||
version = :erlang.system_info(:version)
|
||||
root_dir = :code.root_dir()
|
||||
|
||||
{:filename.join(:code.root_dir(), 'erts-#{version}'), :filename.join(:code.root_dir(), 'bin'),
|
||||
:code.lib_dir(), version}
|
||||
{:filename.join(root_dir, 'erts-#{version}'), :filename.join(root_dir, 'bin'),
|
||||
:code.lib_dir()}
|
||||
end
|
||||
|
||||
defp fetch_body!(url) do
|
||||
|
@ -140,7 +104,7 @@ defmodule Standalone do
|
|||
end
|
||||
end
|
||||
|
||||
defp executable!(path), do: File.chmod!(path, 0o755)
|
||||
defp make_executable(path), do: File.chmod!(path, 0o755)
|
||||
|
||||
defp os() do
|
||||
case :os.type() do
|
||||
|
@ -148,4 +112,31 @@ defmodule Standalone do
|
|||
{:win32, _} -> :windows
|
||||
end
|
||||
end
|
||||
|
||||
defp cp_r!(source, destination) do
|
||||
File.cp_r!(source, destination, fn _, _ -> false end)
|
||||
end
|
||||
|
||||
defp ensure_otp_version(expected_otp_version) do
|
||||
actual_otp_version = otp_version()
|
||||
|
||||
if actual_otp_version != expected_otp_version do
|
||||
raise "expected OTP #{expected_otp_version}, got: #{actual_otp_version}"
|
||||
end
|
||||
end
|
||||
|
||||
# From https://github.com/fishcakez/dialyze/blob/6698ae582c77940ee10b4babe4adeff22f1b7779/lib/mix/tasks/dialyze.ex#L168
|
||||
defp otp_version do
|
||||
major = :erlang.system_info(:otp_release) |> List.to_string()
|
||||
vsn_file = Path.join([:code.root_dir(), "releases", major, "OTP_VERSION"])
|
||||
|
||||
try do
|
||||
vsn_file |> File.read!() |> String.split("\n", trim: true)
|
||||
else
|
||||
[full] -> full
|
||||
_ -> major
|
||||
catch
|
||||
:error, _ -> major
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue