Skip to content

Commit 265782e

Browse files
committed
feat: Zig 0.16.0 compatibility
Cross-compilation fixes (Zig 0.16.0 API changes): - Replace std.c.stat with Io.Dir.cwd().statFile - Rename Permissions.unixNew → Permissions.fromMode - Remove unused arena parameter from maybe_install_musl_runtime - Comptime-guard the musl runtime call site on macOS Process spawning (cross-platform): - Replace std.process.replace with std.process.spawn + child.wait (std.process.replace does not work reliably on macOS arm64 in Zig 0.16.0) - Unify Windows/Unix code paths via the same spawn+wait pattern - Use .exited for Child.Term, var for mutable Child All targets compile: macOS (arm64/x86_64), Linux (x86_64/arm64), Windows (x86_64)
1 parent de9c866 commit 265782e

2 files changed

Lines changed: 31 additions & 47 deletions

File tree

src/erlang_launcher.zig

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ pub fn launch(io: Io, install_dir: []const u8, env_map: *std.process.Environ.Map
4646
release_cookie_content = cookie;
4747
}
4848

49-
// Set all the required release arguments
49+
// Set all the required release arguments. CLI args are passed
50+
// through native argv (after `-extra` below) and reach the BEAM
51+
// via :init.get_plain_arguments/0.
52+
5053
const erlang_cli = &[_][]const u8{
5154
erl_bin_path[0..],
5255
"-elixir ansi_enabled true",
@@ -67,54 +70,37 @@ pub fn launch(io: Io, install_dir: []const u8, env_map: *std.process.Environ.Map
6770
"-extra",
6871
};
6972

70-
if (builtin.os.tag == .windows) {
71-
// Fix up Windows 10+ consoles having ANSI escape support, but only if we set some flags
72-
const final_args = try std.mem.concat(allocator, []const u8, &.{ erlang_cli, args_trimmed });
73-
74-
try env_map.put("RELEASE_ROOT", install_dir);
75-
try env_map.put("RELEASE_SYS_CONFIG", config_sys_path_no_ext);
76-
try env_map.put("__BURRITO", "1");
77-
try env_map.put("__BURRITO_BIN_PATH", self_path);
78-
79-
var win_child_proc = std.process.Child.init(final_args, allocator);
80-
win_child_proc.env_map = env_map;
81-
win_child_proc.stdout_behavior = .Inherit;
82-
win_child_proc.stdin_behavior = .Inherit;
83-
84-
log.debug("CLI List: {any}", .{final_args});
85-
86-
const win_term = try win_child_proc.spawnAndWait();
87-
switch (win_term) {
88-
.Exited => |code| {
89-
std.process.exit(code);
90-
},
91-
else => std.process.exit(1),
92-
}
93-
} else {
94-
const final_args = try std.mem.concat(allocator, []const u8, &.{ erlang_cli, args_trimmed });
73+
// Cross-platform: build args once, set env, spawn child, wait for exit
74+
const final_args = try std.mem.concat(allocator, []const u8, &.{ erlang_cli, args_trimmed });
75+
76+
log.debug("CLI List: {any}", .{final_args});
9577

96-
log.debug("CLI List: {any}", .{final_args});
78+
try env_map.put("RELEASE_ROOT", install_dir);
79+
try env_map.put("RELEASE_SYS_CONFIG", config_sys_path_no_ext);
80+
try env_map.put("__BURRITO", "1");
81+
try env_map.put("__BURRITO_BIN_PATH", self_path);
9782

83+
// Unix: set ROOTDIR, BINDIR, LD_LIBRARY_PATH for NIF .so files
84+
if (builtin.os.tag != .windows) {
9885
try env_map.put("ROOTDIR", install_dir[0..]);
9986
try env_map.put("BINDIR", erts_bin_path[0..]);
100-
try env_map.put("RELEASE_ROOT", install_dir);
101-
try env_map.put("RELEASE_SYS_CONFIG", config_sys_path_no_ext);
102-
try env_map.put("__BURRITO", "1");
103-
try env_map.put("__BURRITO_BIN_PATH", self_path);
10487

105-
// Extend LD_LIBRARY_PATH so NIF .so files can find system shared
106-
// libraries (e.g. libgcc_s.so.1) when using a custom glibc ERTS
10788
const system_lib_paths = "/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib:/usr/lib";
10889
if (env_map.get("LD_LIBRARY_PATH")) |existing| {
10990
const combined = try std.fmt.allocPrint(allocator, "{s}:{s}", .{ existing, system_lib_paths });
11091
try env_map.put("LD_LIBRARY_PATH", combined);
11192
} else {
11293
try env_map.put("LD_LIBRARY_PATH", system_lib_paths);
11394
}
95+
}
11496

115-
return std.process.replace(io, .{
116-
.argv = final_args,
117-
.environ_map = env_map,
118-
});
97+
var child = try std.process.spawn(io, .{
98+
.argv = final_args,
99+
.environ_map = env_map,
100+
});
101+
const term = try child.wait(io);
102+
switch (term) {
103+
.exited => |code| std.process.exit(code),
104+
else => std.process.exit(1),
119105
}
120106
}

src/wrapper.zig

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub fn main(init: std.process.Init) !void {
4646
const environ = init.minimal.environ;
4747

4848
// If on linux, maybe install the musl libc runtime file for our pre-compiled Erlang
49-
try maybe_install_musl_runtime(io, arena);
49+
if (comptime IS_LINUX) try maybe_install_musl_runtime(io);
5050

5151
const self_path = try std.process.executablePathAlloc(io, arena);
5252

@@ -218,16 +218,14 @@ fn install_dir_error(arena: std.mem.Allocator) void {
218218
std.process.exit(1);
219219
}
220220

221-
fn maybe_install_musl_runtime(io: Io, arena: std.mem.Allocator) !void {
222-
if (comptime IS_LINUX and !std.mem.eql(u8, build_options.MUSL_RUNTIME_PATH, "")) {
223-
// Check if the file was already extracted
224-
const cStr = try arena.dupeZ(u8, build_options.MUSL_RUNTIME_PATH);
225-
var statBuffer: std.c.Stat = undefined;
226-
const statResult = std.c.stat(cStr, &statBuffer);
221+
fn maybe_install_musl_runtime(io: Io) !void {
222+
if (!std.mem.eql(u8, build_options.MUSL_RUNTIME_PATH, "")) {
223+
// Check if the file was already extracted using std.fs API (cross-platform)
224+
const file_exists = Io.Dir.cwd().statFile(io, build_options.MUSL_RUNTIME_PATH, .{}) catch null;
227225

228-
if (statResult == 0) {
226+
if (file_exists != null) {
229227
// File exists
230-
log.debug("The musl runtime file is already preset. Continuing.", .{});
228+
log.debug("The musl runtime file is already present. Continuing.", .{});
231229
return;
232230
}
233231

@@ -237,7 +235,7 @@ fn maybe_install_musl_runtime(io: Io, arena: std.mem.Allocator) !void {
237235
};
238236
defer file.close(io);
239237

240-
const exec_permissions = Io.File.Permissions.unixNew(0o754);
238+
const exec_permissions = Io.File.Permissions.fromMode(@intCast(0o754));
241239
try file.setPermissions(io, exec_permissions);
242240

243241
const MUSL_RUNTIME_BYTES = @embedFile("musl-runtime.so");

0 commit comments

Comments
 (0)