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:57:11-07:00
logf09f960ce44ef00c4c05be5919068790898cc049
tree0da6c46111b13fe772d9397d4a79500af76b2a05
parent288b8b535face92941b3f6c7f3eb09baf347a558

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

closes #7162

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

src/Compilation.zig+2-2
...@@ -360,7 +360,7 @@ pub const InitOptions = struct {...@@ -360,7 +360,7 @@ pub const InitOptions = struct {
360 link_emit_relocs: bool = false,360 link_emit_relocs: bool = false,
361 linker_script: ?[]const u8 = null,361 linker_script: ?[]const u8 = null,
362 version_script: ?[]const u8 = null,362 version_script: ?[]const u8 = null,
363 override_soname: ?[]const u8 = null,363 soname: ?[]const u8 = null,
364 linker_gc_sections: ?bool = null,364 linker_gc_sections: ?bool = null,
365 linker_allow_shlib_undefined: ?bool = null,365 linker_allow_shlib_undefined: ?bool = null,
366 linker_bind_global_refs_locally: ?bool = null,366 linker_bind_global_refs_locally: ?bool = null,
...@@ -810,7 +810,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -810,7 +810,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
810 .emit_relocs = options.link_emit_relocs,810 .emit_relocs = options.link_emit_relocs,
811 .rdynamic = options.rdynamic,811 .rdynamic = options.rdynamic,
812 .extra_lld_args = options.lld_argv,812 .extra_lld_args = options.lld_argv,
813 .override_soname = options.override_soname,813 .soname = options.soname,
814 .version = options.version,814 .version = options.version,
815 .libc_installation = libc_dirs.libc_installation,815 .libc_installation = libc_dirs.libc_installation,
816 .pic = pic,816 .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
...@@ -87,7 +87,7 @@ pub const Options = struct {...@@ -87,7 +87,7 @@ pub const Options = struct {
87 subsystem: ?std.Target.SubSystem,87 subsystem: ?std.Target.SubSystem,
88 linker_script: ?[]const u8,88 linker_script: ?[]const u8,
89 version_script: ?[]const u8,89 version_script: ?[]const u8,
90 override_soname: ?[]const u8,90 soname: ?[]const u8,
91 llvm_cpu_features: ?[*:0]const u8,91 llvm_cpu_features: ?[*:0]const u8,
92 /// Extra args passed directly to LLD. Ignored when not linking with LLD.92 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
93 extra_lld_args: []const []const u8,93 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);
...@@ -1505,13 +1503,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1505,13 +1503,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1505 }1503 }
15061504
1507 if (is_dyn_lib) {1505 if (is_dyn_lib) {
1508 const soname = self.base.options.override_soname orelse if (self.base.options.version) |ver|1506 if (self.base.options.soname) |soname| {
1509 try std.fmt.allocPrint(arena, "lib{}.so.{}", .{ self.base.options.root_name, ver.major })1507 try argv.append("-soname");
1510 else1508 try argv.append(soname);
1511 try std.fmt.allocPrint(arena, "lib{}.so", .{self.base.options.root_name});1509 }
1512 try argv.append("-soname");
1513 try argv.append(soname);
1514
1515 if (self.base.options.version_script) |version_script| {1510 if (self.base.options.version_script) |version_script| {
1516 try argv.append("-version-script");1511 try argv.append("-version-script");
1517 try argv.append(version_script);1512 try argv.append(version_script);
src/main.zig+41-12
...@@ -304,6 +304,8 @@ const usage_build_generic =...@@ -304,6 +304,8 @@ const usage_build_generic =
304 \\ --version-script [path] Provide a version .map file304 \\ --version-script [path] Provide a version .map file
305 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)305 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
306 \\ --version [ver] Dynamic library semver306 \\ --version [ver] Dynamic library semver
307 \\ -fsoname[=name] (linux) Override the default SONAME value
308 \\ -fno-soname (linux) Disable emitting a SONAME
307 \\ -rdynamic Add all symbols to the dynamic symbol table309 \\ -rdynamic Add all symbols to the dynamic symbol table
308 \\ -rpath [path] Add directory to the runtime library search path310 \\ -rpath [path] Add directory to the runtime library search path
309 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library311 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
...@@ -348,6 +350,12 @@ const repl_help =...@@ -348,6 +350,12 @@ const repl_help =
348 \\350 \\
349;351;
350352
353const SOName = union(enum) {
354 no,
355 yes_default_value,
356 yes: []const u8,
357};
358
351const Emit = union(enum) {359const Emit = union(enum) {
352 no,360 no,
353 yes_default_path,361 yes_default_path,
...@@ -450,6 +458,7 @@ fn buildOutputType(...@@ -450,6 +458,7 @@ fn buildOutputType(
450 var target_ofmt: ?[]const u8 = null;458 var target_ofmt: ?[]const u8 = null;
451 var output_mode: std.builtin.OutputMode = undefined;459 var output_mode: std.builtin.OutputMode = undefined;
452 var emit_h: Emit = undefined;460 var emit_h: Emit = undefined;
461 var soname: SOName = undefined;
453 var ensure_libc_on_non_freestanding = false;462 var ensure_libc_on_non_freestanding = false;
454 var ensure_libcpp_on_non_freestanding = false;463 var ensure_libcpp_on_non_freestanding = false;
455 var link_libc = false;464 var link_libc = false;
...@@ -464,7 +473,6 @@ fn buildOutputType(...@@ -464,7 +473,6 @@ fn buildOutputType(
464 var linker_script: ?[]const u8 = null;473 var linker_script: ?[]const u8 = null;
465 var version_script: ?[]const u8 = null;474 var version_script: ?[]const u8 = null;
466 var disable_c_depfile = false;475 var disable_c_depfile = false;
467 var override_soname: ?[]const u8 = null;
468 var linker_gc_sections: ?bool = null;476 var linker_gc_sections: ?bool = null;
469 var linker_allow_shlib_undefined: ?bool = null;477 var linker_allow_shlib_undefined: ?bool = null;
470 var linker_bind_global_refs_locally: ?bool = null;478 var linker_bind_global_refs_locally: ?bool = null;
...@@ -561,6 +569,8 @@ fn buildOutputType(...@@ -561,6 +569,8 @@ fn buildOutputType(
561 // .translate_c, .zig_test, .run => emit_h = .no,569 // .translate_c, .zig_test, .run => emit_h = .no,
562 // else => unreachable,570 // else => unreachable,
563 //}571 //}
572
573 soname = .yes_default_value;
564 const args = all_args[2..];574 const args = all_args[2..];
565 var i: usize = 0;575 var i: usize = 0;
566 args_loop: while (i < args.len) : (i += 1) {576 args_loop: while (i < args.len) : (i += 1) {
...@@ -821,6 +831,12 @@ fn buildOutputType(...@@ -821,6 +831,12 @@ fn buildOutputType(
821 use_clang = false;831 use_clang = false;
822 } else if (mem.eql(u8, arg, "-rdynamic")) {832 } else if (mem.eql(u8, arg, "-rdynamic")) {
823 rdynamic = true;833 rdynamic = true;
834 } else if (mem.eql(u8, arg, "-fsoname")) {
835 soname = .yes_default_value;
836 } else if (mem.startsWith(u8, arg, "-fsoname=")) {
837 soname = .{ .yes = arg["-fsoname=".len..] };
838 } else if (mem.eql(u8, arg, "-fno-soname")) {
839 soname = .no;
824 } else if (mem.eql(u8, arg, "-femit-bin")) {840 } else if (mem.eql(u8, arg, "-femit-bin")) {
825 emit_bin = .yes_default_path;841 emit_bin = .yes_default_path;
826 } else if (mem.startsWith(u8, arg, "-femit-bin=")) {842 } else if (mem.startsWith(u8, arg, "-femit-bin=")) {
...@@ -948,6 +964,7 @@ fn buildOutputType(...@@ -948,6 +964,7 @@ fn buildOutputType(
948 },964 },
949 .cc, .cpp => {965 .cc, .cpp => {
950 emit_h = .no;966 emit_h = .no;
967 soname = .no;
951 strip = true;968 strip = true;
952 ensure_libc_on_non_freestanding = true;969 ensure_libc_on_non_freestanding = true;
953 ensure_libcpp_on_non_freestanding = arg_mode == .cpp;970 ensure_libcpp_on_non_freestanding = arg_mode == .cpp;
...@@ -1091,33 +1108,33 @@ fn buildOutputType(...@@ -1091,33 +1108,33 @@ fn buildOutputType(
1091 if (i >= linker_args.items.len) {1108 if (i >= linker_args.items.len) {
1092 fatal("expected linker arg after '{}'", .{arg});1109 fatal("expected linker arg after '{}'", .{arg});
1093 }1110 }
1094 const soname = linker_args.items[i];1111 const name = linker_args.items[i];
1095 override_soname = soname;1112 soname = .{ .yes = name };
1096 // Use it as --name.1113 // Use it as --name.
1097 // Example: libsoundio.so.21114 // Example: libsoundio.so.2
1098 var prefix: usize = 0;1115 var prefix: usize = 0;
1099 if (mem.startsWith(u8, soname, "lib")) {1116 if (mem.startsWith(u8, name, "lib")) {
1100 prefix = 3;1117 prefix = 3;
1101 }1118 }
1102 var end: usize = soname.len;1119 var end: usize = name.len;
1103 if (mem.endsWith(u8, soname, ".so")) {1120 if (mem.endsWith(u8, name, ".so")) {
1104 end -= 3;1121 end -= 3;
1105 } else {1122 } else {
1106 var found_digit = false;1123 var found_digit = false;
1107 while (end > 0 and std.ascii.isDigit(soname[end - 1])) {1124 while (end > 0 and std.ascii.isDigit(name[end - 1])) {
1108 found_digit = true;1125 found_digit = true;
1109 end -= 1;1126 end -= 1;
1110 }1127 }
1111 if (found_digit and end > 0 and soname[end - 1] == '.') {1128 if (found_digit and end > 0 and name[end - 1] == '.') {
1112 end -= 1;1129 end -= 1;
1113 } else {1130 } else {
1114 end = soname.len;1131 end = name.len;
1115 }1132 }
1116 if (mem.endsWith(u8, soname[prefix..end], ".so")) {1133 if (mem.endsWith(u8, name[prefix..end], ".so")) {
1117 end -= 3;1134 end -= 3;
1118 }1135 }
1119 }1136 }
1120 provided_name = soname[prefix..end];1137 provided_name = name[prefix..end];
1121 } else if (mem.eql(u8, arg, "-rpath")) {1138 } else if (mem.eql(u8, arg, "-rpath")) {
1122 i += 1;1139 i += 1;
1123 if (i >= linker_args.items.len) {1140 if (i >= linker_args.items.len) {
...@@ -1419,6 +1436,18 @@ fn buildOutputType(...@@ -1419,6 +1436,18 @@ fn buildOutputType(
1419 const have_enable_cache = enable_cache orelse false;1436 const have_enable_cache = enable_cache orelse false;
1420 const optional_version = if (have_version) version else null;1437 const optional_version = if (have_version) version else null;
14211438
1439 const resolved_soname: ?[]const u8 = switch (soname) {
1440 .yes => |explicit| explicit,
1441 .no => null,
1442 .yes_default_value => switch (object_format) {
1443 .elf => if (have_version)
1444 try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ root_name, version.major })
1445 else
1446 try std.fmt.allocPrint(arena, "lib{s}.so", .{root_name}),
1447 else => null,
1448 },
1449 };
1450
1422 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {1451 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
1423 .no => null,1452 .no => null,
1424 .yes_default_path => Compilation.EmitLoc{1453 .yes_default_path => Compilation.EmitLoc{
...@@ -1645,7 +1674,7 @@ fn buildOutputType(...@@ -1645,7 +1674,7 @@ fn buildOutputType(
1645 .linker_script = linker_script,1674 .linker_script = linker_script,
1646 .version_script = version_script,1675 .version_script = version_script,
1647 .disable_c_depfile = disable_c_depfile,1676 .disable_c_depfile = disable_c_depfile,
1648 .override_soname = override_soname,1677 .soname = resolved_soname,
1649 .linker_gc_sections = linker_gc_sections,1678 .linker_gc_sections = linker_gc_sections,
1650 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,1679 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
1651 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,1680 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,