authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-09 13:31:42-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-09 13:31:42-04:00
logae2345b742053a84e1f64f92b76202702ac872d9
tree969498d967a38d6db7afa56426797d399e04afea
parent038946288cf25e430d1ebfee014847470e0f65ba
signaturelock-open Commit is signed but in an unrecognized format.

zig build: add standardTargetOptions and deprecate setTarget

in favor of setTheTarget

1 files changed, 200 insertions(+), 40 deletions(-)

std/build.zig+200-40
......@@ -380,10 +380,12 @@ pub const Builder = struct {
380380 switch (builtin.os) {
381381 .windows => {},
382382 else => {
383 const triple = (CrossTarget{
384 .arch = builtin.arch,
385 .os = builtin.os,
386 .abi = builtin.abi,
383 const triple = (Target{
384 .Cross = CrossTarget{
385 .arch = builtin.arch,
386 .os = builtin.os,
387 .abi = builtin.abi,
388 },
387389 }).linuxTriple(self.allocator);
388390
389391 // TODO: $ ld --verbose | grep SEARCH_DIR
......@@ -507,6 +509,26 @@ pub const Builder = struct {
507509 return mode;
508510 }
509511
512 /// Exposes standard `zig build` options for choosing a target. Pass `null` to support all targets.
513 pub fn standardTargetOptions(self: *Builder, supported_targets: ?[]const Target) Target {
514 if (supported_targets) |target_list| {
515 // TODO detect multiple args and emit an error message
516 // there's probably a better way to collect the target
517 for (target_list) |targ| {
518 const targ_str = targ.zigTriple(self.allocator) catch unreachable;
519 const targ_desc = targ.allocDescription(self.allocator) catch unreachable;
520 const this_targ_opt = self.option(bool, targ_str, targ_desc) orelse false;
521 if (this_targ_opt) {
522 return targ;
523 }
524 }
525 return Target.Native;
526 } else {
527 const target_str = self.option([]const u8, "target", "the target to build for") orelse return Target.Native;
528 return Target.parse(target_str) catch unreachable; // TODO better error message for bad target
529 }
530 }
531
510532 pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool {
511533 const gop = try self.user_input_options.getOrPut(name);
512534 if (!gop.found_existing) {
......@@ -858,67 +880,193 @@ pub const Builder = struct {
858880 }
859881};
860882
861const Version = struct {
883pub const Version = struct {
862884 major: u32,
863885 minor: u32,
864886 patch: u32,
865887};
866888
867const CrossTarget = struct {
889pub const CrossTarget = struct {
868890 arch: builtin.Arch,
869891 os: builtin.Os,
870892 abi: builtin.Abi,
893};
894
895pub const Target = union(enum) {
896 Native: void,
897 Cross: CrossTarget,
871898
872 pub fn zigTriple(cross_target: CrossTarget, allocator: *Allocator) []u8 {
899 pub fn zigTriple(self: Target, allocator: *Allocator) ![]u8 {
873900 return std.fmt.allocPrint(
874901 allocator,
875902 "{}{}-{}-{}",
876 @tagName(cross_target.arch),
877 Target.archSubArchName(cross_target.arch),
878 @tagName(cross_target.os),
879 @tagName(cross_target.abi),
880 ) catch unreachable;
903 @tagName(self.getArch()),
904 Target.archSubArchName(self.getArch()),
905 @tagName(self.getOs()),
906 @tagName(self.getAbi()),
907 );
908 }
909
910 pub fn allocDescription(self: Target, allocator: *Allocator) ![]u8 {
911 // TODO is there anything else worthy of the description that is not
912 // already captured in the triple?
913 return self.zigTriple(allocator);
881914 }
882915
883 pub fn linuxTriple(cross_target: CrossTarget, allocator: *Allocator) []u8 {
916 pub fn zigTripleNoSubArch(self: Target, allocator: *Allocator) ![]u8 {
884917 return std.fmt.allocPrint(
885918 allocator,
886919 "{}-{}-{}",
887 @tagName(cross_target.arch),
888 @tagName(cross_target.os),
889 @tagName(cross_target.abi),
890 ) catch unreachable;
920 @tagName(self.getArch()),
921 @tagName(self.getOs()),
922 @tagName(self.getAbi()),
923 );
891924 }
892};
893925
894pub const Target = union(enum) {
895 Native: void,
896 Cross: CrossTarget,
926 pub fn linuxTriple(self: Target, allocator: *Allocator) ![]u8 {
927 return std.fmt.allocPrint(
928 allocator,
929 "{}-{}-{}",
930 @tagName(self.getArch()),
931 @tagName(self.getOs()),
932 @tagName(self.getAbi()),
933 );
934 }
935
936 pub fn parse(text: []const u8) !Target {
937 var it = mem.separate(text, "-");
938 const arch_name = it.next() orelse return error.MissingArchitecture;
939 const os_name = it.next() orelse return error.MissingOperatingSystem;
940 const abi_name = it.next();
941
942 var cross = CrossTarget{
943 .arch = try parseArchSub(arch_name),
944 .os = try parseOs(os_name),
945 .abi = undefined,
946 };
947 cross.abi = if (abi_name) |n| try parseAbi(n) else defaultAbi(cross.arch, cross.os);
948 return Target{ .Cross = cross };
949 }
950
951 pub fn defaultAbi(arch: builtin.Arch, target_os: builtin.Os) builtin.Abi {
952 switch (arch) {
953 .wasm32, .wasm64 => return .musl,
954 else => {},
955 }
956 switch (target_os) {
957 .freestanding,
958 .ananas,
959 .cloudabi,
960 .dragonfly,
961 .lv2,
962 .solaris,
963 .haiku,
964 .minix,
965 .rtems,
966 .nacl,
967 .cnk,
968 .aix,
969 .cuda,
970 .nvcl,
971 .amdhsa,
972 .ps4,
973 .elfiamcu,
974 .mesa3d,
975 .contiki,
976 .amdpal,
977 .zen,
978 .hermit,
979 => return .eabi,
980 .openbsd,
981 .macosx,
982 .freebsd,
983 .ios,
984 .tvos,
985 .watchos,
986 .fuchsia,
987 .kfreebsd,
988 .netbsd,
989 .hurd,
990 => return .gnu,
991 .windows,
992 .uefi,
993 => return .msvc,
994 .linux,
995 .wasi,
996 => return .musl,
997 }
998 }
999
1000 pub const ParseArchSubError = error{
1001 UnknownArchitecture,
1002 UnknownSubArchitecture,
1003 };
1004
1005 pub fn parseArchSub(text: []const u8) ParseArchSubError!builtin.Arch {
1006 const info = @typeInfo(builtin.Arch);
1007 inline for (info.Union.fields) |field| {
1008 if (mem.eql(u8, text, field.name)) {
1009 if (field.field_type == void) {
1010 return (builtin.Arch)(@field(builtin.Arch, field.name));
1011 } else {
1012 const sub_info = @typeInfo(field.field_type);
1013 inline for (sub_info.Enum.fields) |sub_field| {
1014 const combined = field.name ++ sub_field.name;
1015 if (mem.eql(u8, text, combined)) {
1016 return @unionInit(builtin.Arch, field.name, @field(field.field_type, sub_field.name));
1017 }
1018 }
1019 return error.UnknownSubArchitecture;
1020 }
1021 }
1022 }
1023 return error.UnknownArchitecture;
1024 }
1025
1026 pub fn parseOs(text: []const u8) !builtin.Os {
1027 const info = @typeInfo(builtin.Os);
1028 inline for (info.Enum.fields) |field| {
1029 if (mem.eql(u8, text, field.name)) {
1030 return @field(builtin.Os, field.name);
1031 }
1032 }
1033 return error.UnknownOperatingSystem;
1034 }
1035
1036 pub fn parseAbi(text: []const u8) !builtin.Abi {
1037 const info = @typeInfo(builtin.Abi);
1038 inline for (info.Enum.fields) |field| {
1039 if (mem.eql(u8, text, field.name)) {
1040 return @field(builtin.Abi, field.name);
1041 }
1042 }
1043 return error.UnknownApplicationBinaryInterface;
1044 }
8971045
8981046 fn archSubArchName(arch: builtin.Arch) []const u8 {
8991047 return switch (arch) {
900 builtin.Arch.arm => |sub| @tagName(sub),
901 builtin.Arch.armeb => |sub| @tagName(sub),
902 builtin.Arch.thumb => |sub| @tagName(sub),
903 builtin.Arch.thumbeb => |sub| @tagName(sub),
904 builtin.Arch.aarch64 => |sub| @tagName(sub),
905 builtin.Arch.aarch64_be => |sub| @tagName(sub),
906 builtin.Arch.kalimba => |sub| @tagName(sub),
1048 .arm => |sub| @tagName(sub),
1049 .armeb => |sub| @tagName(sub),
1050 .thumb => |sub| @tagName(sub),
1051 .thumbeb => |sub| @tagName(sub),
1052 .aarch64 => |sub| @tagName(sub),
1053 .aarch64_be => |sub| @tagName(sub),
1054 .kalimba => |sub| @tagName(sub),
9071055 else => "",
9081056 };
9091057 }
9101058
9111059 pub fn subArchName(self: Target) []const u8 {
9121060 switch (self) {
913 Target.Native => return archSubArchName(builtin.arch),
914 Target.Cross => |cross| return archSubArchName(cross.arch),
1061 .Native => return archSubArchName(builtin.arch),
1062 .Cross => |cross| return archSubArchName(cross.arch),
9151063 }
9161064 }
9171065
9181066 pub fn oFileExt(self: Target) []const u8 {
9191067 const abi = switch (self) {
920 Target.Native => builtin.abi,
921 Target.Cross => |t| t.abi,
1068 .Native => builtin.abi,
1069 .Cross => |t| t.abi,
9221070 };
9231071 return switch (abi) {
9241072 builtin.Abi.msvc => ".obj",
......@@ -942,15 +1090,22 @@ pub const Target = union(enum) {
9421090
9431091 pub fn getOs(self: Target) builtin.Os {
9441092 return switch (self) {
945 Target.Native => builtin.os,
946 Target.Cross => |t| t.os,
1093 .Native => builtin.os,
1094 .Cross => |t| t.os,
9471095 };
9481096 }
9491097
9501098 pub fn getArch(self: Target) builtin.Arch {
9511099 switch (self) {
952 Target.Native => return builtin.arch,
953 Target.Cross => |t| return t.arch,
1100 .Native => return builtin.arch,
1101 .Cross => |t| return t.arch,
1102 }
1103 }
1104
1105 pub fn getAbi(self: Target) builtin.Abi {
1106 switch (self) {
1107 .Native => return builtin.abi,
1108 .Cross => |t| return t.abi,
9541109 }
9551110 }
9561111
......@@ -1206,19 +1361,24 @@ pub const LibExeObjStep = struct {
12061361 }
12071362 }
12081363
1364 /// Deprecated. Use `setTheTarget`.
12091365 pub fn setTarget(
12101366 self: *LibExeObjStep,
12111367 target_arch: builtin.Arch,
12121368 target_os: builtin.Os,
12131369 target_abi: builtin.Abi,
12141370 ) void {
1215 self.target = Target{
1371 return self.setTheTarget(Target{
12161372 .Cross = CrossTarget{
12171373 .arch = target_arch,
12181374 .os = target_os,
12191375 .abi = target_abi,
12201376 },
1221 };
1377 });
1378 }
1379
1380 pub fn setTheTarget(self: *LibExeObjStep, target: Target) void {
1381 self.target = target;
12221382 self.computeOutFileNames();
12231383 }
12241384
......@@ -1595,9 +1755,9 @@ pub const LibExeObjStep = struct {
15951755
15961756 switch (self.target) {
15971757 Target.Native => {},
1598 Target.Cross => |cross_target| {
1758 Target.Cross => {
15991759 try zig_args.append("-target");
1600 try zig_args.append(cross_target.zigTriple(builder.allocator));
1760 try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
16011761 },
16021762 }
16031763