Last active
February 25, 2025 16:53
-
-
Save unmanned-player/f2421eec512d610116f451249cce5920 to your computer and use it in GitHub Desktop.
Actually detecting musl library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /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