From 5a65caa2a3686e12e4dfcfd599ed02f8a09c6017 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 4 Dec 2020 21:33:29 -0700 Subject: [PATCH 1/5] ability to build stage1 using only a zig tarball The main idea here is that there are now 2 ways to get a stage1 zig binary: * The cmake path. Requirements: cmake, system C++ compiler, system LLVM, LLD, Clang libraries, compiled by the system C++ compiler. * The zig path. Requirements: a zig installation, system LLVM, LLD, Clang libraries, compiled by the zig installation. Note that the former can be used to now take the latter path. Removed config.h.in and config.zig.in. The build.zig script no longer is coupled to the cmake script. cmake no longer tries to determine the zig version. A build with cmake will yield a stage1 zig binary that reports 0.0.0+zig0. This is going to get reverted. `zig build` now accepts `-Dstage1` which will build the stage1 compiler, and put the stage2 backend behind a feature flag. build.zig is simplified to only support the use case of enabling LLVM support when the LLVM, LLD, and Clang libraries were built by zig. This part is probably sadly going to have to get reverted to make package maintainers happy. Zig build system addBuildOption supports a couple new types. The biggest reason to make this change is that the zig path is an attractive option for doing compiler development work on Windows. It allows people to work on the compiler without having MSVC installed, using only a .zip file that contains Zig + LLVM/LLD/Clang libraries. --- CMakeLists.txt | 53 +- build.zig | 732 +++++++++++++---------- lib/std/build.zig | 80 ++- src/stage1.zig | 14 + src/stage1/analyze.cpp | 1 - src/stage1/codegen.cpp | 13 +- src/stage1/config.h.in | 26 - src/stage1/dump_analysis.cpp | 3 +- src/stage1/heap.cpp | 1 - src/stage1/heap.hpp | 1 - src/stage1/mem.cpp | 1 - src/stage1/mem.hpp | 1 - src/stage1/mem_type_info.hpp | 2 - src/stage1/stage2.h | 6 + src/stage1/util.hpp | 4 +- src/stage1/zig0.cpp | 8 + src/{config.zig.in => stage1_config.zig} | 8 +- src/zig_clang.h | 2 +- 18 files changed, 533 insertions(+), 423 deletions(-) delete mode 100644 src/stage1/config.h.in rename src/{config.zig.in => stage1_config.zig} (58%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad38cdb18b002ec5f31219653bce3b56029e716b..b9a81575be5502ae7dc2643698d03ef188a27128 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,34 +24,6 @@ set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX project(zig C CXX) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) -set(ZIG_VERSION_MAJOR 0) -set(ZIG_VERSION_MINOR 7) -set(ZIG_VERSION_PATCH 0) -set(ZIG_VERSION "" CACHE STRING "Override Zig version string. Default is to find out with git.") - -if("${ZIG_VERSION}" STREQUAL "") - set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}") - find_program(GIT_EXE NAMES git) - if(GIT_EXE) - execute_process( - COMMAND ${GIT_EXE} -C ${CMAKE_SOURCE_DIR} name-rev HEAD --tags --name-only --no-undefined --always - RESULT_VARIABLE EXIT_STATUS - OUTPUT_VARIABLE ZIG_GIT_REV - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET) - if(EXIT_STATUS EQUAL "0") - if(ZIG_GIT_REV MATCHES "\\^0$") - if(NOT("${ZIG_GIT_REV}" STREQUAL "${ZIG_VERSION}^0")) - message("WARNING: Tag does not match configured Zig version") - endif() - else() - set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}") - endif() - endif() - endif() -endif() -message("Configuring zig version ${ZIG_VERSION}") - set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)") set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries") set(ZIG_PREFER_CLANG_CPP_DYLIB off CACHE BOOL "Try to link against -lclang-cpp") @@ -63,9 +35,6 @@ endif() if(ZIG_STATIC) set(ZIG_STATIC_LLVM "on") - set(ZIG_LINK_MODE "Static") -else() - set(ZIG_LINK_MODE "Dynamic") endif() string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_DIR}") @@ -264,8 +233,6 @@ set(LIBC_FILES_DEST "${ZIG_LIB_DIR}/libc") set(LIBUNWIND_FILES_DEST "${ZIG_LIB_DIR}/libunwind") set(LIBCXX_FILES_DEST "${ZIG_LIB_DIR}/libcxx") set(ZIG_STD_DEST "${ZIG_LIB_DIR}/std") -set(ZIG_CONFIG_H_OUT "${CMAKE_BINARY_DIR}/config.h") -set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig") # This is our shim which will be replaced by stage1.zig. set(ZIG0_SOURCES @@ -313,7 +280,6 @@ set(ZIG_CPP_SOURCES # then manually running the build-obj command (see BUILD_ZIG1_ARGS), and then looking # in the zig-cache directory for the compiler-generated list of zig file dependencies. set(ZIG_STAGE2_SOURCES - "${ZIG_CONFIG_ZIG_OUT}" "${CMAKE_SOURCE_DIR}/lib/std/array_hash_map.zig" "${CMAKE_SOURCE_DIR}/lib/std/array_list.zig" "${CMAKE_SOURCE_DIR}/lib/std/ascii.zig" @@ -553,6 +519,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/src/print_env.zig" "${CMAKE_SOURCE_DIR}/src/print_targets.zig" "${CMAKE_SOURCE_DIR}/src/stage1.zig" + "${CMAKE_SOURCE_DIR}/src/stage1_config.zig" "${CMAKE_SOURCE_DIR}/src/target.zig" "${CMAKE_SOURCE_DIR}/src/tracy.zig" "${CMAKE_SOURCE_DIR}/src/translate_c.zig" @@ -571,15 +538,6 @@ if(MSVC) endif() endif() -configure_file ( - "${CMAKE_SOURCE_DIR}/src/stage1/config.h.in" - "${ZIG_CONFIG_H_OUT}" -) -configure_file ( - "${CMAKE_SOURCE_DIR}/src/config.zig.in" - "${ZIG_CONFIG_ZIG_OUT}" -) - include_directories( ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} @@ -594,6 +552,12 @@ else(MSVC) set(EXE_CFLAGS "-std=c++14") endif(MSVC) +if(ZIG_STATIC) + set(EXE_CFLAGS "${EXE_CFLAGS} -DZIG_LINK_MODE=Static") +else() + set(EXE_CFLAGS "${EXE_CFLAGS} -DZIG_LINK_MODE=Dynamic") +endif() + if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") if(MSVC) set(EXE_CFLAGS "${EXE_CFLAGS} /w") @@ -720,7 +684,7 @@ set(BUILD_ZIG1_ARGS "-femit-bin=${ZIG1_OBJECT}" "${ZIG1_RELEASE_ARG}" -lc - --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}" + --pkg-begin build_options "${CMAKE_SOURCE_DIR}/src/stage1_config.zig" --pkg-end --pkg-begin compiler_rt "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt.zig" --pkg-end @@ -769,7 +733,6 @@ set(ZIG_INSTALL_ARGS "build" --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" "-Dlib-files-only" --prefix "${CMAKE_INSTALL_PREFIX}" - "-Dconfig_h=${ZIG_CONFIG_H_OUT}" install ) diff --git a/build.zig b/build.zig index 2318c04c349d51393aa7fbc46d427ae29b99b117..cd8087d3ee2f3acc9be009b1b9acaa6da438bfb4 100644 --- a/build.zig +++ b/build.zig @@ -53,7 +53,8 @@ pub fn build(b: *Builder) !void { const skip_compile_errors = b.option(bool, "skip-compile-errors", "Main test suite skips compile error tests") orelse false; const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; - const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse false; + const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false; + const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse is_stage1; const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h"); b.installDirectory(InstallDirectoryOptions{ @@ -76,6 +77,8 @@ pub fn build(b: *Builder) !void { const tracy = b.option([]const u8, "tracy", "Enable Tracy integration. Supply path to Tracy source"); const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm; + const main_file = if (is_stage1) "src/stage1.zig" else "src/main.zig"; + var exe = b.addExecutable("zig", "src/main.zig"); exe.install(); exe.setBuildMode(mode); @@ -86,15 +89,51 @@ pub fn build(b: *Builder) !void { exe.addBuildOption(bool, "skip_non_native", skip_non_native); exe.addBuildOption(bool, "have_llvm", enable_llvm); if (enable_llvm) { - const config_h_text = if (config_h_path_option) |config_h_path| - try std.fs.cwd().readFileAlloc(b.allocator, toNativePathSep(b, config_h_path), max_config_h_bytes) - else - try findAndReadConfigH(b); + if (is_stage1) { + exe.addIncludeDir("src"); + exe.addIncludeDir("deps/SoftFloat-3e/source/include"); - var ctx = parseConfigH(b, config_h_text); - ctx.llvm = try findLLVM(b, ctx.llvm_config_exe); + const softfloat = b.addStaticLibrary("softfloat", null); + softfloat.setBuildMode(.ReleaseFast); + softfloat.setTarget(target); + softfloat.addIncludeDir("deps/SoftFloat-3e-prebuilt"); + softfloat.addIncludeDir("deps/SoftFloat-3e/source/8086"); + softfloat.addIncludeDir("deps/SoftFloat-3e/source/include"); + softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" }); + exe.linkLibrary(softfloat); - try configureStage2(b, exe, ctx, tracy != null); + const exe_cflags = &[_][]const u8{ + "-std=c++14", + "-D__STDC_CONSTANT_MACROS", + "-D__STDC_FORMAT_MACROS", + "-D__STDC_LIMIT_MACROS", + "-D_GNU_SOURCE", + "-fvisibility-inlines-hidden", + "-fno-exceptions", + "-fno-rtti", + "-Werror=type-limits", + "-Wno-missing-braces", + "-Wno-comment", + }; + exe.addCSourceFiles(&stage1_sources, exe_cflags); + exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); + exe.addCSourceFiles(&zig_cpp_sources, exe_cflags); + } + + for (clang_libs) |lib_name| { + exe.linkSystemLibrary(lib_name); + } + + for (lld_libs) |lib_name| { + exe.linkSystemLibrary(lib_name); + } + + for (llvm_libs) |lib_name| { + exe.linkSystemLibrary(lib_name); + } + + // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. + exe.linkSystemLibrary("c++"); } if (link_libc) { exe.linkLibC(); @@ -141,7 +180,10 @@ pub fn build(b: *Builder) !void { break :v b.fmt("{}+{}{}", .{ version_string, git_sha_trimmed, dirty_suffix }); } }; - exe.addBuildOption([]const u8, "version", version); + exe.addBuildOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); + + const semver = try std.SemanticVersion.parse(version); + exe.addBuildOption(std.SemanticVersion, "semver", semver); exe.addBuildOption([]const []const u8, "log_scopes", log_scopes); exe.addBuildOption([]const []const u8, "zir_dumps", zir_dumps); @@ -226,327 +268,359 @@ pub fn build(b: *Builder) !void { test_step.dependOn(docs_step); } -fn dependOnLib(b: *Builder, lib_exe_obj: anytype, dep: LibraryDep) void { - for (dep.libdirs.items) |lib_dir| { - lib_exe_obj.addLibPath(lib_dir); - } - const lib_dir = fs.path.join( - b.allocator, - &[_][]const u8{ dep.prefix, "lib" }, - ) catch unreachable; - for (dep.system_libs.items) |lib| { - const static_bare_name = if (mem.eql(u8, lib, "curses")) - @as([]const u8, "libncurses.a") - else - b.fmt("lib{}.a", .{lib}); - const static_lib_name = fs.path.join( - b.allocator, - &[_][]const u8{ lib_dir, static_bare_name }, - ) catch unreachable; - const have_static = fileExists(static_lib_name) catch unreachable; - if (have_static) { - lib_exe_obj.addObjectFile(static_lib_name); - } else { - lib_exe_obj.linkSystemLibrary(lib); - } - } - for (dep.libs.items) |lib| { - lib_exe_obj.addObjectFile(lib); - } - for (dep.includes.items) |include_path| { - lib_exe_obj.addIncludeDir(include_path); - } -} - -fn fileExists(filename: []const u8) !bool { - fs.cwd().access(filename, .{}) catch |err| switch (err) { - error.FileNotFound => return false, - else => return err, - }; - return true; -} - -fn addCppLib(b: *Builder, lib_exe_obj: anytype, cmake_binary_dir: []const u8, lib_name: []const u8) void { - lib_exe_obj.addObjectFile(fs.path.join(b.allocator, &[_][]const u8{ - cmake_binary_dir, - "zigcpp", - b.fmt("{}{}{}", .{ lib_exe_obj.target.libPrefix(), lib_name, lib_exe_obj.target.staticLibSuffix() }), - }) catch unreachable); -} - -const LibraryDep = struct { - prefix: []const u8, - libdirs: ArrayList([]const u8), - libs: ArrayList([]const u8), - system_libs: ArrayList([]const u8), - includes: ArrayList([]const u8), +const softfloat_sources = [_][]const u8{ + "deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c", + "deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c", + "deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c", + "deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c", + "deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c", + "deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c", + "deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c", + "deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c", + "deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c", + "deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c", + "deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c", + "deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c", + "deps/SoftFloat-3e/source/f128M_add.c", + "deps/SoftFloat-3e/source/f128M_div.c", + "deps/SoftFloat-3e/source/f128M_eq.c", + "deps/SoftFloat-3e/source/f128M_eq_signaling.c", + "deps/SoftFloat-3e/source/f128M_le.c", + "deps/SoftFloat-3e/source/f128M_le_quiet.c", + "deps/SoftFloat-3e/source/f128M_lt.c", + "deps/SoftFloat-3e/source/f128M_lt_quiet.c", + "deps/SoftFloat-3e/source/f128M_mul.c", + "deps/SoftFloat-3e/source/f128M_mulAdd.c", + "deps/SoftFloat-3e/source/f128M_rem.c", + "deps/SoftFloat-3e/source/f128M_roundToInt.c", + "deps/SoftFloat-3e/source/f128M_sqrt.c", + "deps/SoftFloat-3e/source/f128M_sub.c", + "deps/SoftFloat-3e/source/f128M_to_f16.c", + "deps/SoftFloat-3e/source/f128M_to_f32.c", + "deps/SoftFloat-3e/source/f128M_to_f64.c", + "deps/SoftFloat-3e/source/f128M_to_i32.c", + "deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c", + "deps/SoftFloat-3e/source/f128M_to_i64.c", + "deps/SoftFloat-3e/source/f128M_to_i64_r_minMag.c", + "deps/SoftFloat-3e/source/f128M_to_ui32.c", + "deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c", + "deps/SoftFloat-3e/source/f128M_to_ui64.c", + "deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c", + "deps/SoftFloat-3e/source/f16_add.c", + "deps/SoftFloat-3e/source/f16_div.c", + "deps/SoftFloat-3e/source/f16_eq.c", + "deps/SoftFloat-3e/source/f16_isSignalingNaN.c", + "deps/SoftFloat-3e/source/f16_lt.c", + "deps/SoftFloat-3e/source/f16_mul.c", + "deps/SoftFloat-3e/source/f16_mulAdd.c", + "deps/SoftFloat-3e/source/f16_rem.c", + "deps/SoftFloat-3e/source/f16_roundToInt.c", + "deps/SoftFloat-3e/source/f16_sqrt.c", + "deps/SoftFloat-3e/source/f16_sub.c", + "deps/SoftFloat-3e/source/f16_to_f128M.c", + "deps/SoftFloat-3e/source/f16_to_f64.c", + "deps/SoftFloat-3e/source/f32_to_f128M.c", + "deps/SoftFloat-3e/source/f64_to_f128M.c", + "deps/SoftFloat-3e/source/f64_to_f16.c", + "deps/SoftFloat-3e/source/i32_to_f128M.c", + "deps/SoftFloat-3e/source/s_add256M.c", + "deps/SoftFloat-3e/source/s_addCarryM.c", + "deps/SoftFloat-3e/source/s_addComplCarryM.c", + "deps/SoftFloat-3e/source/s_addF128M.c", + "deps/SoftFloat-3e/source/s_addM.c", + "deps/SoftFloat-3e/source/s_addMagsF16.c", + "deps/SoftFloat-3e/source/s_addMagsF32.c", + "deps/SoftFloat-3e/source/s_addMagsF64.c", + "deps/SoftFloat-3e/source/s_approxRecip32_1.c", + "deps/SoftFloat-3e/source/s_approxRecipSqrt32_1.c", + "deps/SoftFloat-3e/source/s_approxRecipSqrt_1Ks.c", + "deps/SoftFloat-3e/source/s_approxRecip_1Ks.c", + "deps/SoftFloat-3e/source/s_compare128M.c", + "deps/SoftFloat-3e/source/s_compare96M.c", + "deps/SoftFloat-3e/source/s_countLeadingZeros16.c", + "deps/SoftFloat-3e/source/s_countLeadingZeros32.c", + "deps/SoftFloat-3e/source/s_countLeadingZeros64.c", + "deps/SoftFloat-3e/source/s_countLeadingZeros8.c", + "deps/SoftFloat-3e/source/s_eq128.c", + "deps/SoftFloat-3e/source/s_invalidF128M.c", + "deps/SoftFloat-3e/source/s_isNaNF128M.c", + "deps/SoftFloat-3e/source/s_le128.c", + "deps/SoftFloat-3e/source/s_lt128.c", + "deps/SoftFloat-3e/source/s_mul128MTo256M.c", + "deps/SoftFloat-3e/source/s_mul64To128M.c", + "deps/SoftFloat-3e/source/s_mulAddF128M.c", + "deps/SoftFloat-3e/source/s_mulAddF16.c", + "deps/SoftFloat-3e/source/s_mulAddF32.c", + "deps/SoftFloat-3e/source/s_mulAddF64.c", + "deps/SoftFloat-3e/source/s_negXM.c", + "deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c", + "deps/SoftFloat-3e/source/s_normRoundPackToF16.c", + "deps/SoftFloat-3e/source/s_normRoundPackToF32.c", + "deps/SoftFloat-3e/source/s_normRoundPackToF64.c", + "deps/SoftFloat-3e/source/s_normSubnormalF128SigM.c", + "deps/SoftFloat-3e/source/s_normSubnormalF16Sig.c", + "deps/SoftFloat-3e/source/s_normSubnormalF32Sig.c", + "deps/SoftFloat-3e/source/s_normSubnormalF64Sig.c", + "deps/SoftFloat-3e/source/s_remStepMBy32.c", + "deps/SoftFloat-3e/source/s_roundMToI64.c", + "deps/SoftFloat-3e/source/s_roundMToUI64.c", + "deps/SoftFloat-3e/source/s_roundPackMToF128M.c", + "deps/SoftFloat-3e/source/s_roundPackToF16.c", + "deps/SoftFloat-3e/source/s_roundPackToF32.c", + "deps/SoftFloat-3e/source/s_roundPackToF64.c", + "deps/SoftFloat-3e/source/s_roundToI32.c", + "deps/SoftFloat-3e/source/s_roundToI64.c", + "deps/SoftFloat-3e/source/s_roundToUI32.c", + "deps/SoftFloat-3e/source/s_roundToUI64.c", + "deps/SoftFloat-3e/source/s_shiftLeftM.c", + "deps/SoftFloat-3e/source/s_shiftNormSigF128M.c", + "deps/SoftFloat-3e/source/s_shiftRightJam256M.c", + "deps/SoftFloat-3e/source/s_shiftRightJam32.c", + "deps/SoftFloat-3e/source/s_shiftRightJam64.c", + "deps/SoftFloat-3e/source/s_shiftRightJamM.c", + "deps/SoftFloat-3e/source/s_shiftRightM.c", + "deps/SoftFloat-3e/source/s_shortShiftLeft64To96M.c", + "deps/SoftFloat-3e/source/s_shortShiftLeftM.c", + "deps/SoftFloat-3e/source/s_shortShiftRightExtendM.c", + "deps/SoftFloat-3e/source/s_shortShiftRightJam64.c", + "deps/SoftFloat-3e/source/s_shortShiftRightJamM.c", + "deps/SoftFloat-3e/source/s_shortShiftRightM.c", + "deps/SoftFloat-3e/source/s_sub1XM.c", + "deps/SoftFloat-3e/source/s_sub256M.c", + "deps/SoftFloat-3e/source/s_subM.c", + "deps/SoftFloat-3e/source/s_subMagsF16.c", + "deps/SoftFloat-3e/source/s_subMagsF32.c", + "deps/SoftFloat-3e/source/s_subMagsF64.c", + "deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c", + "deps/SoftFloat-3e/source/softfloat_state.c", + "deps/SoftFloat-3e/source/ui32_to_f128M.c", + "deps/SoftFloat-3e/source/ui64_to_f128M.c", }; -fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { - const shared_mode = try b.exec(&[_][]const u8{ llvm_config_exe, "--shared-mode" }); - const is_static = mem.startsWith(u8, shared_mode, "static"); - const libs_output = if (is_static) - try b.exec(&[_][]const u8{ - llvm_config_exe, - "--libfiles", - "--system-libs", - }) - else - try b.exec(&[_][]const u8{ - llvm_config_exe, - "--libs", - }); - const includes_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--includedir" }); - const libdir_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--libdir" }); - const prefix_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--prefix" }); - - var result = LibraryDep{ - .prefix = mem.tokenize(prefix_output, " \r\n").next().?, - .libs = ArrayList([]const u8).init(b.allocator), - .system_libs = ArrayList([]const u8).init(b.allocator), - .includes = ArrayList([]const u8).init(b.allocator), - .libdirs = ArrayList([]const u8).init(b.allocator), - }; - { - var it = mem.tokenize(libs_output, " \r\n"); - while (it.next()) |lib_arg| { - if (mem.startsWith(u8, lib_arg, "-l")) { - try result.system_libs.append(lib_arg[2..]); - } else { - if (fs.path.isAbsolute(lib_arg)) { - try result.libs.append(lib_arg); - } else { - var lib_arg_copy = lib_arg; - if (mem.endsWith(u8, lib_arg, ".lib")) { - lib_arg_copy = lib_arg[0 .. lib_arg.len - 4]; - } - try result.system_libs.append(lib_arg_copy); - } - } - } - } - { - var it = mem.tokenize(includes_output, " \r\n"); - while (it.next()) |include_arg| { - if (mem.startsWith(u8, include_arg, "-I")) { - try result.includes.append(include_arg[2..]); - } else { - try result.includes.append(include_arg); - } - } - } - { - var it = mem.tokenize(libdir_output, " \r\n"); - while (it.next()) |libdir| { - if (mem.startsWith(u8, libdir, "-L")) { - try result.libdirs.append(libdir[2..]); - } else { - try result.libdirs.append(libdir); - } - } - } - return result; -} - -fn configureStage2(b: *Builder, exe: anytype, ctx: Context, need_cpp_includes: bool) !void { - exe.addIncludeDir("src"); - exe.addIncludeDir(ctx.cmake_binary_dir); - addCppLib(b, exe, ctx.cmake_binary_dir, "zigcpp"); - assert(ctx.lld_include_dir.len != 0); - exe.addIncludeDir(ctx.lld_include_dir); - { - var it = mem.tokenize(ctx.lld_libraries, ";"); - while (it.next()) |lib| { - exe.addObjectFile(lib); - } - } - { - var it = mem.tokenize(ctx.clang_libraries, ";"); - while (it.next()) |lib| { - exe.addObjectFile(lib); - } - } - dependOnLib(b, exe, ctx.llvm); - - // Boy, it sure would be nice to simply linkSystemLibrary("c++") and rely on zig's - // ability to provide libc++ right? Well thanks to C++ not having a stable ABI this - // will cause linker errors. It would work in the situation when `zig cc` is used to - // build LLVM, Clang, and LLD, however when depending on them as system libraries, system - // libc++ must be used. - const cross_compile = false; // TODO - if (cross_compile) { - // In this case we assume that zig cc was used to build the LLVM, Clang, LLD dependencies. - exe.linkSystemLibrary("c++"); - } else { - if (exe.target.getOsTag() == .linux) { - // First we try to static link against gcc libstdc++. If that doesn't work, - // we fall back to -lc++ and cross our fingers. - addCxxKnownPath(b, ctx, exe, "libstdc++.a", "", need_cpp_includes) catch |err| switch (err) { - error.RequiredLibraryNotFound => { - exe.linkSystemLibrary("c++"); - }, - else => |e| return e, - }; - - exe.linkSystemLibrary("pthread"); - } else if (exe.target.isFreeBSD()) { - try addCxxKnownPath(b, ctx, exe, "libc++.a", null, need_cpp_includes); - exe.linkSystemLibrary("pthread"); - } else if (exe.target.isDarwin()) { - if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "", need_cpp_includes)) { - // Compiler is GCC. - try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null, need_cpp_includes); - exe.linkSystemLibrary("pthread"); - // TODO LLD cannot perform this link. - // Set ZIG_SYSTEM_LINKER_HACK env var to use system linker ld instead. - // See https://github.com/ziglang/zig/issues/1535 - } else |err| switch (err) { - error.RequiredLibraryNotFound => { - // System compiler, not gcc. - exe.linkSystemLibrary("c++"); - }, - else => |e| return e, - } - } - - if (ctx.dia_guids_lib.len != 0) { - exe.addObjectFile(ctx.dia_guids_lib); - } - } -} - -fn addCxxKnownPath( - b: *Builder, - ctx: Context, - exe: anytype, - objname: []const u8, - errtxt: ?[]const u8, - need_cpp_includes: bool, -) !void { - const path_padded = try b.exec(&[_][]const u8{ - ctx.cxx_compiler, - b.fmt("-print-file-name={}", .{objname}), - }); - const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?; - if (mem.eql(u8, path_unpadded, objname)) { - if (errtxt) |msg| { - warn("{}", .{msg}); - } else { - warn("Unable to determine path to {}\n", .{objname}); - } - return error.RequiredLibraryNotFound; - } - exe.addObjectFile(path_unpadded); - - // TODO a way to integrate with system c++ include files here - // cc -E -Wp,-v -xc++ /dev/null - if (need_cpp_includes) { - // I used these temporarily for testing something but we obviously need a - // more general purpose solution here. - //exe.addIncludeDir("/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/lib/gcc/x86_64-unknown-linux-gnu/9.2.0/../../../../include/c++/9.2.0"); - //exe.addIncludeDir("/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/lib/gcc/x86_64-unknown-linux-gnu/9.2.0/../../../../include/c++/9.2.0/x86_64-unknown-linux-gnu"); - //exe.addIncludeDir("/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/lib/gcc/x86_64-unknown-linux-gnu/9.2.0/../../../../include/c++/9.2.0/backward"); - } -} - -const Context = struct { - cmake_binary_dir: []const u8, - cxx_compiler: []const u8, - llvm_config_exe: []const u8, - lld_include_dir: []const u8, - lld_libraries: []const u8, - clang_libraries: []const u8, - dia_guids_lib: []const u8, - llvm: LibraryDep, +const stage1_sources = [_][]const u8{ + "src/stage1/analyze.cpp", + "src/stage1/ast_render.cpp", + "src/stage1/bigfloat.cpp", + "src/stage1/bigint.cpp", + "src/stage1/buffer.cpp", + "src/stage1/codegen.cpp", + "src/stage1/dump_analysis.cpp", + "src/stage1/errmsg.cpp", + "src/stage1/error.cpp", + "src/stage1/heap.cpp", + "src/stage1/ir.cpp", + "src/stage1/ir_print.cpp", + "src/stage1/mem.cpp", + "src/stage1/os.cpp", + "src/stage1/parser.cpp", + "src/stage1/range_set.cpp", + "src/stage1/stage1.cpp", + "src/stage1/target.cpp", + "src/stage1/tokenizer.cpp", + "src/stage1/util.cpp", + "src/stage1/softfloat_ext.cpp", +}; +const optimized_c_sources = [_][]const u8{ + "src/stage1/parse_f128.c", +}; +const zig_cpp_sources = [_][]const u8{ + // These are planned to stay even when we are self-hosted. + "src/zig_llvm.cpp", + "src/zig_clang.cpp", + "src/zig_clang_driver.cpp", + "src/zig_clang_cc1_main.cpp", + "src/zig_clang_cc1as_main.cpp", + // https://github.com/ziglang/zig/issues/6363 + "src/windows_sdk.cpp", }; -const max_config_h_bytes = 1 * 1024 * 1024; - -fn findAndReadConfigH(b: *Builder) ![]const u8 { - var check_dir = fs.path.dirname(b.zig_exe).?; - while (true) { - var dir = try fs.cwd().openDir(check_dir, .{}); - defer dir.close(); - - const config_h_text = dir.readFileAlloc(b.allocator, "config.h", max_config_h_bytes) catch |err| switch (err) { - error.FileNotFound => { - const new_check_dir = fs.path.dirname(check_dir); - if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) { - std.debug.warn("Unable to find config.h file relative to Zig executable.\n", .{}); - std.debug.warn("`zig build` must be run using a Zig executable within the source tree.\n", .{}); - std.process.exit(1); - } - check_dir = new_check_dir.?; - continue; - }, - else => |e| return e, - }; - return config_h_text; - } else unreachable; // TODO should not need `else unreachable`. -} - -fn parseConfigH(b: *Builder, config_h_text: []const u8) Context { - var ctx: Context = .{ - .cmake_binary_dir = undefined, - .cxx_compiler = undefined, - .llvm_config_exe = undefined, - .lld_include_dir = undefined, - .lld_libraries = undefined, - .clang_libraries = undefined, - .dia_guids_lib = undefined, - .llvm = undefined, - }; - - const mappings = [_]struct { prefix: []const u8, field: []const u8 }{ - .{ - .prefix = "#define ZIG_CMAKE_BINARY_DIR ", - .field = "cmake_binary_dir", - }, - .{ - .prefix = "#define ZIG_CXX_COMPILER ", - .field = "cxx_compiler", - }, - .{ - .prefix = "#define ZIG_LLD_INCLUDE_PATH ", - .field = "lld_include_dir", - }, - .{ - .prefix = "#define ZIG_LLD_LIBRARIES ", - .field = "lld_libraries", - }, - .{ - .prefix = "#define ZIG_CLANG_LIBRARIES ", - .field = "clang_libraries", - }, - .{ - .prefix = "#define ZIG_LLVM_CONFIG_EXE ", - .field = "llvm_config_exe", - }, - .{ - .prefix = "#define ZIG_DIA_GUIDS_LIB ", - .field = "dia_guids_lib", - }, - }; - - var lines_it = mem.tokenize(config_h_text, "\r\n"); - while (lines_it.next()) |line| { - inline for (mappings) |mapping| { - if (mem.startsWith(u8, line, mapping.prefix)) { - var it = mem.split(line, "\""); - _ = it.next().?; // skip the stuff before the quote - const quoted = it.next().?; // the stuff inside the quote - @field(ctx, mapping.field) = toNativePathSep(b, quoted); - } - } - } - return ctx; -} - -fn toNativePathSep(b: *Builder, s: []const u8) []u8 { - const duplicated = mem.dupe(b.allocator, u8, s) catch unreachable; - for (duplicated) |*byte| switch (byte.*) { - '/' => byte.* = fs.path.sep, - else => {}, - }; - return duplicated; -} +const clang_libs = [_][]const u8{ + "clangFrontendTool", + "clangCodeGen", + "clangFrontend", + "clangDriver", + "clangSerialization", + "clangSema", + "clangStaticAnalyzerFrontend", + "clangStaticAnalyzerCheckers", + "clangStaticAnalyzerCore", + "clangAnalysis", + "clangASTMatchers", + "clangAST", + "clangParse", + "clangSema", + "clangBasic", + "clangEdit", + "clangLex", + "clangARCMigrate", + "clangRewriteFrontend", + "clangRewrite", + "clangCrossTU", + "clangIndex", + "clangToolingCore", +}; +const lld_libs = [_][]const u8{ + "lldDriver", + "lldMinGW", + "lldELF", + "lldCOFF", + "lldMachO", + "lldWasm", + "lldReaderWriter", + "lldCore", + "lldYAML", + "lldCommon", +}; +// This list can be re-generated with `llvm-config --libfiles` and then +// reformatting using your favorite text editor. Note we do not execute +// `llvm-config` here because we are cross compiling. +const llvm_libs = [_][]const u8{ + "LLVMXRay", + "LLVMWindowsManifest", + "LLVMSymbolize", + "LLVMDebugInfoPDB", + "LLVMOrcJIT", + "LLVMOrcError", + "LLVMJITLink", + "LLVMObjectYAML", + "LLVMMCA", + "LLVMLTO", + "LLVMPasses", + "LLVMCoroutines", + "LLVMObjCARCOpts", + "LLVMExtensions", + "LLVMLineEditor", + "LLVMLibDriver", + "LLVMInterpreter", + "LLVMFuzzMutate", + "LLVMMCJIT", + "LLVMExecutionEngine", + "LLVMRuntimeDyld", + "LLVMDWARFLinker", + "LLVMDlltoolDriver", + "LLVMOption", + "LLVMDebugInfoGSYM", + "LLVMCoverage", + "LLVMXCoreDisassembler", + "LLVMXCoreCodeGen", + "LLVMXCoreDesc", + "LLVMXCoreInfo", + "LLVMX86Disassembler", + "LLVMX86CodeGen", + "LLVMX86AsmParser", + "LLVMX86Desc", + "LLVMX86Info", + "LLVMWebAssemblyDisassembler", + "LLVMWebAssemblyCodeGen", + "LLVMWebAssemblyDesc", + "LLVMWebAssemblyAsmParser", + "LLVMWebAssemblyInfo", + "LLVMSystemZDisassembler", + "LLVMSystemZCodeGen", + "LLVMSystemZAsmParser", + "LLVMSystemZDesc", + "LLVMSystemZInfo", + "LLVMSparcDisassembler", + "LLVMSparcCodeGen", + "LLVMSparcAsmParser", + "LLVMSparcDesc", + "LLVMSparcInfo", + "LLVMRISCVDisassembler", + "LLVMRISCVCodeGen", + "LLVMRISCVAsmParser", + "LLVMRISCVDesc", + "LLVMRISCVUtils", + "LLVMRISCVInfo", + "LLVMPowerPCDisassembler", + "LLVMPowerPCCodeGen", + "LLVMPowerPCAsmParser", + "LLVMPowerPCDesc", + "LLVMPowerPCInfo", + "LLVMNVPTXCodeGen", + "LLVMNVPTXDesc", + "LLVMNVPTXInfo", + "LLVMMSP430Disassembler", + "LLVMMSP430CodeGen", + "LLVMMSP430AsmParser", + "LLVMMSP430Desc", + "LLVMMSP430Info", + "LLVMMipsDisassembler", + "LLVMMipsCodeGen", + "LLVMMipsAsmParser", + "LLVMMipsDesc", + "LLVMMipsInfo", + "LLVMLanaiDisassembler", + "LLVMLanaiCodeGen", + "LLVMLanaiAsmParser", + "LLVMLanaiDesc", + "LLVMLanaiInfo", + "LLVMHexagonDisassembler", + "LLVMHexagonCodeGen", + "LLVMHexagonAsmParser", + "LLVMHexagonDesc", + "LLVMHexagonInfo", + "LLVMBPFDisassembler", + "LLVMBPFCodeGen", + "LLVMBPFAsmParser", + "LLVMBPFDesc", + "LLVMBPFInfo", + "LLVMAVRDisassembler", + "LLVMAVRCodeGen", + "LLVMAVRAsmParser", + "LLVMAVRDesc", + "LLVMAVRInfo", + "LLVMARMDisassembler", + "LLVMARMCodeGen", + "LLVMARMAsmParser", + "LLVMARMDesc", + "LLVMARMUtils", + "LLVMARMInfo", + "LLVMAMDGPUDisassembler", + "LLVMAMDGPUCodeGen", + "LLVMMIRParser", + "LLVMipo", + "LLVMInstrumentation", + "LLVMVectorize", + "LLVMLinker", + "LLVMIRReader", + "LLVMAsmParser", + "LLVMFrontendOpenMP", + "LLVMAMDGPUAsmParser", + "LLVMAMDGPUDesc", + "LLVMAMDGPUUtils", + "LLVMAMDGPUInfo", + "LLVMAArch64Disassembler", + "LLVMMCDisassembler", + "LLVMAArch64CodeGen", + "LLVMCFGuard", + "LLVMGlobalISel", + "LLVMSelectionDAG", + "LLVMAsmPrinter", + "LLVMDebugInfoDWARF", + "LLVMCodeGen", + "LLVMTarget", + "LLVMScalarOpts", + "LLVMInstCombine", + "LLVMAggressiveInstCombine", + "LLVMTransformUtils", + "LLVMBitWriter", + "LLVMAnalysis", + "LLVMProfileData", + "LLVMObject", + "LLVMTextAPI", + "LLVMBitReader", + "LLVMCore", + "LLVMRemarks", + "LLVMBitstreamReader", + "LLVMAArch64AsmParser", + "LLVMMCParser", + "LLVMAArch64Desc", + "LLVMMC", + "LLVMDebugInfoCodeView", + "LLVMDebugInfoMSF", + "LLVMBinaryFormat", + "LLVMAArch64Utils", + "LLVMAArch64Info", + "LLVMSupport", + "LLVMDemangle", +}; diff --git a/lib/std/build.zig b/lib/std/build.zig index d820ec639bf8451ca19bd5765157695085712029..329c719573644d99cb7723b58da933bedadad934 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1150,6 +1150,11 @@ const CSourceFile = struct { args: []const []const u8, }; +const CSourceFiles = struct { + files: []const []const u8, + flags: []const []const u8, +}; + fn isLibCLibrary(name: []const u8) bool { const libc_libraries = [_][]const u8{ "c", "m", "dl", "rt", "pthread" }; for (libc_libraries) |libc_lib_name| { @@ -1297,6 +1302,7 @@ pub const LibExeObjStep = struct { SystemLib: []const u8, AssemblyFile: FileSource, CSourceFile: *CSourceFile, + CSourceFiles: *CSourceFiles, }; const IncludeDir = union(enum) { @@ -1670,9 +1676,25 @@ pub const LibExeObjStep = struct { self.filter = text; } - pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void { + /// Handy when you have many C/C++ source files and want them all to have the same flags. + pub fn addCSourceFiles(self: *LibExeObjStep, files: []const []const u8, flags: []const []const u8) void { + const c_source_files = self.builder.allocator.create(CSourceFiles) catch unreachable; + + const flags_copy = self.builder.allocator.alloc([]u8, flags.len) catch unreachable; + for (flags) |flag, i| { + flags_copy[i] = self.builder.dupe(flag); + } + + c_source_files.* = .{ + .files = files, + .flags = flags_copy, + }; + self.link_objects.append(LinkObject{ .CSourceFiles = c_source_files }) catch unreachable; + } + + pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, flags: []const []const u8) void { self.addCSourceFileSource(.{ - .args = args, + .args = flags, .source = .{ .path = file }, }); } @@ -1795,6 +1817,10 @@ pub const LibExeObjStep = struct { out.writeAll("};\n") catch unreachable; return; }, + [:0]const u8 => { + out.print("pub const {z}: [:0]const u8 = \"{Z}\";\n", .{ name, value }) catch unreachable; + return; + }, []const u8 => { out.print("pub const {z}: []const u8 = \"{Z}\";\n", .{ name, value }) catch unreachable; return; @@ -1808,6 +1834,22 @@ pub const LibExeObjStep = struct { } return; }, + std.builtin.Version => { + out.print( + \\pub const {z}: @import("builtin").Version = .{{ + \\ .major = {d}, + \\ .minor = {d}, + \\ .patch = {d}, + \\}}; + \\ + , .{ + name, + + value.major, + value.minor, + value.patch, + }) catch unreachable; + }, std.SemanticVersion => { out.print( \\pub const {z}: @import("std").SemanticVersion = .{{ @@ -2015,8 +2057,7 @@ pub const LibExeObjStep = struct { }, }, .SystemLib => |name| { - try zig_args.append("--library"); - try zig_args.append(name); + try zig_args.append(builder.fmt("-l{s}", .{name})); }, .AssemblyFile => |asm_file| { if (prev_has_extra_flags) { @@ -2026,6 +2067,7 @@ pub const LibExeObjStep = struct { } try zig_args.append(asm_file.getPath(builder)); }, + .CSourceFile => |c_source_file| { if (c_source_file.args.len == 0) { if (prev_has_extra_flags) { @@ -2042,6 +2084,25 @@ pub const LibExeObjStep = struct { } try zig_args.append(c_source_file.source.getPath(builder)); }, + + .CSourceFiles => |c_source_files| { + if (c_source_files.flags.len == 0) { + if (prev_has_extra_flags) { + try zig_args.append("-cflags"); + try zig_args.append("--"); + prev_has_extra_flags = false; + } + } else { + try zig_args.append("-cflags"); + for (c_source_files.flags) |flag| { + try zig_args.append(flag); + } + try zig_args.append("--"); + } + for (c_source_files.files) |file| { + try zig_args.append(builder.pathFromRoot(file)); + } + }, } } @@ -2304,6 +2365,17 @@ pub const LibExeObjStep = struct { } } + for (builder.search_prefixes.items) |search_prefix| { + try zig_args.append("-L"); + try zig_args.append(try fs.path.join(builder.allocator, &[_][]const u8{ + search_prefix, "lib", + })); + try zig_args.append("-isystem"); + try zig_args.append(try fs.path.join(builder.allocator, &[_][]const u8{ + search_prefix, "include", + })); + } + if (self.valgrind_support) |valgrind_support| { if (valgrind_support) { try zig_args.append("-fvalgrind"); diff --git a/src/stage1.zig b/src/stage1.zig index 504b35df9469ef6f0c7d7e451c1b004a339e2845..8576459aa85ba0f3b2e305e4780a4fec7ff488da 100644 --- a/src/stage1.zig +++ b/src/stage1.zig @@ -251,6 +251,20 @@ const Error = extern enum { Locked, }; +// ABI warning +export fn stage2_version_string() [*:0]const u8 { + return build_options.version; +} + +// ABI warning +export fn stage2_version() Stage2SemVer { + return .{ + .major = build_options.semver.major, + .minor = build_options.semver.minor, + .patch = build_options.semver.patch, + }; +} + // ABI warning export fn stage2_attach_segfault_handler() void { if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) { diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index e8958052bcce549c747d601098929a5b0284847e..4bbdd388695c88d34f28dd2df745aa0bf5886be8 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -8,7 +8,6 @@ #include "analyze.hpp" #include "ast_render.hpp" #include "codegen.hpp" -#include "config.h" #include "error.hpp" #include "ir.hpp" #include "ir_print.hpp" diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index eb0495c07dbdc574931f8bd9b3381b70a0df8665..c57325f9545b16a0f97cb096858eee2475a2e0f2 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -8,7 +8,6 @@ #include "analyze.hpp" #include "ast_render.hpp" #include "codegen.hpp" -#include "config.h" #include "errmsg.hpp" #include "error.hpp" #include "hash_map.hpp" @@ -9051,7 +9050,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n"); buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n"); buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n"); - buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", ZIG_LINK_MODE); + buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", ZIG_QUOTE(ZIG_LINK_MODE)); buf_appendf(contents, "pub const is_test = false;\n"); buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); @@ -9251,9 +9250,9 @@ static void init(CodeGen *g) { g->builder = LLVMCreateBuilder(); g->dbuilder = ZigLLVMCreateDIBuilder(g->module, true); - // Don't use ZIG_VERSION_STRING here, llvm misparses it when it includes - // the git revision. - Buf *producer = buf_sprintf("zig %d.%d.%d", ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH); + // Don't use the version string here, llvm misparses it when it includes the git revision. + Stage2SemVer semver = stage2_version(); + Buf *producer = buf_sprintf("zig %d.%d.%d", semver.major, semver.minor, semver.patch); const char *flags = ""; unsigned runtime_version = 0; @@ -9551,9 +9550,9 @@ void codegen_build_object(CodeGen *g) { } do_code_gen(g); - codegen_add_time_event(g, "LLVM Emit Output"); + codegen_add_time_event(g, "LLVM Emit Object"); { - const char *progress_name = "LLVM Emit Output"; + const char *progress_name = "LLVM Emit Object"; codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, progress_name, strlen(progress_name), 0)); } diff --git a/src/stage1/config.h.in b/src/stage1/config.h.in deleted file mode 100644 index e95e9e8ce7f558252b816cfe03510016287758e9..0000000000000000000000000000000000000000 --- a/src/stage1/config.h.in +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2016 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_CONFIG_H -#define ZIG_CONFIG_H - -#define ZIG_VERSION_MAJOR @ZIG_VERSION_MAJOR@ -#define ZIG_VERSION_MINOR @ZIG_VERSION_MINOR@ -#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@ -#define ZIG_VERSION_STRING "@ZIG_VERSION@" - -// Used for communicating build information to self hosted build. -#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@" -#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@" -#define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@" -#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@" -#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@" -#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@" -#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@" -#define ZIG_LINK_MODE "@ZIG_LINK_MODE@" - -#endif diff --git a/src/stage1/dump_analysis.cpp b/src/stage1/dump_analysis.cpp index 06ae5eb97a3899d6c5b5384da84e8f7a47b6dc7d..69a797bdaf0819127cfad22cd64a5767903c6c9f 100644 --- a/src/stage1/dump_analysis.cpp +++ b/src/stage1/dump_analysis.cpp @@ -7,7 +7,6 @@ #include "dump_analysis.hpp" #include "analyze.hpp" -#include "config.h" #include "ir.hpp" #include "codegen.hpp" #include "os.hpp" @@ -1237,7 +1236,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const jw_begin_object(jw); { jw_object_field(jw, "zigVersion"); - jw_string(jw, ZIG_VERSION_STRING); + jw_string(jw, stage2_version_string()); jw_object_field(jw, "builds"); jw_begin_array(jw); diff --git a/src/stage1/heap.cpp b/src/stage1/heap.cpp index 7e7a171bde25f95224d0479064d1f632a29b5bf9..caf15cde365e1dc6c906feba4e37b1d345d4c100 100644 --- a/src/stage1/heap.cpp +++ b/src/stage1/heap.cpp @@ -8,7 +8,6 @@ #include #include -#include "config.h" #include "heap.hpp" namespace heap { diff --git a/src/stage1/heap.hpp b/src/stage1/heap.hpp index ec5c81026d167d31e71bbb3750f8b90bb1438a42..a9467bc8318d887e7520db32801e209ba94c6abb 100644 --- a/src/stage1/heap.hpp +++ b/src/stage1/heap.hpp @@ -8,7 +8,6 @@ #ifndef ZIG_HEAP_HPP #define ZIG_HEAP_HPP -#include "config.h" #include "util_base.hpp" #include "mem.hpp" diff --git a/src/stage1/mem.cpp b/src/stage1/mem.cpp index 48dbd791dea783fa891b05f1292490d3d15ce68e..5931c38e6e527c922ff9a3e7d85ea80fd2d878d3 100644 --- a/src/stage1/mem.cpp +++ b/src/stage1/mem.cpp @@ -5,7 +5,6 @@ * See http://opensource.org/licenses/MIT */ -#include "config.h" #include "mem.hpp" #include "heap.hpp" diff --git a/src/stage1/mem.hpp b/src/stage1/mem.hpp index 3008febbde615bc91cab25296b4432f4f8914ae9..bf732412e4be2d5ca5c28ffdc70f0ca072e99236 100644 --- a/src/stage1/mem.hpp +++ b/src/stage1/mem.hpp @@ -12,7 +12,6 @@ #include #include -#include "config.h" #include "util_base.hpp" #include "mem_type_info.hpp" diff --git a/src/stage1/mem_type_info.hpp b/src/stage1/mem_type_info.hpp index d8a793326885ac63df6ae8ac7e37cf9de4532431..ae4b3414ae8199147afce9b88b46a3f36fd27d75 100644 --- a/src/stage1/mem_type_info.hpp +++ b/src/stage1/mem_type_info.hpp @@ -8,8 +8,6 @@ #ifndef ZIG_MEM_TYPE_INFO_HPP #define ZIG_MEM_TYPE_INFO_HPP -#include "config.h" - namespace mem { struct TypeInfo { diff --git a/src/stage1/stage2.h b/src/stage1/stage2.h index 886a4c26603779a3e954679b1b7e751d712a58b6..1eb494f36258afec1e76ae9bc0f0872c5049ebba 100644 --- a/src/stage1/stage2.h +++ b/src/stage1/stage2.h @@ -156,6 +156,12 @@ struct Stage2SemVer { uint32_t patch; }; +// ABI warning +ZIG_EXTERN_C const char *stage2_version_string(void); + +// ABI warning +ZIG_EXTERN_C Stage2SemVer stage2_version(void); + // ABI warning ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu, const char *dynamic_linker); diff --git a/src/stage1/util.hpp b/src/stage1/util.hpp index 66efe6dfd1736cfdb7d22023ed14b8d7b3a97c00..088249ae7a1d593d64f5dbc9193f092de55c4597 100644 --- a/src/stage1/util.hpp +++ b/src/stage1/util.hpp @@ -17,7 +17,9 @@ #include #endif -#include "config.h" +#define ZIG_Q(x) #x +#define ZIG_QUOTE(x) ZIG_Q(x) + #include "util_base.hpp" #include "heap.hpp" #include "mem.hpp" diff --git a/src/stage1/zig0.cpp b/src/stage1/zig0.cpp index 6b55d97fac09627ad90595dd9e60c4a898c00dff..ffe5ebe244351dd3ffd68c68ed0b30ebcb010da4 100644 --- a/src/stage1/zig0.cpp +++ b/src/stage1/zig0.cpp @@ -537,3 +537,11 @@ const char *stage2_add_link_lib(struct ZigStage1 *stage1, { return nullptr; } + +const char *stage2_version_string(void) { + return "0.0.0+zig0"; +} + +struct Stage2SemVer stage2_version(void) { + return {0, 0, 0}; +} diff --git a/src/config.zig.in b/src/stage1_config.zig similarity index 58% rename from src/config.zig.in rename to src/stage1_config.zig index b6d941588ec47101cf74a537cfc59b95645560a2..3410540d5b11e7b4129e0c849c0938bbc96b2245 100644 --- a/src/config.zig.in +++ b/src/stage1_config.zig @@ -1,5 +1,11 @@ pub const have_llvm = true; -pub const version: []const u8 = "@ZIG_VERSION@"; +pub const version: [:0]const u8 = "0.0.0+zig0"; +pub const semver: @import("std").SemanticVersion = .{ + .major = 0, + .minor = 0, + .patch = 0, + .build = "zig0", +}; pub const log_scopes: []const []const u8 = &[_][]const u8{}; pub const zir_dumps: []const []const u8 = &[_][]const u8{}; pub const enable_tracy = false; diff --git a/src/zig_clang.h b/src/zig_clang.h index d128c74c7ffb7b7a2e92a06b4ffa895d8719f987..32879062aee8196c66275115a9610c4774d17860 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -8,7 +8,7 @@ #ifndef ZIG_ZIG_CLANG_H #define ZIG_ZIG_CLANG_H -#include "stage2.h" +#include "stage1/stage2.h" #include #include -- 2.54.0 From 76e306ad0fa18a205c6c74032b36b33e17a9e454 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 4 Dec 2020 22:24:04 -0700 Subject: [PATCH 2/5] fix wrong entrypoint, undefined package, and wrong build option --- build.zig | 10 +++++++--- src/empty.zig | 0 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 src/empty.zig diff --git a/build.zig b/build.zig index cd8087d3ee2f3acc9be009b1b9acaa6da438bfb4..66f383bd6e41308e5eb6af380449a8515c73c6cb 100644 --- a/build.zig +++ b/build.zig @@ -79,7 +79,7 @@ pub fn build(b: *Builder) !void { const main_file = if (is_stage1) "src/stage1.zig" else "src/main.zig"; - var exe = b.addExecutable("zig", "src/main.zig"); + var exe = b.addExecutable("zig", main_file); exe.install(); exe.setBuildMode(mode); exe.setTarget(target); @@ -92,6 +92,10 @@ pub fn build(b: *Builder) !void { if (is_stage1) { exe.addIncludeDir("src"); exe.addIncludeDir("deps/SoftFloat-3e/source/include"); + // This is intentionally a dummy path. stage1.zig tries to @import("compiler_rt") in case + // of being built by cmake. But when built by zig it's gonna get a compiler_rt so that + // is pointless. + exe.addPackagePath("compiler_rt", "src/empty.zig"); const softfloat = b.addStaticLibrary("softfloat", null); softfloat.setBuildMode(.ReleaseFast); @@ -188,7 +192,7 @@ pub fn build(b: *Builder) !void { exe.addBuildOption([]const []const u8, "log_scopes", log_scopes); exe.addBuildOption([]const []const u8, "zir_dumps", zir_dumps); exe.addBuildOption(bool, "enable_tracy", tracy != null); - exe.addBuildOption(bool, "is_stage1", false); + exe.addBuildOption(bool, "is_stage1", is_stage1); if (tracy) |tracy_path| { const client_cpp = fs.path.join( b.allocator, @@ -210,7 +214,7 @@ pub fn build(b: *Builder) !void { const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc"); test_stage2.addBuildOption(bool, "skip_non_native", skip_non_native); - test_stage2.addBuildOption(bool, "is_stage1", false); + test_stage2.addBuildOption(bool, "is_stage1", is_stage1); test_stage2.addBuildOption(bool, "have_llvm", enable_llvm); test_stage2.addBuildOption(bool, "enable_qemu", is_qemu_enabled); test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled); diff --git a/src/empty.zig b/src/empty.zig new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -- 2.54.0 From 211ac00f8380629653ae475d7c347b0a67b480af Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 4 Dec 2020 22:55:50 -0700 Subject: [PATCH 3/5] build: -lversion -luuid on windows and -DNDEBUG=1 for clang sources --- build.zig | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/build.zig b/build.zig index 66f383bd6e41308e5eb6af380449a8515c73c6cb..37ee924e1cc75a704e649d6110e2d48ec210f3fc 100644 --- a/build.zig +++ b/build.zig @@ -106,7 +106,7 @@ pub fn build(b: *Builder) !void { softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" }); exe.linkLibrary(softfloat); - const exe_cflags = &[_][]const u8{ + const exe_cflags = [_][]const u8{ "-std=c++14", "-D__STDC_CONSTANT_MACROS", "-D__STDC_FORMAT_MACROS", @@ -119,9 +119,13 @@ pub fn build(b: *Builder) !void { "-Wno-missing-braces", "-Wno-comment", }; - exe.addCSourceFiles(&stage1_sources, exe_cflags); + exe.addCSourceFiles(&stage1_sources, &exe_cflags); exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); - exe.addCSourceFiles(&zig_cpp_sources, exe_cflags); + // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling + // in a dependency on llvm::cfg::Update::dump() which is + // unavailable when LLVM is compiled in Release mode. + const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; + exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags); } for (clang_libs) |lib_name| { @@ -138,6 +142,11 @@ pub fn build(b: *Builder) !void { // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. exe.linkSystemLibrary("c++"); + + if (target.getOs().tag == .windows) { + exe.linkSystemLibrary("version"); + exe.linkSystemLibrary("uuid"); + } } if (link_libc) { exe.linkLibC(); -- 2.54.0 From 88dc688bbf10fb95c51783eca0526054d33ef5a1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 7 Dec 2020 17:23:17 -0700 Subject: [PATCH 4/5] restore the option to build with cmake restore cmake to be capable of figuring out the zig version restore config.h and config.zig. config.h is used to detect whether we should propagate cmake configuration information to build.zig; however it can be overridden with -Dstatic-llvm. fix not passing -DZIG_LINK_MODE with zig build. when using the cmake build path, build.zig no longer tries to call llvm-config. Instead it relies 100% on the LLVM_LIBRARIES cmake variable. build.zig logic reworked and simplified. --- CMakeLists.txt | 44 +++- build.zig | 255 +++++++++++++++++++++-- src/{stage1_config.zig => config.zig.in} | 10 +- src/stage1/config.h.in | 27 +++ src/stage1/zig0.cpp | 9 +- 5 files changed, 316 insertions(+), 29 deletions(-) rename src/{stage1_config.zig => config.zig.in} (62%) create mode 100644 src/stage1/config.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index b9a81575be5502ae7dc2643698d03ef188a27128..72035496fd8c56cb60515c38a58e49d570ca99e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,34 @@ set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX project(zig C CXX) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) +set(ZIG_VERSION_MAJOR 0) +set(ZIG_VERSION_MINOR 7) +set(ZIG_VERSION_PATCH 0) +set(ZIG_VERSION "" CACHE STRING "Override Zig version string. Default is to find out with git.") + +if("${ZIG_VERSION}" STREQUAL "") + set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}") + find_program(GIT_EXE NAMES git) + if(GIT_EXE) + execute_process( + COMMAND ${GIT_EXE} -C ${CMAKE_SOURCE_DIR} name-rev HEAD --tags --name-only --no-undefined --always + RESULT_VARIABLE EXIT_STATUS + OUTPUT_VARIABLE ZIG_GIT_REV + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + if(EXIT_STATUS EQUAL "0") + if(ZIG_GIT_REV MATCHES "\\^0$") + if(NOT("${ZIG_GIT_REV}" STREQUAL "${ZIG_VERSION}^0")) + message("WARNING: Tag does not match configured Zig version") + endif() + else() + set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}") + endif() + endif() + endif() +endif() +message("Configuring zig version ${ZIG_VERSION}") + set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)") set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries") set(ZIG_PREFER_CLANG_CPP_DYLIB off CACHE BOOL "Try to link against -lclang-cpp") @@ -233,6 +261,8 @@ set(LIBC_FILES_DEST "${ZIG_LIB_DIR}/libc") set(LIBUNWIND_FILES_DEST "${ZIG_LIB_DIR}/libunwind") set(LIBCXX_FILES_DEST "${ZIG_LIB_DIR}/libcxx") set(ZIG_STD_DEST "${ZIG_LIB_DIR}/std") +set(ZIG_CONFIG_H_OUT "${CMAKE_BINARY_DIR}/config.h") +set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig") # This is our shim which will be replaced by stage1.zig. set(ZIG0_SOURCES @@ -280,6 +310,7 @@ set(ZIG_CPP_SOURCES # then manually running the build-obj command (see BUILD_ZIG1_ARGS), and then looking # in the zig-cache directory for the compiler-generated list of zig file dependencies. set(ZIG_STAGE2_SOURCES + "${ZIG_CONFIG_ZIG_OUT}" "${CMAKE_SOURCE_DIR}/lib/std/array_hash_map.zig" "${CMAKE_SOURCE_DIR}/lib/std/array_list.zig" "${CMAKE_SOURCE_DIR}/lib/std/ascii.zig" @@ -519,7 +550,6 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/src/print_env.zig" "${CMAKE_SOURCE_DIR}/src/print_targets.zig" "${CMAKE_SOURCE_DIR}/src/stage1.zig" - "${CMAKE_SOURCE_DIR}/src/stage1_config.zig" "${CMAKE_SOURCE_DIR}/src/target.zig" "${CMAKE_SOURCE_DIR}/src/tracy.zig" "${CMAKE_SOURCE_DIR}/src/translate_c.zig" @@ -538,6 +568,15 @@ if(MSVC) endif() endif() +configure_file ( + "${CMAKE_SOURCE_DIR}/src/stage1/config.h.in" + "${ZIG_CONFIG_H_OUT}" +) +configure_file ( + "${CMAKE_SOURCE_DIR}/src/config.zig.in" + "${ZIG_CONFIG_ZIG_OUT}" +) + include_directories( ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} @@ -684,7 +723,7 @@ set(BUILD_ZIG1_ARGS "-femit-bin=${ZIG1_OBJECT}" "${ZIG1_RELEASE_ARG}" -lc - --pkg-begin build_options "${CMAKE_SOURCE_DIR}/src/stage1_config.zig" + --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}" --pkg-end --pkg-begin compiler_rt "${CMAKE_SOURCE_DIR}/lib/std/special/compiler_rt.zig" --pkg-end @@ -733,6 +772,7 @@ set(ZIG_INSTALL_ARGS "build" --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" "-Dlib-files-only" --prefix "${CMAKE_INSTALL_PREFIX}" + "-Dconfig_h=${ZIG_CONFIG_H_OUT}" install ) diff --git a/build.zig b/build.zig index 37ee924e1cc75a704e649d6110e2d48ec210f3fc..abf59fa007a0c34da196966e8713d709ae7a2e14 100644 --- a/build.zig +++ b/build.zig @@ -54,7 +54,8 @@ pub fn build(b: *Builder) !void { const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false; - const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse is_stage1; + const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false; + const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm); const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h"); b.installDirectory(InstallDirectoryOptions{ @@ -89,6 +90,7 @@ pub fn build(b: *Builder) !void { exe.addBuildOption(bool, "skip_non_native", skip_non_native); exe.addBuildOption(bool, "have_llvm", enable_llvm); if (enable_llvm) { + const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option); if (is_stage1) { exe.addIncludeDir("src"); exe.addIncludeDir("deps/SoftFloat-3e/source/include"); @@ -96,6 +98,7 @@ pub fn build(b: *Builder) !void { // of being built by cmake. But when built by zig it's gonna get a compiler_rt so that // is pointless. exe.addPackagePath("compiler_rt", "src/empty.zig"); + exe.defineCMacro("ZIG_LINK_MODE=Static"); const softfloat = b.addStaticLibrary("softfloat", null); softfloat.setBuildMode(.ReleaseFast); @@ -121,31 +124,91 @@ pub fn build(b: *Builder) !void { }; exe.addCSourceFiles(&stage1_sources, &exe_cflags); exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); - // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling - // in a dependency on llvm::cfg::Update::dump() which is - // unavailable when LLVM is compiled in Release mode. - const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; - exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags); + if (cmake_cfg == null) { + // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling + // in a dependency on llvm::cfg::Update::dump() which is + // unavailable when LLVM is compiled in Release mode. + const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; + exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags); + } } + if (cmake_cfg) |cfg| { + // Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD. + // That means we also have to rely on stage1 compiled c++ files. We parse config.h to find + // the information passed on to us from cmake. + if (cfg.cmake_prefix_path.len > 0) { + b.addSearchPrefix(cfg.cmake_prefix_path); + } + exe.addObjectFile(fs.path.join(b.allocator, &[_][]const u8{ + cfg.cmake_binary_dir, + "zigcpp", + b.fmt("{s}{s}{s}", .{ exe.target.libPrefix(), "zigcpp", exe.target.staticLibSuffix() }), + }) catch unreachable); + assert(cfg.lld_include_dir.len != 0); + exe.addIncludeDir(cfg.lld_include_dir); + addCMakeLibraryList(exe, cfg.clang_libraries); + addCMakeLibraryList(exe, cfg.lld_libraries); + addCMakeLibraryList(exe, cfg.llvm_libraries); - for (clang_libs) |lib_name| { - exe.linkSystemLibrary(lib_name); - } + const need_cpp_includes = tracy != null; - for (lld_libs) |lib_name| { - exe.linkSystemLibrary(lib_name); - } + // System -lc++ must be used because in this code path we are attempting to link + // against system-provided LLVM, Clang, LLD. + if (exe.target.getOsTag() == .linux) { + // First we try to static link against gcc libstdc++. If that doesn't work, + // we fall back to -lc++ and cross our fingers. + addCxxKnownPath(b, cfg, exe, "libstdc++.a", "", need_cpp_includes) catch |err| switch (err) { + error.RequiredLibraryNotFound => { + exe.linkSystemLibrary("c++"); + }, + else => |e| return e, + }; - for (llvm_libs) |lib_name| { - exe.linkSystemLibrary(lib_name); - } + exe.linkSystemLibrary("pthread"); + } else if (exe.target.isFreeBSD()) { + try addCxxKnownPath(b, cfg, exe, "libc++.a", null, need_cpp_includes); + exe.linkSystemLibrary("pthread"); + } else if (exe.target.isDarwin()) { + if (addCxxKnownPath(b, cfg, exe, "libgcc_eh.a", "", need_cpp_includes)) { + // Compiler is GCC. + try addCxxKnownPath(b, cfg, exe, "libstdc++.a", null, need_cpp_includes); + exe.linkSystemLibrary("pthread"); + // TODO LLD cannot perform this link. + // Set ZIG_SYSTEM_LINKER_HACK env var to use system linker ld instead. + // See https://github.com/ziglang/zig/issues/1535 + } else |err| switch (err) { + error.RequiredLibraryNotFound => { + // System compiler, not gcc. + exe.linkSystemLibrary("c++"); + }, + else => |e| return e, + } + } + + if (cfg.dia_guids_lib.len != 0) { + exe.addObjectFile(cfg.dia_guids_lib); + } + } else { + // Here we are -Denable-llvm but no cmake integration. + for (clang_libs) |lib_name| { + exe.linkSystemLibrary(lib_name); + } + + for (lld_libs) |lib_name| { + exe.linkSystemLibrary(lib_name); + } + + for (llvm_libs) |lib_name| { + exe.linkSystemLibrary(lib_name); + } - // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. - exe.linkSystemLibrary("c++"); + // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. + exe.linkSystemLibrary("c++"); - if (target.getOs().tag == .windows) { - exe.linkSystemLibrary("version"); - exe.linkSystemLibrary("uuid"); + if (target.getOs().tag == .windows) { + exe.linkSystemLibrary("version"); + exe.linkSystemLibrary("uuid"); + } } } if (link_libc) { @@ -281,6 +344,158 @@ pub fn build(b: *Builder) !void { test_step.dependOn(docs_step); } +fn addCxxKnownPath( + b: *Builder, + ctx: CMakeConfig, + exe: *std.build.LibExeObjStep, + objname: []const u8, + errtxt: ?[]const u8, + need_cpp_includes: bool, +) !void { + const path_padded = try b.exec(&[_][]const u8{ + ctx.cxx_compiler, + b.fmt("-print-file-name={}", .{objname}), + }); + const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?; + if (mem.eql(u8, path_unpadded, objname)) { + if (errtxt) |msg| { + warn("{}", .{msg}); + } else { + warn("Unable to determine path to {}\n", .{objname}); + } + return error.RequiredLibraryNotFound; + } + exe.addObjectFile(path_unpadded); + + // TODO a way to integrate with system c++ include files here + // cc -E -Wp,-v -xc++ /dev/null + if (need_cpp_includes) { + // I used these temporarily for testing something but we obviously need a + // more general purpose solution here. + //exe.addIncludeDir("/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/lib/gcc/x86_64-unknown-linux-gnu/9.2.0/../../../../include/c++/9.2.0"); + //exe.addIncludeDir("/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/lib/gcc/x86_64-unknown-linux-gnu/9.2.0/../../../../include/c++/9.2.0/x86_64-unknown-linux-gnu"); + //exe.addIncludeDir("/nix/store/b3zsk4ihlpiimv3vff86bb5bxghgdzb9-gcc-9.2.0/lib/gcc/x86_64-unknown-linux-gnu/9.2.0/../../../../include/c++/9.2.0/backward"); + } +} + +fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void { + var it = mem.tokenize(list, ";"); + while (it.next()) |lib| { + if (mem.startsWith(u8, lib, "-l")) { + exe.linkSystemLibrary(lib["-l".len..]); + } else { + exe.addObjectFile(lib); + } + } +} + +const CMakeConfig = struct { + cmake_binary_dir: []const u8, + cmake_prefix_path: []const u8, + cxx_compiler: []const u8, + lld_include_dir: []const u8, + lld_libraries: []const u8, + clang_libraries: []const u8, + llvm_libraries: []const u8, + dia_guids_lib: []const u8, +}; + +const max_config_h_bytes = 1 * 1024 * 1024; + +fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeConfig { + const config_h_text: []const u8 = if (config_h_path_option) |config_h_path| blk: { + break :blk fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable; + } else blk: { + // TODO this should stop looking for config.h once it detects we hit the + // zig source root directory. + var check_dir = fs.path.dirname(b.zig_exe).?; + while (true) { + var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; + defer dir.close(); + + break :blk dir.readFileAlloc(b.allocator, "config.h", max_config_h_bytes) catch |err| switch (err) { + error.FileNotFound => { + const new_check_dir = fs.path.dirname(check_dir); + if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) { + return null; + } + check_dir = new_check_dir.?; + continue; + }, + else => unreachable, + }; + } else unreachable; // TODO should not need `else unreachable`. + }; + + var ctx: CMakeConfig = .{ + .cmake_binary_dir = undefined, + .cmake_prefix_path = undefined, + .cxx_compiler = undefined, + .lld_include_dir = undefined, + .lld_libraries = undefined, + .clang_libraries = undefined, + .llvm_libraries = undefined, + .dia_guids_lib = undefined, + }; + + const mappings = [_]struct { prefix: []const u8, field: []const u8 }{ + .{ + .prefix = "#define ZIG_CMAKE_BINARY_DIR ", + .field = "cmake_binary_dir", + }, + .{ + .prefix = "#define ZIG_CMAKE_PREFIX_PATH ", + .field = "cmake_prefix_path", + }, + .{ + .prefix = "#define ZIG_CXX_COMPILER ", + .field = "cxx_compiler", + }, + .{ + .prefix = "#define ZIG_LLD_INCLUDE_PATH ", + .field = "lld_include_dir", + }, + .{ + .prefix = "#define ZIG_LLD_LIBRARIES ", + .field = "lld_libraries", + }, + .{ + .prefix = "#define ZIG_CLANG_LIBRARIES ", + .field = "clang_libraries", + }, + .{ + .prefix = "#define ZIG_LLVM_LIBRARIES ", + .field = "llvm_libraries", + }, + .{ + .prefix = "#define ZIG_DIA_GUIDS_LIB ", + .field = "dia_guids_lib", + }, + }; + + var lines_it = mem.tokenize(config_h_text, "\r\n"); + while (lines_it.next()) |line| { + inline for (mappings) |mapping| { + if (mem.startsWith(u8, line, mapping.prefix)) { + var it = mem.split(line, "\""); + _ = it.next().?; // skip the stuff before the quote + const quoted = it.next().?; // the stuff inside the quote + @field(ctx, mapping.field) = toNativePathSep(b, quoted); + } + } + } + return ctx; +} + +fn toNativePathSep(b: *Builder, s: []const u8) []u8 { + const duplicated = mem.dupe(b.allocator, u8, s) catch unreachable; + for (duplicated) |*byte| switch (byte.*) { + '/' => byte.* = fs.path.sep, + else => {}, + }; + return duplicated; +} + const softfloat_sources = [_][]const u8{ "deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c", "deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c", diff --git a/src/stage1_config.zig b/src/config.zig.in similarity index 62% rename from src/stage1_config.zig rename to src/config.zig.in index 3410540d5b11e7b4129e0c849c0938bbc96b2245..871c6e9abf3bf35a856580af9787d05b848397a4 100644 --- a/src/stage1_config.zig +++ b/src/config.zig.in @@ -1,10 +1,10 @@ pub const have_llvm = true; -pub const version: [:0]const u8 = "0.0.0+zig0"; +pub const version: [:0]const u8 = "@ZIG_VERSION@"; pub const semver: @import("std").SemanticVersion = .{ - .major = 0, - .minor = 0, - .patch = 0, - .build = "zig0", + .major = @ZIG_VERSION_MAJOR@, + .minor = @ZIG_VERSION_MINOR@, + .patch = @ZIG_VERSION_PATCH@, + .build = "@ZIG_GIT_REV@", }; pub const log_scopes: []const []const u8 = &[_][]const u8{}; pub const zir_dumps: []const []const u8 = &[_][]const u8{}; diff --git a/src/stage1/config.h.in b/src/stage1/config.h.in new file mode 100644 index 0000000000000000000000000000000000000000..4d375652ff5d91c481db4cab6e94255a58845ef9 --- /dev/null +++ b/src/stage1/config.h.in @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_CONFIG_H +#define ZIG_CONFIG_H + +// Used by zig0.cpp +#define ZIG_VERSION_MAJOR @ZIG_VERSION_MAJOR@ +#define ZIG_VERSION_MINOR @ZIG_VERSION_MINOR@ +#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@ +#define ZIG_VERSION_STRING "@ZIG_VERSION@" + +// Used by build.zig for communicating build information to self hosted build. +#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@" +#define ZIG_CMAKE_PREFIX_PATH "@CMAKE_PREFIX_PATH@" +#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@" +#define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@" +#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@" +#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@" +#define ZIG_LLVM_LIBRARIES "@LLVM_LIBRARIES@" +#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@" + +#endif diff --git a/src/stage1/zig0.cpp b/src/stage1/zig0.cpp index ffe5ebe244351dd3ffd68c68ed0b30ebcb010da4..73f5b4f685867adb3c7989235b738a78559981ff 100644 --- a/src/stage1/zig0.cpp +++ b/src/stage1/zig0.cpp @@ -18,6 +18,11 @@ #include "buffer.hpp" #include "os.hpp" +// This is the only file allowed to include config.h because config.h is +// only produced when building with cmake. When using the zig build system, +// zig0.cpp is never touched. +#include "config.h" + #include #include @@ -539,9 +544,9 @@ const char *stage2_add_link_lib(struct ZigStage1 *stage1, } const char *stage2_version_string(void) { - return "0.0.0+zig0"; + return ZIG_VERSION_STRING; } struct Stage2SemVer stage2_version(void) { - return {0, 0, 0}; + return {ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH}; } -- 2.54.0 From 1afea36a16ba4963f2a4ad0b2efb5e18680305ac Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 7 Dec 2020 17:50:14 -0700 Subject: [PATCH 5/5] update readme installation instructions The readme now links to the wiki for instructions on building from source. I plan to make many updates to the wiki soon as I start to provide tarballs for working on the compiler. --- README.md | 96 +++---------------------------------------------------- 1 file changed, 5 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 6af21a8067cd1e6ad8f9a8e5391b55f72f79ab07..5eedcdab8bfc8b7791ed1e52a63d6c1da9123d2c 100644 --- a/README.md +++ b/README.md @@ -14,98 +14,12 @@ A general-purpose programming language and toolchain for maintaining * [Frequently Asked Questions](https://github.com/ziglang/zig/wiki/FAQ) * [Community Projects](https://github.com/ziglang/zig/wiki/Community-Projects) -## Building from Source +## Installation -[![Build Status](https://dev.azure.com/ziglang/zig/_apis/build/status/ziglang.zig?branchName=master)](https://dev.azure.com/ziglang/zig/_build/latest?definitionId=1&branchName=master) - -Note that you can -[download a binary of the master branch](https://ziglang.org/download/#release-master) or -[install Zig from a package manager](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager). - -### Stage 1: Build Zig from C++ Source Code - -This step must be repeated when you make changes to any of the C++ source code. - -#### Dependencies - -##### POSIX - - * cmake >= 2.8.5 - * gcc >= 5.0.0 or clang >= 3.6.0 - * LLVM, Clang, LLD development libraries == 11.x, compiled with the same gcc or clang version above - - Use the system package manager, or [build from source](https://github.com/ziglang/zig/wiki/How-to-build-LLVM,-libclang,-and-liblld-from-source#posix). - -##### Windows - - * cmake >= 3.15.3 - * Microsoft Visual Studio. Supported versions: - - 2017 (version 15.8) - - 2019 (version 16) - * LLVM, Clang, LLD development libraries == 11.x - - Use the [pre-built binaries](https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows) or [build from source](https://github.com/ziglang/zig/wiki/How-to-build-LLVM,-libclang,-and-liblld-from-source#windows). - -#### Instructions - -##### POSIX - -``` -mkdir build -cd build -cmake .. -make install -``` - -Need help? [Troubleshooting Build Issues](https://github.com/ziglang/zig/wiki/Troubleshooting-Build-Issues) - -##### MacOS - -``` -brew install cmake llvm -brew outdated llvm || brew upgrade llvm -mkdir build -cd build -cmake .. -DCMAKE_PREFIX_PATH=$(brew --prefix llvm) -make install -``` - -##### Windows - -See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows - -### Stage 2: Build Self-Hosted Zig from Zig Source Code - -Now we use the stage1 binary: - -``` -zig build --prefix $(pwd)/stage2 -Denable-llvm -``` - -This produces `stage2/bin/zig` which can be used for testing and development. -Once it is feature complete, it will be used to build stage 3 - the final compiler -binary. - -### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler - -*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is -not yet supported.* - -Once the self-hosted compiler can build itself, this will be the actual -compiler binary that we will install to the system. Until then, users should -use stage 1. - -#### Debug / Development Build - -``` -stage2/bin/zig build -``` - -This produces `zig-cache/bin/zig`. - -#### Release / Install Build - -``` -stage2/bin/zig build install -Drelease -``` + * [download a pre-built binary](https://ziglang.org/download/) + * [install from a package manager](https://github.com/ziglang/zig/wiki/Install-Zig-from-a-Package-Manager) + * [build from source](https://github.com/ziglang/zig/wiki/Building-Zig-From-Source) + * [bootstrap zig for any target](https://github.com/ziglang/zig-bootstrap) ## License -- 2.54.0