Does libtool strip all options with -M?

2019-08-19 08:41发布

问题:

I'm trying to track down a failure to link with a mapfile on Solaris. The missing mapfile causes the following error when I try to run our self tests:

$ ./cryptestcwd v
ld.so.1: cryptestcwd: fatal:
/export/home/cryptopp/.libs/libcryptopp.so.6: hardware capability
(CA_SUNW_HW_1) unsupported: 0x4800000  [ AES SSE4.1 ]
Killed

I've gotten as far as this Automake rule. libcryptopp_la_LINK, which I believe is the shared object, is missing AM_LDFLAGS. AM_LDFLAGS holds the -M cryptopp.mapfile option.

libcryptopp_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
    $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
    $(CXXFLAGS) $(libcryptopp_la_LDFLAGS) $(LDFLAGS) -o $@

I tried to patch it with sed after configure runs:

libcryptopp_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
    $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
    $(CXXFLAGS) $(libcryptopp_la_LDFLAGS) -M cryptopp.mapfile $(LDFLAGS) -o $@

I confirmed the sed is successful, but the same test fails again. When the commands are invoked -M <mapfile> is missing.

The libtool manual talks about -M arguments on Cygwin, but not Solaris (and the discussion only applies to GCC, and not other compilers like IBM XL C/C++, Sun C/C++ and LLVM Clang):

Note that you also need to ensure that the standard Unix directories (like /bin, /lib, /usr, /etc) appear in the root of a drive. This means that you must install Cygwin itself into the C:/ root directory (or D:/, or E:/, etc)—instead of the recommended installation into C:/cygwin/. In addition, all file names used in the build system must be relative, symlinks should not be used within the source or build directory trees, and all -M* options to gcc except -MMD must be avoided.

There is no other mention of -M.

And there is no diagnostic, like "Removing -M <mapfile> options to Sun linker" or "Warning: libtool does not understand option -M <mapfile>".

My question is, does libtool discard -M and its arguments for some reason?

回答1:

Libtool does drop some link options when creating a library. The manual explains:

When creating a shared library, but not when compiling or creating a program, libtool drops some flags from the command line provided by the user. This is done because flags unknown to libtool may interfere with library creation or require additional support from libtool, and because omitting flags is usually the conservative choice for a successful build.

Personally, I find the justification for this behavior to be a bit cavalier, and I furthermore think it warrants a warning from libtool when it occurs, but unless you care to raise an issue against it, that's pretty much moot.

Experimentation shows that -M is indeed among the options that libtool strips. In particular, if I specify LDFLAGS containing an -M option on the make command line then I can observe it echoed in the make output when it runs the libtool link, but not in libtool's own echo of the link command that is actually executed:

$ make LDFLAGS="-M mapfile"

/bin/sh ./libtool --tag=CC --mode=link gcc -g -O2 -M mapfile -o libmylib.la -rpath /usr/local/lib x.lo y.lo

libtool: link: gcc -shared -fPIC -DPIC .libs/x.o .libs/y.o -O2 -Wl,-soname -Wl,libmylib.so.0 -o .libs/libmylib.so.0.0.0

The libtool docs suggest two workarounds to pass link options that otherwise would be stripped:

  • For bona fide linker options, you can use one or more -Wl, or -Xlinker options to pass your options through libtool and the linker driver to the linker itself. For example,

    LDFLAGS=-Wl,-M,cryptopp.mapfile
    
  • For options directed specifically to the linker driver, the docs suggest adding the flags to the compiler driver command (CC="gcc -M mapfile"), but this is ineffective because the $(CC) variable is expanded by make to form the libtool command line, leaving any options expressed in it exposed to libtool for stripping.

Additionally, however, there is

  • The -XCClinker option by which options can be passed through to the linker driver (as opposed to the linker itself), but its behavior seems a bit quirky: it seems to ignore options that don't start with a hyphen (such as the name of your map file).