Skip to content

"Trying to link with static lib archive"

pahaze edited this page Jan 21, 2023 · 2 revisions

Problem

The following message appears in the build log ("uuid" can be any library name):

*** Warning: linker path does not have real file for library -luuid.
*** 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 libuuid and none of the candidates passed a file format test
*** using a file magic. Last file checked: /home/lxe/Code/mxe-shared/usr/armv7-w64-mingw32/lib/libuuid.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.

*** Since this library must not contain undefined symbols,
*** because either the platform does not support them or
*** it was explicitly requested with -no-undefined,
*** libtool will only create a static version of it.

The build fails (or at least fails to produce a DLL, which fails installation anyway).

Analysis

The issue isn't with the component currently being built, but with one of its dependencies that has produced a static-only build. A static library can be linked to an executable without issues because only one executable can be linked at a time. If a static library is linked into a shared library and an executable, or two shared libraries, these binaries can coexist in the same process space and a symbol definition conflict will arise. It MAY be harmless if the conflicting symbols represent identical code or identical readonly data, but fatal otherwise (e.g. you don't want the same static variable to reside at several different memory locations).

To resolve the "diamond dependency" situation correctly, GNU libtool only allows shared (so/dll) dependencies between shared libraries.

Solution

Examine the component that creates the dependency in question. Let's say it's src/libuuid.mk that produces a libuuid.a artifact.

MXE provides a MAKE_SHARED_FROM_STATIC definition. Add the following line in src/libuuid.mk (the path needs to be the actual path to the static library -- $(BUILD_DIR) should be preferred, but you can copy whatever $(INSTALL) uses, for simplicity):

$(if $(BUILD_SHARED), $(MAKE_SHARED_FROM_STATIC) '$(1)/libuuid.a',)

If you need to pass library dependencies to the linker, you can add any linker flags to the command line, directly or via pkgconfig. E.g.:

$(if $(BUILD_SHARED), $(MAKE_SHARED_FROM_STATIC) '$(1)/libuuid.a',) \
    `$(TARGET)-pkg-config --libs-only-l u_impl i_impl d_impl`)

The macro links and installs the shared library — you don't need to issue a separate $(INSTALL) for it.

Implementation notes

MAKE_SHARED_FROM_STATIC is defined in the root Makefile and calls tools/make-shared-from-static internally.

Validity

The information in this article was true as of commit 68cd8de8e5f92983099daba0f153508f41a5f875 ("Merge pull request #13").