6

musl 团队声称不需要检测 musl libc 的方法,因为它们只实现标准功能并且没有需要检测的怪癖。

直到今天,这种说法很可能是正确的,但它不再是正确的。正常功能检测不起作用,因为该功能存在但已损坏,我宁愿不对其进行探测,因为我不想在编译时要求 root 并且不允许交叉编译。该错误已通过最小化的示例代码报告,维护者根本不想修复它,也不会接受我的补丁。

我不会惩罚所有其他 libc,因为 musl 有一个损坏的功能。

从逻辑上讲我想做

#if MUSL || APPLE
    pid = fork();
#else
    pid = vfork();
#endif

我已经有了#if APPLE,因为 Mac OSX 有一个不可信的vfork().

vfork()告诉我不好是没有意义的。自 2008 年以来,情况发生了变化vfork(),无论涉及的复杂性如何,只要有可能,它都是一个更好的选择。一些资料来源:https ://gist.github.com/nicowilliams/a8a07b0fc75df05f684c23c18d7db234

4

2 回答 2

3

我想这有点晚了,但这里有一个解决方案:

#! /bin/sh

tmpf=/tmp/musl.log

# Detect Musl C library.
libc=$(ldd /bin/ls | grep 'musl' | head -1 | cut -d ' ' -f1)
if [ -z $libc ]; then
    # This is not Musl.
    rm -f ${tmpf}
    exit 1
fi
$libc >${tmpf} 2>&1
vstr=$(cat ${tmpf} | grep "Version" | cut -d ' ' -f2)

v_major=$(echo $vstr | cut -d '.' -f1)
v_minor=$(echo $vstr | cut -d '.' -f2)
v_patch=$(echo $vstr | cut -d '.' -f3)

rm -f ${tmpf}

echo "-D__MUSL__ -D__MUSL_VER_MAJOR__=${v_major} -D__MUSL_VER_MINOR__=${v_minor} -D__MUSL_VER_PATCH__=${v_patch}"

这个 shell 脚本会提取一些有趣的信息并打印出-D友好的值,以便头文件/源文件可以从中受益。看,

$ ./detect-musl.sh 
-D__MUSL__ -D__MUSL_VER_MAJOR__=1 -D__MUSL_VER_MINOR__=1 -D__MUSL_VER_PATCH__=24

请尽早在您的 Makefile 中调用它并相应地调整您的CFLAGS

该脚本执行ldd脚本,获取musl名称中包含的库,然后执行该库。所有 libc 库都是可执行的(因为它们实际上包含_start()),甚至产生输出。通常,这是版本信息。例如,GNU 显示:

$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.3.0.
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

并且, musl 显示了这一点:

$ /lib/ld-musl-x86_64.so.1 
musl libc (x86_64)
Version 1.1.24
Dynamic Program Loader
Usage: /lib/ld-musl-x86_64.so.1 [options] [--] pathname [args]

我已经在 Alpine 和 Linux Mint 上测试了我的脚本,它似乎工作正常。

和你一样,我讨厌迂腐的意识形态阻碍实用性。如果您找到更好的解决方案,请随时发布。:)

编辑:在交叉编译的情况下,ldd无法工作。在生成测试程序并读取其 ELF 链接然后检查其中是否包含musl libc字符串时,需要进行一些额外的工作。有关详细信息,请参阅GitHub片段。

于 2020-03-01T01:05:49.167 回答
2

我已经很晚了,但是我在试图找到同一个问题的答案时注意到了 musl libc 的一个特性(在我的例子中,musl 没有实现 pthread_setname_np)。当定义 _GNU_SOURCE 时,它没有在 features.h 中定义 __USE_GNU,而是使用 _GNU_SOURCE 来保护 GNU 扩展。

所以这个过程应该可以创建一个 musl libc 宏(如果另一个 libc 实现具有相同的行为或没有 libc 的人由于某种原因包含一个存根 features.h,它将产生误报;但 Glibc、uClibc 和仿生都定义了 __USE_GNU在 features.h 或 features.h 包含的另一个头文件中,当 _GNU_SOURCE 被定义时)

所以这对我有用:

#define _GNU_SOURCE
#include <features.h>
#ifndef __USE_GNU
    #define __MUSL__ 
#endif
#undef _GNU_SOURCE /* don't contaminate other includes unnecessarily */
于 2021-12-03T08:08:36.407 回答