| ... | @@ -304,6 +304,8 @@ const usage_build_generic = | ... | @@ -304,6 +304,8 @@ const usage_build_generic = |
| 304 | \\ --version-script [path] Provide a version .map file | 304 | \\ --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 semver | 306 | \\ --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 table | 309 | \\ -rdynamic Add all symbols to the dynamic symbol table |
| 308 | \\ -rpath [path] Add directory to the runtime library search path | 310 | \\ -rpath [path] Add directory to the runtime library search path |
| 309 | \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library | 311 | \\ -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 | ; |
| 350 | | 352 | |
| | 353 | const SOName = union(enum) { |
| | 354 | no, |
| | 355 | yes_default_value, |
| | 356 | yes: []const u8, |
| | 357 | }; |
| | 358 | |
| 351 | const Emit = union(enum) { | 359 | const 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.2 | 1114 | // 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; |
| 1421 | | 1438 | |
| | 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, |