Browse Source

cmake: use `readelf` to extract soname from shared elf library

Anonymous Maarten 1 month ago
parent
commit
c34b67250c
1 changed files with 42 additions and 26 deletions
  1. 42 26
      cmake/macros.cmake

+ 42 - 26
cmake/macros.cmake

@@ -208,9 +208,14 @@ function(target_get_dynamic_library DEST TARGET)
       endif()
     endforeach()
   else()
+    if(UNIX AND NOT APPLE)
+      find_program(READELF_BIN NAMES readelf)
+    endif()
     # 1. find the target library a file might be symbolic linking to
-    # 2. find all other files in the same folder that symbolic link to it
-    # 3. sort all these files, and select the 1st item on Linux, and last on macOS
+    # 2. if readelf is available, parse the output of `readelf -d` and output the "(SONAME)" line
+    # 3. Else:
+    #     1. find all other files in the same folder that symbolic link to it
+    #     2. sort all these files, and select the 1st item on Linux, and last on macOS
     set(location_properties IMPORTED_LOCATION)
     if(CMAKE_BUILD_TYPE)
       list(APPEND location_properties IMPORTED_LOCATION_${CMAKE_BUILD_TYPE})
@@ -228,33 +233,44 @@ function(target_get_dynamic_library DEST TARGET)
         get_target_property(library_path "${TARGET}" ${location_property})
         message(DEBUG "get_target_property(${TARGET} ${location_property}) -> ${library_path}")
         if(EXISTS "${library_path}")
-          get_filename_component(library_path "${library_path}" ABSOLUTE)
-          while (IS_SYMLINK "${library_path}")
-            read_absolute_symlink(library_path "${library_path}")
-          endwhile()
-          message(DEBUG "${TARGET} -> ${library_path}")
-          get_filename_component(libdir "${library_path}" DIRECTORY)
-          file(GLOB subfiles "${libdir}/*")
-          set(similar_files "${library_path}")
-          foreach(subfile ${subfiles})
-            if(IS_SYMLINK "${subfile}")
-              read_absolute_symlink(subfile_target "${subfile}")
-              while(IS_SYMLINK "${subfile_target}")
-                read_absolute_symlink(subfile_target "${subfile_target}")
-              endwhile()
-              get_filename_component(subfile_target "${subfile_target}" ABSOLUTE)
-              if(subfile_target STREQUAL library_path AND subfile MATCHES "${valid_shared_library_regex}")
-                list(APPEND similar_files "${subfile}")
+          if(READELF_BIN)
+            execute_process(COMMAND "${READELF_BIN}" -d "${library_path}" RESULTS_VARIABLE readelf_result OUTPUT_VARIABLE readelf_output)
+            if(readelf_output)
+              string(REGEX MATCH "\\(SONAME\\).*\\[([0-9A-Za-z_.-]+)\\]" soname "${readelf_output}")
+              if(soname)
+                set(result "${CMAKE_MATCH_1}")
+              endif()
+            endif()
+          endif()
+          if(NOT result)
+            get_filename_component(library_path "${library_path}" ABSOLUTE)
+            while (IS_SYMLINK "${library_path}")
+              read_absolute_symlink(library_path "${library_path}")
+            endwhile()
+            message(DEBUG "${TARGET} -> ${library_path}")
+            get_filename_component(libdir "${library_path}" DIRECTORY)
+            file(GLOB subfiles "${libdir}/*")
+            set(similar_files "${library_path}")
+            foreach(subfile ${subfiles})
+              if(IS_SYMLINK "${subfile}")
+                read_absolute_symlink(subfile_target "${subfile}")
+                while(IS_SYMLINK "${subfile_target}")
+                  read_absolute_symlink(subfile_target "${subfile_target}")
+                endwhile()
+                get_filename_component(subfile_target "${subfile_target}" ABSOLUTE)
+                if(subfile_target STREQUAL library_path AND subfile MATCHES "${valid_shared_library_regex}")
+                  list(APPEND similar_files "${subfile}")
+                endif()
               endif()
+            endforeach()
+            list(SORT similar_files)
+            message(DEBUG "files that are similar to \"${library_path}\"=${similar_files}")
+            if(APPLE)
+              list(REVERSE similar_files)
             endif()
-          endforeach()
-          list(SORT similar_files)
-          message(DEBUG "files that are similar to \"${library_path}\"=${similar_files}")
-          if(APPLE)
-            list(REVERSE similar_files)
+            list(GET similar_files 0 item)
+            get_filename_component(result "${item}" NAME)
           endif()
-          list(GET similar_files 0 item)
-          get_filename_component(result "${item}" NAME)
         endif()
       endif()
     endforeach()