How to get libtool to statically link dependencies of a shared library

589 Views Asked by At

I'm preparing some patches for libFLAC, a lossless audio codec library. In the past, libFLAC has always been provided to windows users as a single DLL, with its dependency (libogg) embedded. This was no problem when compiled with Microsoft Visual Studio.

I'm trying to patch the autotools/libtool build system to do something similar with MinGW, but I don't seem to be able to do that. I've tried the following things:

The following apparently tries to link with both static and shared libssp

LIBS="-Wl,-static -lssp" ./configure; make all V=1
[...]
libtool: link: gcc -shared  .libs/bitmath.o .libs/bitreader.o .libs/bitwriter.o .libs/cpu.o .libs/crc.o .libs/fixed.o .libs/fixed_intrin_sse2.o .libs/fixed_intrin_ssse3.o .libs/float.o .libs/format.o .libs/lpc.o .libs/lpc_intrin_sse.o .libs/lpc_intrin_sse2.o .libs/lpc_intrin_sse41.o .libs/lpc_intrin_avx2.o .libs/lpc_intrin_vsx.o .libs/md5.o .libs/memory.o .libs/metadata_iterators.o .libs/metadata_object.o .libs/stream_decoder.o .libs/stream_encoder.o .libs/stream_encoder_intrin_sse2.o .libs/stream_encoder_intrin_ssse3.o .libs/stream_encoder_intrin_avx2.o .libs/stream_encoder_framing.o .libs/window.o .libs/windows_unicode_filenames.o .libs/ogg_decoder_aspect.o .libs/ogg_encoder_aspect.o .libs/ogg_helper.o .libs/ogg_mapping.o   -L/mingw64/lib -logg -lssp  -O3 -msse2 -fstack-protector-strong -fstack-protector-strong -Wl,-static   -o .libs/libFLAC-8.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libFLAC.dll.a
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0\libssp.a(ssp.o):(.text+0xe0): multiple definition of `__stack_chk_fail'; C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/libssp.dll.a(d000009.o):(.text+0x0): first defined here

In the following try, nothing really happens: the resulting DLL still has dependency on libssp-0.dll

LDFLAGS="-Wl,-static -lssp" ./configure; make all V=1
libtool: link: gcc -shared  .libs/bitmath.o .libs/bitreader.o .libs/bitwriter.o .libs/cpu.o .libs/crc.o .libs/fixed.o .libs/fixed_intrin_sse2.o .libs/fixed_intrin_ssse3.o .libs/float.o .libs/format.o .libs/lpc.o .libs/lpc_intrin_sse.o .libs/lpc_intrin_sse2.o .libs/lpc_intrin_sse41.o .libs/lpc_intrin_avx2.o .libs/lpc_intrin_vsx.o .libs/md5.o .libs/memory.o .libs/metadata_iterators.o .libs/metadata_object.o .libs/stream_decoder.o .libs/stream_encoder.o .libs/stream_encoder_intrin_sse2.o .libs/stream_encoder_intrin_ssse3.o .libs/stream_encoder_intrin_avx2.o .libs/stream_encoder_framing.o .libs/window.o .libs/windows_unicode_filenames.o .libs/ogg_decoder_aspect.o .libs/ogg_encoder_aspect.o .libs/ogg_helper.o .libs/ogg_mapping.o   -L/mingw64/lib -logg -lssp  -O3 -msse2 -fstack-protector-strong -fstack-protector-strong   -o .libs/libFLAC-8.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libFLAC.dll.a

Next, the -static flag seems to be intercepted and compilation of shared objects is not done at all

CFLAGS="-static" ./configure; make all V=1

Finally, the last example, the -static flag is not intercepted, but compilation of shared objects is not done at all

CC="gcc -static" ./configure; make all V=1

Also, using LIBS="-l:lssp.a", which works fine with CMake, gives me the following error:

*** Warning: linker path does not have real file for library -l:libssp.a.
*** I have the capability to make that library automatically link in when
*** you link to this library.  But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with lib:libssp.a and none of the candidates passed a file format test
*** using a file magic. Last file checked: /mingw64/lib/libogg.dll.a
*** The inter-library dependencies that have been dropped here will be
*** automatically added whenever a program is linked with this library
*** or is declared to -dlopen it.

I got this to work by using make V=1, copying the used linker command and rerunning it with -static added. It seems to me this should be possible without manual intervention.

2

There are 2 best solutions below

5
Brecht Sanders On

Some older libtool files don't properly detect .dll files, for example if they are to know to know 64-bit Windows .dll file signatures.

Sometimes regenerating autoconf files with autoreconf may fix that.

If you are sure you have all the files needed (.a, .dll.a, .dll) you can change libtool to not check if these files actually exist. To do that run the following after running ./configure and before make:

sed -i.bak -e "s/\(deplibs_check_method=\"\)[^\"]*/\1pass_all/" libtool
0
ktmf On

Adding to the solution proposed by Brecht Sanders, the problem is solved by changing the libtool script after it is generated by configure. It is not a nice solution, but it does work.

Changing archive_cmds="\$CC -shared [...] to archive_cmds="\$CC -static -shared [...] enabled building of a shared library while statically linking dependencies.