aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Build.zig62
-rw-r--r--lib/std/Build/Cache.zig4
-rw-r--r--lib/std/Build/Step/Compile.zig88
3 files changed, 132 insertions, 22 deletions
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
index ca55d23937..7ef504851e 100644
--- a/lib/std/Build.zig
+++ b/lib/std/Build.zig
@@ -181,6 +181,7 @@ const TypeId = enum {
@"enum",
string,
list,
+ build_id,
};
const TopLevelStep = struct {
@@ -832,13 +833,13 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
} else if (mem.eql(u8, s, "false")) {
return false;
} else {
- log.err("Expected -D{s} to be a boolean, but received '{s}'\n", .{ name, s });
+ log.err("Expected -D{s} to be a boolean, but received '{s}'", .{ name, s });
self.markInvalidUserInput();
return null;
}
},
.list, .map => {
- log.err("Expected -D{s} to be a boolean, but received a {s}.\n", .{
+ log.err("Expected -D{s} to be a boolean, but received a {s}.", .{
name, @tagName(option_ptr.value),
});
self.markInvalidUserInput();
@@ -847,7 +848,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
},
.int => switch (option_ptr.value) {
.flag, .list, .map => {
- log.err("Expected -D{s} to be an integer, but received a {s}.\n", .{
+ log.err("Expected -D{s} to be an integer, but received a {s}.", .{
name, @tagName(option_ptr.value),
});
self.markInvalidUserInput();
@@ -856,12 +857,12 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
.scalar => |s| {
const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) {
error.Overflow => {
- log.err("-D{s} value {s} cannot fit into type {s}.\n", .{ name, s, @typeName(T) });
+ log.err("-D{s} value {s} cannot fit into type {s}.", .{ name, s, @typeName(T) });
self.markInvalidUserInput();
return null;
},
else => {
- log.err("Expected -D{s} to be an integer of type {s}.\n", .{ name, @typeName(T) });
+ log.err("Expected -D{s} to be an integer of type {s}.", .{ name, @typeName(T) });
self.markInvalidUserInput();
return null;
},
@@ -871,7 +872,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
},
.float => switch (option_ptr.value) {
.flag, .map, .list => {
- log.err("Expected -D{s} to be a float, but received a {s}.\n", .{
+ log.err("Expected -D{s} to be a float, but received a {s}.", .{
name, @tagName(option_ptr.value),
});
self.markInvalidUserInput();
@@ -879,7 +880,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
},
.scalar => |s| {
const n = std.fmt.parseFloat(T, s) catch {
- log.err("Expected -D{s} to be a float of type {s}.\n", .{ name, @typeName(T) });
+ log.err("Expected -D{s} to be a float of type {s}.", .{ name, @typeName(T) });
self.markInvalidUserInput();
return null;
};
@@ -888,7 +889,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
},
.@"enum" => switch (option_ptr.value) {
.flag, .map, .list => {
- log.err("Expected -D{s} to be an enum, but received a {s}.\n", .{
+ log.err("Expected -D{s} to be an enum, but received a {s}.", .{
name, @tagName(option_ptr.value),
});
self.markInvalidUserInput();
@@ -898,7 +899,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
if (std.meta.stringToEnum(T, s)) |enum_lit| {
return enum_lit;
} else {
- log.err("Expected -D{s} to be of type {s}.\n", .{ name, @typeName(T) });
+ log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(T) });
self.markInvalidUserInput();
return null;
}
@@ -906,7 +907,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
},
.string => switch (option_ptr.value) {
.flag, .list, .map => {
- log.err("Expected -D{s} to be a string, but received a {s}.\n", .{
+ log.err("Expected -D{s} to be a string, but received a {s}.", .{
name, @tagName(option_ptr.value),
});
self.markInvalidUserInput();
@@ -914,9 +915,27 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
},
.scalar => |s| return s,
},
+ .build_id => switch (option_ptr.value) {
+ .flag, .map, .list => {
+ log.err("Expected -D{s} to be an enum, but received a {s}.", .{
+ name, @tagName(option_ptr.value),
+ });
+ self.markInvalidUserInput();
+ return null;
+ },
+ .scalar => |s| {
+ if (Step.Compile.BuildId.parse(s)) |build_id| {
+ return build_id;
+ } else |err| {
+ log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) });
+ self.markInvalidUserInput();
+ return null;
+ }
+ },
+ },
.list => switch (option_ptr.value) {
.flag, .map => {
- log.err("Expected -D{s} to be a list, but received a {s}.\n", .{
+ log.err("Expected -D{s} to be a list, but received a {s}.", .{
name, @tagName(option_ptr.value),
});
self.markInvalidUserInput();
@@ -1183,15 +1202,18 @@ pub fn addUserInputFlag(self: *Build, name_raw: []const u8) !bool {
}
fn typeToEnum(comptime T: type) TypeId {
- return switch (@typeInfo(T)) {
- .Int => .int,
- .Float => .float,
- .Bool => .bool,
- .Enum => .@"enum",
- else => switch (T) {
- []const u8 => .string,
- []const []const u8 => .list,
- else => @compileError("Unsupported type: " ++ @typeName(T)),
+ return switch (T) {
+ Step.Compile.BuildId => .build_id,
+ else => return switch (@typeInfo(T)) {
+ .Int => .int,
+ .Float => .float,
+ .Bool => .bool,
+ .Enum => .@"enum",
+ else => switch (T) {
+ []const u8 => .string,
+ []const []const u8 => .list,
+ else => @compileError("Unsupported type: " ++ @typeName(T)),
+ },
},
};
}
diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index 17429c0370..e991aff5b5 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -235,6 +235,10 @@ pub const HashHelper = struct {
.none => {},
}
},
+ std.Build.Step.Compile.BuildId => switch (x) {
+ .none, .fast, .uuid, .sha1, .md5 => hh.add(std.meta.activeTag(x)),
+ .hexstring => |hex_string| hh.addBytes(hex_string.toSlice()),
+ },
else => switch (@typeInfo(@TypeOf(x))) {
.Bool, .Int, .Enum, .Array => hh.addBytes(mem.asBytes(&x)),
else => @compileError("unable to hash type " ++ @typeName(@TypeOf(x))),
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 2371f49daf..d0a2d69bfe 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -116,7 +116,7 @@ each_lib_rpath: ?bool = null,
/// As an example, the bloaty project refuses to work unless its inputs have
/// build ids, in order to prevent accidental mismatches.
/// The default is to not include this section because it slows down linking.
-build_id: ?bool = null,
+build_id: ?BuildId = null,
/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
/// file.
@@ -288,6 +288,82 @@ pub const Options = struct {
use_lld: ?bool = null,
};
+pub const BuildId = union(enum) {
+ none,
+ fast,
+ uuid,
+ sha1,
+ md5,
+ hexstring: HexString,
+
+ pub fn eql(a: BuildId, b: BuildId) bool {
+ const a_tag = std.meta.activeTag(a);
+ const b_tag = std.meta.activeTag(b);
+ if (a_tag != b_tag) return false;
+ return switch (a) {
+ .none, .fast, .uuid, .sha1, .md5 => true,
+ .hexstring => |a_hexstring| mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()),
+ };
+ }
+
+ pub const HexString = struct {
+ bytes: [32]u8,
+ len: u8,
+
+ /// Result is byte values, *not* hex-encoded.
+ pub fn toSlice(hs: *const HexString) []const u8 {
+ return hs.bytes[0..hs.len];
+ }
+ };
+
+ /// Input is byte values, *not* hex-encoded.
+ /// Asserts `bytes` fits inside `HexString`
+ pub fn initHexString(bytes: []const u8) BuildId {
+ var result: BuildId = .{ .hexstring = .{
+ .bytes = undefined,
+ .len = @intCast(u8, bytes.len),
+ } };
+ @memcpy(result.hexstring.bytes[0..bytes.len], bytes);
+ return result;
+ }
+
+ /// Converts UTF-8 text to a `BuildId`.
+ pub fn parse(text: []const u8) !BuildId {
+ if (mem.eql(u8, text, "none")) {
+ return .none;
+ } else if (mem.eql(u8, text, "fast")) {
+ return .fast;
+ } else if (mem.eql(u8, text, "uuid")) {
+ return .uuid;
+ } else if (mem.eql(u8, text, "sha1") or mem.eql(u8, text, "tree")) {
+ return .sha1;
+ } else if (mem.eql(u8, text, "md5")) {
+ return .md5;
+ } else if (mem.startsWith(u8, text, "0x")) {
+ var result: BuildId = .{ .hexstring = undefined };
+ const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]);
+ result.hexstring.len = @intCast(u8, slice.len);
+ return result;
+ }
+ return error.InvalidBuildIdStyle;
+ }
+
+ test parse {
+ try std.testing.expectEqual(BuildId.md5, try parse("md5"));
+ try std.testing.expectEqual(BuildId.none, try parse("none"));
+ try std.testing.expectEqual(BuildId.fast, try parse("fast"));
+ try std.testing.expectEqual(BuildId.uuid, try parse("uuid"));
+ try std.testing.expectEqual(BuildId.sha1, try parse("sha1"));
+ try std.testing.expectEqual(BuildId.sha1, try parse("tree"));
+
+ try std.testing.expect(BuildId.initHexString("").eql(try parse("0x")));
+ try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456")));
+ try std.testing.expectError(error.InvalidLength, parse("0x12-34"));
+ try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb"));
+ try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx"));
+ }
+};
+
pub const Kind = enum {
exe,
lib,
@@ -1810,7 +1886,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
try addFlag(&zig_args, "valgrind", self.valgrind_support);
try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
- try addFlag(&zig_args, "build-id", self.build_id);
+
+ if (self.build_id) |build_id| {
+ try zig_args.append(switch (build_id) {
+ .hexstring => |hs| b.fmt("--build-id=0x{s}", .{
+ std.fmt.fmtSliceHexLower(hs.toSlice()),
+ }),
+ .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}),
+ });
+ }
if (self.zig_lib_dir) |dir| {
try zig_args.append("--zig-lib-dir");