Как на самом деле обнаружить musl libc?

Команда 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


person Joshua    schedule 01.10.2019    source источник
comment
Что вы пытаетесь сделать с vfork()? Имейте в виду, что спецификация POSIX.1-2008 объявила его устаревшим, и даже до этого на него распространялись обширные ограничения.   -  person    schedule 01.10.2019
comment
@duskwuff: Перестаньте платить гигабайты за ошибки страниц каждый раз, когда я создаю двоичный файл дочернего процесса, вот что. vfork() возвращается.   -  person Joshua    schedule 01.10.2019
comment
Оставляя в стороне обсуждение vfork/fork, стоит упомянуть, что в системе, совместимой с POSIX, есть posix_spawn, которые охватывают наиболее распространенные варианты использования vfork (vfork, за которым следует exec). В этом случае posix_spawn может быть более эффективным, чем vfork, поскольку нет необходимости дублировать текущий процесс.   -  person dash-o    schedule 01.10.2019
comment
@dash-o: Нет, не может. Это был долгий тупик. Это было первое, что я попробовал.   -  person Joshua    schedule 01.10.2019
comment
Скорее хак, чем решение; рассмотрите возможность проверки GNU_SOURCE, но НЕ _GLIBC (или _GLIB_MINOR, или __GNU_LIBRARY). Вы можете поместить это в отдельный файл, который будет скомпилирован с помощью _GNU_SOURCE и определит 'my_fork'.   -  person dash-o    schedule 01.10.2019
comment
@UnmannedPlayer: Генеральный директор пытается навязать политику. Тон задается сверху.   -  person Joshua    schedule 01.03.2020


Ответы (1)


Я думаю, что это немного поздно, но вот решение:

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

Этот сценарий оболочки извлекает некоторую интересную информацию и выводит -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.

person Unmanned Player    schedule 01.03.2020
comment
Я действительно кросс-компилирую; иначе я бы уже сейчас пошел на обнаружение сломанной вилки. Хост-компьютер также не может запускать бинарные файлы musl. - person Joshua; 01.03.2020
comment
@Joshua Нет конфеты для SO. :) - person Unmanned Player; 01.03.2020