Skip to content

Instantly share code, notes, and snippets.

@unmanned-player
Last active February 25, 2025 16:53
Show Gist options
  • Save unmanned-player/f2421eec512d610116f451249cce5920 to your computer and use it in GitHub Desktop.
Save unmanned-player/f2421eec512d610116f451249cce5920 to your computer and use it in GitHub Desktop.
Actually detecting musl library
#! /bin/sh
# SPDX-License-Identifier: WTFPL
# Actually detecting musl libc.
# How it works
# -------------
#
# WARNING - This is a hack and the concept will likely change in future.
#
# We write a simple C file and have it compiled with the target compiler. The
# target compiler automatically compiles by dynamically linking against given
# libc. Now, there are 2 ways to do it. One, if host and target are the same
# (native compilation), then its as simple as executing `ldd` and getting the
# name of libc.so from it. The other way, is to run `readelf` with `-d` and grep
# out the names of all libraries its linked to. The last one is always C
# runtime.
#
# If its native compilation, we execute the libc.so (yes, by doing exec()
# because it's literally the `_start()`). And read out its contents. In case
# of cross-compiling, this won't be the case. So we run `strings` and grep out
# for 'musl libc' from it.
#
# In case of cross-compiling, this script will not generate the version numbers
# yet, but that is possible too if we look more intrusively.
# Idea
# -----
# I had asked a question on SO about how to detect various libc's in cross-
# compiling environments and another person asked similar question along those
# lines. See,
#
# Me -> https://stackoverflow.com/questions/50443164/how-to-detect-libc-name-and-version-in-cross-compiler-environments
# Other guy -> https://stackoverflow.com/questions/58177815/how-to-actually-detect-musl-libc
#
# So I decided to release this script in the hopes someone else finds a better
# way to do it. It seems SO has some strong political views that forces its
# users to see only the superficial aspects of the question instead of truly
# understanding the point of view of the question nor the research that has gone
# into it.
# Make sure to set `CROSS_COMPILE` environment variable to the right compiler
# prefix before invoking the script. See how it's used and massage the value
# accordingly.
# CROSS_COMPILE=/opt/buildroot-2020.02-rc1/output/host/bin/aarch64-buildroot-linux-musl
cat > /tmp/test.c <<- EOM
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
EOM
if [ ! -z "${CROSS_COMPILE}" ]; then
CC=${CROSS_COMPILE}-gcc
READELF=${CROSS_COMPILE}-readelf
${CC} -o /tmp/test /tmp/test.c
need_lib=$(${READELF} -d /tmp/test | grep 'NEEDED' | tail -1 | cut -d "[" -f2 | cut -d "]" -f1)
rm -f /tmp/test.c
CC_ROOT=$(dirname ${CC})/../
CC_ROOT=$(realpath ${CC_ROOT})
libc=$(find ${CC_ROOT} -name "$need_lib" -type f | head -1)
is_musl=$(strings ${libc} | grep 'musl libc')
if [ ! -z "${is_musl}" ]; then
echo '-D__MUSL__'
fi
rm -f /tmp/test /tmp/test.c
else
CC=$(which gcc)
tmpf=/tmp/musl.log
${CC} -o /tmp/test /tmp/test.c
# Detect Musl C library.
libc=$(ldd /tmp/test | grep 'musl' | head -1 | cut -d ' ' -f1)
if [ -z $libc ]; then
# This is not Musl.
rm -f ${tmpf} /tmp/test /tmp/test.c
exit 0
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} /tmp/test /tmp/test.c
echo "-D__MUSL__ -D__MUSL_VER_MAJOR__=${v_major} -D__MUSL_VER_MINOR__=${v_minor} -D__MUSL_VER_PATCH__=${v_patch}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment