@@ -118,11 +118,6 @@ pub fn main() anyerror!void {
118
118
const os_can_execve = std .builtin .os .tag != .windows ;
119
119
120
120
pub fn mainArgs (gpa : * Allocator , arena : * Allocator , args : []const []const u8 ) ! void {
121
- if (args .len <= 1 ) {
122
- std .log .info ("{}" , .{usage });
123
- fatal ("expected command argument" , .{});
124
- }
125
-
126
121
if (os_can_execve and std .os .getenvZ ("ZIG_IS_DETECTING_LIBC_PATHS" ) != null ) {
127
122
// In this case we have accidentally invoked ourselves as "the system C compiler"
128
123
// to figure out where libc is installed. This is essentially infinite recursion
@@ -154,6 +149,51 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
154
149
}
155
150
}
156
151
152
+ const is_cgo = std .os .getenvZ ("ZIG_CGO" ) != null ;
153
+ if (is_cgo ) cgo : {
154
+ // Workaround for https://github.com/golang/go/issues/43078, here we fix the order of
155
+ // command line arguments. Dear Go developers please let the Zig project know when
156
+ // we can remove this!
157
+ var fixed_args = std .ArrayList ([]const u8 ).init (arena );
158
+ try fixed_args .ensureCapacity (args .len );
159
+ fixed_args .appendAssumeCapacity (args [0 ]);
160
+ fixed_args .appendAssumeCapacity ("cc" );
161
+ var arg_mode : BuildArgMode = .cc ;
162
+ var found_cc_arg = false ;
163
+ for (args [1.. ]) | arg | {
164
+ if (! found_cc_arg ) {
165
+ if (mem .eql (u8 , arg , "cc" )) {
166
+ arg_mode = .cc ;
167
+ fixed_args .items [1 ] = arg ;
168
+ found_cc_arg = true ;
169
+ } else if (mem .eql (u8 , arg , "c++" )) {
170
+ arg_mode = .cpp ;
171
+ fixed_args .items [1 ] = arg ;
172
+ found_cc_arg = true ;
173
+ } else if (mem .eql (u8 , arg , "clang" ) or
174
+ mem .eql (u8 , arg , "-cc1" ) or
175
+ mem .eql (u8 , arg , "-cc1as" ) or
176
+ mem .eql (u8 , arg , "ld.lld" ) or
177
+ mem .eql (u8 , arg , "ld64.lld" ) or
178
+ mem .eql (u8 , arg , "lld-link" ) or
179
+ mem .eql (u8 , arg , "wasm-ld" ))
180
+ {
181
+ break :cgo ; // fall back to regular arg parsing
182
+ } else {
183
+ fixed_args .appendAssumeCapacity (arg );
184
+ }
185
+ } else {
186
+ fixed_args .appendAssumeCapacity (arg );
187
+ }
188
+ }
189
+ return buildOutputType (gpa , arena , fixed_args .items , arg_mode );
190
+ }
191
+
192
+ if (args .len <= 1 ) {
193
+ std .log .info ("{}" , .{usage });
194
+ fatal ("expected command argument" , .{});
195
+ }
196
+
157
197
const cmd = args [1 ];
158
198
const cmd_args = args [2.. ];
159
199
if (mem .eql (u8 , cmd , "build-exe" )) {
@@ -435,18 +475,20 @@ fn optionalStringEnvVar(arena: *Allocator, name: []const u8) !?[]const u8 {
435
475
}
436
476
}
437
477
478
+ const BuildArgMode = union (enum ) {
479
+ build : std.builtin.OutputMode ,
480
+ cc ,
481
+ cpp ,
482
+ translate_c ,
483
+ zig_test ,
484
+ run ,
485
+ };
486
+
438
487
fn buildOutputType (
439
488
gpa : * Allocator ,
440
489
arena : * Allocator ,
441
490
all_args : []const []const u8 ,
442
- arg_mode : union (enum ) {
443
- build : std.builtin.OutputMode ,
444
- cc ,
445
- cpp ,
446
- translate_c ,
447
- zig_test ,
448
- run ,
449
- },
491
+ arg_mode : BuildArgMode ,
450
492
) ! void {
451
493
var color : Color = .auto ;
452
494
var optimize_mode : std.builtin.Mode = .Debug ;
@@ -477,7 +519,7 @@ fn buildOutputType(
477
519
var emit_zir : Emit = .no ;
478
520
var emit_docs : Emit = .no ;
479
521
var emit_analysis : Emit = .no ;
480
- var target_arch_os_abi : []const u8 = "native" ;
522
+ var target_arch_os_abi : ? []const u8 = null ;
481
523
var target_mcpu : ? []const u8 = null ;
482
524
var target_dynamic_linker : ? []const u8 = null ;
483
525
var target_ofmt : ? []const u8 = null ;
@@ -1361,38 +1403,65 @@ fn buildOutputType(
1361
1403
}
1362
1404
};
1363
1405
1364
- var diags : std.zig.CrossTarget.ParseOptions.Diagnostics = .{};
1365
- const cross_target = std .zig .CrossTarget .parse (.{
1366
- .arch_os_abi = target_arch_os_abi ,
1367
- .cpu_features = target_mcpu ,
1368
- .dynamic_linker = target_dynamic_linker ,
1369
- .diagnostics = & diags ,
1370
- }) catch | err | switch (err ) {
1371
- error .UnknownCpuModel = > {
1372
- help : {
1373
- var help_text = std .ArrayList (u8 ).init (arena );
1374
- for (diags .arch .? .allCpuModels ()) | cpu | {
1375
- help_text .writer ().print (" {}\n " , .{cpu .name }) catch break :help ;
1376
- }
1377
- std .log .info ("Available CPUs for architecture '{}': {}" , .{
1378
- @tagName (diags .arch .? ), help_text .items ,
1406
+ const is_cgo = std .os .getenvZ ("ZIG_CGO" ) != null ;
1407
+
1408
+ const cross_target : std.zig.CrossTarget = t : {
1409
+ if (is_cgo and target_arch_os_abi == null ) {
1410
+ const go_os = std .os .getenvZ ("GOOS" ) orelse "native" ;
1411
+ const go_arch = std .os .getenvZ ("GOARCH" ) orelse "native" ;
1412
+ const cgo_ct = target_util .fromGoTarget (go_arch , go_os ) catch | err | {
1413
+ fatal ("unable to determine target from GOOS={s} GOARCH={s}: {s}" , .{
1414
+ go_os , go_arch , @errorName (err ),
1379
1415
});
1416
+ };
1417
+ // We render the CGO target to a string so that we can call CrossTarget.parse below
1418
+ // and which takes into account the CPU features and dynamic linker CLI parameters.
1419
+ const cpu_arch = if (cgo_ct .cpu_arch ) | arch | @tagName (arch ) else "native" ;
1420
+ const os_tag = if (cgo_ct .os_tag ) | os_tag | @tagName (os_tag ) else "native" ;
1421
+ if (cgo_ct .abi ) | abi | {
1422
+ target_arch_os_abi = try std .fmt .allocPrint (arena , "{s}-{s}-{s}" , .{ cpu_arch , os_tag , abi });
1423
+ } else {
1424
+ target_arch_os_abi = try std .fmt .allocPrint (arena , "{s}-{s}" , .{ cpu_arch , os_tag });
1380
1425
}
1381
- fatal ("Unknown CPU: '{}'" , .{diags .cpu_name .? });
1382
- },
1383
- error .UnknownCpuFeature = > {
1384
- help : {
1385
- var help_text = std .ArrayList (u8 ).init (arena );
1386
- for (diags .arch .? .allFeaturesList ()) | feature | {
1387
- help_text .writer ().print (" {}: {}\n " , .{ feature .name , feature .description }) catch break :help ;
1426
+ }
1427
+
1428
+ var diags : std.zig.CrossTarget.ParseOptions.Diagnostics = .{};
1429
+ const cross_target = std .zig .CrossTarget .parse (.{
1430
+ .arch_os_abi = target_arch_os_abi orelse "native" ,
1431
+ .cpu_features = target_mcpu ,
1432
+ .dynamic_linker = target_dynamic_linker ,
1433
+ .diagnostics = & diags ,
1434
+ }) catch | err | switch (err ) {
1435
+ error .UnknownCpuModel = > {
1436
+ help : {
1437
+ var help_text = std .ArrayList (u8 ).init (arena );
1438
+ for (diags .arch .? .allCpuModels ()) | cpu | {
1439
+ help_text .writer ().print (" {}\n " , .{cpu .name }) catch break :help ;
1440
+ }
1441
+ std .log .info ("Available CPUs for architecture '{}': {}" , .{
1442
+ @tagName (diags .arch .? ), help_text .items ,
1443
+ });
1388
1444
}
1389
- std .log .info ("Available CPU features for architecture '{}': {}" , .{
1390
- @tagName (diags .arch .? ), help_text .items ,
1391
- });
1392
- }
1393
- fatal ("Unknown CPU feature: '{}'" , .{diags .unknown_feature_name });
1394
- },
1395
- else = > | e | return e ,
1445
+ fatal ("Unknown CPU: '{}'" , .{diags .cpu_name .? });
1446
+ },
1447
+ error .UnknownCpuFeature = > {
1448
+ help : {
1449
+ var help_text = std .ArrayList (u8 ).init (arena );
1450
+ for (diags .arch .? .allFeaturesList ()) | feature | {
1451
+ help_text .writer ().print (" {}: {}\n " , .{ feature .name , feature .description }) catch break :help ;
1452
+ }
1453
+ std .log .info ("Available CPU features for architecture '{}': {}" , .{
1454
+ @tagName (diags .arch .? ), help_text .items ,
1455
+ });
1456
+ }
1457
+ fatal ("Unknown CPU feature: '{}'" , .{diags .unknown_feature_name });
1458
+ },
1459
+ error .UnknownOperatingSystem = > {
1460
+ fatal ("Unknown Operating System: '{s}'" , .{diags .os_name });
1461
+ },
1462
+ else = > | e | return e ,
1463
+ };
1464
+ break :t cross_target ;
1396
1465
};
1397
1466
1398
1467
const target_info = try detectNativeTargetInfo (gpa , cross_target );
@@ -1653,7 +1722,7 @@ fn buildOutputType(
1653
1722
.path = local_cache_dir_path ,
1654
1723
};
1655
1724
}
1656
- if (arg_mode == .run ) {
1725
+ if (arg_mode == .run or is_cgo ) {
1657
1726
break :l global_cache_directory ;
1658
1727
}
1659
1728
const cache_dir_path = blk : {
0 commit comments