Commit a7346ea49f

Andrew Kelley <andrew@ziglang.org>
2019-05-09 04:43:11
fix build on macOS
Sadly due to a workaround for LLD linker limitations on macOS we cannot put libuserland into an .a file; instead we have to use object files. Again due to linker limitations, bundling compiler_rt.o into another relocatable object also doesn't work. So we're left with disabling stack probing on macOS for the stage1 self-hosted code. These workarounds could all be removed if the macos support in the LLD linker improved, or if Zig project had its own linker that did not have these issues.
1 parent 4b9e12b
src/all_types.hpp
@@ -1862,6 +1862,7 @@ struct CodeGen {
     bool is_dummy_so;
     bool disable_gen_h;
     bool bundle_compiler_rt;
+    bool disable_stack_probing;
 
     Buf *mmacosx_version_min;
     Buf *mios_version_min;
src/codegen.cpp
@@ -401,7 +401,7 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
 
 static void add_probe_stack_attr(CodeGen *g, LLVMValueRef fn_val) {
     // Windows already emits its own stack probes
-    if (g->zig_target->os != OsWindows &&
+    if (!g->disable_stack_probing && g->zig_target->os != OsWindows &&
         (g->zig_target->arch == ZigLLVM_x86 ||
          g->zig_target->arch == ZigLLVM_x86_64)) {
         addLLVMFnAttrStr(fn_val, "probe-stack", "__zig_probe_stack");
@@ -7043,6 +7043,11 @@ static void zig_llvm_emit_output(CodeGen *g) {
             }
             validate_inline_fns(g);
             g->link_objects.append(output_path);
+            if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
+                (g->out_type == OutTypeLib && !g->is_dynamic)))
+            {
+                zig_link_add_compiler_rt(g);
+            }
             break;
 
         case EmitFileTypeAssembly:
@@ -9347,6 +9352,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
     cache_bool(ch, g->each_lib_rpath);
     cache_bool(ch, g->disable_gen_h);
     cache_bool(ch, g->bundle_compiler_rt);
+    cache_bool(ch, g->disable_stack_probing);
     cache_bool(ch, want_valgrind_support(g));
     cache_bool(ch, g->have_pic);
     cache_bool(ch, g->have_dynamic_link);
src/codegen.hpp
@@ -44,6 +44,7 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc
 void codegen_add_time_event(CodeGen *g, const char *name);
 void codegen_print_timing_report(CodeGen *g, FILE *f);
 void codegen_link(CodeGen *g);
+void zig_link_add_compiler_rt(CodeGen *g);
 void codegen_build_and_link(CodeGen *g);
 
 ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,
src/link.cpp
@@ -25,6 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
     CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
         parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
     child_gen->disable_gen_h = true;
+    child_gen->disable_stack_probing = true;
     child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
     child_gen->verbose_ast = parent_gen->verbose_ast;
     child_gen->verbose_link = parent_gen->verbose_link;
@@ -1653,6 +1654,11 @@ static void construct_linker_job(LinkJob *lj) {
     }
 }
 
+void zig_link_add_compiler_rt(CodeGen *g) {
+    Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj);
+    g->link_objects.append(compiler_rt_o_path);
+}
+
 void codegen_link(CodeGen *g) {
     codegen_add_time_event(g, "Build Dependencies");
 
@@ -1681,10 +1687,6 @@ void codegen_link(CodeGen *g) {
         for (size_t i = 0; i < g->link_objects.length; i += 1) {
             file_names.append(buf_ptr(g->link_objects.at(i)));
         }
-        if (g->bundle_compiler_rt) {
-            Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj);
-            file_names.append(buf_ptr(compiler_rt_o_path));
-        }
         ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
         codegen_add_time_event(g, "LLVM Link");
         if (g->verbose_link) {
src/main.cpp
@@ -56,6 +56,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
         "  --disable-gen-h              do not generate a C header file (.h)\n"
         "  --disable-valgrind           omit valgrind client requests in debug builds\n"
         "  --enable-valgrind            include valgrind client requests release builds\n"
+        "  --disable-stack-probing      workaround for macosx\n"
         "  --emit [asm|bin|llvm-ir]     emit a specific file format as compilation output\n"
         "  -fPIC                        enable Position Independent Code\n"
         "  -fno-PIC                     disable Position Independent Code\n"
@@ -444,6 +445,7 @@ int main(int argc, char **argv) {
     bool want_single_threaded = false;
     bool disable_gen_h = false;
     bool bundle_compiler_rt = false;
+    bool disable_stack_probing = false;
     Buf *override_std_dir = nullptr;
     Buf *override_lib_dir = nullptr;
     Buf *main_pkg_path = nullptr;
@@ -656,6 +658,8 @@ int main(int argc, char **argv) {
                 disable_gen_h = true;
             } else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
                 bundle_compiler_rt = true;
+            } else if (strcmp(arg, "--disable-stack-probing") == 0) {
+                disable_stack_probing = true;
             } else if (strcmp(arg, "--test-cmd-bin") == 0) {
                 test_exec_args.append(nullptr);
             } else if (arg[1] == 'L' && arg[2] != 0) {
@@ -1075,6 +1079,7 @@ int main(int argc, char **argv) {
             g->output_dir = output_dir;
             g->disable_gen_h = disable_gen_h;
             g->bundle_compiler_rt = bundle_compiler_rt;
+            g->disable_stack_probing = disable_stack_probing;
             codegen_set_errmsg_color(g, color);
             g->system_linker_hack = system_linker_hack;
 
std/build.zig
@@ -942,6 +942,7 @@ pub const LibExeObjStep = struct {
     verbose_cc: bool,
     disable_gen_h: bool,
     bundle_compiler_rt: bool,
+    disable_stack_probing: bool,
     c_std: Builder.CStd,
     override_std_dir: ?[]const u8,
     override_lib_dir: ?[]const u8,
@@ -1052,6 +1053,7 @@ pub const LibExeObjStep = struct {
             .filter = null,
             .disable_gen_h = false,
             .bundle_compiler_rt = false,
+            .disable_stack_probing = false,
             .output_dir = null,
             .need_system_paths = false,
             .single_threaded = false,
@@ -1457,6 +1459,9 @@ pub const LibExeObjStep = struct {
         if (self.bundle_compiler_rt) {
             try zig_args.append("--bundle-compiler-rt");
         }
+        if (self.disable_stack_probing) {
+            try zig_args.append("--disable-stack-probing");
+        }
 
         switch (self.target) {
             Target.Native => {},
build.zig
@@ -384,12 +384,17 @@ const Context = struct {
 };
 
 fn addLibUserlandStep(b: *Builder) void {
+    // Sadly macOS requires hacks to work around the buggy MACH-O linker code.
     const artifact = if (builtin.os == .macosx)
         b.addObject("userland", "src-self-hosted/stage1.zig")
     else
         b.addStaticLibrary("userland", "src-self-hosted/stage1.zig");
     artifact.disable_gen_h = true;
-    artifact.bundle_compiler_rt = true;
+    if (builtin.os == .macosx) {
+        artifact.disable_stack_probing = true;
+    } else {
+        artifact.bundle_compiler_rt = true;
+    }
     artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
     artifact.linkSystemLibrary("c");
     const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1");