authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-27 17:54:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-27 17:54:22-07:00
log9268972ff942f1d9db8fd0b89a8efe528d67e930
tree45a3a65f31c53e6839e27aa831f8cd49d9e8b9a4
parent9e4360c335c543ad4ff80791257eabfc556f3ac1
parentc3b0182f31c874eb9f1bb21397debdfdbf6161d3

Merge branch 'kubkon-elf-soname-opt-in' into master

closes #7162

5 files changed, 54 insertions(+), 29 deletions(-)

src/Compilation.zig+2-2
...@@ -364,7 +364,7 @@ pub const InitOptions = struct {...@@ -364,7 +364,7 @@ pub const InitOptions = struct {
364 link_emit_relocs: bool = false,364 link_emit_relocs: bool = false,
365 linker_script: ?[]const u8 = null,365 linker_script: ?[]const u8 = null,
366 version_script: ?[]const u8 = null,366 version_script: ?[]const u8 = null,
367 override_soname: ?[]const u8 = null,367 soname: ?[]const u8 = null,
368 linker_gc_sections: ?bool = null,368 linker_gc_sections: ?bool = null,
369 linker_allow_shlib_undefined: ?bool = null,369 linker_allow_shlib_undefined: ?bool = null,
370 linker_bind_global_refs_locally: ?bool = null,370 linker_bind_global_refs_locally: ?bool = null,
...@@ -828,7 +828,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -828,7 +828,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
828 .emit_relocs = options.link_emit_relocs,828 .emit_relocs = options.link_emit_relocs,
829 .rdynamic = options.rdynamic,829 .rdynamic = options.rdynamic,
830 .extra_lld_args = options.lld_argv,830 .extra_lld_args = options.lld_argv,
831 .override_soname = options.override_soname,831 .soname = options.soname,
832 .version = options.version,832 .version = options.version,
833 .libc_installation = libc_dirs.libc_installation,833 .libc_installation = libc_dirs.libc_installation,
834 .pic = pic,834 .pic = pic,
src/glibc.zig+4-3
...@@ -911,13 +911,14 @@ fn buildSharedLib(...@@ -911,13 +911,14 @@ fn buildSharedLib(
911 const tracy = trace(@src());911 const tracy = trace(@src());
912 defer tracy.end();912 defer tracy.end();
913913
914 const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
914 const emit_bin = Compilation.EmitLoc{915 const emit_bin = Compilation.EmitLoc{
915 .directory = bin_directory,916 .directory = bin_directory,
916 .basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover }),917 .basename = basename,
917 };918 };
918 const version: std.builtin.Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };919 const version: std.builtin.Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
919 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);920 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
920 const override_soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else null;921 const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
921 const map_file_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, all_map_basename });922 const map_file_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, all_map_basename });
922 const c_source_files = [1]Compilation.CSourceFile{923 const c_source_files = [1]Compilation.CSourceFile{
923 .{924 .{
...@@ -955,7 +956,7 @@ fn buildSharedLib(...@@ -955,7 +956,7 @@ fn buildSharedLib(
955 .clang_passthrough_mode = comp.clang_passthrough_mode,956 .clang_passthrough_mode = comp.clang_passthrough_mode,
956 .version = version,957 .version = version,
957 .version_script = map_file_path,958 .version_script = map_file_path,
958 .override_soname = override_soname,959 .soname = soname,
959 .c_source_files = &c_source_files,960 .c_source_files = &c_source_files,
960 .is_compiler_rt_or_libc = true,961 .is_compiler_rt_or_libc = true,
961 });962 });
src/link.zig+1-1
...@@ -88,7 +88,7 @@ pub const Options = struct {...@@ -88,7 +88,7 @@ pub const Options = struct {
88 subsystem: ?std.Target.SubSystem,88 subsystem: ?std.Target.SubSystem,
89 linker_script: ?[]const u8,89 linker_script: ?[]const u8,
90 version_script: ?[]const u8,90 version_script: ?[]const u8,
91 override_soname: ?[]const u8,91 soname: ?[]const u8,
92 llvm_cpu_features: ?[*:0]const u8,92 llvm_cpu_features: ?[*:0]const u8,
93 /// Extra args passed directly to LLD. Ignored when not linking with LLD.93 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
94 extra_lld_args: []const []const u8,94 extra_lld_args: []const []const u8,
src/link/Elf.zig+6-11
...@@ -1313,10 +1313,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1313,10 +1313,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1313 man.hash.addOptionalBytes(self.base.options.dynamic_linker);1313 man.hash.addOptionalBytes(self.base.options.dynamic_linker);
1314 }1314 }
1315 }1315 }
1316 if (is_dyn_lib) {1316 man.hash.addOptionalBytes(self.base.options.soname);
1317 man.hash.addOptionalBytes(self.base.options.override_soname);1317 man.hash.addOptional(self.base.options.version);
1318 man.hash.addOptional(self.base.options.version);
1319 }
1320 man.hash.addStringSet(self.base.options.system_libs);1318 man.hash.addStringSet(self.base.options.system_libs);
1321 man.hash.add(allow_shlib_undefined);1319 man.hash.add(allow_shlib_undefined);
1322 man.hash.add(self.base.options.bind_global_refs_locally);1320 man.hash.add(self.base.options.bind_global_refs_locally);
...@@ -1512,13 +1510,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1512,13 +1510,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1512 }1510 }
15131511
1514 if (is_dyn_lib) {1512 if (is_dyn_lib) {
1515 const soname = self.base.options.override_soname orelse if (self.base.options.version) |ver|1513 if (self.base.options.soname) |soname| {
1516 try std.fmt.allocPrint(arena, "lib{}.so.{}", .{ self.base.options.root_name, ver.major })1514 try argv.append("-soname");
1517 else1515 try argv.append(soname);
1518 try std.fmt.allocPrint(arena, "lib{}.so", .{self.base.options.root_name});1516 }
1519 try argv.append("-soname");
1520 try argv.append(soname);
1521
1522 if (self.base.options.version_script) |version_script| {1517 if (self.base.options.version_script) |version_script| {
1523 try argv.append("-version-script");1518 try argv.append("-version-script");
1524 try argv.append(version_script);1519 try argv.append(version_script);
src/main.zig+41-12
...@@ -306,6 +306,8 @@ const usage_build_generic =...@@ -306,6 +306,8 @@ const usage_build_generic =
306 \\ --version-script [path] Provide a version .map file306 \\ --version-script [path] Provide a version .map file
307 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)307 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
308 \\ --version [ver] Dynamic library semver308 \\ --version [ver] Dynamic library semver
309 \\ -fsoname[=name] (linux) Override the default SONAME value
310 \\ -fno-soname (linux) Disable emitting a SONAME
309 \\ -rdynamic Add all symbols to the dynamic symbol table311 \\ -rdynamic Add all symbols to the dynamic symbol table
310 \\ -rpath [path] Add directory to the runtime library search path312 \\ -rpath [path] Add directory to the runtime library search path
311 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library313 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
...@@ -350,6 +352,12 @@ const repl_help =...@@ -350,6 +352,12 @@ const repl_help =
350 \\352 \\
351;353;
352354
355const SOName = union(enum) {
356 no,
357 yes_default_value,
358 yes: []const u8,
359};
360
353const Emit = union(enum) {361const Emit = union(enum) {
354 no,362 no,
355 yes_default_path,363 yes_default_path,
...@@ -452,6 +460,7 @@ fn buildOutputType(...@@ -452,6 +460,7 @@ fn buildOutputType(
452 var target_ofmt: ?[]const u8 = null;460 var target_ofmt: ?[]const u8 = null;
453 var output_mode: std.builtin.OutputMode = undefined;461 var output_mode: std.builtin.OutputMode = undefined;
454 var emit_h: Emit = undefined;462 var emit_h: Emit = undefined;
463 var soname: SOName = undefined;
455 var ensure_libc_on_non_freestanding = false;464 var ensure_libc_on_non_freestanding = false;
456 var ensure_libcpp_on_non_freestanding = false;465 var ensure_libcpp_on_non_freestanding = false;
457 var link_libc = false;466 var link_libc = false;
...@@ -467,7 +476,6 @@ fn buildOutputType(...@@ -467,7 +476,6 @@ fn buildOutputType(
467 var linker_script: ?[]const u8 = null;476 var linker_script: ?[]const u8 = null;
468 var version_script: ?[]const u8 = null;477 var version_script: ?[]const u8 = null;
469 var disable_c_depfile = false;478 var disable_c_depfile = false;
470 var override_soname: ?[]const u8 = null;
471 var linker_gc_sections: ?bool = null;479 var linker_gc_sections: ?bool = null;
472 var linker_allow_shlib_undefined: ?bool = null;480 var linker_allow_shlib_undefined: ?bool = null;
473 var linker_bind_global_refs_locally: ?bool = null;481 var linker_bind_global_refs_locally: ?bool = null;
...@@ -564,6 +572,8 @@ fn buildOutputType(...@@ -564,6 +572,8 @@ fn buildOutputType(
564 // .translate_c, .zig_test, .run => emit_h = .no,572 // .translate_c, .zig_test, .run => emit_h = .no,
565 // else => unreachable,573 // else => unreachable,
566 //}574 //}
575
576 soname = .yes_default_value;
567 const args = all_args[2..];577 const args = all_args[2..];
568 var i: usize = 0;578 var i: usize = 0;
569 args_loop: while (i < args.len) : (i += 1) {579 args_loop: while (i < args.len) : (i += 1) {
...@@ -828,6 +838,12 @@ fn buildOutputType(...@@ -828,6 +838,12 @@ fn buildOutputType(
828 use_clang = false;838 use_clang = false;
829 } else if (mem.eql(u8, arg, "-rdynamic")) {839 } else if (mem.eql(u8, arg, "-rdynamic")) {
830 rdynamic = true;840 rdynamic = true;
841 } else if (mem.eql(u8, arg, "-fsoname")) {
842 soname = .yes_default_value;
843 } else if (mem.startsWith(u8, arg, "-fsoname=")) {
844 soname = .{ .yes = arg["-fsoname=".len..] };
845 } else if (mem.eql(u8, arg, "-fno-soname")) {
846 soname = .no;
831 } else if (mem.eql(u8, arg, "-femit-bin")) {847 } else if (mem.eql(u8, arg, "-femit-bin")) {
832 emit_bin = .yes_default_path;848 emit_bin = .yes_default_path;
833 } else if (mem.startsWith(u8, arg, "-femit-bin=")) {849 } else if (mem.startsWith(u8, arg, "-femit-bin=")) {
...@@ -955,6 +971,7 @@ fn buildOutputType(...@@ -955,6 +971,7 @@ fn buildOutputType(
955 },971 },
956 .cc, .cpp => {972 .cc, .cpp => {
957 emit_h = .no;973 emit_h = .no;
974 soname = .no;
958 strip = true;975 strip = true;
959 ensure_libc_on_non_freestanding = true;976 ensure_libc_on_non_freestanding = true;
960 ensure_libcpp_on_non_freestanding = arg_mode == .cpp;977 ensure_libcpp_on_non_freestanding = arg_mode == .cpp;
...@@ -1108,33 +1125,33 @@ fn buildOutputType(...@@ -1108,33 +1125,33 @@ fn buildOutputType(
1108 if (i >= linker_args.items.len) {1125 if (i >= linker_args.items.len) {
1109 fatal("expected linker arg after '{}'", .{arg});1126 fatal("expected linker arg after '{}'", .{arg});
1110 }1127 }
1111 const soname = linker_args.items[i];1128 const name = linker_args.items[i];
1112 override_soname = soname;1129 soname = .{ .yes = name };
1113 // Use it as --name.1130 // Use it as --name.
1114 // Example: libsoundio.so.21131 // Example: libsoundio.so.2
1115 var prefix: usize = 0;1132 var prefix: usize = 0;
1116 if (mem.startsWith(u8, soname, "lib")) {1133 if (mem.startsWith(u8, name, "lib")) {
1117 prefix = 3;1134 prefix = 3;
1118 }1135 }
1119 var end: usize = soname.len;1136 var end: usize = name.len;
1120 if (mem.endsWith(u8, soname, ".so")) {1137 if (mem.endsWith(u8, name, ".so")) {
1121 end -= 3;1138 end -= 3;
1122 } else {1139 } else {
1123 var found_digit = false;1140 var found_digit = false;
1124 while (end > 0 and std.ascii.isDigit(soname[end - 1])) {1141 while (end > 0 and std.ascii.isDigit(name[end - 1])) {
1125 found_digit = true;1142 found_digit = true;
1126 end -= 1;1143 end -= 1;
1127 }1144 }
1128 if (found_digit and end > 0 and soname[end - 1] == '.') {1145 if (found_digit and end > 0 and name[end - 1] == '.') {
1129 end -= 1;1146 end -= 1;
1130 } else {1147 } else {
1131 end = soname.len;1148 end = name.len;
1132 }1149 }
1133 if (mem.endsWith(u8, soname[prefix..end], ".so")) {1150 if (mem.endsWith(u8, name[prefix..end], ".so")) {
1134 end -= 3;1151 end -= 3;
1135 }1152 }
1136 }1153 }
1137 provided_name = soname[prefix..end];1154 provided_name = name[prefix..end];
1138 } else if (mem.eql(u8, arg, "-rpath")) {1155 } else if (mem.eql(u8, arg, "-rpath")) {
1139 i += 1;1156 i += 1;
1140 if (i >= linker_args.items.len) {1157 if (i >= linker_args.items.len) {
...@@ -1433,6 +1450,18 @@ fn buildOutputType(...@@ -1433,6 +1450,18 @@ fn buildOutputType(
1433 const have_enable_cache = enable_cache orelse false;1450 const have_enable_cache = enable_cache orelse false;
1434 const optional_version = if (have_version) version else null;1451 const optional_version = if (have_version) version else null;
14351452
1453 const resolved_soname: ?[]const u8 = switch (soname) {
1454 .yes => |explicit| explicit,
1455 .no => null,
1456 .yes_default_value => switch (object_format) {
1457 .elf => if (have_version)
1458 try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ root_name, version.major })
1459 else
1460 try std.fmt.allocPrint(arena, "lib{s}.so", .{root_name}),
1461 else => null,
1462 },
1463 };
1464
1436 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {1465 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
1437 .no => null,1466 .no => null,
1438 .yes_default_path => Compilation.EmitLoc{1467 .yes_default_path => Compilation.EmitLoc{
...@@ -1660,7 +1689,7 @@ fn buildOutputType(...@@ -1660,7 +1689,7 @@ fn buildOutputType(
1660 .linker_script = linker_script,1689 .linker_script = linker_script,
1661 .version_script = version_script,1690 .version_script = version_script,
1662 .disable_c_depfile = disable_c_depfile,1691 .disable_c_depfile = disable_c_depfile,
1663 .override_soname = override_soname,1692 .soname = resolved_soname,
1664 .linker_gc_sections = linker_gc_sections,1693 .linker_gc_sections = linker_gc_sections,
1665 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,1694 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
1666 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,1695 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,