@@ -364,7 +364,7 @@ pub const InitOptions = struct {
|
||||
link_emit_relocs: bool = false,
|
||||
linker_script: ?[]const u8 = null,
|
||||
version_script: ?[]const u8 = null,
|
||||
override_soname: ?[]const u8 = null,
|
||||
soname: ?[]const u8 = null,
|
||||
linker_gc_sections: ?bool = null,
|
||||
linker_allow_shlib_undefined: ?bool = null,
|
||||
linker_bind_global_refs_locally: ?bool = null,
|
||||
@@ -828,7 +828,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.emit_relocs = options.link_emit_relocs,
|
||||
.rdynamic = options.rdynamic,
|
||||
.extra_lld_args = options.lld_argv,
|
||||
.override_soname = options.override_soname,
|
||||
.soname = options.soname,
|
||||
.version = options.version,
|
||||
.libc_installation = libc_dirs.libc_installation,
|
||||
.pic = pic,
|
||||
|
||||
@@ -911,13 +911,14 @@ fn buildSharedLib(
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover });
|
||||
const emit_bin = Compilation.EmitLoc{
|
||||
.directory = bin_directory,
|
||||
.basename = try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ lib.name, lib.sover }),
|
||||
.basename = basename,
|
||||
};
|
||||
const version: std.builtin.Version = .{ .major = lib.sover, .minor = 0, .patch = 0 };
|
||||
const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
|
||||
const override_soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else null;
|
||||
const soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else basename;
|
||||
const map_file_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, all_map_basename });
|
||||
const c_source_files = [1]Compilation.CSourceFile{
|
||||
.{
|
||||
@@ -955,7 +956,7 @@ fn buildSharedLib(
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.version = version,
|
||||
.version_script = map_file_path,
|
||||
.override_soname = override_soname,
|
||||
.soname = soname,
|
||||
.c_source_files = &c_source_files,
|
||||
.is_compiler_rt_or_libc = true,
|
||||
});
|
||||
|
||||
@@ -88,7 +88,7 @@ pub const Options = struct {
|
||||
subsystem: ?std.Target.SubSystem,
|
||||
linker_script: ?[]const u8,
|
||||
version_script: ?[]const u8,
|
||||
override_soname: ?[]const u8,
|
||||
soname: ?[]const u8,
|
||||
llvm_cpu_features: ?[*:0]const u8,
|
||||
/// Extra args passed directly to LLD. Ignored when not linking with LLD.
|
||||
extra_lld_args: []const []const u8,
|
||||
|
||||
@@ -1313,10 +1313,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
man.hash.addOptionalBytes(self.base.options.dynamic_linker);
|
||||
}
|
||||
}
|
||||
if (is_dyn_lib) {
|
||||
man.hash.addOptionalBytes(self.base.options.override_soname);
|
||||
man.hash.addOptional(self.base.options.version);
|
||||
}
|
||||
man.hash.addOptionalBytes(self.base.options.soname);
|
||||
man.hash.addOptional(self.base.options.version);
|
||||
man.hash.addStringSet(self.base.options.system_libs);
|
||||
man.hash.add(allow_shlib_undefined);
|
||||
man.hash.add(self.base.options.bind_global_refs_locally);
|
||||
@@ -1512,13 +1510,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
if (is_dyn_lib) {
|
||||
const soname = self.base.options.override_soname orelse if (self.base.options.version) |ver|
|
||||
try std.fmt.allocPrint(arena, "lib{}.so.{}", .{ self.base.options.root_name, ver.major })
|
||||
else
|
||||
try std.fmt.allocPrint(arena, "lib{}.so", .{self.base.options.root_name});
|
||||
try argv.append("-soname");
|
||||
try argv.append(soname);
|
||||
|
||||
if (self.base.options.soname) |soname| {
|
||||
try argv.append("-soname");
|
||||
try argv.append(soname);
|
||||
}
|
||||
if (self.base.options.version_script) |version_script| {
|
||||
try argv.append("-version-script");
|
||||
try argv.append(version_script);
|
||||
|
||||
53
src/main.zig
53
src/main.zig
@@ -306,6 +306,8 @@ const usage_build_generic =
|
||||
\\ --version-script [path] Provide a version .map file
|
||||
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
|
||||
\\ --version [ver] Dynamic library semver
|
||||
\\ -fsoname[=name] (linux) Override the default SONAME value
|
||||
\\ -fno-soname (linux) Disable emitting a SONAME
|
||||
\\ -rdynamic Add all symbols to the dynamic symbol table
|
||||
\\ -rpath [path] Add directory to the runtime library search path
|
||||
\\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
|
||||
@@ -350,6 +352,12 @@ const repl_help =
|
||||
\\
|
||||
;
|
||||
|
||||
const SOName = union(enum) {
|
||||
no,
|
||||
yes_default_value,
|
||||
yes: []const u8,
|
||||
};
|
||||
|
||||
const Emit = union(enum) {
|
||||
no,
|
||||
yes_default_path,
|
||||
@@ -452,6 +460,7 @@ fn buildOutputType(
|
||||
var target_ofmt: ?[]const u8 = null;
|
||||
var output_mode: std.builtin.OutputMode = undefined;
|
||||
var emit_h: Emit = undefined;
|
||||
var soname: SOName = undefined;
|
||||
var ensure_libc_on_non_freestanding = false;
|
||||
var ensure_libcpp_on_non_freestanding = false;
|
||||
var link_libc = false;
|
||||
@@ -467,7 +476,6 @@ fn buildOutputType(
|
||||
var linker_script: ?[]const u8 = null;
|
||||
var version_script: ?[]const u8 = null;
|
||||
var disable_c_depfile = false;
|
||||
var override_soname: ?[]const u8 = null;
|
||||
var linker_gc_sections: ?bool = null;
|
||||
var linker_allow_shlib_undefined: ?bool = null;
|
||||
var linker_bind_global_refs_locally: ?bool = null;
|
||||
@@ -564,6 +572,8 @@ fn buildOutputType(
|
||||
// .translate_c, .zig_test, .run => emit_h = .no,
|
||||
// else => unreachable,
|
||||
//}
|
||||
|
||||
soname = .yes_default_value;
|
||||
const args = all_args[2..];
|
||||
var i: usize = 0;
|
||||
args_loop: while (i < args.len) : (i += 1) {
|
||||
@@ -828,6 +838,12 @@ fn buildOutputType(
|
||||
use_clang = false;
|
||||
} else if (mem.eql(u8, arg, "-rdynamic")) {
|
||||
rdynamic = true;
|
||||
} else if (mem.eql(u8, arg, "-fsoname")) {
|
||||
soname = .yes_default_value;
|
||||
} else if (mem.startsWith(u8, arg, "-fsoname=")) {
|
||||
soname = .{ .yes = arg["-fsoname=".len..] };
|
||||
} else if (mem.eql(u8, arg, "-fno-soname")) {
|
||||
soname = .no;
|
||||
} else if (mem.eql(u8, arg, "-femit-bin")) {
|
||||
emit_bin = .yes_default_path;
|
||||
} else if (mem.startsWith(u8, arg, "-femit-bin=")) {
|
||||
@@ -955,6 +971,7 @@ fn buildOutputType(
|
||||
},
|
||||
.cc, .cpp => {
|
||||
emit_h = .no;
|
||||
soname = .no;
|
||||
strip = true;
|
||||
ensure_libc_on_non_freestanding = true;
|
||||
ensure_libcpp_on_non_freestanding = arg_mode == .cpp;
|
||||
@@ -1108,33 +1125,33 @@ fn buildOutputType(
|
||||
if (i >= linker_args.items.len) {
|
||||
fatal("expected linker arg after '{}'", .{arg});
|
||||
}
|
||||
const soname = linker_args.items[i];
|
||||
override_soname = soname;
|
||||
const name = linker_args.items[i];
|
||||
soname = .{ .yes = name };
|
||||
// Use it as --name.
|
||||
// Example: libsoundio.so.2
|
||||
var prefix: usize = 0;
|
||||
if (mem.startsWith(u8, soname, "lib")) {
|
||||
if (mem.startsWith(u8, name, "lib")) {
|
||||
prefix = 3;
|
||||
}
|
||||
var end: usize = soname.len;
|
||||
if (mem.endsWith(u8, soname, ".so")) {
|
||||
var end: usize = name.len;
|
||||
if (mem.endsWith(u8, name, ".so")) {
|
||||
end -= 3;
|
||||
} else {
|
||||
var found_digit = false;
|
||||
while (end > 0 and std.ascii.isDigit(soname[end - 1])) {
|
||||
while (end > 0 and std.ascii.isDigit(name[end - 1])) {
|
||||
found_digit = true;
|
||||
end -= 1;
|
||||
}
|
||||
if (found_digit and end > 0 and soname[end - 1] == '.') {
|
||||
if (found_digit and end > 0 and name[end - 1] == '.') {
|
||||
end -= 1;
|
||||
} else {
|
||||
end = soname.len;
|
||||
end = name.len;
|
||||
}
|
||||
if (mem.endsWith(u8, soname[prefix..end], ".so")) {
|
||||
if (mem.endsWith(u8, name[prefix..end], ".so")) {
|
||||
end -= 3;
|
||||
}
|
||||
}
|
||||
provided_name = soname[prefix..end];
|
||||
provided_name = name[prefix..end];
|
||||
} else if (mem.eql(u8, arg, "-rpath")) {
|
||||
i += 1;
|
||||
if (i >= linker_args.items.len) {
|
||||
@@ -1433,6 +1450,18 @@ fn buildOutputType(
|
||||
const have_enable_cache = enable_cache orelse false;
|
||||
const optional_version = if (have_version) version else null;
|
||||
|
||||
const resolved_soname: ?[]const u8 = switch (soname) {
|
||||
.yes => |explicit| explicit,
|
||||
.no => null,
|
||||
.yes_default_value => switch (object_format) {
|
||||
.elf => if (have_version)
|
||||
try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ root_name, version.major })
|
||||
else
|
||||
try std.fmt.allocPrint(arena, "lib{s}.so", .{root_name}),
|
||||
else => null,
|
||||
},
|
||||
};
|
||||
|
||||
const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
|
||||
.no => null,
|
||||
.yes_default_path => Compilation.EmitLoc{
|
||||
@@ -1660,7 +1689,7 @@ fn buildOutputType(
|
||||
.linker_script = linker_script,
|
||||
.version_script = version_script,
|
||||
.disable_c_depfile = disable_c_depfile,
|
||||
.override_soname = override_soname,
|
||||
.soname = resolved_soname,
|
||||
.linker_gc_sections = linker_gc_sections,
|
||||
.linker_allow_shlib_undefined = linker_allow_shlib_undefined,
|
||||
.linker_bind_global_refs_locally = linker_bind_global_refs_locally,
|
||||
|
||||
Reference in New Issue
Block a user