c - 使用 GCC 驱动程序时,什么使静态库成为 "incompatible"?

标签 c linux gcc musl

所以我想做的是在 Ubuntu 14.04 (x86_64) 上,我想根据目前可用的最新发布的 1.1.11 版本设置 musl-libc

我所做的是:

  1. 为 GCC 安装 multilib 支持:sudo apt-get --no-install-recommends install gcc-multilib
  2. 分别为 32 位和 64 位配置库并将它们安装到单独的文件夹中:
    • CFLAGS=-m32 ./configure --prefix=$HOME/bin/musl-32-bit --disable-shared --target=i386-linux-gnu && make && make install
    • CFLAGS=-m64 ./configure --prefix=$HOME/bin/musl-64-bit --disable-shared --target=x86_64-linux-gnu

然后为了构建静态链接的 premake4,我在 premake4 生成的 Makefile 上像这样调用 GNU make:

make -j 8 CC=$HOME/bin/musl-32-bit/bin/musl-gcc ARCH=-m32 LDFLAGS="-v -static" verbose=1

这似乎在链接步骤之前起作用,它会轰炸:

Linking Premake4
$HOME/bin/musl-32-bit/bin/musl-gcc -o bin/release/premake4 intermediate/gmake__/premake.o intermediate/gmake__/os_uuid.o intermediate/gmake__/os_pathsearch.o intermediate/gmake__/os_match.o intermediate/gmake__/os_chdir.o intermediate/gmake__/os_mkdir.o intermediate/gmake__/os_stat.o intermediate/gmake__/os_getversion.o intermediate/gmake__/premake_main.o intermediate/gmake__/os_isdir.o intermediate/gmake__/string_endswith.o intermediate/gmake__/os_isfile.o intermediate/gmake__/scripts.o intermediate/gmake__/path_isabsolute.o intermediate/gmake__/os_rmdir.o intermediate/gmake__/os_getcwd.o intermediate/gmake__/os_is64bit.o intermediate/gmake__/os_copyfile.o intermediate/gmake__/lstate.o intermediate/gmake__/ltable.o intermediate/gmake__/lgc.o intermediate/gmake__/lobject.o intermediate/gmake__/lcode.o intermediate/gmake__/lmathlib.o intermediate/gmake__/lbaselib.o intermediate/gmake__/lmem.o intermediate/gmake__/lfunc.o intermediate/gmake__/lparser.o intermediate/gmake__/ldblib.o intermediate/gmake__/lzio.o intermediate/gmake__/lstrlib.o intermediate/gmake__/lvm.o intermediate/gmake__/lauxlib.o intermediate/gmake__/llex.o intermediate/gmake__/lstring.o intermediate/gmake__/ldump.o intermediate/gmake__/ldebug.o intermediate/gmake__/loadlib.o intermediate/gmake__/lopcodes.o intermediate/gmake__/linit.o intermediate/gmake__/ldo.o intermediate/gmake__/lapi.o intermediate/gmake__/liolib.o intermediate/gmake__/loslib.o intermediate/gmake__/lundump.o intermediate/gmake__/ltm.o intermediate/gmake__/ltablib.o    -v -static -L. -s -rdynamic  -lm -ldl
Using built-in specs.
Reading specs from $HOME/bin/musl-32-bit/lib/musl-gcc.specs
rename spec cpp_options to old_cpp_options
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib32/:/lib/../lib32/:/usr/lib/../lib32/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-m32' '-o' 'bin/release/premake4' '-v' '-static' '-L.' '-s' '-rdynamic' '-specs=$HOME/bin/musl-32-bit/lib/musl-gcc.specs' '-mtune=generic' '-march=i686'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 -dynamic-linker /lib/ld-musl-i386.so.1 -nostdlib -static -export-dynamic -z relro -o bin/release/premake4 -s $HOME/bin/musl-32-bit/lib/crt1.o $HOME/bin/musl-32-bit/lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L. -L$HOME/bin/musl-32-bit/lib -L /usr/lib/gcc/x86_64-linux-gnu/4.8/. intermediate/gmake__/premake.o intermediate/gmake__/os_uuid.o intermediate/gmake__/os_pathsearch.o intermediate/gmake__/os_match.o intermediate/gmake__/os_chdir.o intermediate/gmake__/os_mkdir.o intermediate/gmake__/os_stat.o intermediate/gmake__/os_getversion.o intermediate/gmake__/premake_main.o intermediate/gmake__/os_isdir.o intermediate/gmake__/string_endswith.o intermediate/gmake__/os_isfile.o intermediate/gmake__/scripts.o intermediate/gmake__/path_isabsolute.o intermediate/gmake__/os_rmdir.o intermediate/gmake__/os_getcwd.o intermediate/gmake__/os_is64bit.o intermediate/gmake__/os_copyfile.o intermediate/gmake__/lstate.o intermediate/gmake__/ltable.o intermediate/gmake__/lgc.o intermediate/gmake__/lobject.o intermediate/gmake__/lcode.o intermediate/gmake__/lmathlib.o intermediate/gmake__/lbaselib.o intermediate/gmake__/lmem.o intermediate/gmake__/lfunc.o intermediate/gmake__/lparser.o intermediate/gmake__/ldblib.o intermediate/gmake__/lzio.o intermediate/gmake__/lstrlib.o intermediate/gmake__/lvm.o intermediate/gmake__/lauxlib.o intermediate/gmake__/llex.o intermediate/gmake__/lstring.o intermediate/gmake__/ldump.o intermediate/gmake__/ldebug.o intermediate/gmake__/loadlib.o intermediate/gmake__/lopcodes.o intermediate/gmake__/linit.o intermediate/gmake__/ldo.o intermediate/gmake__/lapi.o intermediate/gmake__/liolib.o intermediate/gmake__/loslib.o intermediate/gmake__/lundump.o intermediate/gmake__/ltm.o intermediate/gmake__/ltablib.o -lm -ldl --start-group /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_eh.a -lc --end-group /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o $HOME/bin/musl-32-bit/lib/crtn.o
/usr/bin/ld: skipping incompatible $HOME/bin/musl-32-bit/lib/libc.a when searching for -lc
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
make[1]: *** [bin/release/premake4] Error 1
make: *** [Premake4] Error 2

