Building a shared library created a static library instead - gcc

I am trying to build libass into a shared library with static linking under MinGW-w64. When I configure with
./configure --disable-static --enable-shared
it generates the shared library (dynamically-linked) as expected. However, when I attempt to force static linking by setting
LDFLAGS=-static
instead of generating a statically-linked shared library (.dll with no dependency), it generates a static library (.a).
I am almost certain that I have all the dependent static libraries and no error or warning message is shown in the make process.
Can anyone please shed some light on what I'm doing wrong?

libtool says No.
The package's stock autotools ltmain.sh script parses the linkage flags and
if it finds -static it will not build a shared library, just a static
one.
Which is the most it could reasonably do, because you can't statically link a shared
library. A shared library must consist entirely of Position Independent (PIC)
code or the linkage will fail, whereas a static linkage will call for the linkage
of non-PIC object files, contributed by the non-PIC standard and runtime libraries,
if nothing else.
foo.c
#include <stdio.h>
void foo(void)
{
puts("foo");
}
Build a dynamically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -o libfoo.so foo.o
$ file libfoo.so
libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), \
dynamically linked, BuildID[sha1]=1adff7204d84d138a80bc4b6f3f38211e4b42812, \
not stripped
Attempt to build a statically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -static -o libfoo.so foo.o
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/6/crtbeginT.o: \
relocation R_X86_64_32 against hidden symbol `__TMC_END__' cannot be used \
when making a shared object
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

The static lib is just an ar package.
You can use command of ar to make the pack and unpack it.

Related

Statically linking the dependencies of a shared object in linux

I'm trying to create a share object which has its own dependencies statically linked.
Here is an example:
/* File: add.c */
#include <stdio.h>
int add(int a, int b) {
printf("Adding: %d %d\n", a, b);
return a + b;
}
When I try to compile I get the following error:
$ gcc -g -shared -fPIC -o libadd.so add.c -Wl,-Bstatic -lc -Wl,-Bdynamic
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libc.a(malloc.o): relocation R_X86_64_TPOFF32 against `tcache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libc.a(libc_fatal.o): relocation R_X86_64_PC32 against symbol `_dl_pagesize' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
Running on Ubuntu 18.04.4 LTS with gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 and GNU ld (GNU Binutils for Ubuntu) 2.30.
My questions:
How can I make the above work?
Would it be an issue if 2 libcs run simultaneously (one statically linked in my shared object and one from a hypothetical executable that will link against my shared object and libc)?
I also found this article here highlighting a similar issue but without a solution.
How can I make the above work?
Normal build of libc.a does not have -fPIC. On i386, you can actually link non-PIC object files into a .so, but the result would be an .so which requires text relocations (.text of such .so can't be shared between processes).
But on x86_64 you can't (relocations only have 4 bytes in the medium memory model, and you would need to relocate .text by more than +/-2GiB).
So to make this work, you must rebuild libc.a with -fPIC.
Would it be an issue if 2 libcs run simultaneously (one statically linked in my shared object and one from a hypothetical executable that will link against my shared object and libc)?
Most things will work, but TLS may cause complications.

Fortran compile shared object which includes netcdf static library

I am trying to create a shared object in fortran, that uses the netcdf static library.
The ultimate aim is to use this shared object in R, but I think the problem starts with my makefile, so I am just focusing on this here:
In my makefile i use the following flags
'F90 = ifort
FFLAGS = -O3 -fPIC -r8 # double-precision now run in Fortran , -fpic
for creating shared object file
LDFLAGS = -lnetcdff -lnetcdf -shared #-shared, for creating a shared
object file'
I think I managed to link everything allright, (you see all my object files below in the error message), but in the next step, when creating the shared object, there is a netcdf-library specific error message:
'ifort -O3 -fPIC -r8 -o HX.so HX.o HANDLE_ERR.o GET_CLM.o INTEGRATE.o
CLIMATE.o STATE.o PARAMETERS.o CONTROL.o HYDRO.o DYNAMICS.o CARBON.o
RINGS.o INIT.o SET_PARAMS.o -lnetcdff -lnetcdf -shared
ld: /usr/local/Cluster-Apps/netcdf/4.1.3/lib/libnetcdff.a(netcdf4.o):
relocation R_X86_64_32 against `.bss' can not be used when making a
shared object; recompile with -fPIC
/usr/local/Cluster-Apps/netcdf/4.1.3/lib/libnetcdff.a: could not read
symbols: Bad value
make: *** [HX.so] Error 1'
I find 'similar' problems, but as I am not familiar with the terminology and this is my very first try in generating a shared object, I cannot follow their instructions for my problem.
You need to install the dynamic (.so) version of NetCDF, be it from your repository or by compiling it yourself. As tim18 say in the comments, it also needs to be compiled with -fPIC, and the .so version will be.

Non-GOT style relocation for executable in GCC

In GCC, if I compile something into a shared library with GCC with g++ -shared func.cpp -o libfunc.so -fPIC, internal function calls to global symbols go through GOT in this generated shared library file. But if I compile with g++ func.cpp -o libfunc.so -mcmodel=large, it will not generate GOT but instead relocate by patching with R_X86_64_64 style relocation directly.
I want this behavior for executables as well. If I compile an executable with g++ main.cpp libfunc.so -o a.out, GCC will generate GOT for any function call from main.cpp to one defined in libfunc.so. I don't want this behavior. I want R_X86_64_64 style relocation. How can I achieve that?
Executables are compiled with -fPIE by default in modern distros for security reasons. To get old behavior add -no-pie to CFLAGS/CXXFLAGS.

fail when creating shared library with libstdc++ statically linked

using gcc 4.5.1 in a 64bit x86 machine,I first create a.o as following:
g++ -fPIC -c a.cc -o a.o
then try to create liba.so as following:
g++ -static-libstdc++ -shared -W1,-soname,liba.so -o liba.so.1.0.0 a.o
but failed, with the following information:
relocation R_X86_64_32S against `vtable for __gnu_cxx::stdio_filebuf >' can not be used when making a shared object; recompile with -fPIC
I try to recompile libstdc++ library,with -fPIC added,but it failed anyway
I would expect that the static libstdc++ library was not build with -fPIC, and therefore can't be linked into a shared library.
Theoretically you could put non-PIC compiled code into a dynamic library, but it wouldn't be sharable (each program using it would have to have its own copy) so it's often not implemented.
You're going to need to link against the shared C++ library, make your own library a static library, or else rebuild libstdc++ yourself and grab the .o files from the build directory.
There is a similar question about this topic on stackoverflow, which refers to an external site about static linking of libstdc++.

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