From cb7116f08bd338c2505df8e0b5c46772e3cc7a62 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 19 Aug 2024 01:06:51 +0200 Subject: [PATCH] New linker options handling --- src/compiler/compiler.c | 4 +- src/compiler/linker.c | 339 ++++++++++++++++++++++++---------------- src/utils/lib.h | 3 - src/utils/stringutils.c | 75 --------- 4 files changed, 202 insertions(+), 219 deletions(-) diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index e10f1ca6a..4d0c6fb5e 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -252,13 +252,13 @@ static void free_arenas(void) if (debug_stats) print_arena_status(); } -static int compile_cfiles(const char *compiler, const char **files, const char *flags, const char **include_dirs, +static int compile_cfiles(const char *cc, const char **files, const char *flags, const char **include_dirs, const char **out_files, const char *output_subdir) { int total = 0; FOREACH(const char *, file, files) { - out_files[total++] = cc_compiler(compiler, file, flags, include_dirs, output_subdir); + out_files[total++] = cc_compiler(cc, file, flags, include_dirs, output_subdir); } return total; } diff --git a/src/compiler/linker.c b/src/compiler/linker.c index eca35e140..59bc93308 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -5,8 +5,18 @@ #include #endif -#define add_arg(arg_) vec_add(*args_ref, (arg_)) -#define add_arg2(arg_, arg_2) vec_add(*args_ref, str_cat((arg_), (arg_2))) +const char *quote_arg = "\""; +const char *concat_arg = ":"; +const char *concat_quote_arg = "+"; +const char *quote_concat_arg = "++"; +#define add_quote_arg(arg_) vec_add(*args_ref, quote_arg); vec_add(*args_ref, (arg_)) +#define add_plain_arg(arg_) vec_add(*args_ref, (arg_)) +#define add_concat_arg(arg_, arg2_) vec_add(*args_ref, concat_arg); vec_add(*args_ref, (arg_)); vec_add(*args_ref, (arg2_)) +#define add_concat_quote_arg(arg_, arg2_) vec_add(*args_ref, concat_quote_arg); vec_add(*args_ref, (arg_)); vec_add(*args_ref, (arg2_)) +#define add_quote_concat_arg(arg_, arg2_) vec_add(*args_ref, quote_concat_arg); vec_add(*args_ref, (arg_)); vec_add(*args_ref, (arg2_)) + +static char *assemble_linker_command(const char **args, bool extra_quote); +static unsigned assemble_link_arguments(const char **arguments, unsigned len); static inline bool is_no_pie(RelocModel reloc) { @@ -37,9 +47,11 @@ static const char *ld_target(ArchType arch_type) } + + static void linker_setup_windows(const char ***args_ref, Linker linker_type) { - add_arg(compiler.build.win.use_win_subsystem ? "/SUBSYSTEM:WINDOWS" : "/SUBSYSTEM:CONSOLE"); + add_plain_arg(compiler.build.win.use_win_subsystem ? "/SUBSYSTEM:WINDOWS" : "/SUBSYSTEM:CONSOLE"); if (link_libc()) linking_add_link(&compiler.linking, "dbghelp"); if (linker_type == LINKER_CC) return; //add_arg("/MACHINE:X64"); @@ -49,11 +61,11 @@ static void linker_setup_windows(const char ***args_ref, Linker linker_type) case DEBUG_INFO_NOT_SET: break; case DEBUG_INFO_NONE: - add_arg("/DEBUG:NONE"); + add_plain_arg("/DEBUG:NONE"); break; case DEBUG_INFO_LINE_TABLES: case DEBUG_INFO_FULL: - add_arg("/DEBUG:FULL"); + add_plain_arg("/DEBUG:FULL"); is_debug = true; break; default: @@ -112,11 +124,11 @@ static void linker_setup_windows(const char ***args_ref, Linker linker_type) } if (compiler.build.win.def) { - add_arg(str_printf("/def:%s", compiler.build.win.def)); + add_concat_quote_arg("/def:", compiler.build.win.def); } if (compiler.build.win.sdk) { - add_arg(str_printf("/LIBPATH:%s", compiler.build.win.sdk)); + add_concat_quote_arg("/LIBPATH:", compiler.build.win.sdk); } else { @@ -125,9 +137,9 @@ static void linker_setup_windows(const char ***args_ref, Linker linker_type) if (!file_is_dir(windows_sdk->vs_library_path)) error_exit("Failed to find windows sdk."); - add_arg(str_printf("/LIBPATH:%s", windows_sdk->windows_sdk_um_library_path)); - add_arg(str_printf("/LIBPATH:%s", windows_sdk->windows_sdk_ucrt_library_path)); - add_arg(str_printf("/LIBPATH:%s", windows_sdk->vs_library_path)); + add_concat_quote_arg("/LIBPATH:", windows_sdk->windows_sdk_um_library_path); + add_concat_quote_arg("/LIBPATH:", windows_sdk->windows_sdk_ucrt_library_path); + add_concat_quote_arg("/LIBPATH:", windows_sdk->vs_library_path); } linking_add_link(&compiler.linking, "kernel32"); linking_add_link(&compiler.linking, "ntdll"); @@ -176,23 +188,23 @@ static void linker_setup_windows(const char ***args_ref, Linker linker_type) linking_add_link(&compiler.linking, "msvcprt"); } } - add_arg("/NOLOGO"); + add_plain_arg("/NOLOGO"); } static void linker_setup_macos(const char ***args_ref, Linker linker_type) { if (linker_type == LINKER_CC) { - add_arg("-target"); - add_arg(compiler.platform.target_triple); + add_plain_arg("-target"); + add_plain_arg(compiler.platform.target_triple); return; } - add_arg("-arch"); - add_arg(arch_to_linker_arch(compiler.platform.arch)); + add_plain_arg("-arch"); + add_plain_arg(arch_to_linker_arch(compiler.platform.arch)); if (strip_unused() && compiler.build.type == TARGET_TYPE_EXECUTABLE) { - add_arg("-no_exported_symbols"); - add_arg("-dead_strip"); + add_plain_arg("-no_exported_symbols"); + add_plain_arg("-dead_strip"); } // Skip if no libc. @@ -204,27 +216,27 @@ static void linker_setup_macos(const char ***args_ref, Linker linker_type) } linking_add_link(&compiler.linking, "System"); linking_add_link(&compiler.linking, "m"); - add_arg("-syslibroot"); - add_arg(compiler.build.macos.sysroot); - if (is_no_pie(compiler.platform.reloc_model)) add_arg("-no_pie"); - if (is_pie(compiler.platform.reloc_model)) add_arg("-pie"); - add_arg("-platform_version"); - add_arg("macos"); + add_plain_arg("-syslibroot"); + add_quote_arg(compiler.build.macos.sysroot); + if (is_no_pie(compiler.platform.reloc_model)) add_plain_arg("-no_pie"); + if (is_pie(compiler.platform.reloc_model)) add_plain_arg("-pie"); + add_plain_arg("-platform_version"); + add_plain_arg("macos"); if (compiler.build.macos.min_version) { - add_arg(compiler.build.macos.min_version); + add_plain_arg(compiler.build.macos.min_version); } else { - add_arg(str_printf("%d.%d.0", compiler.build.macos.sdk->macos_min_deploy_target.major, compiler.build.macos.sdk->macos_min_deploy_target.minor)); + add_plain_arg(str_printf("%d.%d.0", compiler.build.macos.sdk->macos_min_deploy_target.major, compiler.build.macos.sdk->macos_min_deploy_target.minor)); } if (compiler.build.macos.sdk_version) { - add_arg(compiler.build.macos.sdk_version); + add_plain_arg(compiler.build.macos.sdk_version); } else { - add_arg(str_printf("%d.%d", compiler.build.macos.sdk->macos_deploy_target.major, compiler.build.macos.sdk->macos_deploy_target.minor)); + add_plain_arg(str_printf("%d.%d", compiler.build.macos.sdk->macos_deploy_target.major, compiler.build.macos.sdk->macos_deploy_target.minor)); } } @@ -295,7 +307,7 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type) { if (!link_libc()) { - add_arg("-nostdlib"); + add_plain_arg("-nostdlib"); return; } else @@ -304,25 +316,25 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type) } if (compiler.build.debug_info == DEBUG_INFO_FULL) { - add_arg("-rdynamic"); + add_plain_arg("-rdynamic"); } - add_arg("-pthread"); + add_plain_arg("-pthread"); return; } if (compiler.build.debug_info == DEBUG_INFO_FULL) { - add_arg("-export-dynamic"); + add_plain_arg("-export-dynamic"); } - if (is_no_pie(compiler.platform.reloc_model)) add_arg("-no-pie"); - if (is_pie(compiler.platform.reloc_model)) add_arg("-pie"); - if (compiler.platform.arch == ARCH_TYPE_X86_64) add_arg("--eh-frame-hdr"); + if (is_no_pie(compiler.platform.reloc_model)) add_plain_arg("-no-pie"); + if (is_pie(compiler.platform.reloc_model)) add_plain_arg("-pie"); + if (compiler.platform.arch == ARCH_TYPE_X86_64) add_plain_arg("--eh-frame-hdr"); if (!link_libc()) return; const char *crt_begin_dir = find_linux_crt_begin(); const char *crt_dir = find_linux_crt(); if (strip_unused() && compiler.build.type == TARGET_TYPE_EXECUTABLE) { - add_arg("--gc-sections"); + add_plain_arg("--gc-sections"); } if (!crt_begin_dir || !crt_dir) @@ -331,39 +343,38 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type) } if (is_pie_pic(compiler.platform.reloc_model)) { - add_arg("-pie"); - add_arg2(crt_dir, "Scrt1.o"); - add_arg2(crt_begin_dir, "crtbeginS.o"); - add_arg2(crt_dir, "crti.o"); - add_arg2(crt_begin_dir, "crtendS.o"); + add_plain_arg("-pie"); + add_quote_concat_arg(crt_dir, "Scrt1.o"); + add_quote_concat_arg(crt_begin_dir, "crtbeginS.o"); + add_quote_concat_arg(crt_dir, "crti.o"); + add_quote_concat_arg(crt_begin_dir, "crtendS.o"); } else { - add_arg2(crt_dir, "crt1.o"); - add_arg2(crt_begin_dir, "crtbegin.o"); - add_arg2(crt_dir, "crti.o"); - add_arg2(crt_begin_dir, "crtend.o"); + add_quote_concat_arg(crt_dir, "crt1.o"); + add_quote_concat_arg(crt_begin_dir, "crtbegin.o"); + add_quote_concat_arg(crt_dir, "crti.o"); + add_quote_concat_arg(crt_begin_dir, "crtend.o"); } - add_arg2(crt_dir, "crtn.o"); - add_arg2("-L", crt_dir); - add_arg("-L"); - add_arg("/usr/lib/x86_64-linux-gnu/libdl.so"); - add_arg("--dynamic-linker=/lib64/ld-linux-x86-64.so.2"); + add_quote_concat_arg(crt_dir, "crtn.o"); + add_concat_quote_arg("-L", crt_dir); + add_plain_arg("-L/usr/lib/x86_64-linux-gnu/libdl.so"); + add_plain_arg("--dynamic-linker=/lib64/ld-linux-x86-64.so.2"); linking_add_link(&compiler.linking, "m"); linking_add_link(&compiler.linking, "pthread"); linking_add_link(&compiler.linking, "c"); - add_arg("-L/usr/lib/"); - add_arg("-L/lib/"); - add_arg("-m"); - add_arg(ld_target(compiler.platform.arch)); + add_plain_arg("-L/usr/lib/"); + add_plain_arg("-L/lib/"); + add_plain_arg("-m"); + add_plain_arg(ld_target(compiler.platform.arch)); } static void linker_setup_freebsd(const char ***args_ref, Linker linker_type) { if (linker_type == LINKER_CC) return; - if (is_no_pie(compiler.platform.reloc_model)) add_arg("-no-pie"); - if (is_pie(compiler.platform.reloc_model)) add_arg("-pie"); - if (compiler.platform.arch == ARCH_TYPE_X86_64) add_arg("--eh-frame-hdr"); + if (is_no_pie(compiler.platform.reloc_model)) add_plain_arg("-no-pie"); + if (is_pie(compiler.platform.reloc_model)) add_plain_arg("-pie"); + if (compiler.platform.arch == ARCH_TYPE_X86_64) add_plain_arg("--eh-frame-hdr"); if (!link_libc()) return; @@ -374,35 +385,35 @@ static void linker_setup_freebsd(const char ***args_ref, Linker linker_type) } if (strip_unused() && compiler.build.type == TARGET_TYPE_EXECUTABLE) { - add_arg("--gc-sections"); + add_plain_arg("--gc-sections"); } if (is_pie_pic(compiler.platform.reloc_model)) { - add_arg("-pie"); - add_arg2(crt_dir, "Scrt1.o"); - add_arg2(crt_dir, "crtbeginS.o"); - add_arg2(crt_dir, "crti.o"); - add_arg2(crt_dir, "crtendS.o"); + add_plain_arg("-pie"); + add_quote_concat_arg(crt_dir, "Scrt1.o"); + add_quote_concat_arg(crt_dir, "crtbeginS.o"); + add_quote_concat_arg(crt_dir, "crti.o"); + add_quote_concat_arg(crt_dir, "crtendS.o"); } else { - add_arg2(crt_dir, "crt1.o"); - add_arg2(crt_dir, "crtbegin.o"); - add_arg2(crt_dir, "crti.o"); - add_arg2(crt_dir, "crtend.o"); + add_quote_concat_arg(crt_dir, "crt1.o"); + add_quote_concat_arg(crt_dir, "crtbegin.o"); + add_quote_concat_arg(crt_dir, "crti.o"); + add_quote_concat_arg(crt_dir, "crtend.o"); } - add_arg2(crt_dir, "crtn.o"); - add_arg2("-L", crt_dir); - add_arg("--dynamic-linker=/libexec/ld-elf.so.1"); + add_quote_concat_arg(crt_dir, "crtn.o"); + add_concat_quote_arg("-L", crt_dir); + add_plain_arg("--dynamic-linker=/libexec/ld-elf.so.1"); linking_add_link(&compiler.linking, "c"); linking_add_link(&compiler.linking, "m"); linking_add_link(&compiler.linking, "gcc"); linking_add_link(&compiler.linking, "gcc_s"); - add_arg("-L/usr/lib/"); - add_arg("-m"); - add_arg(ld_target(compiler.platform.arch)); + add_plain_arg("-L/usr/lib/"); + add_plain_arg("-m"); + add_plain_arg(ld_target(compiler.platform.arch)); } static void add_linked_libs(const char ***args_ref, const char **libs, bool is_win) @@ -413,19 +424,19 @@ static void add_linked_libs(const char ***args_ref, const char **libs, bool is_w const char *framework = str_remove_suffix(lib, ".framework"); if (framework) { - add_arg("-framework"); - add_arg(framework); + add_plain_arg("-framework"); + add_plain_arg(framework); continue; } if (is_win) { if (str_has_suffix(lib, ".lib")) { - add_arg(lib); + add_plain_arg(lib); } else { - add_arg2(lib, ".lib"); + add_concat_arg(lib, ".lib"); } } else @@ -433,11 +444,11 @@ static void add_linked_libs(const char ***args_ref, const char **libs, bool is_w if (str_has_suffix(lib, ".a") || str_has_suffix(lib, ".so") || str_has_suffix(lib, ".dylib") || str_has_suffix(lib, ".tbd")) { - add_arg(lib); + add_plain_arg(lib); } else { - add_arg2("-l", lib); + add_concat_quote_arg("-l", lib); } } } @@ -450,31 +461,31 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns bool use_win = linker_type == LINKER_LINK_EXE; if (!use_win) { - add_arg("-o"); - add_arg(output_file); + add_plain_arg("-o"); + add_quote_arg(output_file); } switch (linker_type) { case LINKER_UNKNOWN: break; case LINKER_WASM: - if (!is_dylib && compiler.build.no_entry) add_arg("--no-entry"); + if (!is_dylib && compiler.build.no_entry) add_plain_arg("--no-entry"); break; case LINKER_LD64: - if (is_dylib) vec_add(*args_ref, "-dylib"); + if (is_dylib) add_plain_arg("-dylib"); break; case LINKER_LD: - if (is_dylib) vec_add(*args_ref, "-shared"); + if (is_dylib) add_plain_arg("-shared"); break; case LINKER_LINK_EXE: - add_arg2("/OUT:", output_file); + add_concat_quote_arg("/OUT:", output_file); if (is_dylib) { - add_arg("/DLL"); + add_plain_arg("/DLL"); } else { - if (compiler.build.no_entry) add_arg("/NOENTRY"); + if (compiler.build.no_entry) add_plain_arg("/NOENTRY"); } case LINKER_CC: break; @@ -517,22 +528,22 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns } for (unsigned i = 0; i < file_count; i++) { - add_arg(files_to_link[i]); + add_quote_arg(files_to_link[i]); } FOREACH(const char *, dir, compiler.build.linker_libdirs) { - add_arg2(lib_path_opt, dir); + add_quote_concat_arg(lib_path_opt, dir); } FOREACH(const char *, arg, compiler.build.link_args) { - add_arg(arg); + add_plain_arg(arg); } add_linked_libs(args_ref, compiler.build.linker_libs, use_win); FOREACH(Library *, library, compiler.build.library_list) { LibraryTarget *target = library->target_used; - FOREACH(const char *, flag, target->link_flags) add_arg(flag); + FOREACH(const char *, flag, target->link_flags) add_plain_arg(flag); add_linked_libs(args_ref, target->linked_libs, use_win); } add_linked_libs(args_ref, linking->links, use_win); @@ -548,24 +559,24 @@ static void append_fpie_pic_options(RelocModel reloc, const char ***args_ref) case RELOC_DEFAULT: UNREACHABLE case RELOC_NONE: - vec_add(*args_ref, "-fno-pic"); - vec_add(*args_ref, "-fno-pie"); - vec_add(*args_ref, "-fno-PIC"); - vec_add(*args_ref, "-fno-PIE"); + add_plain_arg("-fno-pic"); + add_plain_arg("-fno-pie"); + add_plain_arg("-fno-PIC"); + add_plain_arg("-fno-PIE"); break; case RELOC_SMALL_PIC: - vec_add(*args_ref, "-fpic"); + add_plain_arg("-fpic"); break; case RELOC_BIG_PIC: - vec_add(*args_ref, "-fPIC"); + add_plain_arg("-fPIC"); break; case RELOC_SMALL_PIE: - vec_add(*args_ref, "-fpie"); - vec_add(*args_ref, "-fpic"); + add_plain_arg("-fpie"); + add_plain_arg("-fpic"); break; case RELOC_BIG_PIE: - vec_add(*args_ref, "-fPIE"); - vec_add(*args_ref, "-fPIC"); + add_plain_arg("-fPIE"); + add_plain_arg("-fPIC"); break; } } @@ -596,6 +607,34 @@ Linker linker_find_linker_type(void) UNREACHABLE } +static unsigned assemble_link_arguments(const char **arguments, unsigned len) +{ + unsigned count = 0; + for (unsigned i = 0; i < len ; i++) + { + const char *arg = arguments[i]; + if (arg == quote_arg) continue; + if (arg == concat_arg || arg == quote_concat_arg || arg == concat_quote_arg) + { + const char *a = arguments[++i]; + const char *b = arguments[++i]; + arguments[count++] = str_cat(a, b); + continue; + } + if (count != i) + { + arguments[count] = arg; + } + count++; + } + if (compiler.build.print_linking) + { + for (int i = 0; i < count - 1; i++) printf("%s ", arguments[i]); + puts(arguments[count - 1]); + } + return count; +} + static bool link_exe(const char *output_file, const char **files_to_link, unsigned file_count) { INFO_LOG("Using linker directly."); @@ -607,28 +646,20 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign // This isn't used in most cases, but its contents should get freed after linking. bool success; - const char *arg_list = ""; - FOREACH(const char *, arg, args) - { - arg_list = str_cat(arg_list, " "); - arg_list = str_cat(arg_list, arg); - } - INFO_LOG("Linker arguments: %s to %d", arg_list, compiler.platform.object_format); - if (compiler.build.print_linking) puts(arg_list); - + unsigned count = assemble_link_arguments(args, vec_size(args)); switch (compiler.platform.object_format) { case OBJ_FORMAT_COFF: - success = llvm_link_coff(args, (int)vec_size(args), &error); + success = llvm_link_coff(args, count, &error); break; case OBJ_FORMAT_ELF: - success = llvm_link_elf(args, (int)vec_size(args), &error); + success = llvm_link_elf(args, count, &error); break; case OBJ_FORMAT_MACHO: - success = llvm_link_macho(args, (int)vec_size(args), &error); + success = llvm_link_macho(args, count, &error); break; case OBJ_FORMAT_WASM: - success = llvm_link_wasm(args, (int)vec_size(args), &error); + success = llvm_link_wasm(args, count, &error); break; default: UNREACHABLE @@ -660,33 +691,61 @@ bool obj_format_linking_supported(ObjectFormatType format_type) } -const char *concat_string_parts(const char **args) +static char *assemble_linker_command(const char **args, bool extra_quote) { scratch_buffer_clear(); - FOREACH(const char *, arg, args) + if (extra_quote) scratch_buffer_append_char('"'); + unsigned count = vec_size(args); + for (unsigned i = 0; i < count; i++) { + if (i != 0) scratch_buffer_append_char(' '); + const char *arg = args[i]; assert(arg != scratch_buffer.str && "Incorrectly passed a scratch buffer string as an argument."); - if (PLATFORM_WINDOWS && arg == *args) + if (arg == quote_arg) { - scratch_buffer_append(arg); + scratch_buffer_append_char('"'); + scratch_buffer_append(args[++i]); + scratch_buffer_append_char('"'); + continue; } - else + if (arg == concat_arg) { - scratch_buffer_append_argument(arg); + scratch_buffer_append(args[++i]); + scratch_buffer_append(args[++i]); + continue; } + if (arg == quote_concat_arg) + { + scratch_buffer_append_char('"'); + scratch_buffer_append(args[++i]); + scratch_buffer_append(args[++i]); + scratch_buffer_append_char('"'); + continue; + } + if (arg == concat_quote_arg) + { + scratch_buffer_append(args[++i]); + scratch_buffer_append_char('"'); + scratch_buffer_append(args[++i]); + scratch_buffer_append_char('"'); + continue; + } + scratch_buffer_append(arg); } - return scratch_buffer_copy(); + if (extra_quote) scratch_buffer_append_char('"'); + return scratch_buffer_to_string(); } void platform_linker(const char *output_file, const char **files, unsigned file_count) { const char **parts = NULL; + const char ***args_ref = &parts; Linker linker_type = LINKER_CC; if (compiler.build.linker_type == LINKER_TYPE_CUSTOM) { INFO_LOG("Using linker %s.", compiler.build.custom_linker_path); - vec_add(parts, compiler.build.custom_linker_path); + add_quote_arg(compiler.build.custom_linker_path); switch (compiler.platform.object_format) { case OBJ_FORMAT_UNSUPPORTED: @@ -717,7 +776,7 @@ void platform_linker(const char *output_file, const char **files, unsigned file_ } linker_setup(&parts, files, file_count, output_file, linker_type, &compiler.linking); - const char *output = concat_string_parts(parts); + const char *output = assemble_linker_command(parts, PLATFORM_WINDOWS); if (compiler.build.print_linking) puts(output); if (system(output) != 0) { @@ -727,7 +786,7 @@ void platform_linker(const char *output_file, const char **files, unsigned file_ { // Create .dSYM scratch_buffer_clear(); - scratch_buffer_printf("dsymutil -arch %s %s", arch_to_linker_arch(compiler.platform.arch), output_file); + scratch_buffer_printf("dsymutil -arch %s \"%s\"", arch_to_linker_arch(compiler.platform.arch), output_file); if (compiler.build.print_linking) puts(scratch_buffer_to_string()); if (system(scratch_buffer_to_string()) != 0) { @@ -763,11 +822,12 @@ const char *cc_compiler(const char *cc, const char *file, const char *flags, con ? str_printf("%s/%s%s", dir, filename, get_object_extension()) : str_printf("%s%s", filename, get_object_extension());; const char **parts = NULL; - vec_add(parts, cc); + const char ***args_ref = &parts; + add_quote_arg(cc); FOREACH(const char *, include_dir, include_dirs) { - vec_add(parts, str_printf(is_cl_exe ? "/I%s" : "-I%s", include_dir)); + add_concat_quote_arg(is_cl_exe ? "/I" : "-I ", include_dir); } const bool pie_set = @@ -781,20 +841,20 @@ const char *cc_compiler(const char *cc, const char *file, const char *flags, con append_fpie_pic_options(compiler.platform.reloc_model, &parts); } - vec_add(parts, is_cl_exe ? "/c" : "-c"); - if (flags) vec_add(parts, flags); - vec_add(parts, file); + add_plain_arg(is_cl_exe ? "/c" : "-c"); + if (flags) add_plain_arg(flags); + add_quote_arg(file); if (is_cl_exe) { - vec_add(parts, str_printf("/Fo:%s", out_name)); + add_concat_quote_arg("/Fo:", out_name); } else { - vec_add(parts, "-o"); - vec_add(parts, out_name); + add_plain_arg("-o"); + add_quote_arg(out_name); } - const char *output = concat_string_parts(parts); + const char *output = assemble_linker_command(parts, PLATFORM_WINDOWS); DEBUG_LOG("Compiling c sources using '%s'", output); if (system(output) != 0) { @@ -811,11 +871,11 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi Linker linker_type = linker_find_linker_type(); linker_setup(&args, files, file_count, output_file, linker_type, &compiler.linking); - const char *command = concat_string_parts(args); - if (compiler.build.print_linking) puts(command); - DEBUG_LOG("Linker arguments: %s to %d", command, compiler.platform.object_format); if (compiler.build.linker_type == LINKER_TYPE_CUSTOM) { + const char *command = assemble_linker_command(args, PLATFORM_WINDOWS); + if (compiler.build.print_linking) puts(command); + DEBUG_LOG("Linker arguments: %s to %d", command, compiler.platform.object_format); if (system(command) != 0) { error_exit("Failed to create a dynamic library using command '%s'.", command); @@ -824,19 +884,20 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi } bool success; const char *error = NULL; + unsigned count = assemble_link_arguments(args, vec_size(args)); switch (compiler.platform.object_format) { case OBJ_FORMAT_COFF: - success = llvm_link_coff(args, (int)vec_size(args), &error); + success = llvm_link_coff(args, count, &error); break; case OBJ_FORMAT_ELF: - success = llvm_link_elf(args, (int)vec_size(args), &error); + success = llvm_link_elf(args, count, &error); break; case OBJ_FORMAT_MACHO: - success = llvm_link_macho(args, (int)vec_size(args), &error); + success = llvm_link_macho(args, count, &error); break; case OBJ_FORMAT_WASM: - success = llvm_link_wasm(args, (int)vec_size(args), &error); + success = llvm_link_wasm(args, count, &error); break; default: UNREACHABLE diff --git a/src/utils/lib.h b/src/utils/lib.h index fe4458004..8552d286a 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -154,9 +154,6 @@ void slice_trim(StringSlice *slice); void scratch_buffer_clear(void); void scratch_buffer_append(const char *string); -void scratch_buffer_append_argument(const char *string); -void scratch_buffer_append_double_quoted(const char *string); -void scratch_buffer_append_shell_escaped(const char *string); void scratch_buffer_append_len(const char *string, size_t len); void scratch_buffer_append_char(char c); void scratch_buffer_append_char_repeat(char c, size_t count); diff --git a/src/utils/stringutils.c b/src/utils/stringutils.c index 83bc69c08..0e9717679 100644 --- a/src/utils/stringutils.c +++ b/src/utils/stringutils.c @@ -340,81 +340,6 @@ static bool contains_whitespace_or_quotes(const char *string) } #endif -void scratch_buffer_append_argument(const char *string) -{ - if (scratch_buffer.len != 0) scratch_buffer_append_char(' '); -#if PLATFORM_WINDOWS - if (contains_whitespace_or_quotes(string)) - { - scratch_buffer_append_double_quoted(string); - } - else - { - scratch_buffer_append(string); - } -#else - scratch_buffer_append_shell_escaped(string); -#endif -} - -void scratch_buffer_append_double_quoted(const char *string) -{ - scratch_buffer_append_char('"'); - size_t len = strlen(string); - for (size_t i = 0; i < len; ) - { - char c = string[i++]; - switch (c) - { - case '"': - scratch_buffer_append("\\\""); - continue; - case '\\': - { - int backslash_count = 1; - for (; i < len && string[i] == '\\'; i++, backslash_count++) {} - if (i == len || string[i] == '"') - { - scratch_buffer_append_char_repeat('\\', backslash_count * 2); - } - else - { - scratch_buffer_append_char_repeat('\\', backslash_count); - } - continue; - } - } - scratch_buffer_append_char(c); - } - scratch_buffer_append_char('"'); -} - -void scratch_buffer_append_shell_escaped(const char *string) -{ - char c; - while ((c = string++[0]) != '\0') - { - if ((unsigned)c < 0x80) - { - switch (c) - { - case LOWER_CHAR_CASE: - case UPPER_CHAR_CASE: - case NUMBER_CHAR_CASE: - case '_': - case '/': - case '.': - case ',': - case '-': - break; - default: - scratch_buffer_append_char('\\'); - break; - } - } - scratch_buffer_append_char(c); - } -} void scratch_buffer_append(const char *string) { scratch_buffer_append_len(string, strlen(string));