我有一个使用CMake构建的C / C ++项目。在尝试编译静态二进制文件时,我GLIBC在计算机和目标计算机上遇到了不同版本的问题。在关于SO的另一个问题中,对类似问题的公认答案是使用libc的替代实现,例如musl或uClibc。(请参阅此处)
我找不到有关如何指向cmake使用此类替代libc的任何信息。FindMusl.cmake文件既没有寄出,也无法在互联网上找到。简单使用CC=/usr/bin/musl-gcc是行不通的。
如何将我的cmake项目与此类替代libc实现静态链接,使其独立于GLIBC?
我有一个依赖于Hyper和Diesel的项目,因此,在本机库OpenSSL和libpq上.该项目建立在每晚Rust上,因为它使用编译器插件.
我目前的尝试是建立在Docker容器上.我有MUSL libc和库make'd并安装了前缀/usr/local/musl.我cargo使用以下命令运行:(不确定某些选项是否冗余,我不太熟悉编译器链,甚至不确定它们是否最终到链接器,但我必须尝试,对.)
LDFLAGS="-static -L/usr/local/musl/lib" \
LD_LIBRARY_PATH=/usr/local/musl/lib:$LD_LIBRARY_PATH \
CFLAGS="-I/usr/local/musl/include" \
PKG_CONFIG_PATH=/usr/local/musl/lib/pkgconfig \
cargo build --release --target=x86_64-unknown-linux-musl
Run Code Online (Sandbox Code Playgroud)
当我ldd得到的文件,它揭示了这个:
$ ldd server
linux-vdso.so.1 (0x00007fffb878e000)
libpq.so.5 => /usr/local/musl/lib/libpq.so.5 (0x00007f4d730e7000)
libssl.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f4d72e82000)
libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f4d72a85000)
libc.so => /usr/local/musl/lib/libc.so (0x00007f4d727f6000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4d725f2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4d72246000)
/lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x000055e2124a2000)
Run Code Online (Sandbox Code Playgroud)
有所有动态链接的东西,有些甚至与"x86_64-linux-gnu"链!什么地方出了错?
我可以毫无问题地制作静态链接,简单的纯Rust项目.ldd说它们是静态链接的,它们运行没有问题,不像我遇到问题的可执行文件.
当我使用--verbose与货物,我得到了下面rustc的命令,即实际编制的可执行文件:http://pastebin.com/ywv0zNBK(哎呀,这人有一个自定义的outdir和-Z print-link-args,由我添加)添加print-link-args标志,我得到了下面的链接器命令:http://pastebin.com/Aw43qd7h
我如何得到 …
musl C 库只有符号版本控制的近似实现。这可能导致具有不同符号版本的符号绑定在一起,这在完整实现中不会发生。因此,希望使用 musl 构建的项目最好完全避免符号版本控制。(不支持符号版本控制本身对于工具链来说不一定是一个糟糕的选择;这完全取决于目标受众。)
但是,Alpine Linux 工具链编译 binutils 时具有完整的符号版本支持:GAS 支持该.symver指令,链接编辑器处理版本脚本并分配符号版本(就像在 GNU/Linux 上一样)。一个简单的编译器/汇编器或链接检查显示符号版本的支持。因此,Alpine Linux 在发行版中包含的一些共享对象实际上使用了符号版本控制,尽管 musl 动态加载器会忽略这些数据。(数据只会使二进制文件膨胀。)
在某些情况下,软件无法运行(在构建正常之后),因为它以 musl 动态链接器不支持的方式使用兼容性符号(没有默认版本的符号)。这是一个不起作用的小例子:
cat > symver.c <<EOF
void
compat_function (void)
{
}
__asm__ (".symver compat_function,compat_function@SYMVER");
void
call_compat_function (void)
{
return compat_function ();
}
EOF
echo "SYMVER { };" > symver.map
cat > main.c <<EOF
extern void call_compat_function (void);
int
main (void)
{
call_compat_function ();
}
EOF
gcc -fpic -shared -o symver.so -Wl,--version-script=symver.map symver.c
gcc -Wl,--rpath=. -o main …Run Code Online (Sandbox Code Playgroud) musl 团队声称不需要检测 musl libc 的方法,因为他们只实现标准功能并且没有需要检测的怪癖。
直到今天,这种说法很可能是正确的,但它不再是正确的。正常功能检测不起作用,因为该功能存在但已损坏,我宁愿不对其进行探测,因为我不想在编译时要求 root 并禁止交叉编译。该错误已通过最小化示例代码报告,维护人员根本不想修复它,也不会接受我的补丁。
我不会惩罚所有其他 libc,因为 musl 有一个损坏的功能。
从逻辑上讲我想做
#if MUSL || APPLE
pid = fork();
#else
pid = vfork();
#endif
Run Code Online (Sandbox Code Playgroud)
我已经有了,#if APPLE因为 Mac OSX 有一个不值得信赖的vfork().
说我vfork()不好是没有意义的。自 2008 年以来,情况发生了变化vfork(),无论涉及的复杂性如何,只要有可能,这都是更好的选择。一些来源:https : //gist.github.com/nicowilliams/a8a07b0fc75df05f684c23c18d7db234
我尝试使用以下命令在ARM Cortex A7上为OpenWRT编译一个简单的.NET Core hello world 应用程序:linux-musl-arm
dotnet publish --configuration Release --runtime linux-musl-arm --self-contained
Run Code Online (Sandbox Code Playgroud)
但是当我尝试执行它时出现以下错误:
root@Routeur:~/RutxApp# ./RutxApp
Error relocating ./RutxApp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED2Ev: symbol not found
Error relocating ./RutxApp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_createERjj: symbol not found
Error relocating ./RutxApp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_assignERKS4_: symbol not found
Error relocating ./RutxApp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE10_M_replaceEjjPKcj: symbol not found
Error relocating ./RutxApp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_mutateEjjPKcj: symbol not found
Error relocating ./RutxApp: _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_appendEPKcj: symbol not found
Error relocating ./RutxApp: _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindEPKcjj: symbol not found
Error relocating ./RutxApp: _ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE5rfindEcj: symbol not found
Error relocating …Run Code Online (Sandbox Code Playgroud) 我使用 Nix 作为 Rust 程序的依赖管理器。我有以下 default.nix (简化,但有效):
rec {
pkgs = import <nixpkgs> {};
hello = pkgs.stdenv.mkDerivation rec {
name = "rust-hello";
buildInputs = [
pkgs.rustc
];
src = ./source;
buildPhase = "rustc main.rs -o rust-hello";
installPhase = ''
mkdir -p $out/bin
install -s rust-hello $out/bin
'';
};
}
Run Code Online (Sandbox Code Playgroud)
我试图将所有依赖项(包括 Rust 编译器)的 libc 覆盖为 pkg.musl,但我没有这样做。如何才能实现这一目标?
我试图弄清楚为什么 GCC 生成的二进制文件如此之大。
考虑这个空程序:
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在我使用GCC 9.2.1 20190827 (Red Hat 9.2.1-1)和glibc 2.29构建它,没有任何附加参数:
gcc -o test test.c
生成的二进制文件为 21984 字节 (~22 KB)。查看使用 生成的文件xxd,在多个地方有大量的空字节:
00000370: 006c 6962 632e 736f 2e36 005f 5f6c 6962 .libc.so.6.__lib
00000380: 635f 7374 6172 745f 6d61 696e 0047 4c49 c_start_main.GLI
00000390: 4243 5f32 2e32 2e35 005f 5f67 6d6f 6e5f BC_2.2.5.__gmon_
000003a0: 7374 6172 745f 5f00 0000 0200 0000 0000 start__.........
000003b0: 0100 0100 0100 0000 1000 0000 …Run Code Online (Sandbox Code Playgroud) 我正在尝试调试在具有 MIPS cpu 的板上远程运行的程序,使用 musl 作为其 libc。如果我在板上启动 gdbserver,设置 sysroot viaset sysroot /path/to/sysroot并从 gdb 进行实时连接,我会得到有意义的堆栈跟踪(由于 musl 缺乏 MIPS 上的 CFI 指令,而我必须添加它们,因此需要花费数小时的时间,但这是一个单独的问题),我可以看到 gdb 从libc.sosysroot 加载符号。
另一方面,如果我让该程序崩溃并生成核心转储(我曾经kill -6 <pid>强制使用一个核心转储进行测试),gdb 将从二进制文件中加载符号,但不会加载其任何共享库,甚至不会加载libc.so. 虽然其他共享库很好但不是必需的,如果没有来自 libc.so 的调试信息,gdb 无法解析堆栈跟踪,并且它们看起来都像垃圾。
$ mipsel-poky-linux-gdb -iex "set sysroot /path/to/sysroot" /path/to/testprog
GNU gdb (GDB) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute …Run Code Online (Sandbox Code Playgroud) My application is unable to handle time operations like time(2) when it runs in alpine docker container on an arm device.
What I have: I am building a native c application which is statically linked to musl with toolchain from musl.cc (arm-linux-musleabihf-gcc). I am using latest alpine container (without image tag).
How it behaves:
我有一个 Java 桌面应用程序,应该可以在 GNU Linux 发行版(Debian 和 Ubuntu)和 MUSL Linux 发行版(Alpine)中运行。我的应用程序也使用本机库,并且两种类型的 Linux 发行版的本机库构建都不同。
我会将两者与我的申请放在不同的文件夹中。因此,在运行时,Java 程序需要根据 Linux(GNU 或 MUSL)选择正确的本地库发行版。
我没有找到任何机制来了解 Java 程序中运行的是哪个 Linux 发行版 JVM。
我正在考虑从 Linux 的 /etc/ 文件夹中读取操作系统文件的一种方法。但我认为这不是一个好的解决方案(因为某些自定义构建可能会更改此细节),有人可以为这个问题建议一些更好的解决方案吗?或者如何做到这一点?