Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load shared library only if dependencies are met

I have an executable that is linked to two shared libraries, each of which have dependencies to system shared libraries. (In this case these are the OpenCL and CUDA runtime libraries, but this does not affect the problem)

     +--> libA.so  --->  libOpenCL.so (on system)
Exe -|
     +--> libB.so  --->  libcudart.so (on system)

Exe, along with libA.so and libB.so are distributed to a user. The user may not have libOpenCL.so and/or libcudart.so installed on their system.

The goal is that Exe should be able to launch anyways, and detect at runtime that e.g. libA.so could not be loaded because its dependencies are not met.

One possibility would be to make it so that libA.so get loaded at runtime using dlopen(), where it detects if loading failed.

Is it also possible to normally link libA.so to Exe, but in a way that Exe can still launch if libA.so could not be loaded? Is this possible on Linux and/or Windows platforms?

like image 364
tmlen Avatar asked Sep 28 '18 14:09

tmlen


2 Answers

If you want to do this, you need dlopen. At program load time there is no vector for error reporting other than failure to execute, nor any reasonable choice for what the symbols intended to be found in the missing library would resolve to if they lack a definition.

like image 58
R.. GitHub STOP HELPING ICE Avatar answered Oct 23 '22 00:10

R.. GitHub STOP HELPING ICE


On Windows you can link libA and libB against potentially missing DLLs in delay-loaded mode. This will prevent runtime system from loading DLL until your program actually calls one of its functions.

Linux doesn't have delay load functionality out of the box but you can mimic it by adding dummy wrappers for functions from libOpenCL.so (or libcudart.so) into libA (or libB). Wrappers would dlopen needed libraries on first call and jump to real function implementations. Such wrappers can be written by hand or generated automatically via Implib.so:

# This will generate libOpenCL.tramp.S and libOpenCL.init.c
# which need to be linked into libA.
$ implib-gen.py libOpenCL.so

As a result libA will no longer be linked directly against libOpenCL.so and your program will run fine unless you call functions that use OpenCL.

like image 21
yugr Avatar answered Oct 23 '22 01:10

yugr