| author | |
| committer | |
| log | 6bf554f9a75b412f3d1f2306dff8c0036555f08c |
| tree | dde036caf73e984c02000e668c7c1c60394d924a |
| parent | 87a397ab0c7d1d355ce512f97ddf13d066afb9e1 |
In most cases "GLIBC_2.X" strings and `/lib/libc-2.x.so` files do not contain third (`patch`) field,
which causes std.SemanticVersion.parse function to return error. To fix this, we
reuse [now-public] std.zig.CrossTarget.parseVersion function,
which accounts for this third field and makes it 0 in case it was not found.
This new behaviour is similar to std.builtin.Version.parse, which was removed in
https://github.com/ziglang/zig/commit/6e84f469904a24615a6721265a88ad8dcb4ed83a
Fixes regression from https://github.com/ziglang/zig/commit/6e84f469904a24615a6721265a88ad8dcb4ed83a
and https://github.com/ziglang/zig/pull/13998 .
Related: https://github.com/ziglang/zig/issues/17626 . Results with `zig end`:
Before: `"target": "x86_64-linux.6.5.7...6.5.7-gnu.2.19",`
After: `"target": "x86_64-linux.6.5.7...6.5.7-gnu.2.36",`
Also, while we are here, write explicit error sets and remove duplicate
logic from std.zig.system.darwin.macos.parseSystemVersion .
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>4 files changed, 39 insertions(+), 41 deletions(-)
lib/std/SemanticVersion.zig+2-2| ... | ... | @@ -140,13 +140,13 @@ pub fn parse(text: []const u8) !Version { |
| 140 | 140 | return ver; |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | fn parseNum(text: []const u8) !usize { | |
| 143 | fn parseNum(text: []const u8) error{ InvalidVersion, Overflow }!usize { | |
| 144 | 144 | // Leading zeroes are not allowed. |
| 145 | 145 | if (text.len > 1 and text[0] == '0') return error.InvalidVersion; |
| 146 | 146 | |
| 147 | 147 | return std.fmt.parseUnsigned(usize, text, 10) catch |err| switch (err) { |
| 148 | 148 | error.InvalidCharacter => return error.InvalidVersion, |
| 149 | else => |e| return e, | |
| 149 | error.Overflow => return error.Overflow, | |
| 150 | 150 | }; |
| 151 | 151 | } |
| 152 | 152 |
lib/std/zig/CrossTarget.zig+21-15| ... | ... | @@ -354,31 +354,37 @@ pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch { |
| 354 | 354 | } |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | /// Parses a version with an omitted patch component, such as "1.0", | |
| 358 | /// which SemanticVersion.parse is not capable of. | |
| 359 | fn parseVersion(ver: []const u8) !SemanticVersion { | |
| 360 | const parseVersionComponent = struct { | |
| 361 | fn parseVersionComponent(component: []const u8) !usize { | |
| 362 | return std.fmt.parseUnsigned(usize, component, 10) catch |err| { | |
| 363 | switch (err) { | |
| 364 | error.InvalidCharacter => return error.InvalidVersion, | |
| 365 | error.Overflow => return error.Overflow, | |
| 366 | } | |
| 357 | /// Similar to `SemanticVersion.parse`, but with following changes: | |
| 358 | /// * Leading zeroes are allowed. | |
| 359 | /// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0. | |
| 360 | pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion { | |
| 361 | const parseVersionComponentFn = (struct { | |
| 362 | fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize { | |
| 363 | return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) { | |
| 364 | error.InvalidCharacter => return error.InvalidVersion, | |
| 365 | error.Overflow => return error.Overflow, | |
| 367 | 366 | }; |
| 368 | 367 | } |
| 369 | }.parseVersionComponent; | |
| 370 | var version_components = mem.split(u8, ver, "."); | |
| 368 | }).parseVersionComponentInner; | |
| 369 | var version_components = mem.splitScalar(u8, ver, '.'); | |
| 371 | 370 | const major = version_components.first(); |
| 372 | 371 | const minor = version_components.next() orelse return error.InvalidVersion; |
| 373 | 372 | const patch = version_components.next() orelse "0"; |
| 374 | 373 | if (version_components.next() != null) return error.InvalidVersion; |
| 375 | 374 | return .{ |
| 376 | .major = try parseVersionComponent(major), | |
| 377 | .minor = try parseVersionComponent(minor), | |
| 378 | .patch = try parseVersionComponent(patch), | |
| 375 | .major = try parseVersionComponentFn(major), | |
| 376 | .minor = try parseVersionComponentFn(minor), | |
| 377 | .patch = try parseVersionComponentFn(patch), | |
| 379 | 378 | }; |
| 380 | 379 | } |
| 381 | 380 | |
| 381 | test parseVersion { | |
| 382 | try std.testing.expectError(error.InvalidVersion, parseVersion("1")); | |
| 383 | try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 0 }, try parseVersion("1.2")); | |
| 384 | try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 3 }, try parseVersion("1.2.3")); | |
| 385 | try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4")); | |
| 386 | } | |
| 387 | ||
| 382 | 388 | /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. |
| 383 | 389 | pub fn getCpu(self: CrossTarget) Target.Cpu { |
| 384 | 390 | switch (self.cpu_model) { |
lib/std/zig/system/NativeTargetInfo.zig+15-4| ... | ... | @@ -557,7 +557,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { |
| 557 | 557 | var buf: [80000]u8 = undefined; |
| 558 | 558 | if (buf.len < dynstr.size) return error.InvalidGnuLibCVersion; |
| 559 | 559 | |
| 560 | const dynstr_size = @as(usize, @intCast(dynstr.size)); | |
| 560 | const dynstr_size: usize = @intCast(dynstr.size); | |
| 561 | 561 | const dynstr_bytes = buf[0..dynstr_size]; |
| 562 | 562 | _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len); |
| 563 | 563 | var it = mem.splitScalar(u8, dynstr_bytes, 0); |
| ... | ... | @@ -565,7 +565,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { |
| 565 | 565 | while (it.next()) |s| { |
| 566 | 566 | if (mem.startsWith(u8, s, "GLIBC_2.")) { |
| 567 | 567 | const chopped = s["GLIBC_".len..]; |
| 568 | const ver = std.SemanticVersion.parse(chopped) catch |err| switch (err) { | |
| 568 | const ver = CrossTarget.parseVersion(chopped) catch |err| switch (err) { | |
| 569 | 569 | error.Overflow => return error.InvalidGnuLibCVersion, |
| 570 | 570 | error.InvalidVersion => return error.InvalidGnuLibCVersion, |
| 571 | 571 | }; |
| ... | ... | @@ -578,7 +578,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { |
| 578 | 578 | return max_ver; |
| 579 | 579 | } |
| 580 | 580 | |
| 581 | fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.SemanticVersion { | |
| 581 | fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) error{ UnrecognizedGnuLibCFileName, InvalidGnuLibCVersion }!std.SemanticVersion { | |
| 582 | 582 | // example: "libc-2.3.4.so" |
| 583 | 583 | // example: "libc-2.27.so" |
| 584 | 584 | // example: "ld-2.33.so" |
| ... | ... | @@ -588,12 +588,23 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.Semantic |
| 588 | 588 | } |
| 589 | 589 | // chop off "libc-" and ".so" |
| 590 | 590 | const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len]; |
| 591 | return std.SemanticVersion.parse(link_name_chopped) catch |err| switch (err) { | |
| 591 | return CrossTarget.parseVersion(link_name_chopped) catch |err| switch (err) { | |
| 592 | 592 | error.Overflow => return error.InvalidGnuLibCVersion, |
| 593 | 593 | error.InvalidVersion => return error.InvalidGnuLibCVersion, |
| 594 | 594 | }; |
| 595 | 595 | } |
| 596 | 596 | |
| 597 | test glibcVerFromLinkName { | |
| 598 | try std.testing.expectError(error.UnrecognizedGnuLibCFileName, glibcVerFromLinkName("ld-2.37.so", "this-prefix-does-not-exist")); | |
| 599 | try std.testing.expectError(error.UnrecognizedGnuLibCFileName, glibcVerFromLinkName("libc-2.37.so-is-not-end", "libc-")); | |
| 600 | ||
| 601 | try std.testing.expectError(error.InvalidGnuLibCVersion, glibcVerFromLinkName("ld-2.so", "ld-")); | |
| 602 | try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 0 }, try glibcVerFromLinkName("ld-2.37.so", "ld-")); | |
| 603 | try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 0 }, try glibcVerFromLinkName("ld-2.37.0.so", "ld-")); | |
| 604 | try std.testing.expectEqual(std.SemanticVersion{ .major = 2, .minor = 37, .patch = 1 }, try glibcVerFromLinkName("ld-2.37.1.so", "ld-")); | |
| 605 | try std.testing.expectError(error.InvalidGnuLibCVersion, glibcVerFromLinkName("ld-2.37.4.5.so", "ld-")); | |
| 606 | } | |
| 607 | ||
| 597 | 608 | pub const AbiAndDynamicLinkerFromFileError = error{ |
| 598 | 609 | FileSystem, |
| 599 | 610 | SystemResources, |
lib/std/zig/system/darwin/macos.zig+1-20| ... | ... | @@ -87,26 +87,7 @@ fn parseSystemVersion(buf: []const u8) !std.SemanticVersion { |
| 87 | 87 | const ver = try svt.expectContent(); |
| 88 | 88 | try svt.skipUntilTag(.end, "string"); |
| 89 | 89 | |
| 90 | const parseVersionComponent = struct { | |
| 91 | fn parseVersionComponent(component: []const u8) !usize { | |
| 92 | return std.fmt.parseUnsigned(usize, component, 10) catch |err| { | |
| 93 | switch (err) { | |
| 94 | error.InvalidCharacter => return error.InvalidVersion, | |
| 95 | error.Overflow => return error.Overflow, | |
| 96 | } | |
| 97 | }; | |
| 98 | } | |
| 99 | }.parseVersionComponent; | |
| 100 | var version_components = mem.split(u8, ver, "."); | |
| 101 | const major = version_components.first(); | |
| 102 | const minor = version_components.next() orelse return error.InvalidVersion; | |
| 103 | const patch = version_components.next() orelse "0"; | |
| 104 | if (version_components.next() != null) return error.InvalidVersion; | |
| 105 | return .{ | |
| 106 | .major = try parseVersionComponent(major), | |
| 107 | .minor = try parseVersionComponent(minor), | |
| 108 | .patch = try parseVersionComponent(patch), | |
| 109 | }; | |
| 90 | return try std.zig.CrossTarget.parseVersion(ver); | |
| 110 | 91 | } |
| 111 | 92 | |
| 112 | 93 | const SystemVersionTokenizer = struct { |