相关行是:

/usr/bin/ld: skipping incompatible $HOME/bin/musl-32-bit/lib/libc.a when searching for -lc

现在我不明白的部分是,当我ar x libc.a(进入文件夹$HOME/bin/musl-32-bit/lib/libc) 在 musl-libc 的构建步骤中生成(见上文),它证明包含的所有对象似乎都是正确的目标体系结构(所有显示 ELF 32 位 LSB 可重定位,Intel 80386,版本 1 (SYSV),未剥离),我可以证明在发出以下命令时出现空白:

find $HOME/bin/musl-32-bit/lib -name '*.o' -exec file {} +|grep -v 'ELF 32-bit LSB  relocatable, Intel 80386, version 1 (SYSV), not stripped'

事实上,这没有输出。同样,当使用相同的方法查看构建目录时,我找不到任何不符合我预期的目标文件。

为了更好的衡量,我决定也让 objdump 告诉我更多关于 libc.a 的问题,并得出相同的结果:

objdump -a $HOME/bin/musl-32-bit/lib/libc.a|grep 'file format'|grep -v 'file format elf32-i386'

所以我的问题是双重的:

  1. 当 GCC 被要求链接静态库时,是什么将其视为“不兼容”?
  2. 我遇到的具体问题可能是什么?

第一个是我真正感兴趣的,但是对于第二个,我想与您分享解决此类问题的经验。例如,我错过了哪些验证步骤?


请注意,“原生”premake4 可以很好地构建:

make -j 8 CC=$HOME/bin/musl-64-bit/bin/musl-gcc ARCH=-m64 LDFLAGS=-static verbose=1

从将 -v 标志添加到 LDFLAGS 时的输出来看,目标似乎始终停留在 x86_64-linux-gnu。不过,我还没有想出解决这个问题的方法。

最佳答案

简而言之,musl-gcc 包装器脚本设置不太适合与 -m32 一起使用。我认为发生的事情是实际编译器在默认(64 位)模式下被 musl-gcc 调用,然后生成的目标文件与(预期的 32 位)不兼容库。

如果您将 -m32 放入生成的包装器脚本中,它可能会起作用。如果您将 -m32 放入 $CC(即 CC="gcc -m32")而不是将它在 $CFLAGS 中。

更新:正如转移到聊天的讨论中所述,可能还需要添加 -Wl,-melf_i386(由于 musl-gcc 使用的规范文件中的缺陷 不考虑 -m32 支持的包装器)但似乎仍然不够。

关于c - 使用 GCC 驱动程序时,什么使静态库成为 "incompatible"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32696841/

相关文章:

c - 链接 c 和程序集

c - 更改宏值时出现段错误

c++ - const 是谎言吗? (因为 const 可以被抛弃)

linux - 当为可执行文件设置 set-user-ID 时, `exec` 如何以及何时更改有效用户 ID

python - 如何在安装前检查 SD 卡大小并且不需要 root

android - 交叉编译 GLibC 2.24 失败并出现错误 1

c++ - 是否有用于检测 C++11x 支持的预处理器指令?

你能解释一下这个C代码吗? (创建守护程序)

c - 1到n之间素数的个数

c++ - 一个类的 VTT 是什么?