Linking SDL2 statically without pulling in X11 dynamically - static-libraries

I am using SDL2.0.12 on Ubuntu 20.04. I link statically to SDL2, adding the linker argument:
`sdl2-config --static-libs`
So far, so good.
However, the SDL static link flags pull in a slew of SDL2 dependencies, that are linked dynamically:
$ sdl2-config --static-libs
-lSDL2 -Wl,--no-undefined -lm -ldl -lasound -lm -ldl -lpthread -lpulse-simple -lpulse -lX11 -lXext -lXcursor -lXinerama -lXi -lXrandr -lXss -lXxf86vm -lwayland-egl -lwayland-client -lwayland-cursor -lxkbcommon -lpthread -lrt
Which leaves me with a slew of dynamic dependencies that may not be present on other linux distributions:
readelf -d foo | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libGL.so.1]
0x0000000000000001 (NEEDED) Shared library: [libSDL2-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libasound.so.2]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libpulse-simple.so.0]
0x0000000000000001 (NEEDED) Shared library: [libpulse.so.0]
0x0000000000000001 (NEEDED) Shared library: [libX11.so.6]
0x0000000000000001 (NEEDED) Shared library: [libXext.so.6]
0x0000000000000001 (NEEDED) Shared library: [libXcursor.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXinerama.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXi.so.6]
0x0000000000000001 (NEEDED) Shared library: [libXrandr.so.2]
0x0000000000000001 (NEEDED) Shared library: [libXss.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXxf86vm.so.1]
0x0000000000000001 (NEEDED) Shared library: [libwayland-egl.so.1]
0x0000000000000001 (NEEDED) Shared library: [libwayland-client.so.0]
0x0000000000000001 (NEEDED) Shared library: [libwayland-cursor.so.0]
0x0000000000000001 (NEEDED) Shared library: [libxkbcommon.so.0]
0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
How can I get rid of these dynamic dependencies?
For starters, how could I link statically against X11?

The SDL development libraries provided in Ubuntu have many dynamic dependencies. Even for the static libSDL2.a library.
When building SDL2 from source, you can avoid these.
For instance, to avoid a dependency on X11, you would feed it these autoconf flags:
./configure \
--enable-x11-shared \
--enable-video-x11 \
The --enable-x11-shared will actually make SDL2 link in that dependency at run-time. And not, as you may expect, link against X11 .so dependencies.

Related

cmake not including /usr/local/opt/openssl/lib

though I do
add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS})
include_directories(/usr/local/opt/openssl/include)
link_directories(/usr/local/opt/openssl/lib)
target_link_libraries(${PROJECT_NAME} ssl crypto)
the cmake generated compiler command doesn't have -L/usr/local/opt/openssl/lib and linker is terminated by
ld: library not found for -lssl
the /usr/local/opt/openssl/lib do has the libssl.dylib. Does cmake deliberately avoiding it in favour of Apples's ssl library?

gccgo -static vs -static-libgo

What is the difference between -static and -static-libgo for gccgo? The documentation doesn't seem to really shed light on what is going on:
Use the -static-libgo option to link statically against the compiled packages.
Use the -static option to do a fully static link (the default for the gc compiler).
Is -static-libgo only static linking libgo.a only? While -static is full glibc library?
Check the dynamic linkage in the generated ELFs:
gc builds statically:
$ go build hello.go
$ readelf -d hello
There is no dynamic section in this file.
gccgo links dynamically against libgo, libc etc. by default:
$ go build -compiler gccgo hello.go
$ readelf -d hello
Dynamic section at offset 0x36e0 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libgo.so.5]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
Bake libgo inside the executable, but still link dynamically to libc and friends:
$ go build -compiler gccgo -gccgoflags '-static-libgo' hello.go
$ readelf -d hello
Dynamic section at offset 0x128068 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
Link everything statically:
$ go build -compiler gccgo -gccgoflags '-static' hello.go
$ readelf -d hello
There is no dynamic section in this file.

Finding shared library dependencies when linking executable

