How to actually detect musl libc?

人走茶凉 提交于 2020-06-29 05:32:14

问题


The musl team claims that there is no need of a way of detecting musl libc because they only implement standard functionality and have no quirks that need detecting.

Up until today, that claim may well have been true, but it is no longer true. Normal feature detection is not working because the feature is there but broken, I'd rather not probe for it because I don't want to demand root at compile time and disallow cross-compilation. The bug has been reported with minimized sample code, and the maintainers don't want to fix it at all, nor will they take my patch.

I am not going to penalize every other libc because musl has a broken feature.

Logically speaking I want to do

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

where I already have #if APPLE because Mac OSX has an untrustworthy vfork().

There is no point telling me vfork() is bad. The situation has changed since 2008, and vfork() is a better choice whenever possible, no matter the complexities involved. Some Source: https://gist.github.com/nicowilliams/a8a07b0fc75df05f684c23c18d7db234


回答1:


I guess this is a bit late, but here's a solution:

#! /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}"

This shell script extracts some interesting information and prints out -D friendly values so headers/source files can benefit from them. See,

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

Please invoke this early on in your Makefile and adjust your CFLAGS accordingly.

This script executes ldd script, gets the library that has musl in its name, then executes that. All libc libraries are executable (because they literally contains _start()) and even produce output. Normally, this is the version information. For example, GNU shows this:

$ /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>.

and, musl shows this:

$ /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]

I've tested my script on Alpine and Linux Mint and it seems to work fine.

Like you, I hate when pedantic ideologies hinder practicalities. If you find a better solution, please feel free to up post it. :)

Edit: In case of cross compiling, ldd can't work. There's a bit of extra work involved where you generate a test program and read its ELF links out then check if its contains musl libc string in it. See GitHub snippet for details.



来源:https://stackoverflow.com/questions/58177815/how-to-actually-detect-musl-libc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!