From 1576d1aae18d9a0cd4cdbd06a230276d50613a7c Mon Sep 17 00:00:00 2001 From: Cuong Truong Date: Wed, 25 Dec 2024 16:32:14 +0100 Subject: [PATCH 1/6] New sub-command to uninstall the cached version without confirming --- src/maintenance.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/maintenance.zig b/src/maintenance.zig index f02f5a3..0ad7e1c 100644 --- a/src/maintenance.zig +++ b/src/maintenance.zig @@ -11,6 +11,10 @@ pub fn do_maint(args: [][]u8, install_dir: []const u8) !void { if (args.len < 1) { logger.warn("No sub-command provided!", .{}); } else { + if (std.mem.eql(u8, args[0], "uninstall_yes")) { + try do_uninstall_confirmed(install_dir); + } + if (std.mem.eql(u8, args[0], "uninstall")) { try do_uninstall(install_dir); } @@ -55,6 +59,13 @@ fn do_uninstall(install_dir: []const u8) !void { logger.info("Quitting.", .{}); } +fn do_uninstall_confirmed(install_dir: []const u8) !void { + logger.info("Deleting directory: {s}", .{install_dir}); + try std.fs.deleteTreeAbsolute(install_dir); + logger.info("Uninstall complete!", .{}); + logger.info("Quitting.", .{}); +} + fn print_metadata() !void { var stdout = std.io.getStdOut().writer(); stdout.print("{s}", .{wrapper.RELEASE_METADATA_JSON}) catch {}; From f3d95643a376868c7a0c9eef2e0d4cfde6bf7717 Mon Sep 17 00:00:00 2001 From: Cuong Truong Date: Wed, 25 Dec 2024 16:56:20 +0100 Subject: [PATCH 2/6] introduce auto_confirm option for 'maintenance uninstall' task --- src/maintenance.zig | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/maintenance.zig b/src/maintenance.zig index 0ad7e1c..c7763ae 100644 --- a/src/maintenance.zig +++ b/src/maintenance.zig @@ -11,12 +11,9 @@ pub fn do_maint(args: [][]u8, install_dir: []const u8) !void { if (args.len < 1) { logger.warn("No sub-command provided!", .{}); } else { - if (std.mem.eql(u8, args[0], "uninstall_yes")) { - try do_uninstall_confirmed(install_dir); - } - if (std.mem.eql(u8, args[0], "uninstall")) { - try do_uninstall(install_dir); + const confirmed = args.len >= 2 and std.mem.eql(u8, args[1], "confirmed"); + try do_uninstall(install_dir, confirmed); } if (std.mem.eql(u8, args[0], "directory")) { @@ -45,12 +42,14 @@ fn confirm() !bool { } } -fn do_uninstall(install_dir: []const u8) !void { - logger.warn("This will uninstall the application runtime for this Burrito binary!", .{}); - if ((try confirm()) == false) { - logger.warn("Uninstall was aborted!", .{}); - logger.info("Quitting.", .{}); - return; +fn do_uninstall(install_dir: []const u8, auto_confirmed: bool) !void { + if (!auto_confirmed) { + logger.warn("This will uninstall the application runtime for this Burrito binary!", .{}); + if ((try confirm()) == false) { + logger.warn("Uninstall was aborted!", .{}); + logger.info("Quitting.", .{}); + return; + } } logger.info("Deleting directory: {s}", .{install_dir}); From 55f0a581c7255a67cc4260cb2edf875c42a37705 Mon Sep 17 00:00:00 2001 From: Cuong Truong Date: Thu, 16 Jan 2025 10:41:36 +0100 Subject: [PATCH 3/6] use '--no-confirm' instead of 'confirmed' for uninstall task --- src/maintenance.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maintenance.zig b/src/maintenance.zig index c7763ae..2b679ec 100644 --- a/src/maintenance.zig +++ b/src/maintenance.zig @@ -12,7 +12,7 @@ pub fn do_maint(args: [][]u8, install_dir: []const u8) !void { logger.warn("No sub-command provided!", .{}); } else { if (std.mem.eql(u8, args[0], "uninstall")) { - const confirmed = args.len >= 2 and std.mem.eql(u8, args[1], "confirmed"); + const confirmed = args.len >= 2 and std.mem.eql(u8, args[1], "--no-confirm"); try do_uninstall(install_dir, confirmed); } From 81f1457f5c896d088b2e3a1d185cad6b5c7e8453 Mon Sep 17 00:00:00 2001 From: Cuong Truong Date: Thu, 30 Jan 2025 16:40:47 +0100 Subject: [PATCH 4/6] skip specific nifs or all --- lib/steps/patch/recompile_nifs.ex | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/steps/patch/recompile_nifs.ex b/lib/steps/patch/recompile_nifs.ex index 132c5e0..7302299 100644 --- a/lib/steps/patch/recompile_nifs.ex +++ b/lib/steps/patch/recompile_nifs.ex @@ -12,17 +12,26 @@ defmodule Burrito.Steps.Patch.RecompileNIFs do cxxflags = Keyword.get(context.target.qualifiers, :nif_cxxflags, "") nif_env = Keyword.get(context.target.qualifiers, :nif_env, []) nif_make_args = Keyword.get(context.target.qualifiers, :nif_make_args, []) - skip_nifs? = Keyword.get(context.target.qualifiers, :skip_nifs, false) - - if context.target.cross_build and not skip_nifs? do - triplet = Target.make_triplet(context.target) - - {:local_unpacked, path: erts_location} = context.target.erts_source - - nif_sniff() - |> Enum.each(fn dep -> - maybe_recompile_nif(dep, context.work_dir, erts_location, triplet, cflags, cxxflags, nif_env, nif_make_args) - end) + skip_nifs = Keyword.get(context.target.qualifiers, :skip_nifs, :all) + + if context.target.cross_build do + case skip_nifs do + :all -> :do_nothing + skips when not is_list(skips) -> raise "skip_nifs must be either :all or a list" + skips -> + triplet = Target.make_triplet(context.target) + {:local_unpacked, path: erts_location} = context.target.erts_source + Enum.each(nif_sniff(), fn dep -> + case Enum.member?(skips, dep) do + true -> Log.info(:step, "Ignored NIF #{dep}.") + false -> + maybe_recompile_nif( + dep, context.work_dir, erts_location, triplet, + cflags, cxxflags, nif_env, nif_make_args + ) + end + end) + end end context From 3f89a0a72a96728493260e1928890ff01b49b460 Mon Sep 17 00:00:00 2001 From: Cuong Truong Date: Thu, 30 Jan 2025 16:56:41 +0100 Subject: [PATCH 5/6] print log for skipped nifs --- lib/steps/patch/recompile_nifs.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/steps/patch/recompile_nifs.ex b/lib/steps/patch/recompile_nifs.ex index 7302299..f1e133d 100644 --- a/lib/steps/patch/recompile_nifs.ex +++ b/lib/steps/patch/recompile_nifs.ex @@ -22,8 +22,9 @@ defmodule Burrito.Steps.Patch.RecompileNIFs do triplet = Target.make_triplet(context.target) {:local_unpacked, path: erts_location} = context.target.erts_source Enum.each(nif_sniff(), fn dep -> + Log.info(:step, "Considering NIF #{inspect(dep)} against skip list #{inspect(skips)}...") case Enum.member?(skips, dep) do - true -> Log.info(:step, "Ignored NIF #{dep}.") + true -> Log.info(:step, "Ignored NIF #{inspect(dep)}.") false -> maybe_recompile_nif( dep, context.work_dir, erts_location, triplet, From 52eba6b1eda05f611b678652f16bea42569e27dc Mon Sep 17 00:00:00 2001 From: Cuong Truong Date: Thu, 30 Jan 2025 17:07:48 +0100 Subject: [PATCH 6/6] make sure dep name extracted from tuple --- lib/steps/patch/recompile_nifs.ex | 165 +++++++++++++++--------------- 1 file changed, 83 insertions(+), 82 deletions(-) diff --git a/lib/steps/patch/recompile_nifs.ex b/lib/steps/patch/recompile_nifs.ex index f1e133d..9be952f 100644 --- a/lib/steps/patch/recompile_nifs.ex +++ b/lib/steps/patch/recompile_nifs.ex @@ -22,15 +22,10 @@ defmodule Burrito.Steps.Patch.RecompileNIFs do triplet = Target.make_triplet(context.target) {:local_unpacked, path: erts_location} = context.target.erts_source Enum.each(nif_sniff(), fn dep -> - Log.info(:step, "Considering NIF #{inspect(dep)} against skip list #{inspect(skips)}...") - case Enum.member?(skips, dep) do - true -> Log.info(:step, "Ignored NIF #{inspect(dep)}.") - false -> - maybe_recompile_nif( - dep, context.work_dir, erts_location, triplet, - cflags, cxxflags, nif_env, nif_make_args - ) - end + maybe_recompile_nif( + dep, context.work_dir, erts_location, triplet, + cflags, cxxflags, nif_env, nif_make_args, skips + ) end) end end @@ -60,84 +55,90 @@ defmodule Burrito.Steps.Patch.RecompileNIFs do end) end - defp maybe_recompile_nif({_, _, false}, _, _, _, _, _, _, _), do: :no_nif + defp maybe_recompile_nif({_, _, false}, _, _, _, _, _, _, _, _), do: :no_nif defp maybe_recompile_nif( - {dep, path, true}, - release_working_path, - erts_path, - cross_target, - extra_cflags, - extra_cxxflags, - extra_env, - extra_make_args - ) do - dep = Atom.to_string(dep) - - Log.info(:step, "Going to recompile NIF for cross-build: #{dep} -> #{cross_target}") - - output_priv_dir = - Path.join(release_working_path, ["lib/#{dep}*/"]) - |> Path.expand() - |> Path.wildcard() - |> List.first() - - _ = System.cmd("make", ["clean"], cd: path, stderr_to_stdout: true, into: IO.stream()) - - # Compose env variables for cross-compilation, if we're building for linux, force dynamic linking - erts_env = - if String.contains?(cross_target, "linux") do - erts_make_env(erts_path) ++ [{"LDFLAGS", "-dynamic-linker /dev/null"}] - else - erts_make_env(erts_path) - end - - # This currently is only designed for elixir_make NIFs - build_result = - System.cmd("make", ["all", "--always-make"] ++ extra_make_args, - cd: path, - stderr_to_stdout: true, - env: - [ - {"MIX_APP_PATH", output_priv_dir}, - {"RANLIB", "zig ranlib"}, - {"AR", "zig ar"}, - {"CC", - "zig cc -target #{cross_target} -O2 -dynamic -shared -Wl,-undefined=dynamic_lookup #{extra_cflags}"}, - {"CXX", - "zig c++ -target #{cross_target} -O2 -dynamic -shared -Wl,-undefined=dynamic_lookup #{extra_cxxflags}"} - ] ++ erts_env ++ extra_env, - into: IO.stream() - ) - - case build_result do - {_, 0} -> - Log.info(:step, "Successfully re-built #{dep} for #{cross_target}!") - - src_priv_files = - Path.join(output_priv_dir, ["priv/*"]) |> Path.expand() |> Path.wildcard() - - final_output_priv_dir = Path.join(output_priv_dir, "priv") - - Enum.each(src_priv_files, fn file -> - file_name = Path.basename(file) - - if Path.extname(file_name) == ".so" && String.contains?(cross_target, "windows") do - new_file_name = String.replace_trailing(file_name, ".so", ".dll") - dst_fullpath = Path.join(final_output_priv_dir, new_file_name) - - Log.info(:step, "#{file} -> #{dst_fullpath}") - - File.rename!(file, dst_fullpath) + {dep, path, true}, + release_working_path, + erts_path, + cross_target, + extra_cflags, + extra_cxxflags, + extra_env, + extra_make_args, + skip_nifs + ) do + Log.info(:step, "Considering NIF #{inspect(dep)} against skip list #{inspect(skip_nifs)}...") + case Enum.member?(skip_nifs, dep) do + true -> Log.info(:step, "Ignored NIF #{inspect(dep)}.") + false -> + dep = Atom.to_string(dep) + + Log.info(:step, "Going to recompile NIF for cross-build: #{dep} -> #{cross_target}") + + output_priv_dir = + Path.join(release_working_path, ["lib/#{dep}*/"]) + |> Path.expand() + |> Path.wildcard() + |> List.first() + + _ = System.cmd("make", ["clean"], cd: path, stderr_to_stdout: true, into: IO.stream()) + + # Compose env variables for cross-compilation, if we're building for linux, force dynamic linking + erts_env = + if String.contains?(cross_target, "linux") do + erts_make_env(erts_path) ++ [{"LDFLAGS", "-dynamic-linker /dev/null"}] else - file_name + erts_make_env(erts_path) end - end) - {output, _} -> - Log.error(:step, "Failed to rebuild #{dep} for #{cross_target}!") - Log.error(:step, output) - exit(1) + # This currently is only designed for elixir_make NIFs + build_result = + System.cmd("make", ["all", "--always-make"] ++ extra_make_args, + cd: path, + stderr_to_stdout: true, + env: + [ + {"MIX_APP_PATH", output_priv_dir}, + {"RANLIB", "zig ranlib"}, + {"AR", "zig ar"}, + {"CC", + "zig cc -target #{cross_target} -O2 -dynamic -shared -Wl,-undefined=dynamic_lookup #{extra_cflags}"}, + {"CXX", + "zig c++ -target #{cross_target} -O2 -dynamic -shared -Wl,-undefined=dynamic_lookup #{extra_cxxflags}"} + ] ++ erts_env ++ extra_env, + into: IO.stream() + ) + + case build_result do + {_, 0} -> + Log.info(:step, "Successfully re-built #{dep} for #{cross_target}!") + + src_priv_files = + Path.join(output_priv_dir, ["priv/*"]) |> Path.expand() |> Path.wildcard() + + final_output_priv_dir = Path.join(output_priv_dir, "priv") + + Enum.each(src_priv_files, fn file -> + file_name = Path.basename(file) + + if Path.extname(file_name) == ".so" && String.contains?(cross_target, "windows") do + new_file_name = String.replace_trailing(file_name, ".so", ".dll") + dst_fullpath = Path.join(final_output_priv_dir, new_file_name) + + Log.info(:step, "#{file} -> #{dst_fullpath}") + + File.rename!(file, dst_fullpath) + else + file_name + end + end) + + {output, _} -> + Log.error(:step, "Failed to rebuild #{dep} for #{cross_target}!") + Log.error(:step, output) + exit(1) + end end end