I am attempting to cross-compile gstreamer for ARM hosts on a Ubuntu 12.04 (32-bit) build system. None of what I'm about to describe happens with the i686-linux-gnu GCC. I am compiling on Ubuntu 12.04 using this gcc:
> arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.6/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5'
--with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6
--enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/arm-linux-gnueabihf/include/c++/4.6.3 --libdir=/usr/lib
--enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes
--enable-gnu-unique-object --enable-plugin --enable-objc-gc --enable-multilib
--disable-sjlj-exceptions --with-arch=armv7-a --with-float=hard --with-fpu=vfpv3-d16
--with-mode=thumb --disable-werror --enable-checking=release --build=i686-linux-gnu
--host=i686-linux-gnu --target=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf-
--includedir=/usr/arm-linux-gnueabihf/include
--with-headers=/usr/arm-linux-gnueabihf/include
--with-libs=/usr/arm-linux-gnueabihf/lib
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
And this ld:
arm-linux-gnueabihf-ld -v
GNU ld (GNU Binutils for Ubuntu) 2.22
GCC was installed from the default Ubuntu 12.04 PPAs. When the build system gets to linking the gst-discoverer-1.0 executable, I get the following error:
/usr/lib/gcc/arm-linux-gnueabihf/4.6/../../../../arm-linux-gnueabihf/bin/ld: warning: liborc-0.4.so.0, needed by ../gst-libs/gst/video/.libs/libgstvideo-1.0.so, not found (try using -rpath or -rpath-link)
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_program_compile'
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_program_set_backup_function'
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_program_new_from_static_bytecode'
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_program_free'
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_once_mutex_lock'
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_program_take_code'
../gst-libs/gst/video/.libs/libgstvideo-1.0.so: undefined reference to `orc_once_mutex_unlock'
collect2: ld returned 1 exit status
gst-discoverer-1.0 depends on libgstvideo-1.0.so. libgstvideo-1.0.so (which was built successfully earlier in the process) has a dependency on liborc-0.4.so. Inspecting the libgstvideo-1.0.so with arm-linux-gnueabihf-readelf -a yields the following snippet:
Dynamic section at offset 0x29ed8 contains 33 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libgstbase-1.0.so.0]
0x00000001 (NEEDED) Shared library: [libgstreamer-1.0.so.0]
0x00000001 (NEEDED) Shared library: [libgobject-2.0.so.0]
0x00000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x00000001 (NEEDED) Shared library: [liborc-0.4.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000e (SONAME) Library soname: [libgstvideo-1.0.so.0]
0x0000000f (RPATH) Library rpath: [/home/test/gst/gstreamer/gstreamer/libs/gst/base/.libs:/
home/test/gst/gstreamer/gstreamer/gst/.libs:/home/test/gst/gstreamer/orc/orc/.libs]
The path to liborc-0.4.so in the RPATH entry is correct. The link line for gst-discoverer-1.0 does not contain references to liborc because it is not directly dependent on it (only indirectly dependent via libgstvideo-1.0.so). I have tried adding "-rpath-link=/home/test/gst/gstreamer/orc/orc/.libs" to my LDFLAGS, but it didn't work. Any ideas about why the cross-compile linker is not able to find a dependency of this shared library?
It seems I was on the right track, but I was passing -rpath-link to ld (using LDFLAGS on my configure line). Since it is gcc that is actually doing the linking, I need to use CFLAGS and the -Wl argument like this:
./configure CFLAGS="-Wl,-rpath=/home/test/gst/gstreamer/orc/orc/libs"
According to some, there might be a bug in the cross-linker.

gcc -g conflicts with -fPIC?

Tested under CentOS 5.1 g++ 4.1.2 and 4.6.3 and 4.7.0, they all produce same results. How do I solve this? Basically I can't build llvm with Debug build.
[hidden]$ cat x.cpp
#include <iostream>
int main() {
}
[hidden]$ g++ -c -fPIC -g x.cpp
[hidden]$ objdump -r x.o | grep R_X86_64_32 | head -10
000000000000001c R_X86_64_32 .debug_frame
0000000000000044 R_X86_64_32 .debug_frame
000000000000006c R_X86_64_32 .debug_frame
0000000000000006 R_X86_64_32 .debug_abbrev
000000000000000c R_X86_64_32 .debug_str+0x0000000000000414
0000000000000011 R_X86_64_32 .debug_str+0x00000000000007f2
0000000000000015 R_X86_64_32 .debug_str+0x000000000000017b
0000000000000029 R_X86_64_32 .debug_line
000000000000002e R_X86_64_32 .debug_str+0x0000000000000422
0000000000000034 R_X86_64_32 .debug_str+0x0000000000000607
How do I solve this?
You don't have a problem to solve (you haven't shown any signs of the problem existing).
And no, -g and -fPIC are perfectly compatible and do not conflict with each other.
These are not dynamic relocations. They will be resolved at link time. This does not break -fPIC.
Remember there are two kinds of linking, static and dynamic. Static linking is done by the compiler/linker when you compile the final program binary from the object files, and dynamic linking is done by the OS (ld-linux.so in the case of linux).
To get a list of dynamic relocations, use objdump -R. It will only work on dynamically linked binaries, however (i.e. not .o files).

g++, static initialization and -nostdlib

Compiling / linking with -nostdlib seems to prevent static initialization, even if I add my own crti.s and crtn.s with .init/.fini sections.
Are there workarounds to make g++ generate static initialization code that is inserted in .init or that I can call manually?
This is what I tried:
g++ -o test.o -c -fno-use-cxa-atexit test.cc # has _start (entry point)
# that calls _init and _main
as -o crti.o crti.s # has _init in section .init
as -o crtn.o crtn.s
g++ -o test ./crti.o test.o -nodefaultlibs -nostartfiles ./crtn.o
-nodefaultlibs alone includes static initialization code and call, but forces use of libc-_start/_init.
-nodefaultlibs -nostartfiles allows me to use my own _start / _init, but does not include code or call to static initialization.
From gcc linker docs,
-nostdlib
Do not use the standard system startup files or libraries when
linking. No startup files and only the libraries you specify will be
passed to the linker, and options specifying linkage of the system
libraries, such as -static-libgcc or -shared-libgcc, are ignored.
Hence use,
-nodefaultlibs
Do not use the standard system libraries when linking. Only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored. The standard startup files are used normally, unless -nostartfiles is used. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.
Also try,
g++ -Wl, -static
-Wl passes the next command on to the linker
-static On systems that support dynamic linking, this prevents linking with
the shared libraries. On other systems, this option has no effect.

Resources