Skip to content

Commit f1a5676

Browse files
fix cross-compilation
1 parent 7b9e70e commit f1a5676

File tree

3 files changed

+26
-21
lines changed

3 files changed

+26
-21
lines changed

src/cli/app_stub.zig

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,12 @@ fn addRocCallAbiStub(
161161
wip.cursor = .{ .block = entry };
162162

163163
// Generate actual implementation based on function name
164-
if (std.mem.eql(u8, name, "addInts")) {
164+
if (std.mem.eql(u8, name, "add_ints")) {
165165
try addIntsImplementation(&wip, llvm_builder);
166-
} else if (std.mem.eql(u8, name, "multiplyInts")) {
166+
} else if (std.mem.eql(u8, name, "multiply_ints")) {
167167
try multiplyIntsImplementation(&wip, llvm_builder);
168-
} else if (std.mem.eql(u8, name, "processString")) {
169-
// processString not supported in cross-compilation stubs - only int platform supported
168+
} else if (std.mem.eql(u8, name, "process_string")) {
169+
// process_string not supported in cross-compilation stubs - only int platform supported
170170
_ = try wip.retVoid();
171171
} else {
172172
// Default: just return void for unknown functions
@@ -180,11 +180,11 @@ fn addRocCallAbiStub(
180180
pub fn getTestPlatformEntrypoints(allocator: Allocator, platform_type: []const u8) ![]PlatformEntrypoint {
181181
if (std.mem.eql(u8, platform_type, "int")) {
182182
// Based on test/int/platform/host.zig:
183-
// extern fn roc__addInts(ops: *builtins.host_abi.RocOps, ret_ptr: *anyopaque, arg_ptr: ?*anyopaque) callconv(.c) void;
184-
// extern fn roc__multiplyInts(ops: *builtins.host_abi.RocOps, ret_ptr: *anyopaque, arg_ptr: ?*anyopaque) callconv(.c) void;
183+
// extern fn roc__add_ints(ops: *builtins.host_abi.RocOps, ret_ptr: *anyopaque, arg_ptr: ?*anyopaque) callconv(.c) void;
184+
// extern fn roc__multiply_ints(ops: *builtins.host_abi.RocOps, ret_ptr: *anyopaque, arg_ptr: ?*anyopaque) callconv(.c) void;
185185
const entrypoints = try allocator.alloc(PlatformEntrypoint, 2);
186-
entrypoints[0] = PlatformEntrypoint{ .name = "addInts" };
187-
entrypoints[1] = PlatformEntrypoint{ .name = "multiplyInts" };
186+
entrypoints[0] = PlatformEntrypoint{ .name = "add_ints" };
187+
entrypoints[1] = PlatformEntrypoint{ .name = "multiply_ints" };
188188
return entrypoints;
189189
}
190190

src/cli/main.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,8 @@ fn generatePlatformHostShim(allocs: *Allocators, cache_dir: []const u8, entrypoi
625625
}
626626

627627
// Create the complete platform shim
628-
platform_host_shim.createInterpreterShim(&llvm_builder, entrypoints.items) catch |err| {
628+
// Note: Symbol names include platform-specific prefixes (underscore for macOS)
629+
platform_host_shim.createInterpreterShim(&llvm_builder, entrypoints.items, target) catch |err| {
629630
std.log.err("Failed to create interpreter shim: {}", .{err});
630631
return err;
631632
};

src/cli/platform_host_shim.zig

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
//! Helpers for using Zig's LLVM Builder API to generate a shim library for the
22
//! Roc interpreter that translates from the platform host API.
3+
//!
4+
//! Note: Symbol names in LLVM IR need platform-specific prefixes for macOS.
5+
//! MachO format requires underscore prefix on all C symbols.
36

47
const std = @import("std");
58
const Builder = std.zig.llvm.Builder;
69
const WipFunction = Builder.WipFunction;
7-
const builtin = @import("builtin");
10+
const RocTarget = @import("target.zig").RocTarget;
811

912
/// Represents a single entrypoint that a Roc platform host expects to call.
1013
/// Each entrypoint corresponds to a specific function the host can invoke,
@@ -27,7 +30,7 @@ pub const EntryPoint = struct {
2730
/// Roc platform functions will delegate to. The Roc interpreter provides
2831
/// the actual implementation of this function, which acts as a dispatcher
2932
/// based on the entry_idx parameter.
30-
fn addRocEntrypoint(builder: *Builder) !Builder.Function.Index {
33+
fn addRocEntrypoint(builder: *Builder, target: RocTarget) !Builder.Function.Index {
3134
// Create pointer type for generic pointers (i8* in LLVM)
3235
const ptr_type = try builder.ptrType(.default);
3336

@@ -36,14 +39,14 @@ fn addRocEntrypoint(builder: *Builder) !Builder.Function.Index {
3639
const entrypoint_params = [_]Builder.Type{ .i32, ptr_type, ptr_type, ptr_type };
3740
const entrypoint_type = try builder.fnType(.void, &entrypoint_params, .normal);
3841

39-
// Create function name with platform-specific prefix
42+
// Add underscore prefix for macOS (required for MachO symbol names)
4043
const base_name = "roc_entrypoint";
41-
const fn_name_str = if (builtin.target.os.tag == .macos)
44+
const full_name = if (target.isMacOS())
4245
try std.fmt.allocPrint(builder.gpa, "_{s}", .{base_name})
4346
else
4447
try builder.gpa.dupe(u8, base_name);
45-
defer builder.gpa.free(fn_name_str);
46-
const fn_name = try builder.strtabString(fn_name_str);
48+
defer builder.gpa.free(full_name);
49+
const fn_name = try builder.strtabString(full_name);
4750

4851
// Add the extern function declaration (no body)
4952
const entrypoint_fn = try builder.addFunction(entrypoint_type, fn_name, .default);
@@ -72,7 +75,7 @@ fn addRocEntrypoint(builder: *Builder) !Builder.Function.Index {
7275
/// 2. The pre-built Roc interpreter to handle all calls through a single dispatch mechanism
7376
/// 3. Efficient code generation since each wrapper is just a simple function call
7477
/// 4. Easy addition/removal of platform functions without changing the pre-built interpreter binary which is embedded in the roc cli executable.
75-
fn addRocExportedFunction(builder: *Builder, entrypoint_fn: Builder.Function.Index, name: []const u8, entry_idx: u32) !Builder.Function.Index {
78+
fn addRocExportedFunction(builder: *Builder, entrypoint_fn: Builder.Function.Index, name: []const u8, entry_idx: u32, target: RocTarget) !Builder.Function.Index {
7679
// Create pointer type for generic pointers
7780
const ptr_type = try builder.ptrType(.default);
7881

@@ -81,10 +84,11 @@ fn addRocExportedFunction(builder: *Builder, entrypoint_fn: Builder.Function.Ind
8184
const roc_fn_params = [_]Builder.Type{ ptr_type, ptr_type, ptr_type };
8285
const roc_fn_type = try builder.fnType(.void, &roc_fn_params, .normal);
8386

84-
// Create function name with roc__ prefix and platform-specific prefix
87+
// Create function name with roc__ prefix.
88+
// Add underscore prefix for macOS (required for MachO symbol names)
8589
const base_name = try std.fmt.allocPrint(builder.gpa, "roc__{s}", .{name});
8690
defer builder.gpa.free(base_name);
87-
const full_name = if (builtin.target.os.tag == .macos)
91+
const full_name = if (target.isMacOS())
8892
try std.fmt.allocPrint(builder.gpa, "_{s}", .{base_name})
8993
else
9094
try builder.gpa.dupe(u8, base_name);
@@ -153,12 +157,12 @@ fn addRocExportedFunction(builder: *Builder, entrypoint_fn: Builder.Function.Ind
153157
///
154158
/// The generated library is then compiled using LLVM to an object file and linked with
155159
/// both the host and the Roc interpreter to create a dev build executable.
156-
pub fn createInterpreterShim(builder: *Builder, entrypoints: []const EntryPoint) !void {
160+
pub fn createInterpreterShim(builder: *Builder, entrypoints: []const EntryPoint, target: RocTarget) !void {
157161
// Add the extern roc_entrypoint declaration
158-
const entrypoint_fn = try addRocEntrypoint(builder);
162+
const entrypoint_fn = try addRocEntrypoint(builder, target);
159163

160164
// Add each exported entrypoint function
161165
for (entrypoints) |entry| {
162-
_ = try addRocExportedFunction(builder, entrypoint_fn, entry.name, entry.idx);
166+
_ = try addRocExportedFunction(builder, entrypoint_fn, entry.name, entry.idx, target);
163167
}
164168
}

0 commit comments

Comments
 (0)