From 5314641e117f3b3d9cef2db527af532ddf18ccfc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 2 Apr 2020 17:29:22 -0400 Subject: [PATCH] zig cc: support more linker args --- src/all_types.hpp | 11 +++++++ src/codegen.cpp | 5 +++ src/link.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++----- src/main.cpp | 35 +++++++++++++++++++++ 4 files changed, 124 insertions(+), 7 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 483a098474..9b22279b91 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2015,6 +2015,12 @@ enum WantCSanitize { WantCSanitizeEnabled, }; +enum OptionalBool { + OptionalBoolNull, + OptionalBoolFalse, + OptionalBoolTrue, +}; + struct CFile { ZigList args; const char *source_path; @@ -2260,6 +2266,8 @@ struct CodeGen { TargetSubsystem subsystem; // careful using this directly; see detect_subsystem ValgrindSupport valgrind_support; CodeModel code_model; + OptionalBool linker_gc_sections; + OptionalBool linker_allow_shlib_undefined; bool strip_debug_symbols; bool is_test_build; bool is_single_threaded; @@ -2280,6 +2288,8 @@ struct CodeGen { bool emit_asm; bool emit_llvm_ir; bool test_is_evented; + bool linker_z_nodelete; + bool linker_z_defs; Buf *root_out_name; Buf *test_filter; @@ -2288,6 +2298,7 @@ struct CodeGen { Buf *zig_std_dir; Buf *version_script_path; Buf *override_soname; + Buf *linker_optimization; const char **llvm_argv; size_t llvm_argv_len; diff --git a/src/codegen.cpp b/src/codegen.cpp index c02b79e97d..c9e67dcac5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -10558,6 +10558,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { } cache_buf_opt(ch, g->version_script_path); cache_buf_opt(ch, g->override_soname); + cache_buf_opt(ch, g->linker_optimization); + cache_int(ch, g->linker_gc_sections); + cache_int(ch, g->linker_allow_shlib_undefined); + cache_bool(ch, g->linker_z_nodelete); + cache_bool(ch, g->linker_z_defs); // gen_c_objects appends objects to g->link_objects which we want to include in the hash gen_c_objects(g); diff --git a/src/link.cpp b/src/link.cpp index fba572de98..e26a7ea436 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1769,8 +1769,17 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append(g->linker_script); } - if (g->out_type != OutTypeObj) { - lj->args.append("--gc-sections"); + switch (g->linker_gc_sections) { + case OptionalBoolNull: + if (g->out_type != OutTypeObj) { + lj->args.append("--gc-sections"); + } + break; + case OptionalBoolTrue: + lj->args.append("--gc-sections"); + break; + case OptionalBoolFalse: + break; } if (g->link_eh_frame_hdr) { @@ -1781,6 +1790,19 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append("--export-dynamic"); } + if (g->linker_optimization != nullptr) { + lj->args.append(buf_ptr(g->linker_optimization)); + } + + if (g->linker_z_nodelete) { + lj->args.append("-z"); + lj->args.append("nodelete"); + } + if (g->linker_z_defs) { + lj->args.append("-z"); + lj->args.append("defs"); + } + lj->args.append("-m"); lj->args.append(getLDMOption(g->zig_target)); @@ -1971,8 +1993,17 @@ static void construct_linker_job_elf(LinkJob *lj) { } } - if (!g->zig_target->is_native_os) { - lj->args.append("--allow-shlib-undefined"); + switch (g->linker_allow_shlib_undefined) { + case OptionalBoolNull: + if (!g->zig_target->is_native_os) { + lj->args.append("--allow-shlib-undefined"); + } + break; + case OptionalBoolFalse: + break; + case OptionalBoolTrue: + lj->args.append("--allow-shlib-undefined"); + break; } } @@ -2536,10 +2567,34 @@ static void construct_linker_job_macho(LinkJob *lj) { //lj->args.append("-error-limit=0"); lj->args.append("-demangle"); + switch (g->linker_gc_sections) { + case OptionalBoolNull: + // TODO why do we not follow the same logic of elf here? + break; + case OptionalBoolTrue: + lj->args.append("--gc-sections"); + break; + case OptionalBoolFalse: + break; + } + if (g->linker_rdynamic) { lj->args.append("-export_dynamic"); } + if (g->linker_optimization != nullptr) { + lj->args.append(buf_ptr(g->linker_optimization)); + } + + if (g->linker_z_nodelete) { + lj->args.append("-z"); + lj->args.append("nodelete"); + } + if (g->linker_z_defs) { + lj->args.append("-z"); + lj->args.append("defs"); + } + bool is_lib = g->out_type == OutTypeLib; bool is_dyn_lib = g->is_dynamic && is_lib; if (is_lib && !g->is_dynamic) { @@ -2654,9 +2709,20 @@ static void construct_linker_job_macho(LinkJob *lj) { // and change between versions. // so we always link against libSystem lj->args.append("-lSystem"); - } else { - lj->args.append("-undefined"); - lj->args.append("dynamic_lookup"); + } + switch (g->linker_allow_shlib_undefined) { + case OptionalBoolNull: + if (!g->zig_target->is_native_os) { + lj->args.append("-undefined"); + lj->args.append("dynamic_lookup"); + } + break; + case OptionalBoolFalse: + break; + case OptionalBoolTrue: + lj->args.append("-undefined"); + lj->args.append("dynamic_lookup"); + break; } for (size_t i = 0; i < g->framework_dirs.length; i += 1) { diff --git a/src/main.cpp b/src/main.cpp index 278f684181..cd45d40e5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -459,6 +459,11 @@ static int main0(int argc, char **argv) { bool ensure_libc_on_non_freestanding = false; bool ensure_libcpp_on_non_freestanding = false; bool disable_c_depfile = false; + Buf *linker_optimization = nullptr; + OptionalBool linker_gc_sections = OptionalBoolNull; + OptionalBool linker_allow_shlib_undefined = OptionalBoolNull; + bool linker_z_nodelete = false; + bool linker_z_defs = false; ZigList llvm_argv = {0}; llvm_argv.append("zig (LLVM option parsing)"); @@ -822,6 +827,30 @@ static int main0(int argc, char **argv) { return EXIT_FAILURE; } version_script = linker_args.at(i); + } else if (buf_starts_with_str(arg, "-O")) { + linker_optimization = arg; + } else if (buf_eql_str(arg, "--gc-sections")) { + linker_gc_sections = OptionalBoolTrue; + } else if (buf_eql_str(arg, "--no-gc-sections")) { + linker_gc_sections = OptionalBoolFalse; + } else if (buf_eql_str(arg, "--allow-shlib-undefined")) { + linker_allow_shlib_undefined = OptionalBoolTrue; + } else if (buf_eql_str(arg, "--no-allow-shlib-undefined")) { + linker_allow_shlib_undefined = OptionalBoolFalse; + } else if (buf_eql_str(arg, "-z")) { + i += 1; + if (i >= linker_args.length) { + fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg)); + return EXIT_FAILURE; + } + Buf *z_arg = linker_args.at(i); + if (buf_eql_str(z_arg, "nodelete")) { + linker_z_nodelete = true; + } else if (buf_eql_str(z_arg, "defs")) { + linker_z_defs = true; + } else { + fprintf(stderr, "warning: unsupported linker arg: -z %s\n", buf_ptr(z_arg)); + } } else { fprintf(stderr, "warning: unsupported linker arg: %s\n", buf_ptr(arg)); } @@ -1542,6 +1571,12 @@ static int main0(int argc, char **argv) { g->code_model = code_model; g->disable_c_depfile = disable_c_depfile; + g->linker_optimization = linker_optimization; + g->linker_gc_sections = linker_gc_sections; + g->linker_allow_shlib_undefined = linker_allow_shlib_undefined; + g->linker_z_nodelete = linker_z_nodelete; + g->linker_z_defs = linker_z_defs; + if (override_soname) { g->override_soname = buf_create_from_str(override_soname); }