| author | |
| committer | |
| log | 728ce2d7c18e23ca6c36d86f4ee1ea4ce3ac81e2 |
| tree | b84ffae450a01a7fa2cf22d87176fb633125b359 |
| parent | df5085bde012773b974f58e8ee28ed90ff686468 |
* build.zig: the result of b.option() can be assigned directly in many
cases thanks to the return type being an optional
* std.Build: make the build system aware of the
std.Build.Step.Compile.BuildId type when used as an option.
- remove extraneous newlines in error logs
* simplify caching logic
* simplify hexstring parsing tests and use a doc test
* simplify hashing logic. don't use an optional when the `none` tag
already provides this meaning.
* CLI: fix incorrect linker arg parsing9 files changed, 169 insertions(+), 164 deletions(-)
build.zig+5-2| ... | ... | @@ -167,8 +167,11 @@ pub fn build(b: *std.Build) !void { |
| 167 | 167 | exe.sanitize_thread = sanitize_thread; |
| 168 | 168 | exe.entitlements = entitlements; |
| 169 | 169 | |
| 170 | if (b.option([]const u8, "build-id", "Include a build id note")) |build_id| | |
| 171 | exe.build_id = try std.Build.CompileStep.BuildId.parse(b.allocator, build_id); | |
| 170 | exe.build_id = b.option( | |
| 171 | std.Build.Step.Compile.BuildId, | |
| 172 | "build-id", | |
| 173 | "Request creation of '.note.gnu.build-id' section", | |
| 174 | ); | |
| 172 | 175 | |
| 173 | 176 | b.installArtifact(exe); |
| 174 | 177 |
lib/std/Build.zig+42-20| ... | ... | @@ -181,6 +181,7 @@ const TypeId = enum { |
| 181 | 181 | @"enum", |
| 182 | 182 | string, |
| 183 | 183 | list, |
| 184 | build_id, | |
| 184 | 185 | }; |
| 185 | 186 | |
| 186 | 187 | const TopLevelStep = struct { |
| ... | ... | @@ -832,13 +833,13 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 832 | 833 | } else if (mem.eql(u8, s, "false")) { |
| 833 | 834 | return false; |
| 834 | 835 | } else { |
| 835 | log.err("Expected -D{s} to be a boolean, but received '{s}'\n", .{ name, s }); | |
| 836 | log.err("Expected -D{s} to be a boolean, but received '{s}'", .{ name, s }); | |
| 836 | 837 | self.markInvalidUserInput(); |
| 837 | 838 | return null; |
| 838 | 839 | } |
| 839 | 840 | }, |
| 840 | 841 | .list, .map => { |
| 841 | log.err("Expected -D{s} to be a boolean, but received a {s}.\n", .{ | |
| 842 | log.err("Expected -D{s} to be a boolean, but received a {s}.", .{ | |
| 842 | 843 | name, @tagName(option_ptr.value), |
| 843 | 844 | }); |
| 844 | 845 | self.markInvalidUserInput(); |
| ... | ... | @@ -847,7 +848,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 847 | 848 | }, |
| 848 | 849 | .int => switch (option_ptr.value) { |
| 849 | 850 | .flag, .list, .map => { |
| 850 | log.err("Expected -D{s} to be an integer, but received a {s}.\n", .{ | |
| 851 | log.err("Expected -D{s} to be an integer, but received a {s}.", .{ | |
| 851 | 852 | name, @tagName(option_ptr.value), |
| 852 | 853 | }); |
| 853 | 854 | self.markInvalidUserInput(); |
| ... | ... | @@ -856,12 +857,12 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 856 | 857 | .scalar => |s| { |
| 857 | 858 | const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) { |
| 858 | 859 | error.Overflow => { |
| 859 | log.err("-D{s} value {s} cannot fit into type {s}.\n", .{ name, s, @typeName(T) }); | |
| 860 | log.err("-D{s} value {s} cannot fit into type {s}.", .{ name, s, @typeName(T) }); | |
| 860 | 861 | self.markInvalidUserInput(); |
| 861 | 862 | return null; |
| 862 | 863 | }, |
| 863 | 864 | else => { |
| 864 | log.err("Expected -D{s} to be an integer of type {s}.\n", .{ name, @typeName(T) }); | |
| 865 | log.err("Expected -D{s} to be an integer of type {s}.", .{ name, @typeName(T) }); | |
| 865 | 866 | self.markInvalidUserInput(); |
| 866 | 867 | return null; |
| 867 | 868 | }, |
| ... | ... | @@ -871,7 +872,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 871 | 872 | }, |
| 872 | 873 | .float => switch (option_ptr.value) { |
| 873 | 874 | .flag, .map, .list => { |
| 874 | log.err("Expected -D{s} to be a float, but received a {s}.\n", .{ | |
| 875 | log.err("Expected -D{s} to be a float, but received a {s}.", .{ | |
| 875 | 876 | name, @tagName(option_ptr.value), |
| 876 | 877 | }); |
| 877 | 878 | self.markInvalidUserInput(); |
| ... | ... | @@ -879,7 +880,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 879 | 880 | }, |
| 880 | 881 | .scalar => |s| { |
| 881 | 882 | const n = std.fmt.parseFloat(T, s) catch { |
| 882 | log.err("Expected -D{s} to be a float of type {s}.\n", .{ name, @typeName(T) }); | |
| 883 | log.err("Expected -D{s} to be a float of type {s}.", .{ name, @typeName(T) }); | |
| 883 | 884 | self.markInvalidUserInput(); |
| 884 | 885 | return null; |
| 885 | 886 | }; |
| ... | ... | @@ -888,7 +889,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 888 | 889 | }, |
| 889 | 890 | .@"enum" => switch (option_ptr.value) { |
| 890 | 891 | .flag, .map, .list => { |
| 891 | log.err("Expected -D{s} to be an enum, but received a {s}.\n", .{ | |
| 892 | log.err("Expected -D{s} to be an enum, but received a {s}.", .{ | |
| 892 | 893 | name, @tagName(option_ptr.value), |
| 893 | 894 | }); |
| 894 | 895 | self.markInvalidUserInput(); |
| ... | ... | @@ -898,7 +899,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 898 | 899 | if (std.meta.stringToEnum(T, s)) |enum_lit| { |
| 899 | 900 | return enum_lit; |
| 900 | 901 | } else { |
| 901 | log.err("Expected -D{s} to be of type {s}.\n", .{ name, @typeName(T) }); | |
| 902 | log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(T) }); | |
| 902 | 903 | self.markInvalidUserInput(); |
| 903 | 904 | return null; |
| 904 | 905 | } |
| ... | ... | @@ -906,7 +907,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 906 | 907 | }, |
| 907 | 908 | .string => switch (option_ptr.value) { |
| 908 | 909 | .flag, .list, .map => { |
| 909 | log.err("Expected -D{s} to be a string, but received a {s}.\n", .{ | |
| 910 | log.err("Expected -D{s} to be a string, but received a {s}.", .{ | |
| 910 | 911 | name, @tagName(option_ptr.value), |
| 911 | 912 | }); |
| 912 | 913 | self.markInvalidUserInput(); |
| ... | ... | @@ -914,9 +915,27 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 914 | 915 | }, |
| 915 | 916 | .scalar => |s| return s, |
| 916 | 917 | }, |
| 918 | .build_id => switch (option_ptr.value) { | |
| 919 | .flag, .map, .list => { | |
| 920 | log.err("Expected -D{s} to be an enum, but received a {s}.", .{ | |
| 921 | name, @tagName(option_ptr.value), | |
| 922 | }); | |
| 923 | self.markInvalidUserInput(); | |
| 924 | return null; | |
| 925 | }, | |
| 926 | .scalar => |s| { | |
| 927 | if (Step.Compile.BuildId.parse(s)) |build_id| { | |
| 928 | return build_id; | |
| 929 | } else |err| { | |
| 930 | log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) }); | |
| 931 | self.markInvalidUserInput(); | |
| 932 | return null; | |
| 933 | } | |
| 934 | }, | |
| 935 | }, | |
| 917 | 936 | .list => switch (option_ptr.value) { |
| 918 | 937 | .flag, .map => { |
| 919 | log.err("Expected -D{s} to be a list, but received a {s}.\n", .{ | |
| 938 | log.err("Expected -D{s} to be a list, but received a {s}.", .{ | |
| 920 | 939 | name, @tagName(option_ptr.value), |
| 921 | 940 | }); |
| 922 | 941 | self.markInvalidUserInput(); |
| ... | ... | @@ -1183,15 +1202,18 @@ pub fn addUserInputFlag(self: *Build, name_raw: []const u8) !bool { |
| 1183 | 1202 | } |
| 1184 | 1203 | |
| 1185 | 1204 | fn typeToEnum(comptime T: type) TypeId { |
| 1186 | return switch (@typeInfo(T)) { | |
| 1187 | .Int => .int, | |
| 1188 | .Float => .float, | |
| 1189 | .Bool => .bool, | |
| 1190 | .Enum => .@"enum", | |
| 1191 | else => switch (T) { | |
| 1192 | []const u8 => .string, | |
| 1193 | []const []const u8 => .list, | |
| 1194 | else => @compileError("Unsupported type: " ++ @typeName(T)), | |
| 1205 | return switch (T) { | |
| 1206 | Step.Compile.BuildId => .build_id, | |
| 1207 | else => return switch (@typeInfo(T)) { | |
| 1208 | .Int => .int, | |
| 1209 | .Float => .float, | |
| 1210 | .Bool => .bool, | |
| 1211 | .Enum => .@"enum", | |
| 1212 | else => switch (T) { | |
| 1213 | []const u8 => .string, | |
| 1214 | []const []const u8 => .list, | |
| 1215 | else => @compileError("Unsupported type: " ++ @typeName(T)), | |
| 1216 | }, | |
| 1195 | 1217 | }, |
| 1196 | 1218 | }; |
| 1197 | 1219 | } |
lib/std/Build/Cache.zig+4| ... | ... | @@ -235,6 +235,10 @@ pub const HashHelper = struct { |
| 235 | 235 | .none => {}, |
| 236 | 236 | } |
| 237 | 237 | }, |
| 238 | std.Build.Step.Compile.BuildId => switch (x) { | |
| 239 | .none, .fast, .uuid, .sha1, .md5 => hh.add(std.meta.activeTag(x)), | |
| 240 | .hexstring => |hex_string| hh.addBytes(hex_string.toSlice()), | |
| 241 | }, | |
| 238 | 242 | else => switch (@typeInfo(@TypeOf(x))) { |
| 239 | 243 | .Bool, .Int, .Enum, .Array => hh.addBytes(mem.asBytes(&x)), |
| 240 | 244 | else => @compileError("unable to hash type " ++ @typeName(@TypeOf(x))), |
lib/std/Build/Step/Compile.zig+55-86| ... | ... | @@ -294,27 +294,41 @@ pub const BuildId = union(enum) { |
| 294 | 294 | uuid, |
| 295 | 295 | sha1, |
| 296 | 296 | md5, |
| 297 | hexstring: []const u8, | |
| 297 | hexstring: HexString, | |
| 298 | ||
| 299 | pub fn eql(a: BuildId, b: BuildId) bool { | |
| 300 | const a_tag = std.meta.activeTag(a); | |
| 301 | const b_tag = std.meta.activeTag(b); | |
| 302 | if (a_tag != b_tag) return false; | |
| 303 | return switch (a) { | |
| 304 | .none, .fast, .uuid, .sha1, .md5 => true, | |
| 305 | .hexstring => |a_hexstring| mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()), | |
| 306 | }; | |
| 307 | } | |
| 298 | 308 | |
| 299 | pub fn hash(self: BuildId, hasher: anytype) void { | |
| 300 | switch (self) { | |
| 301 | .none, .fast, .uuid, .sha1, .md5 => { | |
| 302 | hasher.update(@tagName(self)); | |
| 303 | }, | |
| 304 | .hexstring => |str| { | |
| 305 | hasher.update("0x"); | |
| 306 | hasher.update(str); | |
| 307 | }, | |
| 309 | pub const HexString = struct { | |
| 310 | bytes: [32]u8, | |
| 311 | len: u8, | |
| 312 | ||
| 313 | /// Result is byte values, *not* hex-encoded. | |
| 314 | pub fn toSlice(hs: *const HexString) []const u8 { | |
| 315 | return hs.bytes[0..hs.len]; | |
| 308 | 316 | } |
| 317 | }; | |
| 318 | ||
| 319 | /// Input is byte values, *not* hex-encoded. | |
| 320 | /// Asserts `bytes` fits inside `HexString` | |
| 321 | pub fn initHexString(bytes: []const u8) BuildId { | |
| 322 | var result: BuildId = .{ .hexstring = .{ | |
| 323 | .bytes = undefined, | |
| 324 | .len = @intCast(u8, bytes.len), | |
| 325 | } }; | |
| 326 | @memcpy(result.hexstring.bytes[0..bytes.len], bytes); | |
| 327 | return result; | |
| 309 | 328 | } |
| 310 | 329 | |
| 311 | // parses the incoming BuildId. If returns a hexstring, it is allocated | |
| 312 | // by the provided allocator. | |
| 313 | pub fn parse(allocator: std.mem.Allocator, text: []const u8) error{ | |
| 314 | InvalidHexInt, | |
| 315 | InvalidBuildId, | |
| 316 | OutOfMemory, | |
| 317 | }!BuildId { | |
| 330 | /// Converts UTF-8 text to a `BuildId`. | |
| 331 | pub fn parse(text: []const u8) !BuildId { | |
| 318 | 332 | if (mem.eql(u8, text, "none")) { |
| 319 | 333 | return .none; |
| 320 | 334 | } else if (mem.eql(u8, text, "fast")) { |
| ... | ... | @@ -326,27 +340,27 @@ pub const BuildId = union(enum) { |
| 326 | 340 | } else if (mem.eql(u8, text, "md5")) { |
| 327 | 341 | return .md5; |
| 328 | 342 | } else if (mem.startsWith(u8, text, "0x")) { |
| 329 | var clean_hex_string = try allocator.alloc(u8, text.len); | |
| 330 | errdefer allocator.free(clean_hex_string); | |
| 331 | ||
| 332 | var i: usize = 0; | |
| 333 | for (text["0x".len..]) |c| { | |
| 334 | if (std.ascii.isHex(c)) { | |
| 335 | clean_hex_string[i] = c; | |
| 336 | i += 1; | |
| 337 | } else if (c == '-' or c == ':') { | |
| 338 | continue; | |
| 339 | } else { | |
| 340 | return error.InvalidHexInt; | |
| 341 | } | |
| 342 | } | |
| 343 | if (i < text.len) | |
| 344 | _ = allocator.resize(clean_hex_string, i); | |
| 345 | ||
| 346 | return BuildId{ .hexstring = clean_hex_string[0..i] }; | |
| 343 | var result: BuildId = .{ .hexstring = undefined }; | |
| 344 | const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]); | |
| 345 | result.hexstring.len = @intCast(u8, slice.len); | |
| 346 | return result; | |
| 347 | 347 | } |
| 348 | return error.InvalidBuildIdStyle; | |
| 349 | } | |
| 350 | ||
| 351 | test parse { | |
| 352 | try std.testing.expectEqual(BuildId.md5, try parse("md5")); | |
| 353 | try std.testing.expectEqual(BuildId.none, try parse("none")); | |
| 354 | try std.testing.expectEqual(BuildId.fast, try parse("fast")); | |
| 355 | try std.testing.expectEqual(BuildId.uuid, try parse("uuid")); | |
| 356 | try std.testing.expectEqual(BuildId.sha1, try parse("sha1")); | |
| 357 | try std.testing.expectEqual(BuildId.sha1, try parse("tree")); | |
| 348 | 358 | |
| 349 | return error.InvalidBuildId; | |
| 359 | try std.testing.expect(BuildId.initHexString("").eql(try parse("0x"))); | |
| 360 | try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456"))); | |
| 361 | try std.testing.expectError(error.InvalidLength, parse("0x12-34")); | |
| 362 | try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); | |
| 363 | try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); | |
| 350 | 364 | } |
| 351 | 365 | }; |
| 352 | 366 | |
| ... | ... | @@ -1872,11 +1886,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1872 | 1886 | |
| 1873 | 1887 | try addFlag(&zig_args, "valgrind", self.valgrind_support); |
| 1874 | 1888 | try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath); |
| 1889 | ||
| 1875 | 1890 | if (self.build_id) |build_id| { |
| 1876 | const fmt_str = "--build-id={s}{s}"; | |
| 1877 | 1891 | try zig_args.append(switch (build_id) { |
| 1878 | .hexstring => |str| try std.fmt.allocPrint(b.allocator, fmt_str, .{ "0x", str }), | |
| 1879 | .none, .fast, .uuid, .sha1, .md5 => try std.fmt.allocPrint(b.allocator, fmt_str, .{ "", @tagName(build_id) }), | |
| 1892 | .hexstring => |hs| b.fmt("--build-id=0x{s}", .{ | |
| 1893 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1894 | }), | |
| 1895 | .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}), | |
| 1880 | 1896 | }); |
| 1881 | 1897 | } |
| 1882 | 1898 | |
| ... | ... | @@ -2243,50 +2259,3 @@ fn checkCompileErrors(self: *Compile) !void { |
| 2243 | 2259 | \\========================================= |
| 2244 | 2260 | , .{ expected_generated.items, actual_stderr }); |
| 2245 | 2261 | } |
| 2246 | ||
| 2247 | const testing = std.testing; | |
| 2248 | ||
| 2249 | test "BuildId.parse" { | |
| 2250 | const tests = &[_]struct { | |
| 2251 | []const u8, | |
| 2252 | ?BuildId, | |
| 2253 | ?anyerror, | |
| 2254 | }{ | |
| 2255 | .{ "0x", BuildId{ .hexstring = "" }, null }, | |
| 2256 | .{ "0x12-34:", BuildId{ .hexstring = "1234" }, null }, | |
| 2257 | .{ "0x123456", BuildId{ .hexstring = "123456" }, null }, | |
| 2258 | .{ "md5", .md5, null }, | |
| 2259 | .{ "none", .none, null }, | |
| 2260 | .{ "fast", .fast, null }, | |
| 2261 | .{ "uuid", .uuid, null }, | |
| 2262 | .{ "sha1", .sha1, null }, | |
| 2263 | .{ "tree", .sha1, null }, | |
| 2264 | .{ "0xfoobbb", null, error.InvalidHexInt }, | |
| 2265 | .{ "yaddaxxx", null, error.InvalidBuildId }, | |
| 2266 | }; | |
| 2267 | ||
| 2268 | for (tests) |tt| { | |
| 2269 | const input = tt[0]; | |
| 2270 | const expected = tt[1]; | |
| 2271 | const expected_err = tt[2]; | |
| 2272 | ||
| 2273 | _ = (if (expected_err) |err| { | |
| 2274 | try testing.expectError(err, BuildId.parse(testing.allocator, input)); | |
| 2275 | } else blk: { | |
| 2276 | const actual = BuildId.parse(testing.allocator, input) catch |e| break :blk e; | |
| 2277 | switch (expected.?) { | |
| 2278 | .hexstring => |expected_str| { | |
| 2279 | try testing.expectEqualStrings(expected_str, actual.hexstring); | |
| 2280 | testing.allocator.free(actual.hexstring); | |
| 2281 | }, | |
| 2282 | else => try testing.expectEqual(expected.?, actual), | |
| 2283 | } | |
| 2284 | }) catch |e| { | |
| 2285 | std.log.err( | |
| 2286 | "BuildId.parse failed on {s}: expected {} got {!}", | |
| 2287 | .{ input, expected.?, e }, | |
| 2288 | ); | |
| 2289 | return e; | |
| 2290 | }; | |
| 2291 | } | |
| 2292 | } |
src/Compilation.zig+4-5| ... | ... | @@ -798,6 +798,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 798 | 798 | const unwind_tables = options.want_unwind_tables orelse |
| 799 | 799 | (link_libunwind or target_util.needUnwindTables(options.target)); |
| 800 | 800 | const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables; |
| 801 | const build_id = options.build_id orelse .none; | |
| 801 | 802 | |
| 802 | 803 | // Make a decision on whether to use LLD or our own linker. |
| 803 | 804 | const use_lld = options.use_lld orelse blk: { |
| ... | ... | @@ -828,7 +829,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 828 | 829 | options.output_mode == .Lib or |
| 829 | 830 | options.linker_script != null or options.version_script != null or |
| 830 | 831 | options.emit_implib != null or |
| 831 | options.build_id != null or | |
| 832 | build_id != .none or | |
| 832 | 833 | options.symbol_wrap_set.count() > 0) |
| 833 | 834 | { |
| 834 | 835 | break :blk true; |
| ... | ... | @@ -1514,7 +1515,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1514 | 1515 | .skip_linker_dependencies = options.skip_linker_dependencies, |
| 1515 | 1516 | .parent_compilation_link_libc = options.parent_compilation_link_libc, |
| 1516 | 1517 | .each_lib_rpath = options.each_lib_rpath orelse options.is_native_os, |
| 1517 | .build_id = options.build_id, | |
| 1518 | .build_id = build_id, | |
| 1518 | 1519 | .cache_mode = cache_mode, |
| 1519 | 1520 | .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, |
| 1520 | 1521 | .subsystem = options.subsystem, |
| ... | ... | @@ -2269,9 +2270,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes |
| 2269 | 2270 | man.hash.addListOfBytes(comp.bin_file.options.rpath_list); |
| 2270 | 2271 | man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys()); |
| 2271 | 2272 | man.hash.add(comp.bin_file.options.each_lib_rpath); |
| 2272 | if (comp.bin_file.options.build_id) |build_id| { | |
| 2273 | build_id.hash(&man.hash.hasher); | |
| 2274 | } | |
| 2273 | man.hash.add(comp.bin_file.options.build_id); | |
| 2275 | 2274 | man.hash.add(comp.bin_file.options.skip_linker_dependencies); |
| 2276 | 2275 | man.hash.add(comp.bin_file.options.z_nodelete); |
| 2277 | 2276 | man.hash.add(comp.bin_file.options.z_notext); |
src/link.zig+1-1| ... | ... | @@ -158,7 +158,7 @@ pub const Options = struct { |
| 158 | 158 | skip_linker_dependencies: bool, |
| 159 | 159 | parent_compilation_link_libc: bool, |
| 160 | 160 | each_lib_rpath: bool, |
| 161 | build_id: ?BuildId, | |
| 161 | build_id: BuildId, | |
| 162 | 162 | disable_lld_caching: bool, |
| 163 | 163 | is_test: bool, |
| 164 | 164 | hash_style: HashStyle, |
src/link/Elf.zig+13-8| ... | ... | @@ -1399,8 +1399,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 1399 | 1399 | man.hash.add(self.base.options.each_lib_rpath); |
| 1400 | 1400 | if (self.base.options.output_mode == .Exe) { |
| 1401 | 1401 | man.hash.add(stack_size); |
| 1402 | if (self.base.options.build_id) |build_id| | |
| 1403 | build_id.hash(&man.hash.hasher); | |
| 1402 | man.hash.add(self.base.options.build_id); | |
| 1404 | 1403 | } |
| 1405 | 1404 | man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys()); |
| 1406 | 1405 | man.hash.add(self.base.options.skip_linker_dependencies); |
| ... | ... | @@ -1543,12 +1542,18 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 1543 | 1542 | try argv.append("-z"); |
| 1544 | 1543 | try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size})); |
| 1545 | 1544 | |
| 1546 | if (self.base.options.build_id) |build_id| { | |
| 1547 | const fmt_str = "--build-id={s}{s}"; | |
| 1548 | try argv.append(switch (build_id) { | |
| 1549 | .hexstring => |str| try std.fmt.allocPrint(arena, fmt_str, .{ "0x", str }), | |
| 1550 | .none, .fast, .uuid, .sha1, .md5 => try std.fmt.allocPrint(arena, fmt_str, .{ "", @tagName(build_id) }), | |
| 1551 | }); | |
| 1545 | switch (self.base.options.build_id) { | |
| 1546 | .none => {}, | |
| 1547 | .fast, .uuid, .sha1, .md5 => { | |
| 1548 | try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{ | |
| 1549 | @tagName(self.base.options.build_id), | |
| 1550 | })); | |
| 1551 | }, | |
| 1552 | .hexstring => |hs| { | |
| 1553 | try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{ | |
| 1554 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1555 | })); | |
| 1556 | }, | |
| 1552 | 1557 | } |
| 1553 | 1558 | } |
| 1554 | 1559 |
src/link/Wasm.zig+25-25| ... | ... | @@ -3163,8 +3163,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 3163 | 3163 | try man.addOptionalFile(compiler_rt_path); |
| 3164 | 3164 | man.hash.addOptionalBytes(options.entry); |
| 3165 | 3165 | man.hash.addOptional(options.stack_size_override); |
| 3166 | if (wasm.base.options.build_id) |build_id| | |
| 3167 | build_id.hash(&man.hash.hasher); | |
| 3166 | man.hash.add(wasm.base.options.build_id); | |
| 3168 | 3167 | man.hash.add(options.import_memory); |
| 3169 | 3168 | man.hash.add(options.import_table); |
| 3170 | 3169 | man.hash.add(options.export_table); |
| ... | ... | @@ -3798,27 +3797,29 @@ fn writeToFile( |
| 3798 | 3797 | if (!wasm.base.options.strip) { |
| 3799 | 3798 | // The build id must be computed on the main sections only, |
| 3800 | 3799 | // so we have to do it now, before the debug sections. |
| 3801 | if (wasm.base.options.build_id) |build_id| { | |
| 3802 | switch (build_id) { | |
| 3803 | .none => {}, | |
| 3804 | .fast => { | |
| 3805 | var id: [16]u8 = undefined; | |
| 3806 | std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{}); | |
| 3807 | var uuid: [36]u8 = undefined; | |
| 3808 | _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{ | |
| 3809 | std.fmt.fmtSliceHexLower(id[0..4]), | |
| 3810 | std.fmt.fmtSliceHexLower(id[4..6]), | |
| 3811 | std.fmt.fmtSliceHexLower(id[6..8]), | |
| 3812 | std.fmt.fmtSliceHexLower(id[8..10]), | |
| 3813 | std.fmt.fmtSliceHexLower(id[10..]), | |
| 3814 | }); | |
| 3815 | try emitBuildIdSection(&binary_bytes, &uuid); | |
| 3816 | }, | |
| 3817 | .hexstring => |str| { | |
| 3818 | try emitBuildIdSection(&binary_bytes, str); | |
| 3819 | }, | |
| 3820 | else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}), | |
| 3821 | } | |
| 3800 | switch (wasm.base.options.build_id) { | |
| 3801 | .none => {}, | |
| 3802 | .fast => { | |
| 3803 | var id: [16]u8 = undefined; | |
| 3804 | std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{}); | |
| 3805 | var uuid: [36]u8 = undefined; | |
| 3806 | _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{ | |
| 3807 | std.fmt.fmtSliceHexLower(id[0..4]), | |
| 3808 | std.fmt.fmtSliceHexLower(id[4..6]), | |
| 3809 | std.fmt.fmtSliceHexLower(id[6..8]), | |
| 3810 | std.fmt.fmtSliceHexLower(id[8..10]), | |
| 3811 | std.fmt.fmtSliceHexLower(id[10..]), | |
| 3812 | }); | |
| 3813 | try emitBuildIdSection(&binary_bytes, &uuid); | |
| 3814 | }, | |
| 3815 | .hexstring => |hs| { | |
| 3816 | var buffer: [32 * 2]u8 = undefined; | |
| 3817 | const str = std.fmt.bufPrint(&buffer, "{s}", .{ | |
| 3818 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 3819 | }) catch unreachable; | |
| 3820 | try emitBuildIdSection(&binary_bytes, str); | |
| 3821 | }, | |
| 3822 | else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}), | |
| 3822 | 3823 | } |
| 3823 | 3824 | |
| 3824 | 3825 | // if (wasm.dwarf) |*dwarf| { |
| ... | ... | @@ -4211,8 +4212,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 4211 | 4212 | try man.addOptionalFile(compiler_rt_path); |
| 4212 | 4213 | man.hash.addOptionalBytes(wasm.base.options.entry); |
| 4213 | 4214 | man.hash.addOptional(wasm.base.options.stack_size_override); |
| 4214 | if (wasm.base.options.build_id) |build_id| | |
| 4215 | build_id.hash(&man.hash.hasher); | |
| 4215 | man.hash.add(wasm.base.options.build_id); | |
| 4216 | 4216 | man.hash.add(wasm.base.options.import_memory); |
| 4217 | 4217 | man.hash.add(wasm.base.options.import_table); |
| 4218 | 4218 | man.hash.add(wasm.base.options.export_table); |
src/main.zig+20-17| ... | ... | @@ -494,7 +494,10 @@ const usage_build_generic = |
| 494 | 494 | \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library |
| 495 | 495 | \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries |
| 496 | 496 | \\ -fno-allow-shlib-undefined Disallows undefined symbols in shared libraries |
| 497 | \\ --build-id[=style] Generate a build ID note | |
| 497 | \\ --build-id[=style] At a minor link-time expense, coordinates stripped binaries | |
| 498 | \\ fast, uuid, sha1, md5 with debug symbols via a '.note.gnu.build-id' section | |
| 499 | \\ 0x[hexstring] Maximum 32 bytes | |
| 500 | \\ none (default) Disable build-id | |
| 498 | 501 | \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker |
| 499 | 502 | \\ --emit-relocs Enable output of relocation sections for post build tools |
| 500 | 503 | \\ -z [arg] Set linker extension flags |
| ... | ... | @@ -1445,11 +1448,11 @@ fn buildOutputType( |
| 1445 | 1448 | } else if (mem.eql(u8, arg, "--build-id")) { |
| 1446 | 1449 | build_id = .fast; |
| 1447 | 1450 | } else if (mem.startsWith(u8, arg, "--build-id=")) { |
| 1448 | const value = arg["--build-id=".len..]; | |
| 1449 | build_id = BuildId.parse(arena, value) catch |err| switch (err) { | |
| 1450 | error.InvalidHexInt => fatal("failed to parse hex value {s}", .{value}), | |
| 1451 | error.InvalidBuildId => fatal("invalid --build-id={s}", .{value}), | |
| 1452 | error.OutOfMemory => fatal("OOM", .{}), | |
| 1451 | const style = arg["--build-id=".len..]; | |
| 1452 | build_id = BuildId.parse(style) catch |err| { | |
| 1453 | fatal("unable to parse --build-id style '{s}': {s}", .{ | |
| 1454 | style, @errorName(err), | |
| 1455 | }); | |
| 1453 | 1456 | }; |
| 1454 | 1457 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { |
| 1455 | 1458 | if (!crash_report.is_enabled) { |
| ... | ... | @@ -1689,7 +1692,14 @@ fn buildOutputType( |
| 1689 | 1692 | if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| { |
| 1690 | 1693 | const key = linker_arg[0..equals_pos]; |
| 1691 | 1694 | const value = linker_arg[equals_pos + 1 ..]; |
| 1692 | if (mem.eql(u8, key, "--sort-common")) { | |
| 1695 | if (mem.eql(u8, key, "--build-id")) { | |
| 1696 | build_id = BuildId.parse(value) catch |err| { | |
| 1697 | fatal("unable to parse --build-id style '{s}': {s}", .{ | |
| 1698 | value, @errorName(err), | |
| 1699 | }); | |
| 1700 | }; | |
| 1701 | continue; | |
| 1702 | } else if (mem.eql(u8, key, "--sort-common")) { | |
| 1693 | 1703 | // this ignores --sort=common=<anything>; ignoring plain --sort-common |
| 1694 | 1704 | // is done below. |
| 1695 | 1705 | continue; |
| ... | ... | @@ -1699,7 +1709,9 @@ fn buildOutputType( |
| 1699 | 1709 | continue; |
| 1700 | 1710 | } |
| 1701 | 1711 | } |
| 1702 | if (mem.eql(u8, linker_arg, "--as-needed")) { | |
| 1712 | if (mem.eql(u8, linker_arg, "--build-id")) { | |
| 1713 | build_id = .fast; | |
| 1714 | } else if (mem.eql(u8, linker_arg, "--as-needed")) { | |
| 1703 | 1715 | needed = false; |
| 1704 | 1716 | } else if (mem.eql(u8, linker_arg, "--no-as-needed")) { |
| 1705 | 1717 | needed = true; |
| ... | ... | @@ -1731,15 +1743,6 @@ fn buildOutputType( |
| 1731 | 1743 | search_strategy = .paths_first; |
| 1732 | 1744 | } else if (mem.eql(u8, linker_arg, "-search_dylibs_first")) { |
| 1733 | 1745 | search_strategy = .dylibs_first; |
| 1734 | } else if (mem.eql(u8, linker_arg, "--build-id")) { | |
| 1735 | build_id = .fast; | |
| 1736 | } else if (mem.startsWith(u8, linker_arg, "--build-id=")) { | |
| 1737 | const value = linker_arg["--build-id=".len..]; | |
| 1738 | build_id = BuildId.parse(arena, value) catch |err| switch (err) { | |
| 1739 | error.InvalidHexInt => fatal("failed to parse hex value {s}", .{value}), | |
| 1740 | error.InvalidBuildId => fatal("invalid --build-id={s}", .{value}), | |
| 1741 | error.OutOfMemory => fatal("OOM", .{}), | |
| 1742 | }; | |
| 1743 | 1746 | } else { |
| 1744 | 1747 | try linker_args.append(linker_arg); |
| 1745 | 1748 | } |