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 {
360360 link_emit_relocs: bool = false,
361361 linker_script: ?[]const u8 = null,
362362 version_script: ?[]const u8 = null,
363 override_soname: ?[]const u8 = null,
363 soname: ?[]const u8 = null,
364364 linker_gc_sections: ?bool = null,
365365 linker_allow_shlib_undefined: ?bool = null,
366366 linker_bind_global_refs_locally: ?bool = null,
......@@ -810,7 +810,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
810810 .emit_relocs = options.link_emit_relocs,
811811 .rdynamic = options.rdynamic,
812812 .extra_lld_args = options.lld_argv,
813 .override_soname = options.override_soname,
813 .soname = options.soname,
814814 .version = options.version,
815815 .libc_installation = libc_dirs.libc_installation,
816816 .pic = pic,
src/glibc.zig+4-3
......@@ -911,13 +911,14 @@ fn buildSharedLib(
911911 const tracy = trace(@src());
912912 defer tracy.end();
913913
914 const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
914915 const emit_bin = Compilation.EmitLoc{
915916 .directory = bin_directory,
916 .basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover }),
917 .basename = basename,
917918 };
918919 const version: std.builtin.Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
919920 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;
921922 const map_file_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, all_map_basename });
922923 const c_source_files = [1]Compilation.CSourceFile{
923924 .{
......@@ -955,7 +956,7 @@ fn buildSharedLib(
955956 .clang_passthrough_mode = comp.clang_passthrough_mode,
956957 .version = version,
957958 .version_script = map_file_path,
958 .override_soname = override_soname,
959 .soname = soname,
959960 .c_source_files = &c_source_files,
960961 .is_compiler_rt_or_libc = true,
961962 });
src/link.zig+1-1
......@@ -87,7 +87,7 @@ pub const Options = struct {
8787 subsystem: ?std.Target.SubSystem,
8888 linker_script: ?[]const u8,
8989 version_script: ?[]const u8,
90 override_soname: ?[]const u8,
90 soname: ?[]const u8,
9191 llvm_cpu_features: ?[*:0]const u8,
9292 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
9393 extra_lld_args: []const []const u8,
src/link/Elf.zig+6-11
......@@ -1313,10 +1313,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
13131313 man.hash.addOptionalBytes(self.base.options.dynamic_linker);
13141314 }
13151315 }
1316 if (is_dyn_lib) {
1317 man.hash.addOptionalBytes(self.base.options.override_soname);
1318 man.hash.addOptional(self.base.options.version);
1319 }
1316 man.hash.addOptionalBytes(self.base.options.soname);
1317 man.hash.addOptional(self.base.options.version);
13201318 man.hash.addStringSet(self.base.options.system_libs);
13211319 man.hash.add(allow_shlib_undefined);
13221320 man.hash.add(self.base.options.bind_global_refs_locally);
......@@ -1505,13 +1503,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
15051503 }
15061504
15071505 if (is_dyn_lib) {
1508 const soname = self.base.options.override_soname orelse if (self.base.options.version) |ver|
1509 try std.fmt.allocPrint(arena, "lib{}.so.{}", .{ self.base.options.root_name, ver.major })
1510 else
1511 try std.fmt.allocPrint(arena, "lib{}.so", .{self.base.options.root_name});
1512 try argv.append("-soname");
1513 try argv.append(soname);
1514
1506 if (self.base.options.soname) |soname| {
1507 try argv.append("-soname");
1508 try argv.append(soname);
1509 }
15151510 if (self.base.options.version_script) |version_script| {
15161511 try argv.append("-version-script");
15171512 try argv.append(version_script);
src/main.zig+41-12
......@@ -304,6 +304,8 @@ const usage_build_generic =
304304 \\ --version-script [path] Provide a version .map file
305305 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
306306 \\ --version [ver] Dynamic library semver
307 \\ -fsoname[=name] (linux) Override the default SONAME value
308 \\ -fno-soname (linux) Disable emitting a SONAME
307309 \\ -rdynamic Add all symbols to the dynamic symbol table
308310 \\ -rpath [path] Add directory to the runtime library search path
309311 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
......@@ -348,6 +350,12 @@ const repl_help =
348350 \\
349351;
350352
353const SOName = union(enum) {
354 no,
355 yes_default_value,
356 yes: []const u8,
357};
358
351359const Emit = union(enum) {
352360 no,
353361 yes_default_path,
......@@ -450,6 +458,7 @@ fn buildOutputType(
450458 var target_ofmt: ?[]const u8 = null;
451459 var output_mode: std.builtin.OutputMode = undefined;
452460 var emit_h: Emit = undefined;
461 var soname: SOName = undefined;
453462 var ensure_libc_on_non_freestanding = false;
454463 var ensure_libcpp_on_non_freestanding = false;
455464 var link_libc = false;
......@@ -464,7 +473,6 @@ fn buildOutputType(
464473 var linker_script: ?[]const u8 = null;
465474 var version_script: ?[]const u8 = null;
466475 var disable_c_depfile = false;
467 var override_soname: ?[]const u8 = null;
468476 var linker_gc_sections: ?bool = null;
469477 var linker_allow_shlib_undefined: ?bool = null;
470478 var linker_bind_global_refs_locally: ?bool = null;
......@@ -561,6 +569,8 @@ fn buildOutputType(
561569 // .translate_c, .zig_test, .run => emit_h = .no,
562570 // else => unreachable,
563571 //}
572
573 soname = .yes_default_value;
564574 const args = all_args[2..];
565575 var i: usize = 0;
566576 args_loop: while (i < args.len) : (i += 1) {
......@@ -821,6 +831,12 @@ fn buildOutputType(
821831 use_clang = false;
822832 } else if (mem.eql(u8, arg, "-rdynamic")) {
823833 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;
824840 } else if (mem.eql(u8, arg, "-femit-bin")) {
825841 emit_bin = .yes_default_path;
826842 } else if (mem.startsWith(u8, arg, "-femit-bin=")) {
......@@ -948,6 +964,7 @@ fn buildOutputType(
948964 },
949965 .cc, .cpp => {
950966 emit_h = .no;
967 soname = .no;
951968 strip = true;
952969 ensure_libc_on_non_freestanding = true;
953970 ensure_libcpp_on_non_freestanding = arg_mode == .cpp;
......@@ -1091,33 +1108,33 @@ fn buildOutputType(
10911108 if (i >= linker_args.items.len) {
10921109 fatal("expected linker arg after '{}'", .{arg});
10931110 }
1094 const soname = linker_args.items[i];
1095 override_soname = soname;
1111 const name = linker_args.items[i];
1112 soname = .{ .yes = name };
10961113 // Use it as --name.
10971114 // Example: libsoundio.so.2
10981115 var prefix: usize = 0;
1099 if (mem.startsWith(u8, soname, "lib")) {
1116 if (mem.startsWith(u8, name, "lib")) {
11001117 prefix = 3;
11011118 }
1102 var end: usize = soname.len;
1103 if (mem.endsWith(u8, soname, ".so")) {
1119 var end: usize = name.len;
1120 if (mem.endsWith(u8, name, ".so")) {
11041121 end -= 3;
11051122 } else {
11061123 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])) {
11081125 found_digit = true;
11091126 end -= 1;
11101127 }
1111 if (found_digit and end > 0 and soname[end - 1] == '.') {
1128 if (found_digit and end > 0 and name[end - 1] == '.') {
11121129 end -= 1;
11131130 } else {
1114 end = soname.len;
1131 end = name.len;
11151132 }
1116 if (mem.endsWith(u8, soname[prefix..end], ".so")) {
1133 if (mem.endsWith(u8, name[prefix..end], ".so")) {
11171134 end -= 3;
11181135 }
11191136 }
1120 provided_name = soname[prefix..end];
1137 provided_name = name[prefix..end];
11211138 } else if (mem.eql(u8, arg, "-rpath")) {
11221139 i += 1;
11231140 if (i >= linker_args.items.len) {
......@@ -1419,6 +1436,18 @@ fn buildOutputType(
14191436 const have_enable_cache = enable_cache orelse false;
14201437 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
14221451 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
14231452 .no => null,
14241453 .yes_default_path => Compilation.EmitLoc{
......@@ -1645,7 +1674,7 @@ fn buildOutputType(
16451674 .linker_script = linker_script,
16461675 .version_script = version_script,
16471676 .disable_c_depfile = disable_c_depfile,
1648 .override_soname = override_soname,
1677 .soname = resolved_soname,
16491678 .linker_gc_sections = linker_gc_sections,
16501679 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
16511680 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,