Lines 252-257
pub fn build(b: *Builder) !void {
Link Here
|
252 |
}; |
252 |
}; |
253 |
exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); |
253 |
exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); |
254 |
|
254 |
|
|
|
255 |
// -Dzig0 makes extra assumptions about the system config/bootstrapping, which we verify here. |
256 |
if (use_zig0) { |
257 |
if (!have_stage1) { |
258 |
std.log.err("-Dzig0 is currently only supported in combination with -Denable-stage1", .{}); |
259 |
std.os.exit(1); |
260 |
} |
261 |
if (!static_llvm) { |
262 |
std.log.err("-Dzig0 is currently only supported with -Dstatic-llvm", .{}); |
263 |
std.os.exit(1); |
264 |
} |
265 |
} |
266 |
|
255 |
if (enable_llvm) { |
267 |
if (enable_llvm) { |
256 |
const cmake_cfg = if (static_llvm) null else blk: { |
268 |
const cmake_cfg = if (static_llvm) null else blk: { |
257 |
if (findConfigH(b, config_h_path_option)) |config_h_path| { |
269 |
if (findConfigH(b, config_h_path_option)) |config_h_path| { |
Lines 286-300
pub fn build(b: *Builder) !void {
Link Here
|
286 |
artifact.addIncludePath("deps/SoftFloat-3e/source/include"); |
298 |
artifact.addIncludePath("deps/SoftFloat-3e/source/include"); |
287 |
artifact.addIncludePath("deps/SoftFloat-3e-prebuilt"); |
299 |
artifact.addIncludePath("deps/SoftFloat-3e-prebuilt"); |
288 |
|
300 |
|
289 |
artifact.defineCMacro("ZIG_LINK_MODE", "Static"); |
301 |
if (cmake_cfg) |cfg| { |
|
|
302 |
artifact.defineCMacro("ZIG_LINK_MODE", if (cfg.llvm_linkage == .dynamic) "Dynamic" else "Static"); |
303 |
} else { |
304 |
artifact.defineCMacro("ZIG_LINK_MODE", "Static"); |
305 |
} |
290 |
|
306 |
|
291 |
artifact.addCSourceFiles(&stage1_sources, &exe_cflags); |
307 |
artifact.addCSourceFiles(&stage1_sources, &exe_cflags); |
292 |
artifact.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); |
308 |
artifact.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); |
293 |
|
309 |
|
294 |
artifact.linkLibrary(softfloat); |
310 |
artifact.linkLibrary(softfloat); |
295 |
artifact.linkLibCpp(); |
|
|
296 |
} |
311 |
} |
297 |
|
312 |
|
|
|
313 |
zig0.linkLibCpp(); |
298 |
try addStaticLlvmOptionsToExe(zig0); |
314 |
try addStaticLlvmOptionsToExe(zig0); |
299 |
|
315 |
|
300 |
const zig1_obj_ext = target.getObjectFormat().fileExt(target.getCpuArch()); |
316 |
const zig1_obj_ext = target.getObjectFormat().fileExt(target.getCpuArch()); |
Lines 349-354
pub fn build(b: *Builder) !void {
Link Here
|
349 |
// is pointless. |
365 |
// is pointless. |
350 |
exe.addPackagePath("compiler_rt", "src/empty.zig"); |
366 |
exe.addPackagePath("compiler_rt", "src/empty.zig"); |
351 |
} |
367 |
} |
|
|
368 |
|
352 |
if (cmake_cfg) |cfg| { |
369 |
if (cmake_cfg) |cfg| { |
353 |
// Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD. |
370 |
// Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD. |
354 |
// That means we also have to rely on stage1 compiled c++ files. We parse config.h to find |
371 |
// That means we also have to rely on stage1 compiled c++ files. We parse config.h to find |
Lines 567-577
fn addCmakeCfgOptionsToExe(
Link Here
|
567 |
exe: *std.build.LibExeObjStep, |
584 |
exe: *std.build.LibExeObjStep, |
568 |
use_zig_libcxx: bool, |
585 |
use_zig_libcxx: bool, |
569 |
) !void { |
586 |
) !void { |
570 |
exe.addObjectFile(fs.path.join(b.allocator, &[_][]const u8{ |
587 |
// Adds the Zig C++ sources which both stage1 and stage2 need. |
571 |
cfg.cmake_binary_dir, |
588 |
// |
572 |
"zigcpp", |
589 |
// We need this because otherwise zig_clang_cc1_main.cpp ends up pulling |
573 |
b.fmt("{s}{s}{s}", .{ exe.target.libPrefix(), "zigcpp", exe.target.staticLibSuffix() }), |
590 |
// in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is |
574 |
}) catch unreachable); |
591 |
// unavailable when LLVM is compiled in Release mode. |
|
|
592 |
const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; |
593 |
exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags); |
594 |
|
575 |
assert(cfg.lld_include_dir.len != 0); |
595 |
assert(cfg.lld_include_dir.len != 0); |
576 |
exe.addIncludePath(cfg.lld_include_dir); |
596 |
exe.addIncludePath(cfg.lld_include_dir); |
577 |
exe.addIncludePath(cfg.llvm_include_dir); |
597 |
exe.addIncludePath(cfg.llvm_include_dir); |
Lines 583-589
fn addCmakeCfgOptionsToExe(
Link Here
|
583 |
if (use_zig_libcxx) { |
603 |
if (use_zig_libcxx) { |
584 |
exe.linkLibCpp(); |
604 |
exe.linkLibCpp(); |
585 |
} else { |
605 |
} else { |
586 |
const need_cpp_includes = true; |
|
|
587 |
const lib_suffix = switch (cfg.llvm_linkage) { |
606 |
const lib_suffix = switch (cfg.llvm_linkage) { |
588 |
.static => exe.target.staticLibSuffix()[1..], |
607 |
.static => exe.target.staticLibSuffix()[1..], |
589 |
.dynamic => exe.target.dynamicLibSuffix()[1..], |
608 |
.dynamic => exe.target.dynamicLibSuffix()[1..], |
Lines 594-614
fn addCmakeCfgOptionsToExe(
Link Here
|
594 |
if (exe.target.getOsTag() == .linux) { |
613 |
if (exe.target.getOsTag() == .linux) { |
595 |
// First we try to link against gcc libstdc++. If that doesn't work, we fall |
614 |
// First we try to link against gcc libstdc++. If that doesn't work, we fall |
596 |
// back to -lc++ and cross our fingers. |
615 |
// back to -lc++ and cross our fingers. |
597 |
addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), "", need_cpp_includes) catch |err| switch (err) { |
616 |
addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), "") catch |err| switch (err) { |
598 |
error.RequiredLibraryNotFound => { |
617 |
error.RequiredLibraryNotFound => { |
599 |
exe.linkSystemLibrary("c++"); |
618 |
exe.linkSystemLibrary("c++"); |
600 |
}, |
619 |
}, |
601 |
else => |e| return e, |
620 |
else => |e| return e, |
602 |
}; |
621 |
}; |
|
|
622 |
try addLibcxxIncludePaths(b, cfg, exe); |
603 |
exe.linkSystemLibrary("unwind"); |
623 |
exe.linkSystemLibrary("unwind"); |
604 |
} else if (exe.target.isFreeBSD()) { |
624 |
} else if (exe.target.isFreeBSD()) { |
605 |
try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes); |
625 |
try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null); |
606 |
exe.linkSystemLibrary("pthread"); |
626 |
exe.linkSystemLibrary("pthread"); |
607 |
} else if (exe.target.getOsTag() == .openbsd) { |
627 |
} else if (exe.target.getOsTag() == .openbsd) { |
608 |
try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes); |
628 |
try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null); |
609 |
try addCxxKnownPath(b, cfg, exe, b.fmt("libc++abi.{s}", .{lib_suffix}), null, need_cpp_includes); |
629 |
try addCxxKnownPath(b, cfg, exe, b.fmt("libc++abi.{s}", .{lib_suffix}), null); |
|
|
630 |
try addLibcxxIncludePaths(b, cfg, exe); |
610 |
} else if (exe.target.isDarwin()) { |
631 |
} else if (exe.target.isDarwin()) { |
611 |
exe.linkSystemLibrary("c++"); |
632 |
if (cfg.llvm_linkage == .dynamic and cfg.apple_libcpp_path.len > 0) { |
|
|
633 |
exe.addObjectFile(cfg.apple_libcpp_path); |
634 |
const sysroot = std.fs.path.dirname(std.fs.path.dirname(std.fs.path.dirname(cfg.apple_libcpp_path).?).?).?; |
635 |
exe.addIncludePath(b.fmt("{s}/usr/include/c++/v1/", .{sysroot})); |
636 |
} else { |
637 |
exe.linkSystemLibrary("c++"); |
638 |
} |
612 |
} |
639 |
} |
613 |
} |
640 |
} |
614 |
|
641 |
|
Lines 651-663
fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
Link Here
|
651 |
} |
678 |
} |
652 |
} |
679 |
} |
653 |
|
680 |
|
|
|
681 |
/// Invoke the system C++ compiler and have it locate `objname`, usually |
682 |
/// a static or shared library file that's included in the stdlib. |
654 |
fn addCxxKnownPath( |
683 |
fn addCxxKnownPath( |
655 |
b: *Builder, |
684 |
b: *Builder, |
656 |
ctx: CMakeConfig, |
685 |
ctx: CMakeConfig, |
657 |
exe: *std.build.LibExeObjStep, |
686 |
exe: *std.build.LibExeObjStep, |
658 |
objname: []const u8, |
687 |
objname: []const u8, |
659 |
errtxt: ?[]const u8, |
688 |
errtxt: ?[]const u8, |
660 |
need_cpp_includes: bool, |
|
|
661 |
) !void { |
689 |
) !void { |
662 |
if (!std.process.can_spawn) |
690 |
if (!std.process.can_spawn) |
663 |
return error.RequiredLibraryNotFound; |
691 |
return error.RequiredLibraryNotFound; |
Lines 676-689
fn addCxxKnownPath(
Link Here
|
676 |
return error.RequiredLibraryNotFound; |
704 |
return error.RequiredLibraryNotFound; |
677 |
} |
705 |
} |
678 |
exe.addObjectFile(path_unpadded); |
706 |
exe.addObjectFile(path_unpadded); |
|
|
707 |
} |
679 |
|
708 |
|
680 |
// TODO a way to integrate with system c++ include files here |
709 |
/// Invoke the system C++ compiler and add to the build any libc++ include |
|
|
710 |
/// paths in its system include search list. |
711 |
fn addLibcxxIncludePaths( |
712 |
b: *Builder, |
713 |
ctx: CMakeConfig, |
714 |
exe: *std.build.LibExeObjStep, |
715 |
) !void { |
681 |
// c++ -E -Wp,-v -xc++ /dev/null |
716 |
// c++ -E -Wp,-v -xc++ /dev/null |
682 |
if (need_cpp_includes) { |
717 |
const max_output_size = 400 * 1024; |
683 |
// I used these temporarily for testing something but we obviously need a |
718 |
var child = std.ChildProcess.init(&[_][]const u8{ ctx.cxx_compiler, "-E", "-Wp,-v", "-xc++", "/dev/null" }, b.allocator); |
684 |
// more general purpose solution here. |
719 |
child.stdin_behavior = .Ignore; |
685 |
//exe.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0"); |
720 |
child.stdout_behavior = .Ignore; |
686 |
//exe.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0/x86_64-unknown-linux-gnu"); |
721 |
child.stderr_behavior = .Pipe; |
|
|
722 |
try child.spawn(); |
723 |
const stderr = child.stderr.?.reader().readAllAlloc(b.allocator, max_output_size) catch unreachable; |
724 |
errdefer b.allocator.free(stderr); |
725 |
|
726 |
const term = try child.wait(); |
727 |
assert(term == .Exited and term.Exited == 0); |
728 |
|
729 |
var it = mem.tokenize(u8, stderr, "\r\n"); |
730 |
while (it.next()) |line| { |
731 |
if (std.mem.eql(u8, line, "#include <...> search starts here:")) |
732 |
break; |
733 |
} else unreachable; |
734 |
|
735 |
paths: while (it.next()) |line| { |
736 |
if (line[0] != ' ') |
737 |
break; |
738 |
|
739 |
// Look for a directory name starting with "c++" or "g++" within the last three |
740 |
// components of the path. |
741 |
var i: u8 = 0; |
742 |
var parent_dir = line[1..]; |
743 |
while (i < 3) : (i += 1) { |
744 |
if (std.mem.startsWith(u8, std.fs.path.basename(parent_dir), "c++") or |
745 |
std.mem.startsWith(u8, std.fs.path.basename(parent_dir), "g++")) |
746 |
{ |
747 |
|
748 |
// TODO: Use `addSystemIncludePath` once |
749 |
// https://github.com/ziglang/zig/issues/13496 is resolved. |
750 |
exe.addIncludePath(line[1..]); |
751 |
continue :paths; |
752 |
} else parent_dir = std.fs.path.dirname(parent_dir) orelse continue :paths; |
753 |
} |
687 |
} |
754 |
} |
688 |
} |
755 |
} |
689 |
|
756 |
|
Lines 700-705
fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void {
Link Here
|
700 |
|
767 |
|
701 |
const CMakeConfig = struct { |
768 |
const CMakeConfig = struct { |
702 |
llvm_linkage: std.build.LibExeObjStep.Linkage, |
769 |
llvm_linkage: std.build.LibExeObjStep.Linkage, |
|
|
770 |
apple_libcpp_path: []const u8, |
703 |
cmake_binary_dir: []const u8, |
771 |
cmake_binary_dir: []const u8, |
704 |
cmake_prefix_path: []const u8, |
772 |
cmake_prefix_path: []const u8, |
705 |
cxx_compiler: []const u8, |
773 |
cxx_compiler: []const u8, |
Lines 763-768
fn findConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?[]const u8 {
Link Here
|
763 |
fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig { |
831 |
fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig { |
764 |
var ctx: CMakeConfig = .{ |
832 |
var ctx: CMakeConfig = .{ |
765 |
.llvm_linkage = undefined, |
833 |
.llvm_linkage = undefined, |
|
|
834 |
.apple_libcpp_path = undefined, |
766 |
.cmake_binary_dir = undefined, |
835 |
.cmake_binary_dir = undefined, |
767 |
.cmake_prefix_path = undefined, |
836 |
.cmake_prefix_path = undefined, |
768 |
.cxx_compiler = undefined, |
837 |
.cxx_compiler = undefined, |
Lines 816-821
fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
Link Here
|
816 |
.prefix = "#define ZIG_LLVM_LIB_PATH ", |
885 |
.prefix = "#define ZIG_LLVM_LIB_PATH ", |
817 |
.field = "llvm_lib_dir", |
886 |
.field = "llvm_lib_dir", |
818 |
}, |
887 |
}, |
|
|
888 |
.{ |
889 |
.prefix = "#define ZIG_APPLE_LIBCPP_PATH ", |
890 |
.field = "apple_libcpp_path", |
891 |
}, |
819 |
// .prefix = ZIG_LLVM_LINK_MODE parsed manually below |
892 |
// .prefix = ZIG_LLVM_LINK_MODE parsed manually below |
820 |
}; |
893 |
}; |
821 |
|
894 |
|