[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: How to determine the filename for dlopen()



Hi,

Am 2017-11-13 13:23, schrieb wferi@niif.hu:
I'm packaging a program which wants to dlopen() some library.  It finds
this library via pkg-config (PKG_CHECK_MODULES).  How to best determine
the filename to use in the dlopen() call?  It should work cross-distro,
for cross-compilation and whatnot.  Is it always safe to use the SONAME
as the filename?

The SONAME is the right thing to do here, as that is what's encoded in
the DT_NEEDED field by the linker.

I'm currently considering something like

ld -shared -o dummy.so $(my_LIBS)
objdump -p dummy.so | fgrep NEEDED

That might work, but I'm not sure that's very stable.

I've created the following example code that works for me with libpng:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(example)
enable_language(C)

find_library(PNG_LIBRARY_FILE NAMES png)
if(PNG_LIBRARY_FILE)
  execute_process(COMMAND objdump -p "${PNG_LIBRARY_FILE}"
                  OUTPUT_VARIABLE PNG_CONTENTS)
  if (PNG_CONTENTS)
    string(REGEX MATCH "\n[ \t]*SONAME[ \t]+([^ \t\r\n]*)"
           DUMMY "${PNG_CONTENTS}")
    if (DUMMY)
set(PNG_SONAME "${CMAKE_MATCH_1}" CACHE STRING "The SONAME of the PNG library")
      message(STATUS "Got libpng soname: ${PNG_SONAME}")
    else()
message(FATAL_ERROR "Could not extract SONAME from ${PNG_LIBRARY_FILE}")
    endif()
  else()
message(FATAL_ERROR "Could not run objdump -p on ${PNG_LIBRARY_FILE}")
  endif()
else()
  message(FATAL_ERROR "Could not find -lpng")
endif()

Important:

 - This assumes that objdump -p actually works. This is basically only
   true if you use the GNU toolchain on ELF systems. If you have another
   platform then you need to call different things:

     - On Mac OS X you need to do otool -D $LIBRARY and then parse that
       (it will give you back something like (notice the newline!)

           $filename:\n$library_id_abspath

       The base name of the second line of that output is what you're
       looking for for dlopen().

     - On other UNIX platforms I don't really know.

     - On Windows with the MinGW toolchain, when you have an import
       library (*.dll.a MinGW style or *.lib Microsoft style) then you
       may use dlltool -I $IMPORTLIB to extract the DLL name from
       that. However, MinGW does support linking directly against DLLs
       in some cases (when they were also compiled with MinGW, for
       example, and fulfill some additional criteria), and it may be
       the case that your linker finds the DLL directly if no import
       library is found, in which case dlltool -I will fail, but you
       can just use the basename of the DLL.

       Note that objdump -p does work on MinGW on Windows, but doesn't
       give you a SONAME. (It does mention the DLL name multiple times,
       but I'm not sure that's easy to parse.)

     - On Windows with MSVC I have no idea how to get the DLL name
       from an import library (*.lib), but there's definitely going
       to be a tool you'll be able to use.

     - No idea on yet other operating systems.

 - I'm hacked this together and am not sure this is the sanest way of
   parsing this in CMake... YMMV.

 - CMake might only find a static library depending on how your search
   path is set up (*.a on UNIX systems including Mac OS X, as well as
   on MinGW, but *.lib on Windows system with MSVC). On Windows the
   fact that import libraries and static libraries share the same
   extension actually makes it quite difficult to handle this case
   properly.

 - If you do manage to write some relatively generic code, I would
   urge you to contribute that to CMake as a macro, so that other
   people could also profit from it.

Regards,
Christian


Reply to: