From e565ff305ae208b15058a462d348fde515b3e950 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 1 Aug 2023 23:14:50 -0700 Subject: [PATCH] CLI: revert -l behavior chicken out and make -l match the status quo behavior, where it looks for dynamic libraries and then falls back to static libraries. library resolution is still done in the CLI now though, and these options are added: -search_static_first Search for static libs in all library search paths, then dynamic libs. -search_dylibs_only Only search for dynamic libs. -search_static_only Only search for static libs. this matches the already existing options below: -search_paths_first For each library search path, check for dynamic lib then static lib before proceeding to next path. -search_dylibs_first Search for dynamic libs in all library search So, it is still possible to get the strict behavior by passing `-search_dylibs_only` or `-search_static_only`. This commit also makes -dynamic and -static affect the preferred link mode and search strategy. --- cmake/Findllvm.cmake | 78 +++++++++++++++++++++++++++++------------ src/main.zig | 82 ++++++++++++++++++++++++-------------------- 2 files changed, 102 insertions(+), 58 deletions(-) diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake index bbf01f9563..28e2382e93 100644 --- a/cmake/Findllvm.cmake +++ b/cmake/Findllvm.cmake @@ -52,8 +52,6 @@ if(ZIG_USE_LLVM_CONFIG) set(STATIC_OR_SHARED_LINK "--link-shared") elseif (ZIG_STATIC_LLVM) set(STATIC_OR_SHARED_LINK "--link-static") - else() - set(STATIC_OR_SHARED_LINK "") endif() execute_process( @@ -105,31 +103,69 @@ if(ZIG_USE_LLVM_CONFIG) break() endwhile() + if(ZIG_SHARED_LLVM OR ZIG_STATIC_LLVM) + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --libfiles ${STATIC_OR_SHARED_LINK} + OUTPUT_VARIABLE LLVM_LIBRARIES_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBRARIES "${LLVM_LIBRARIES_SPACES}") - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --shared-mode ${STATIC_OR_SHARED_LINK} - OUTPUT_VARIABLE LLVM_LINK_MODE - OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --libdir ${STATIC_OR_SHARED_LINK} + OUTPUT_VARIABLE LLVM_LIBDIRS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --libfiles ${STATIC_OR_SHARED_LINK} - OUTPUT_VARIABLE LLVM_LIBRARIES_SPACES + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs ${STATIC_OR_SHARED_LINK} + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --shared-mode ${STATIC_OR_SHARED_LINK} + OUTPUT_VARIABLE LLVM_LINK_MODE OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_LIBRARIES "${LLVM_LIBRARIES_SPACES}") + else() + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --libs + OUTPUT_VARIABLE LLVM_LIBRARIES_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBRARIES "${LLVM_LIBRARIES_SPACES}") - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --libdir ${STATIC_OR_SHARED_LINK} - OUTPUT_VARIABLE LLVM_LIBDIRS_SPACES + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --libdir + OUTPUT_VARIABLE LLVM_LIBDIRS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") + + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --shared-mode + OUTPUT_VARIABLE LLVM_LINK_MODE OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") + endif() - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --system-libs ${STATIC_OR_SHARED_LINK} - OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + if (${LLVM_LINK_MODE} STREQUAL "shared") + # We always ask for the system libs corresponding to static linking, + # since on some distros LLD is only available as a static library + # and we need these libraries to link it successfully + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs --link-static + OUTPUT_VARIABLE LLVM_STATIC_SYSTEM_LIBS_SPACES + ERROR_QUIET # Some installations have no static libs, we just ignore the failure + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_STATIC_SYSTEM_LIBS "${LLVM_STATIC_SYSTEM_LIBS_SPACES}") - set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS}) + set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS} ${LLVM_STATIC_SYSTEM_LIBS}) + else() + set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS}) + endif() execute_process( COMMAND ${LLVM_CONFIG_EXE} --includedir @@ -337,4 +373,4 @@ endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(llvm DEFAULT_MSG LLVM_LIBRARIES LLVM_INCLUDE_DIRS) -mark_as_advanced(LLVM_INCLUDE_DIRS LLVM_LIBRARIES LLVM_LIBDIRS LLVM_LINK_MODE) +mark_as_advanced(LLVM_INCLUDE_DIRS LLVM_LIBRARIES LLVM_LIBDIRS) diff --git a/src/main.zig b/src/main.zig index bd306fa49e..8327659a6f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -482,6 +482,10 @@ const usage_build_generic = \\ lib then static lib before proceeding to next path. \\ -search_dylibs_first Search for dynamic libs in all library search \\ paths, then static libs. + \\ -search_static_first Search for static libs in all library search + \\ paths, then dynamic libs. + \\ -search_dylibs_only Only search for dynamic libs. + \\ -search_static_only Only search for static libs. \\ -T[script], --script [script] Use a custom linker script \\ --version-script [path] Provide a version .map file \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) @@ -878,8 +882,8 @@ fn buildOutputType( var hash_style: link.HashStyle = .both; var entitlements: ?[]const u8 = null; var pagezero_size: ?u64 = null; - var lib_search_strategy: ?SystemLib.SearchStrategy = null; - var lib_preferred_mode: ?std.builtin.LinkMode = null; + var lib_search_strategy: SystemLib.SearchStrategy = .paths_first; + var lib_preferred_mode: std.builtin.LinkMode = .Dynamic; var headerpad_size: ?u32 = null; var headerpad_max_install_names: bool = false; var dead_strip_dylibs: bool = false; @@ -1111,6 +1115,15 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-search_dylibs_first")) { lib_search_strategy = .mode_first; lib_preferred_mode = .Dynamic; + } else if (mem.eql(u8, arg, "-search_static_first")) { + lib_search_strategy = .mode_first; + lib_preferred_mode = .Static; + } else if (mem.eql(u8, arg, "-search_dylibs_only")) { + lib_search_strategy = .no_fallback; + lib_preferred_mode = .Dynamic; + } else if (mem.eql(u8, arg, "-search_static_only")) { + lib_search_strategy = .no_fallback; + lib_preferred_mode = .Static; } else if (mem.eql(u8, arg, "-headerpad")) { const next_arg = args_iter.nextOrFatal(); headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -1136,8 +1149,8 @@ fn buildOutputType( // -l always dynamic links. For static libraries, // users are expected to use positional arguments // which are always unambiguous. - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .no_fallback, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "--needed-library") or mem.eql(u8, arg, "-needed-l") or @@ -1147,15 +1160,15 @@ fn buildOutputType( try system_libs.put(next_arg, .{ .needed = true, .weak = false, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .no_fallback, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) { try system_libs.put(args_iter.nextOrFatal(), .{ .needed = false, .weak = true, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .no_fallback, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-D")) { try clang_argv.append(arg); @@ -1388,8 +1401,12 @@ fn buildOutputType( emit_implib_arg_provided = true; } else if (mem.eql(u8, arg, "-dynamic")) { link_mode = .Dynamic; + lib_preferred_mode = .Dynamic; + lib_search_strategy = .mode_first; } else if (mem.eql(u8, arg, "-static")) { link_mode = .Static; + lib_preferred_mode = .Static; + lib_search_strategy = .no_fallback; } else if (mem.eql(u8, arg, "-fdll-export-fns")) { dll_export_fns = true; } else if (mem.eql(u8, arg, "-fno-dll-export-fns")) { @@ -1541,22 +1558,22 @@ fn buildOutputType( // -l always dynamic links. For static libraries, // users are expected to use positional arguments // which are always unambiguous. - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .no_fallback, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-needed-l")) { try system_libs.put(arg["-needed-l".len..], .{ .needed = true, .weak = false, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .no_fallback, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-weak-l")) { try system_libs.put(arg["-weak-l".len..], .{ .needed = false, .weak = true, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .no_fallback, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-D")) { try clang_argv.append(arg); @@ -1632,7 +1649,6 @@ fn buildOutputType( var emit_llvm = false; var needed = false; var must_link = false; - var force_static_libs = false; var file_ext: ?Compilation.FileExt = null; while (it.has_next) { it.next() catch |err| { @@ -1702,22 +1718,12 @@ fn buildOutputType( .must_link = must_link, .loption = true, }); - } else if (force_static_libs) { - try system_libs.put(it.only_arg, .{ - .needed = false, - .weak = false, - .preferred_mode = .Static, - .search_strategy = .no_fallback, - }); } else { - // C compilers are traditionally expected to look - // first for dynamic libraries and then fall back - // to static libraries. try system_libs.put(it.only_arg, .{ .needed = needed, .weak = false, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .paths_first, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } }, @@ -1814,13 +1820,15 @@ fn buildOutputType( mem.eql(u8, linker_arg, "-dy") or mem.eql(u8, linker_arg, "-call_shared")) { - force_static_libs = false; + lib_search_strategy = .no_fallback; + lib_preferred_mode = .Dynamic; } else if (mem.eql(u8, linker_arg, "-Bstatic") or mem.eql(u8, linker_arg, "-dn") or mem.eql(u8, linker_arg, "-non_shared") or mem.eql(u8, linker_arg, "-static")) { - force_static_libs = true; + lib_search_strategy = .no_fallback; + lib_preferred_mode = .Static; } else if (mem.eql(u8, linker_arg, "-search_paths_first")) { lib_search_strategy = .paths_first; lib_preferred_mode = .Dynamic; @@ -1939,8 +1947,8 @@ fn buildOutputType( .weak_library => try system_libs.put(it.only_arg, .{ .needed = false, .weak = true, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .paths_first, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }), .weak_framework => try frameworks.put(gpa, it.only_arg, .{ .weak = true }), .headerpad_max_install_names => headerpad_max_install_names = true, @@ -2240,22 +2248,22 @@ fn buildOutputType( try system_libs.put(linker_args_it.nextOrFatal(), .{ .weak = false, .needed = true, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .paths_first, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.startsWith(u8, arg, "-weak-l")) { try system_libs.put(arg["-weak-l".len..], .{ .weak = true, .needed = false, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .paths_first, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-weak_library")) { try system_libs.put(linker_args_it.nextOrFatal(), .{ .weak = true, .needed = false, - .preferred_mode = lib_preferred_mode orelse .Dynamic, - .search_strategy = lib_search_strategy orelse .paths_first, + .preferred_mode = lib_preferred_mode, + .search_strategy = lib_search_strategy, }); } else if (mem.eql(u8, arg, "-compatibility_version")) { const compat_version = linker_args_it.nextOrFatal();