diff --git a/lib/steps/patch/recompile_nifs.ex b/lib/steps/patch/recompile_nifs.ex index 132c5e0..9be952f 100644 --- a/lib/steps/patch/recompile_nifs.ex +++ b/lib/steps/patch/recompile_nifs.ex @@ -12,17 +12,22 @@ 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 -> + maybe_recompile_nif( + dep, context.work_dir, erts_location, triplet, + cflags, cxxflags, nif_env, nif_make_args, skips + ) + end) + end end context @@ -50,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 diff --git a/src/maintenance.zig b/src/maintenance.zig index f02f5a3..2b679ec 100644 --- a/src/maintenance.zig +++ b/src/maintenance.zig @@ -12,7 +12,8 @@ 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")) { - try do_uninstall(install_dir); + const confirmed = args.len >= 2 and std.mem.eql(u8, args[1], "--no-confirm"); + try do_uninstall(install_dir, confirmed); } if (std.mem.eql(u8, args[0], "directory")) { @@ -41,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}); @@ -55,6 +58,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 {};