libtool 更改了 autotools 中链接器标志的顺序?

libtool changes the order of my linker flags in autotools?

我正在尝试使用 musl(对于 x86)作为我的编译器和 lighttpd 的 autotools 构建系统来静态构建 web 服务器 lighttpd(版本 1.4.49)。我的配置脚本如下:

CC=/home/musl-1.1.23/install/bin/musl-gcc CFLAGS="-g --static" LDFLAGS="-L/home/lighttpd -lwrappers -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown LIGHTTPD_STATIC=yes ./configure --prefix=/home/lighttpd/install --enable-static --disable-shared --without-zlib --disable-ipv6 --without-bzip2 --without-pcre

我在其中创建了自己的静态库“包装器”,其中包含在我的配置的 LDFLAGS 参数中指定的函数的包装定义。一切设置的方式我需要我的包装库成为第一个链接的库(甚至在 musl 的标准 c 库之前),但是 libtool 正在将我的 LDFLAGS 参数的顺序从上面更改为以下:

libtool: link: /home/musl-1.1.23/install/bin/musl-gcc -g --static -Wall -W -Wshadow -pedantic -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown -o proc_open proc_open-proc_open.o proc_open-buffer.o  -L/home/lighttpd-1.4.49 -lwrappers

而不是:

libtool: link: /home/musl-1.1.23/install/bin/musl-gcc -g --static -Wall -W -Wshadow -pedantic -L/home/lighttpd-1.4.49 -lwrappers -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown -o proc_open proc_open-proc_open.o proc_open-buffer.o

导致以下错误(我只包括了前几个,其他的都差不多):

/usr/local/bin/ld: /home/musl-1.1.23/install/lib/libc.a(syslog.o): in function `__openlog':
/home/musl-1.1.23/src/misc/syslog.c:51: undefined reference to `__wrap_socket'
/usr/local/bin/ld: /home/musl-1.1.23/install/lib/libc.a(syslog.o): in function `_vsyslog':
/usr/local/bin/ld: /home/musl-1.1.23/src/misc/syslog.c:111: undefined reference to `__wrap_send'
/usr/local/bin/ld: /home/musl-1.1.23/src/misc/syslog.c:113: undefined reference to `__wrap_send'

我很奇怪为什么会这样,因为 LDFLAGS 在其他任何地方都以正确的顺序出现:

/bin/bash ../libtool  --tag=CC   --mode=link /home/musl-1.1.23/install/bin/musl-gcc   -g --static -Wall -W -Wshadow -pedantic -module -export-dynamic -avoid-version -L/home/lighttpd -lwrappers -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown -o mod_setenv.la -rpath /home/lighttpd/install/lib mod_setenv.lo  
libtool: link: ranlib .libs/mod_scgi.a

如有任何帮助,我们将不胜感激!提前谢谢你。

LDFLAGS 不是为了库添加到 link。 libtool 尽管如此,LDFLAGS 在 link 命令中展开得太早了,这不是 autotools 特有的。

在您的情况下,libtool 似乎正在识别该错误,并且在重要的情况下,将 -L-l 选项移动到需要的位置, 对象被 link 编辑之后。 (或者至少 -l 选项需要存在,特别是对于静态 link,如果 libtool 将移动这些选项,那么移动 [=15] 是有实际原因的=] 选项。)

不幸的是,也没有其他适合您所述目的的面向用户的 Autotools 变量。将额外的库注入 link 不是 Autotools 旨在支持的用例,并且将它们注入 在 link 的开头 不太可能可行无需破解自动工具。

另一方面,您似乎误解了问题。你声称

I need my wrapped library to be the first library linked (even before musl's standard c library)

但是这...

/usr/local/bin/ld: /home/musl-1.1.23/install/lib/libc.a(syslog.o): in function `_vsyslog':
/usr/local/bin/ld: /home/musl-1.1.23/src/misc/syslog.c:111: undefined reference to `__wrap_send'

...告诉我恰恰相反:即使是来自 libc 中标准库函数内部的调用也被包装,因此包装器需要出现 last,甚至 标准库(通常是最后一个,而不是第一个)之后。* 并且由于 libwrap 可能调用标准库函数本身,您可能需要 link libc 两次。当然,这假设你真的想以这种方式搞乱标准库,这对我来说似乎不可取。

如果您正在执行动态 link 那么这将不是问题:首先不可能包装 C 库的内部调用。这向我表明,linker 的 --wrap 选项可能在设计时并未考虑到标准库的静态 linking。

我不想建立一个测试平台来验证以下内容,但如果你真的想包装 libc 自己的内部函数调用,那么这可能会起作用:... LDFLAGS="-static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown" LIBS="-L/home/lighttpd -lc -lwrappers -lc" ./configure ...

LIBS 并不是真正打算成为用户变量,这是该计划的潜在弱点。但它是 Autoconf 的标准输出变量之一,它的内容应该出现在 link 行的末尾。 configure 可以将其他库添加到 LIBS 之前,但不应添加任何内容。风险是 configure 可能会清除任何初始内容。

出现在-lwrappers之前的-lc是秘诀。通常,您不需要明确指定 -lc,但在这种情况下您需要指定,因为您需要针对 libwrappers 解析其中的一些符号,否则会过早地 linked。您还(可能)需要 link libwrappers 中的一些符号来对抗 libc。这可能是多余的,但在 libwrappers 之后再次显式 linking libc 可能是必要的,以克服 linker 不需要的聪明才智。

如果你想避免包装内部 libc 自我调用,那么你可以尝试 ... LDFLAGS="-static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown" LIBS="-L/home/lighttpd -lwrappers -Wl,--no-wrap=socket -Wl,--no-wrap=bind -Wl,--no-wrap=listen -Wl,--no-wrap=accept4 -Wl,--no-wrap=send -Wl,--no-wrap=recv -Wl,--no-wrap=shutdown" ./configure ...。那里的想法是关闭 libc 的包装(仅),但它是相当推测的,因为虽然用 no- 否定长选项是标准的 GNU 形式,但特别是 --no-wrap 选项没有记录。


*所以 libtool 的重新排序不会导致您出现的问题。事实上,如果 libtool 没有执行重新排序,那么您会遇到更多 link 错误。