@@ -380,10 +380,12 @@ pub const Builder = struct {
380
380
switch (builtin .os ) {
381
381
.windows = > {},
382
382
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
+ },
387
389
}).linuxTriple (self .allocator );
388
390
389
391
// TODO: $ ld --verbose | grep SEARCH_DIR
@@ -507,6 +509,26 @@ pub const Builder = struct {
507
509
return mode ;
508
510
}
509
511
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
+
510
532
pub fn addUserInputOption (self : * Builder , name : []const u8 , value : []const u8 ) ! bool {
511
533
const gop = try self .user_input_options .getOrPut (name );
512
534
if (! gop .found_existing ) {
@@ -858,67 +880,193 @@ pub const Builder = struct {
858
880
}
859
881
};
860
882
861
- const Version = struct {
883
+ pub const Version = struct {
862
884
major : u32 ,
863
885
minor : u32 ,
864
886
patch : u32 ,
865
887
};
866
888
867
- const CrossTarget = struct {
889
+ pub const CrossTarget = struct {
868
890
arch : builtin.Arch ,
869
891
os : builtin.Os ,
870
892
abi : builtin.Abi ,
893
+ };
894
+
895
+ pub const Target = union (enum ) {
896
+ Native : void ,
897
+ Cross : CrossTarget ,
871
898
872
- pub fn zigTriple (cross_target : CrossTarget , allocator : * Allocator ) []u8 {
899
+ pub fn zigTriple (self : Target , allocator : * Allocator ) ! []u8 {
873
900
return std .fmt .allocPrint (
874
901
allocator ,
875
902
"{}{}-{}-{}" ,
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 );
881
914
}
882
915
883
- pub fn linuxTriple ( cross_target : CrossTarget , allocator : * Allocator ) []u8 {
916
+ pub fn zigTripleNoSubArch ( self : Target , allocator : * Allocator ) ! []u8 {
884
917
return std .fmt .allocPrint (
885
918
allocator ,
886
919
"{}-{}-{}" ,
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
+ );
891
924
}
892
- };
893
925
894
- pub 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
+ }
897
1045
898
1046
fn archSubArchName (arch : builtin.Arch ) []const u8 {
899
1047
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 ),
907
1055
else = > "" ,
908
1056
};
909
1057
}
910
1058
911
1059
pub fn subArchName (self : Target ) []const u8 {
912
1060
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 ),
915
1063
}
916
1064
}
917
1065
918
1066
pub fn oFileExt (self : Target ) []const u8 {
919
1067
const abi = switch (self ) {
920
- Target .Native = > builtin .abi ,
921
- Target .Cross = > | t | t .abi ,
1068
+ .Native = > builtin .abi ,
1069
+ .Cross = > | t | t .abi ,
922
1070
};
923
1071
return switch (abi ) {
924
1072
builtin .Abi .msvc = > ".obj" ,
@@ -942,15 +1090,22 @@ pub const Target = union(enum) {
942
1090
943
1091
pub fn getOs (self : Target ) builtin.Os {
944
1092
return switch (self ) {
945
- Target .Native = > builtin .os ,
946
- Target .Cross = > | t | t .os ,
1093
+ .Native = > builtin .os ,
1094
+ .Cross = > | t | t .os ,
947
1095
};
948
1096
}
949
1097
950
1098
pub fn getArch (self : Target ) builtin.Arch {
951
1099
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 ,
954
1109
}
955
1110
}
956
1111
@@ -1206,19 +1361,24 @@ pub const LibExeObjStep = struct {
1206
1361
}
1207
1362
}
1208
1363
1364
+ /// Deprecated. Use `setTheTarget`.
1209
1365
pub fn setTarget (
1210
1366
self : * LibExeObjStep ,
1211
1367
target_arch : builtin.Arch ,
1212
1368
target_os : builtin.Os ,
1213
1369
target_abi : builtin.Abi ,
1214
1370
) void {
1215
- self .target = Target {
1371
+ return self .setTheTarget ( Target {
1216
1372
.Cross = CrossTarget {
1217
1373
.arch = target_arch ,
1218
1374
.os = target_os ,
1219
1375
.abi = target_abi ,
1220
1376
},
1221
- };
1377
+ });
1378
+ }
1379
+
1380
+ pub fn setTheTarget (self : * LibExeObjStep , target : Target ) void {
1381
+ self .target = target ;
1222
1382
self .computeOutFileNames ();
1223
1383
}
1224
1384
@@ -1595,9 +1755,9 @@ pub const LibExeObjStep = struct {
1595
1755
1596
1756
switch (self .target ) {
1597
1757
Target .Native = > {},
1598
- Target .Cross = > | cross_target | {
1758
+ Target .Cross = > {
1599
1759
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 );
1601
1761
},
1602
1762
}
1603
1763
0 commit comments