Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to actually detect musl libc?

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

like image 608
Joshua Avatar asked Oct 01 '19 03:10

Joshua


People also ask

How do you pronounce musl libc?

musl, pronounced like the word “mussel” or “muscle”, is a “libc”, an implementation of the standard library functionality described in the ISO C and POSIX standards, plus common extensions, built on top of the Linux system calls API.

Should I use glibc or musl?

For broad-based usage, things are less likely to break with glibc. For a specific use case, that may be less important. As a dangerous generalization, musl is usually lighter on resources, but glibc is faster.

What is the difference between glibc and musl?

Under musl, constructors only run the first time a library is run, and destructors only run on exit. Under glibc, the contents of all static storage in a library will be reset to its original state if the library is unloaded and reloaded. Under musl, it will never be reset.


1 Answers

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.

like image 133
Unmanned Player Avatar answered Sep 19 '22 13:09

Unmanned Player