| 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,13 +140,13 @@ pub fn parse(text: []const u8) !Version { |
| 140 | return ver; | 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 | // Leading zeroes are not allowed. | 144 | // Leading zeroes are not allowed. |
| 145 | if (text.len > 1 and text[0] == '0') return error.InvalidVersion; | 145 | if (text.len > 1 and text[0] == '0') return error.InvalidVersion; |
| 146 | 146 | ||
| 147 | return std.fmt.parseUnsigned(usize, text, 10) catch |err| switch (err) { | 147 | return std.fmt.parseUnsigned(usize, text, 10) catch |err| switch (err) { |
| 148 | error.InvalidCharacter => return error.InvalidVersion, | 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,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", | 357 | /// Similar to `SemanticVersion.parse`, but with following changes: |
| 358 | /// which SemanticVersion.parse is not capable of. | 358 | /// * Leading zeroes are allowed. |
| 359 | fn parseVersion(ver: []const u8) !SemanticVersion { | 359 | /// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0. |
| 360 | const parseVersionComponent = struct { | 360 | pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion { |
| 361 | fn parseVersionComponent(component: []const u8) !usize { | 361 | const parseVersionComponentFn = (struct { |
| 362 | return std.fmt.parseUnsigned(usize, component, 10) catch |err| { | 362 | fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize { |
| 363 | switch (err) { | 363 | return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) { |
| 364 | error.InvalidCharacter => return error.InvalidVersion, | 364 | error.InvalidCharacter => return error.InvalidVersion, |
| 365 | error.Overflow => return error.Overflow, | 365 | error.Overflow => return error.Overflow, |
| 366 | } | ||
| 367 | }; | 366 | }; |
| 368 | } | 367 | } |
| 369 | }.parseVersionComponent; | 368 | }).parseVersionComponentInner; |
| 370 | var version_components = mem.split(u8, ver, "."); | 369 | var version_components = mem.splitScalar(u8, ver, '.'); |
| 371 | const major = version_components.first(); | 370 | const major = version_components.first(); |
| 372 | const minor = version_components.next() orelse return error.InvalidVersion; | 371 | const minor = version_components.next() orelse return error.InvalidVersion; |
| 373 | const patch = version_components.next() orelse "0"; | 372 | const patch = version_components.next() orelse "0"; |
| 374 | if (version_components.next() != null) return error.InvalidVersion; | 373 | if (version_components.next() != null) return error.InvalidVersion; |
| 375 | return .{ | 374 | return .{ |
| 376 | .major = try parseVersionComponent(major), | 375 | .major = try parseVersionComponentFn(major), |
| 377 | .minor = try parseVersionComponent(minor), | 376 | .minor = try parseVersionComponentFn(minor), |
| 378 | .patch = try parseVersionComponent(patch), | 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 | /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. | 388 | /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. |
| 383 | pub fn getCpu(self: CrossTarget) Target.Cpu { | 389 | pub fn getCpu(self: CrossTarget) Target.Cpu { |
| 384 | switch (self.cpu_model) { | 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,7 +557,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { |
| 557 | var buf: [80000]u8 = undefined; | 557 | var buf: [80000]u8 = undefined; |
| 558 | if (buf.len < dynstr.size) return error.InvalidGnuLibCVersion; | 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 | const dynstr_bytes = buf[0..dynstr_size]; | 561 | const dynstr_bytes = buf[0..dynstr_size]; |
| 562 | _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len); | 562 | _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len); |
| 563 | var it = mem.splitScalar(u8, dynstr_bytes, 0); | 563 | var it = mem.splitScalar(u8, dynstr_bytes, 0); |
| ... | @@ -565,7 +565,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { | ... | @@ -565,7 +565,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { |
| 565 | while (it.next()) |s| { | 565 | while (it.next()) |s| { |
| 566 | if (mem.startsWith(u8, s, "GLIBC_2.")) { | 566 | if (mem.startsWith(u8, s, "GLIBC_2.")) { |
| 567 | const chopped = s["GLIBC_".len..]; | 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 | error.Overflow => return error.InvalidGnuLibCVersion, | 569 | error.Overflow => return error.InvalidGnuLibCVersion, |
| 570 | error.InvalidVersion => return error.InvalidGnuLibCVersion, | 570 | error.InvalidVersion => return error.InvalidGnuLibCVersion, |
| 571 | }; | 571 | }; |
| ... | @@ -578,7 +578,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { | ... | @@ -578,7 +578,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { |
| 578 | return max_ver; | 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 | // example: "libc-2.3.4.so" | 582 | // example: "libc-2.3.4.so" |
| 583 | // example: "libc-2.27.so" | 583 | // example: "libc-2.27.so" |
| 584 | // example: "ld-2.33.so" | 584 | // example: "ld-2.33.so" |
| ... | @@ -588,12 +588,23 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.Semantic | ... | @@ -588,12 +588,23 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) !std.Semantic |
| 588 | } | 588 | } |
| 589 | // chop off "libc-" and ".so" | 589 | // chop off "libc-" and ".so" |
| 590 | const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len]; | 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 | error.Overflow => return error.InvalidGnuLibCVersion, | 592 | error.Overflow => return error.InvalidGnuLibCVersion, |
| 593 | error.InvalidVersion => return error.InvalidGnuLibCVersion, | 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 | pub const AbiAndDynamicLinkerFromFileError = error{ | 608 | pub const AbiAndDynamicLinkerFromFileError = error{ |
| 598 | FileSystem, | 609 | FileSystem, |
| 599 | SystemResources, | 610 | SystemResources, |
lib/std/zig/system/darwin/macos.zig+1-20| ... | @@ -87,26 +87,7 @@ fn parseSystemVersion(buf: []const u8) !std.SemanticVersion { | ... | @@ -87,26 +87,7 @@ fn parseSystemVersion(buf: []const u8) !std.SemanticVersion { |
| 87 | const ver = try svt.expectContent(); | 87 | const ver = try svt.expectContent(); |
| 88 | try svt.skipUntilTag(.end, "string"); | 88 | try svt.skipUntilTag(.end, "string"); |
| 89 | 89 | ||
| 90 | const parseVersionComponent = struct { | 90 | return try std.zig.CrossTarget.parseVersion(ver); |
| 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 | }; | ||
| 110 | } | 91 | } |
| 111 | 92 | ||
| 112 | const SystemVersionTokenizer = struct { | 93 | const SystemVersionTokenizer = struct { |