authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-17 00:18:45+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-18 17:55:53-08:00
loga08137330c20ce77724a9fc80acf46a7e7978a90
tree64495bae9db54d234e2bc78599a7594d7529d3d2
parent9a8fdbe0a07ed9ece1d44634c6fe82c23b6209eb

macho: handle -install_name option for dylibs/MachO

The status quo for the `build.zig` build system is preserved in the sense that, if the user does not explicitly override `dylib.setInstallName(...);` in their build script, the default of `@rpath/libname.dylib` applies. However, should they want to override the default behaviour, they can either: 1) unset it with ```dylib.setIntallName(null);``` 2) set it to an explicit string with ```dylib.setInstallName("somename.dylib");``` When it comes to the command line however, the default is not to use `@rpath` for the install name when creating a dylib. The user will now be required to explicitly specify the `@rpath` as part of the desired install name should they choose so like so: 1) with `build-lib` ``` zig build-lib -dynamic foo.zig -install_name @rpath/libfoo.dylib ``` 2) with `cc` ``` zig cc -shared foo.c -o libfoo.dylib -Wl,"-install_name=@rpath/libfoo.dylib" ```

5 files changed, 38 insertions(+), 9 deletions(-)

lib/std/build.zig+13
......@@ -1537,6 +1537,9 @@ pub const LibExeObjStep = struct {
15371537 /// Permit read-only relocations in read-only segments. Disallowed by default.
15381538 link_z_notext: bool = false,
15391539
1540 /// (Darwin) Install name for the dylib
1541 install_name: ?[]const u8 = null,
1542
15401543 /// Position Independent Code
15411544 force_pic: ?bool = null,
15421545
......@@ -2451,6 +2454,16 @@ pub const LibExeObjStep = struct {
24512454 zig_args.append("--version") catch unreachable;
24522455 zig_args.append(builder.fmt("{}", .{version})) catch unreachable;
24532456 }
2457
2458 if (self.target.isDarwin()) {
2459 const install_name = self.install_name orelse builder.fmt("@rpath/{s}{s}{s}", .{
2460 self.target.libPrefix(),
2461 self.name,
2462 self.target.dynamicLibSuffix(),
2463 });
2464 try zig_args.append("-install_name");
2465 try zig_args.append(install_name);
2466 }
24542467 }
24552468
24562469 if (self.bundle_compiler_rt) |x| {
src/Compilation.zig+3
......@@ -780,6 +780,8 @@ pub const InitOptions = struct {
780780 enable_link_snapshots: bool = false,
781781 /// (Darwin) Path and version of the native SDK if detected.
782782 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
783 /// (Darwin) Install name of the dylib
784 install_name: ?[]const u8 = null,
783785};
784786
785787fn addPackageTableToCacheHash(
......@@ -1509,6 +1511,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15091511 .use_stage1 = use_stage1,
15101512 .enable_link_snapshots = options.enable_link_snapshots,
15111513 .native_darwin_sdk = options.native_darwin_sdk,
1514 .install_name = options.install_name,
15121515 });
15131516 errdefer bin_file.destroy();
15141517 comp.* = .{
src/link.zig+3
......@@ -157,6 +157,9 @@ pub const Options = struct {
157157 /// (Darwin) Path and version of the native SDK if detected.
158158 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
159159
160 /// (Darwin) Install name for the dylib
161 install_name: ?[]const u8 = null,
162
160163 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
161164 return if (options.use_lld) .Obj else options.output_mode;
162165 }
src/link/MachO.zig+6-9
......@@ -479,6 +479,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
479479 man.hash.addListOfBytes(self.base.options.frameworks);
480480 man.hash.addListOfBytes(self.base.options.rpath_list);
481481 if (is_dyn_lib) {
482 man.hash.addOptionalBytes(self.base.options.install_name);
482483 man.hash.addOptional(self.base.options.version);
483484 }
484485 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
......@@ -811,11 +812,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
811812 if (is_dyn_lib) {
812813 try argv.append("-dylib");
813814
814 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{
815 self.base.options.emit.?.sub_path,
816 });
817 try argv.append("-install_name");
818 try argv.append(install_name);
815 if (self.base.options.install_name) |install_name| {
816 try argv.append("-install_name");
817 try argv.append(install_name);
818 }
819819 }
820820
821821 if (self.base.options.sysroot) |syslibroot| {
......@@ -4336,10 +4336,7 @@ fn populateMissingMetadata(self: *MachO) !void {
43364336
43374337 if (self.dylib_id_cmd_index == null and self.base.options.output_mode == .Lib) {
43384338 self.dylib_id_cmd_index = @intCast(u16, self.load_commands.items.len);
4339 const install_name = try std.fmt.allocPrint(self.base.allocator, "@rpath/{s}", .{
4340 self.base.options.emit.?.sub_path,
4341 });
4342 defer self.base.allocator.free(install_name);
4339 const install_name = self.base.options.install_name orelse self.base.options.emit.?.sub_path;
43434340 const current_version = self.base.options.version orelse
43444341 std.builtin.Version{ .major = 1, .minor = 0, .patch = 0 };
43454342 const compat_version = self.base.options.compatibility_version orelse
src/main.zig+13
......@@ -430,6 +430,7 @@ const usage_build_generic =
430430 \\ --image-base [addr] Set base address for executable image
431431 \\ -framework [name] (Darwin) link against framework
432432 \\ -F[dir] (Darwin) add search path for frameworks
433 \\ -install_name=[value] (Darwin) add dylib's install name
433434 \\ --import-memory (WebAssembly) import memory from the environment
434435 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory
435436 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory
......@@ -668,6 +669,7 @@ fn buildOutputType(
668669 var wasi_exec_model: ?std.builtin.WasiExecModel = null;
669670 var enable_link_snapshots: bool = false;
670671 var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
672 var install_name: ?[]const u8 = null;
671673
672674 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
673675 // This array is populated by zig cc frontend and then has to be converted to zig-style
......@@ -873,6 +875,10 @@ fn buildOutputType(
873875 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
874876 i += 1;
875877 try frameworks.append(args[i]);
878 } else if (mem.eql(u8, arg, "-install_name")) {
879 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
880 i += 1;
881 install_name = args[i];
876882 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
877883 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
878884 i += 1;
......@@ -1721,6 +1727,12 @@ fn buildOutputType(
17211727 } else {
17221728 fatal("unsupported -undefined option '{s}'", .{linker_args.items[i]});
17231729 }
1730 } else if (mem.eql(u8, arg, "-install_name")) {
1731 i += 1;
1732 if (i >= linker_args.items.len) {
1733 fatal("expected linker arg after '{s}'", .{arg});
1734 }
1735 install_name = linker_args.items[i];
17241736 } else {
17251737 warn("unsupported linker arg: {s}", .{arg});
17261738 }
......@@ -2495,6 +2507,7 @@ fn buildOutputType(
24952507 .debug_compile_errors = debug_compile_errors,
24962508 .enable_link_snapshots = enable_link_snapshots,
24972509 .native_darwin_sdk = native_darwin_sdk,
2510 .install_name = install_name,
24982511 }) catch |err| switch (err) {
24992512 error.LibCUnavailable => {
25002513 const target = target_info.target;