- Dynamically linking from a static libarary?
- dlopen a dynamic library from a static library linux C++
- 1 Answer 1
- Link Static/Dynamic Library in C/C++ on Linux
- Link Static/Dynamic Library in C/C++ using GCC Compiler
- Static Library
- Dynamic Link Library
- Calling C++ Shared Library from Python Code
- Convert Static Lib to Dynamic
- 1 Answer 1
Dynamically linking from a static libarary?
I’m currently attempting to rebuild FlightGear on my Ubuntu 14.04 machine. Everything went smoothly until I decided to build fgrun which requires Qt. I decided to compile Qt as a static library since I didn’t want self-built libraries overrunning any on the system. I statically built Qt on the system like so:
./configure -static -opensource -nomake tests -gtkstyle -prefix /home/user/Qt/5.4/Src/qtbuild -no-rpath -no-compile-examples -system-proxies -skip qtwebkit -skip qtwebkit-examples -nomake tools -nomake examples -skip script -release -skip multimedia -verbose -l dl -skip location -skip multimedia -skip quick1 -skip quickcontrols -skip sensors -skip serialport -skip svg -skip tools -skip translations -skip wayland -skip webchannel -skip webengine -skip xmlpatterns -skip activeqt -skip connectivity -skip declarative -skip doc -skip enginio -skip graphicaleffects -skip imageformats -skip websockets
I showed FlightGear’s CMake where to find the libraries and everything appeared fine until the final linking stage:
Linking CXX executable fgfs /usr/bin/ld: /home/user/Qt/5.4/Src/qtbuild/lib/libQt5Core.a(qlibrary_unix.o): undefined reference to symbol 'dlclose@@GLIBC_2.2.5' /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libdl.so: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status
Now, I’ve run into this issue before and it was a matter of not linking the the dynamic linker library via -ldl . However, I’ve ensured that both Qt and FlightGear are built with the -ldl flag, yet I still get this error. So now, this begs the question in my mind: is it even possible to dynamically link from a static library? I would imagine that -ldl would have to be included in the static library which would be a Bad Idea, is this correct?
dlopen a dynamic library from a static library linux C++
I’ve a linux application that links against a static library (.a) and that library uses the dlopen function to load dynamic libraries (.so) If I compile the static library as dynamic and link it to the application, the dlopen it will work as expected, but if I use it as described above it won’t. Can’t a static library uses the dlopen function to load shared libraries? Thanks.
1 Answer 1
There should be no problem with what you’re trying to do:
#include "staticlib.h" #include "stdio.h" int main()
#ifndef __STATICLIB_H__ #define __STATICLIB_H__ int doSomethingDynamicish(); #endif
#include "staticlib.h" #include "dlfcn.h" #include "stdio.h" int doSomethingDynamicish() < void* handle = dlopen("./libdynlib.so",RTLD_NOW); if(!handle) < printf("could not dlopen: %s\n",dlerror()); return 0; >typedef int(*dynamicfnc)(); dynamicfnc func = (dynamicfnc)dlsym(handle,"GetMeANumber"); const char* err = dlerror(); if(err) < printf("could not dlsym: %s\n",err); return 0; >return func(); >
gcc -c -o staticlib.o staticlib.c ar rcs libstaticlib.a staticlib.o gcc -o app app.c libstaticlib.a -ldl gcc -shared -o libdynlib.so dynlib.c
First line builds the lib
second line packs it into a static lib
third builds the test app, linking in the newly created static, plus the linux dynamic linking library(libdl)
fourth line builds the soon-to-be-dynamically-loaded shared lib.
./app and the magic number is: 1337
Link Static/Dynamic Library in C/C++ on Linux
Link Static/Dynamic Library in C/C++ using GCC Compiler
Static Library
A static library is basically an archive (like a zip file) of object files, which are compiled from the .c/.cpp source code.
(The -c switch means: Compile and assemble, but do not link.)
Thus, we get two files test1.o and test2.o.
Now, we can use ar to put these object files together into a single static library.
ar rsv testlib.a test1.o test2.o
Now the testlib.a contains test1.o and test2.o.
gcc -o test.out test.c testlib.a
Alternatively, you could use the explicity linking options to link the static library (-L switch specifies the static library path and -l followed by the name of the static library):
gcc -o test.out test.c -L. -ltestlib
The static library is distributed with a function declaration header files .h, so that you know how to invoke them and the compiler takes care of them e.g. linking .a static libraries into your executables.
Dynamic Link Library
The Dynamic Link Library (DLL) is stored separately from the target application and shared among different applications, compared to Static Library. The DLL is the file extension on Windows while on Linux, it is *.so (Shared Object).
The .so/.dll can be loaded right before the application starts or during the application’s runtime. On Windows, the Win32 API LoadLibrary is used while on Linux gcc compiler, the dlopen function is used.
gcc -shared -o libhello.so -fPIC hello.c
g++ Application.cpp -o Application -I/home/wjw/dev/Youtube/OpenGL/Dependencies/GLFW/include -L/home/wjw/dev/Youtube/OpenGL/Dependencies/GLFW/lib -lglfw
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/dev/Youtube/OpenGL/Dependencies/GLFW/lib
Calling C++ Shared Library from Python Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// https://helloacm.com
extern «C»
{
// A function adding two integers and returning the result
int SampleAddInt(int i1, int i2)
{
return i1 + i2;
}
// A function doing nothing 😉
void SampleFunction1()
{
// insert code here
}
// A function always returning one
int SampleFunction2()
{
// insert code here
return 1;
}
}
g++ -Wall -O3 -shared TestLib.c -o TestLib.so
#!/usr/bin/python
import ctypes
def main():
TestLib = ctypes.cdll.LoadLibrary(‘/home/wjw/misc/cpp_static_dynamic_lib/TestLib.so’)
print(TestLib.SampleAddInt(1, 2))
if __name__ == ‘__main__’:
main()
Convert Static Lib to Dynamic
I have a libsomething.a file which is a static library with all dependencies included. I need to be able to import this in Python as it is a Python C library. According to this, it is not possible to use a static library as a CPython library. How can I take my .a file and make it a .so , keeping all static dependencies baked in? Background: I am using Crowbar to build a CPython shared library which can be called from Python in AWS Lambda. Until now, it has worked flawlessly, but as soon as I added in dependencies which require OpenSSL, I get linker problems when running the code in Lambda. The issue here is that the Amazon Linux image that is used to execute code has an ancient OpenSSL version. I have recreated the runtime environment, but the issue is that the old version of OpenSSL no longer exists in Amazon’s yum repository. This means that installing openssl-devel pulls down OpenSSL 1.0.2k, where in the runtime the version of OpenSSL provided is 1.0.1. This results in linking failing at runtime in Lambda. Therefore, I need a way to build a (mostly) statically linked shared library. The only shared libraries I want my SO to link from are libc and the kernel, with everything else statically compiled in. In the Lambda execution environment, LD_LIBRARY_PATH is set to /usr/lib64:/lib64:./lib , so anything in the lib folder will be loaded, but only as a last result, and if I link against OpenSSL, I get the wrong version every time. In Rust, I have the option of producing liblambda.a or liblambda.so , a static or a shared library. I’m assuming that producing a *.a and then converting into a shared library only linking to glibc and kernel dependencies.
1 Answer 1
No, you cannot do that conversion from static library to shared one (at least not in practice). Read How To Write Shared Libraries by Drepper.
One of the main reason is that shared libraries want (that it nearly need) to have position independent code (which static libraries usually don’t have).
However, on Linux most libraries are free software. So why don’t you recompile your library from source code into a shared library?
(you might perhaps recompile that specific version of OpenSSL from source)