Load shared library only if dependencies are met
Asked Answered
A

2

6

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?

Amphibious answered 28/9, 2018 at 14:32 Comment(2)
Do you build libA and libB libraries yourself or they are external?Repetitious
@Repetitious Yes libA and libB are build along with Exe, with the same compiler/ABI. They could also be static, or even part of Exe. They are libraries mainly as a way to group their dependencies (e.g. libB needs multiple CUDA libraries)Amphibious
B
5

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.

Billet answered 28/9, 2018 at 14:35 Comment(2)
In case explicit dependency on potentially missing DLL is not mandatory, one can use delay loading (see my answer for details).Repetitious
Indeed, your answer may be suitable to OP. Something similar might be achievable with custom library paths with dummy libraries in a fallback path, but it seems fragile.Billet
R
4

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.

Repetitious answered 28/9, 2018 at 15:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.