Commit e565ff305a

Andrew Kelley <andrew@ziglang.org>
2023-08-02 08:14:50
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.
1 parent 9e50f96
Changed files (2)
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
-      OUTPUT_STRIP_TRAILING_WHITESPACE)
-  string(REPLACE " " ";" LLVM_LIBRARIES "${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} --libdir ${STATIC_OR_SHARED_LINK}
-      OUTPUT_VARIABLE LLVM_LIBDIRS_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_LIBDIRS "${LLVM_LIBDIRS_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} --system-libs ${STATIC_OR_SHARED_LINK}
-      OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_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_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}")
+  endif()
+
+  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)
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();