@@ -224,7 +224,7 @@ pub fn build(b: *Builder) !void {
224
224
225
225
const opt_version_string = b .option ([]const u8 , "version-string" , "Override Zig version string. Default is to find out with git." );
226
226
const version = if (opt_version_string ) | version | version else v : {
227
- const version_string = b .fmt ("{}.{}.{}" , .{ zig_version .major , zig_version .minor , zig_version .patch });
227
+ const version_string = b .fmt ("{d }.{d }.{d }" , .{ zig_version .major , zig_version .minor , zig_version .patch });
228
228
229
229
var code : u8 = undefined ;
230
230
const git_describe_untrimmed = b .execAllowFail (&[_ ][]const u8 {
@@ -238,7 +238,7 @@ pub fn build(b: *Builder) !void {
238
238
0 = > {
239
239
// Tagged release version (e.g. 0.7.0).
240
240
if (! mem .eql (u8 , git_describe , version_string )) {
241
- std .debug .print ("Zig version '{}' does not match Git tag '{}'\n " , .{ version_string , git_describe });
241
+ std .debug .print ("Zig version '{s }' does not match Git tag '{s }'\n " , .{ version_string , git_describe });
242
242
std .process .exit (1 );
243
243
}
244
244
break :v version_string ;
@@ -258,15 +258,15 @@ pub fn build(b: *Builder) !void {
258
258
259
259
// Check that the commit hash is prefixed with a 'g' (a Git convention).
260
260
if (commit_id .len < 1 or commit_id [0 ] != 'g' ) {
261
- std .debug .print ("Unexpected `git describe` output: {}\n " , .{git_describe });
261
+ std .debug .print ("Unexpected `git describe` output: {s }\n " , .{git_describe });
262
262
break :v version_string ;
263
263
}
264
264
265
265
// The version is reformatted in accordance with the https://semver.org specification.
266
- break :v b .fmt ("{}-dev.{}+{}" , .{ version_string , commit_height , commit_id [1.. ] });
266
+ break :v b .fmt ("{s }-dev.{s }+{s }" , .{ version_string , commit_height , commit_id [1.. ] });
267
267
},
268
268
else = > {
269
- std .debug .print ("Unexpected `git describe` output: {}\n " , .{git_describe });
269
+ std .debug .print ("Unexpected `git describe` output: {s }\n " , .{git_describe });
270
270
break :v version_string ;
271
271
},
272
272
}
@@ -359,6 +359,195 @@ pub fn build(b: *Builder) !void {
359
359
test_step .dependOn (docs_step );
360
360
}
361
361
362
+ fn dependOnLib (b : * Builder , lib_exe_obj : anytype , dep : LibraryDep ) void {
363
+ for (dep .libdirs .items ) | lib_dir | {
364
+ lib_exe_obj .addLibPath (lib_dir );
365
+ }
366
+ const lib_dir = fs .path .join (
367
+ b .allocator ,
368
+ &[_ ][]const u8 { dep .prefix , "lib" },
369
+ ) catch unreachable ;
370
+ for (dep .system_libs .items ) | lib | {
371
+ const static_bare_name = if (mem .eql (u8 , lib , "curses" ))
372
+ @as ([]const u8 , "libncurses.a" )
373
+ else
374
+ b .fmt ("lib{s}.a" , .{lib });
375
+ const static_lib_name = fs .path .join (
376
+ b .allocator ,
377
+ &[_ ][]const u8 { lib_dir , static_bare_name },
378
+ ) catch unreachable ;
379
+ const have_static = fileExists (static_lib_name ) catch unreachable ;
380
+ if (have_static ) {
381
+ lib_exe_obj .addObjectFile (static_lib_name );
382
+ } else {
383
+ lib_exe_obj .linkSystemLibrary (lib );
384
+ }
385
+ }
386
+ for (dep .libs .items ) | lib | {
387
+ lib_exe_obj .addObjectFile (lib );
388
+ }
389
+ for (dep .includes .items ) | include_path | {
390
+ lib_exe_obj .addIncludeDir (include_path );
391
+ }
392
+ }
393
+
394
+ fn fileExists (filename : []const u8 ) ! bool {
395
+ fs .cwd ().access (filename , .{}) catch | err | switch (err ) {
396
+ error .FileNotFound = > return false ,
397
+ else = > return err ,
398
+ };
399
+ return true ;
400
+ }
401
+
402
+ fn addCppLib (b : * Builder , lib_exe_obj : anytype , cmake_binary_dir : []const u8 , lib_name : []const u8 ) void {
403
+ lib_exe_obj .addObjectFile (fs .path .join (b .allocator , &[_ ][]const u8 {
404
+ cmake_binary_dir ,
405
+ "zigcpp" ,
406
+ b .fmt ("{s}{s}{s}" , .{ lib_exe_obj .target .libPrefix (), lib_name , lib_exe_obj .target .staticLibSuffix () }),
407
+ }) catch unreachable );
408
+ }
409
+
410
+ const LibraryDep = struct {
411
+ prefix : []const u8 ,
412
+ libdirs : ArrayList ([]const u8 ),
413
+ libs : ArrayList ([]const u8 ),
414
+ system_libs : ArrayList ([]const u8 ),
415
+ includes : ArrayList ([]const u8 ),
416
+ };
417
+
418
+ fn findLLVM (b : * Builder , llvm_config_exe : []const u8 ) ! LibraryDep {
419
+ const shared_mode = try b .exec (&[_ ][]const u8 { llvm_config_exe , "--shared-mode" });
420
+ const is_static = mem .startsWith (u8 , shared_mode , "static" );
421
+ const libs_output = if (is_static )
422
+ try b .exec (&[_ ][]const u8 {
423
+ llvm_config_exe ,
424
+ "--libfiles" ,
425
+ "--system-libs" ,
426
+ })
427
+ else
428
+ try b .exec (&[_ ][]const u8 {
429
+ llvm_config_exe ,
430
+ "--libs" ,
431
+ });
432
+ const includes_output = try b .exec (&[_ ][]const u8 { llvm_config_exe , "--includedir" });
433
+ const libdir_output = try b .exec (&[_ ][]const u8 { llvm_config_exe , "--libdir" });
434
+ const prefix_output = try b .exec (&[_ ][]const u8 { llvm_config_exe , "--prefix" });
435
+
436
+ var result = LibraryDep {
437
+ .prefix = mem .tokenize (prefix_output , " \r \n " ).next ().? ,
438
+ .libs = ArrayList ([]const u8 ).init (b .allocator ),
439
+ .system_libs = ArrayList ([]const u8 ).init (b .allocator ),
440
+ .includes = ArrayList ([]const u8 ).init (b .allocator ),
441
+ .libdirs = ArrayList ([]const u8 ).init (b .allocator ),
442
+ };
443
+ {
444
+ var it = mem .tokenize (libs_output , " \r \n " );
445
+ while (it .next ()) | lib_arg | {
446
+ if (mem .startsWith (u8 , lib_arg , "-l" )) {
447
+ try result .system_libs .append (lib_arg [2.. ]);
448
+ } else {
449
+ if (fs .path .isAbsolute (lib_arg )) {
450
+ try result .libs .append (lib_arg );
451
+ } else {
452
+ var lib_arg_copy = lib_arg ;
453
+ if (mem .endsWith (u8 , lib_arg , ".lib" )) {
454
+ lib_arg_copy = lib_arg [0 .. lib_arg .len - 4 ];
455
+ }
456
+ try result .system_libs .append (lib_arg_copy );
457
+ }
458
+ }
459
+ }
460
+ }
461
+ {
462
+ var it = mem .tokenize (includes_output , " \r \n " );
463
+ while (it .next ()) | include_arg | {
464
+ if (mem .startsWith (u8 , include_arg , "-I" )) {
465
+ try result .includes .append (include_arg [2.. ]);
466
+ } else {
467
+ try result .includes .append (include_arg );
468
+ }
469
+ }
470
+ }
471
+ {
472
+ var it = mem .tokenize (libdir_output , " \r \n " );
473
+ while (it .next ()) | libdir | {
474
+ if (mem .startsWith (u8 , libdir , "-L" )) {
475
+ try result .libdirs .append (libdir [2.. ]);
476
+ } else {
477
+ try result .libdirs .append (libdir );
478
+ }
479
+ }
480
+ }
481
+ return result ;
482
+ }
483
+
484
+ fn configureStage2 (b : * Builder , exe : anytype , ctx : Context , need_cpp_includes : bool ) ! void {
485
+ exe .addIncludeDir ("src" );
486
+ exe .addIncludeDir (ctx .cmake_binary_dir );
487
+ addCppLib (b , exe , ctx .cmake_binary_dir , "zigcpp" );
488
+ assert (ctx .lld_include_dir .len != 0 );
489
+ exe .addIncludeDir (ctx .lld_include_dir );
490
+ {
491
+ var it = mem .tokenize (ctx .lld_libraries , ";" );
492
+ while (it .next ()) | lib | {
493
+ exe .addObjectFile (lib );
494
+ }
495
+ }
496
+ {
497
+ var it = mem .tokenize (ctx .clang_libraries , ";" );
498
+ while (it .next ()) | lib | {
499
+ exe .addObjectFile (lib );
500
+ }
501
+ }
502
+ dependOnLib (b , exe , ctx .llvm );
503
+
504
+ // Boy, it sure would be nice to simply linkSystemLibrary("c++") and rely on zig's
505
+ // ability to provide libc++ right? Well thanks to C++ not having a stable ABI this
506
+ // will cause linker errors. It would work in the situation when `zig cc` is used to
507
+ // build LLVM, Clang, and LLD, however when depending on them as system libraries, system
508
+ // libc++ must be used.
509
+ const cross_compile = false ; // TODO
510
+ if (cross_compile ) {
511
+ // In this case we assume that zig cc was used to build the LLVM, Clang, LLD dependencies.
512
+ exe .linkSystemLibrary ("c++" );
513
+ } else {
514
+ if (exe .target .getOsTag () == .linux ) {
515
+ // First we try to static link against gcc libstdc++. If that doesn't work,
516
+ // we fall back to -lc++ and cross our fingers.
517
+ addCxxKnownPath (b , ctx , exe , "libstdc++.a" , "" , need_cpp_includes ) catch | err | switch (err ) {
518
+ error .RequiredLibraryNotFound = > {
519
+ exe .linkSystemLibrary ("c++" );
520
+ },
521
+ else = > | e | return e ,
522
+ };
523
+
524
+ exe .linkSystemLibrary ("pthread" );
525
+ } else if (exe .target .isFreeBSD ()) {
526
+ try addCxxKnownPath (b , ctx , exe , "libc++.a" , null , need_cpp_includes );
527
+ exe .linkSystemLibrary ("pthread" );
528
+ } else if (exe .target .isDarwin ()) {
529
+ if (addCxxKnownPath (b , ctx , exe , "libgcc_eh.a" , "" , need_cpp_includes )) {
530
+ // Compiler is GCC.
531
+ try addCxxKnownPath (b , ctx , exe , "libstdc++.a" , null , need_cpp_includes );
532
+ exe .linkSystemLibrary ("pthread" );
533
+ // TODO LLD cannot perform this link.
534
+ // Set ZIG_SYSTEM_LINKER_HACK env var to use system linker ld instead.
535
+ // See https://github.com/ziglang/zig/issues/1535
536
+ } else | err | switch (err ) {
537
+ error .RequiredLibraryNotFound = > {
538
+ // System compiler, not gcc.
539
+ exe .linkSystemLibrary ("c++" );
540
+ },
541
+ else = > | e | return e ,
542
+ }
543
+ }
544
+
545
+ if (ctx .dia_guids_lib .len != 0 ) {
546
+ exe .addObjectFile (ctx .dia_guids_lib );
547
+ }
548
+ }
549
+ }
550
+
362
551
fn addCxxKnownPath (
363
552
b : * Builder ,
364
553
ctx : CMakeConfig ,
@@ -369,14 +558,14 @@ fn addCxxKnownPath(
369
558
) ! void {
370
559
const path_padded = try b .exec (&[_ ][]const u8 {
371
560
ctx .cxx_compiler ,
372
- b .fmt ("-print-file-name={}" , .{objname }),
561
+ b .fmt ("-print-file-name={s }" , .{objname }),
373
562
});
374
563
const path_unpadded = mem .tokenize (path_padded , "\r \n " ).next ().? ;
375
564
if (mem .eql (u8 , path_unpadded , objname )) {
376
565
if (errtxt ) | msg | {
377
- warn ("{}" , .{msg });
566
+ warn ("{s }" , .{msg });
378
567
} else {
379
- warn ("Unable to determine path to {}\n " , .{objname });
568
+ warn ("Unable to determine path to {s }\n " , .{objname });
380
569
}
381
570
return error .RequiredLibraryNotFound ;
382
571
}
0 commit comments