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 {...@@ -1537,6 +1537,9 @@ pub const LibExeObjStep = struct {
1537 /// Permit read-only relocations in read-only segments. Disallowed by default.1537 /// Permit read-only relocations in read-only segments. Disallowed by default.
1538 link_z_notext: bool = false,1538 link_z_notext: bool = false,
15391539
1540 /// (Darwin) Install name for the dylib
1541 install_name: ?[]const u8 = null,
1542
1540 /// Position Independent Code1543 /// Position Independent Code
1541 force_pic: ?bool = null,1544 force_pic: ?bool = null,
15421545
...@@ -2451,6 +2454,16 @@ pub const LibExeObjStep = struct {...@@ -2451,6 +2454,16 @@ pub const LibExeObjStep = struct {
2451 zig_args.append("--version") catch unreachable;2454 zig_args.append("--version") catch unreachable;
2452 zig_args.append(builder.fmt("{}", .{version})) catch unreachable;2455 zig_args.append(builder.fmt("{}", .{version})) catch unreachable;
2453 }2456 }
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 }
2454 }2467 }
24552468
2456 if (self.bundle_compiler_rt) |x| {2469 if (self.bundle_compiler_rt) |x| {
src/Compilation.zig+3
...@@ -780,6 +780,8 @@ pub const InitOptions = struct {...@@ -780,6 +780,8 @@ pub const InitOptions = struct {
780 enable_link_snapshots: bool = false,780 enable_link_snapshots: bool = false,
781 /// (Darwin) Path and version of the native SDK if detected.781 /// (Darwin) Path and version of the native SDK if detected.
782 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,782 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
783 /// (Darwin) Install name of the dylib
784 install_name: ?[]const u8 = null,
783};785};
784786
785fn addPackageTableToCacheHash(787fn addPackageTableToCacheHash(
...@@ -1509,6 +1511,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1509,6 +1511,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1509 .use_stage1 = use_stage1,1511 .use_stage1 = use_stage1,
1510 .enable_link_snapshots = options.enable_link_snapshots,1512 .enable_link_snapshots = options.enable_link_snapshots,
1511 .native_darwin_sdk = options.native_darwin_sdk,1513 .native_darwin_sdk = options.native_darwin_sdk,
1514 .install_name = options.install_name,
1512 });1515 });
1513 errdefer bin_file.destroy();1516 errdefer bin_file.destroy();
1514 comp.* = .{1517 comp.* = .{
src/link.zig+3
...@@ -157,6 +157,9 @@ pub const Options = struct {...@@ -157,6 +157,9 @@ pub const Options = struct {
157 /// (Darwin) Path and version of the native SDK if detected.157 /// (Darwin) Path and version of the native SDK if detected.
158 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,158 native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
159159
160 /// (Darwin) Install name for the dylib
161 install_name: ?[]const u8 = null,
162
160 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {163 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
161 return if (options.use_lld) .Obj else options.output_mode;164 return if (options.use_lld) .Obj else options.output_mode;
162 }165 }
src/link/MachO.zig+6-9
...@@ -479,6 +479,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -479,6 +479,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
479 man.hash.addListOfBytes(self.base.options.frameworks);479 man.hash.addListOfBytes(self.base.options.frameworks);
480 man.hash.addListOfBytes(self.base.options.rpath_list);480 man.hash.addListOfBytes(self.base.options.rpath_list);
481 if (is_dyn_lib) {481 if (is_dyn_lib) {
482 man.hash.addOptionalBytes(self.base.options.install_name);
482 man.hash.addOptional(self.base.options.version);483 man.hash.addOptional(self.base.options.version);
483 }484 }
484 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);485 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
...@@ -811,11 +812,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -811,11 +812,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
811 if (is_dyn_lib) {812 if (is_dyn_lib) {
812 try argv.append("-dylib");813 try argv.append("-dylib");
813814
814 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{815 if (self.base.options.install_name) |install_name| {
815 self.base.options.emit.?.sub_path,816 try argv.append("-install_name");
816 });817 try argv.append(install_name);
817 try argv.append("-install_name");818 }
818 try argv.append(install_name);
819 }819 }
820820
821 if (self.base.options.sysroot) |syslibroot| {821 if (self.base.options.sysroot) |syslibroot| {
...@@ -4336,10 +4336,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4336,10 +4336,7 @@ fn populateMissingMetadata(self: *MachO) !void {
43364336
4337 if (self.dylib_id_cmd_index == null and self.base.options.output_mode == .Lib) {4337 if (self.dylib_id_cmd_index == null and self.base.options.output_mode == .Lib) {
4338 self.dylib_id_cmd_index = @intCast(u16, self.load_commands.items.len);4338 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}", .{4339 const install_name = self.base.options.install_name orelse self.base.options.emit.?.sub_path;
4340 self.base.options.emit.?.sub_path,
4341 });
4342 defer self.base.allocator.free(install_name);
4343 const current_version = self.base.options.version orelse4340 const current_version = self.base.options.version orelse
4344 std.builtin.Version{ .major = 1, .minor = 0, .patch = 0 };4341 std.builtin.Version{ .major = 1, .minor = 0, .patch = 0 };
4345 const compat_version = self.base.options.compatibility_version orelse4342 const compat_version = self.base.options.compatibility_version orelse
src/main.zig+13
...@@ -430,6 +430,7 @@ const usage_build_generic =...@@ -430,6 +430,7 @@ const usage_build_generic =
430 \\ --image-base [addr] Set base address for executable image430 \\ --image-base [addr] Set base address for executable image
431 \\ -framework [name] (Darwin) link against framework431 \\ -framework [name] (Darwin) link against framework
432 \\ -F[dir] (Darwin) add search path for frameworks432 \\ -F[dir] (Darwin) add search path for frameworks
433 \\ -install_name=[value] (Darwin) add dylib's install name
433 \\ --import-memory (WebAssembly) import memory from the environment434 \\ --import-memory (WebAssembly) import memory from the environment
434 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory435 \\ --initial-memory=[bytes] (WebAssembly) initial size of the linear memory
435 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory436 \\ --max-memory=[bytes] (WebAssembly) maximum size of the linear memory
...@@ -668,6 +669,7 @@ fn buildOutputType(...@@ -668,6 +669,7 @@ fn buildOutputType(
668 var wasi_exec_model: ?std.builtin.WasiExecModel = null;669 var wasi_exec_model: ?std.builtin.WasiExecModel = null;
669 var enable_link_snapshots: bool = false;670 var enable_link_snapshots: bool = false;
670 var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;671 var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
672 var install_name: ?[]const u8 = null;
671673
672 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.674 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
673 // This array is populated by zig cc frontend and then has to be converted to zig-style675 // This array is populated by zig cc frontend and then has to be converted to zig-style
...@@ -873,6 +875,10 @@ fn buildOutputType(...@@ -873,6 +875,10 @@ fn buildOutputType(
873 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});875 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
874 i += 1;876 i += 1;
875 try frameworks.append(args[i]);877 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];
876 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {882 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
877 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});883 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
878 i += 1;884 i += 1;
...@@ -1721,6 +1727,12 @@ fn buildOutputType(...@@ -1721,6 +1727,12 @@ fn buildOutputType(
1721 } else {1727 } else {
1722 fatal("unsupported -undefined option '{s}'", .{linker_args.items[i]});1728 fatal("unsupported -undefined option '{s}'", .{linker_args.items[i]});
1723 }1729 }
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];
1724 } else {1736 } else {
1725 warn("unsupported linker arg: {s}", .{arg});1737 warn("unsupported linker arg: {s}", .{arg});
1726 }1738 }
...@@ -2495,6 +2507,7 @@ fn buildOutputType(...@@ -2495,6 +2507,7 @@ fn buildOutputType(
2495 .debug_compile_errors = debug_compile_errors,2507 .debug_compile_errors = debug_compile_errors,
2496 .enable_link_snapshots = enable_link_snapshots,2508 .enable_link_snapshots = enable_link_snapshots,
2497 .native_darwin_sdk = native_darwin_sdk,2509 .native_darwin_sdk = native_darwin_sdk,
2510 .install_name = install_name,
2498 }) catch |err| switch (err) {2511 }) catch |err| switch (err) {
2499 error.LibCUnavailable => {2512 error.LibCUnavailable => {
2500 const target = target_info.target;2513 const target = target_info.target;