[О блоге] [наверх] [пред] [2022-08-16 22:39:43+03:00] [6760ed109b74423e9f0ba1e5b851f5628709cfc3]

Clang с обновлённым libstdc++

За неделю мне попались две программы, в которых используется C++17
include <filesystem>, где прежде была абстракция из Boost-а. И у меня
оно не компилировалось, ибо не находит этот <filesystem>. Действительно,
при сборке используется штатный /usr/include, который у меня в системе
старый и в нём никаких <filesystem> просто ещё не было реализовано и всё
собрано на Clang 6.x ещё древнем.

Но я использую LLVM/Clang 14.x установленном через GNU Stow в ~/local,
где есть ~/local/include/c++/v1/filesystem. Пробую добавить этот путь
через -I -- ругается на то, что не может найти __config_state. Он есть в
include/x86_64-unknown-freebsd12.0/c++/v1/. Если его добавить в -I, то
дальше лавина ошибок из-за каких-то проблем с define-ами.

Под GNU GCC в GNU/Linux этот <filesystem> работает. Под виртуальной
машиной запускаю FreeBSD 13.1 с Clang-ом 13.x -- тоже всё работает, хотя
filesystem тоже под c++/v1.

Verbose показывает что при компиляции c++ (14.x) не пытается смотреть в
c++/v1 поддиректорию свою, а смотрит только в /usr/include, где старьё
сплошное, и в -I директории. Смотрю на вывод verbose под FreeBSD 13.1.
И разница только у указании "isystem" директории. Пробую повторить
полную команду "clang ... -triple x86_64-... -x c++" у себя локально, но
указывая isystem директорию ~/local/include/c++/v1. Снова падает на
невозможности найти __config_state. Скопировал его, ибо там ничего кроме
простых define-ов нет, и всё компилируется. Выходит что это не тоже
самое что просто добавление -I директории. Благо, в clang в 2019-ом году
добавили опцию -stdlib++-isystem, которая может переопределить эту
isystem.

Компилируется теперь с <filesystem> успешно, но не запускается. Уже
потому что libstdc++ не содержит всего нужного. Пришлось добавить в
LD_LIBRARY_PATH и ~/local/lib/x86_64-unknown-freebsd12.0.

Но перед этим кучу времени потратил на перекомпилирования LLVM-а, думая
что он как-то вообще не так собирает или не собирает вовсе этот
filesystem.

    [оставить комментарий]
    комментарий 0:
    From: kmeaw
    Date: 2022-08-18 17:32:07Z
    
    Не уверен, что эти способы хорошо подойдут для FreeBSD, но можно
    попробовать - на первый взгляд поддержка BSD у них есть.
    
    Можно поставить Nix в качестве пакетного менеджера, и тогда получать
    нужное окружение будет совсем легко:
    
    nix-shell -p clang_14 llvm_14
    
    Или использовать Zig в качестве C/C++-компилятора:
    
    zig c++ -target x86_64-freebsd-gnu -c -o unit.o unit.cpp
    
    Авторы Zig уже проделали работу по вендорингу различных C-библиотек, что
    позволяет, например, собрать DLL для 32-битной Windows из 64-битного
    GNU/Linux окружения, просто переключив значение -target.
    
    комментарий 1:
    From: Sergey Matveev
    Date: 2022-08-18 17:58:12Z
    
    *** kmeaw [2022-08-18 20:31]:
    >Можно поставить Nix в качестве пакетного менеджера
    
    Вот у меня нет какого-то негативного предвзятого отношения к nix, но
    теперь появилось:
    
    * сколько-то лет назад я хотел было его установить на FreeBSD. И
      когда-то поддержка этой ОС в нём была, даже был порт -- но *очень*
      старый (уже на тот момент). И тогда я не смог собрать Nix, потому что,
      насколько помню, реально были какие-то Linux-специфичные зависимости
    * решил собрать сейчас. Захожу в https://nixos.org/download.html и вижу
      что нет ни одной ссылки ни на source tarball, ни на репозиторий хотя
      бы где происходит разработка. Только curl|bash
    * скачал их install файл и вижу что действительно там установка
      предполагает только бинарно собранные вещи для ряда ОС, где нет FreeBSD
    * зайдя в https://nixos.org/guides/contributing.html, нахожу ссылку на
      https://nixos.org/manual/nix/stable/contributing/hacking.html, что
      вообще суммарно уже не одну минуту потребовало чтобы найти информацию
      о доставании исходного кода
    * клонирую, делаю ./bootstrap.sh, как они и предлагают, всё на свете
      падает потому что у меня нет bash. Честно говоря, на последний месяц я
      раз десять делал ./boostrap.sh в разных проектах (десятке проектов) и
      не встречал зависимости от bash ни разу
    * ладно, так уж и быть, ставлю из пакетов bash, снова делаю
      ./boostrap.sh, падает с:
        configure.ac:108: error: possibly undefined macro: AC_MSG_ERROR
              If this token and others are legitimate, please use m4_pattern_allow.
              See the Autoconf documentation.
      так как я вообще не возился с autoconf-ов толком, то я понятия не имею
      что это, насколько серьёзно, и уж точно не собираюсь читать по нему
      документацию
    * на этом шаге я точно не буду дальше предпринимать попыток его собрать.
      Запас терпения иссяк. И это, повторюсь, учитывая что с десяток
      проектов за прошедший месяц я собирал, где тоже приходилось делать
      bootstrap autoconf внутри них, что априори дело конечно рисковое, но
      всё отрабатывало
    
    Судя по git grep -i freebsd, вроде бы какая-то поддержка заложена в
    него, действительно. Но что прежде его не удалось собрать, что сейчас --
    крайне неприятное впечатление. И буквально пару недель назад коллега
    рассказывал что, будучи очень многолетним пользователем nix, встретился
    что при статической сборки чего-то-там обнаружил hard-coded скачивание
    бинарной сборки busybox (если не путаю), без попытки его честной сборки
    (и кэширования). Что тоже пошатнуло веру в nix у него, ибо он занимался
    как-раз созданием окружения сборки полностью независимого от Интернета,
    и тут он упорно в него лез для скачивания бинарников.
    
    >Или использовать Zig в качестве C/C++-компилятора:
    
    Вот Zig я чую что рано или поздно обязательно попробую! Ибо
    поверхностный взгляд на него мне очень понравился
    (204898c65eddc5d9ce27c309afd0bdac1720bca9). Но пока на самом деле то у
    меня проблем с LLVM/whatever то и нет. Пока было просто полное незнание
    и незнакомство с isystem концепцией, да и вообще миром C++ (который то и
    не хочу трогать, но некоторый софт уж пишется на нём, который хочется
    использовать).
    
    >Авторы Zig уже проделали работу по вендорингу различных C-библиотек, что
    >позволяет, например, собрать DLL для 32-битной Windows из 64-битного
    >GNU/Linux окружения, просто переключив значение -target.
    
    Но потребуется ещё прилично времени чтобы проверить и посмотреть что
    именно он там вообще делает и творит. Ибо сейчас стало нормой просто
    качать бинари из Интернета -- молодых модных современных программистов
    даже не посещает мысль о том, что это может быть чем-то не правильно.
    Nix например у меня сейчас относится к этой модной теме как-раз (с его
    curl|bash и отсутствием source tarball-ов, где autoconf они, как
    полагается, выполнили бы). Но автор Zig-а вроде бы разумный как-раз.
    
    комментарий 2:
    From: kmeaw
    Date: 2022-08-18 19:48:02Z
    
    Всегда ставил nix либо в составе NixOS, либо брал из пакетного менеджера
    той системы, куда нужно было его поставить. Если при этом ставилась
    старая версия, то всегда удавалось получить новую средставми самого nix.
    
    Стало интересно, откуда сам nix берёт nix. Посмотрел в nixpkgs.
    
    pkgs/tools/package-management/nix/common.nix начинается вот так:
    
    { lib, fetchFromGitHub
    , version
    , suffix ? ""
    , curl
    , sha256 ? null
    , src ? fetchFromGitHub { owner = "NixOS"; repo = "nix"; rev = version; inherit sha256; }
    , patches ? [ ]
    }:
    
    а в pkgs/tools/package-management/nix/default.nix есть такие строки:
    
      nix_2_9 = common {
        version = "2.9.1";
        sha256 = "sha256-qNL3lQPBsnStkru3j1ajN/H+knXI+X3dku8/dBfSw3g=";
    …
      stable = self.nix_2_9;
    
    Так что с воспроизводимостью всё вроде бы хорошо, и можно получить
    свежий nix на своей системе, без всяких curl|sh.
    
    > error: possibly undefined macro: AC_MSG_ERROR
    
    С autotools всё плохо, да. Я периодически смотрю, как коллега занимается
    исправлением различных костылей для того, чтобы добавить очередной пакет
    в свой дистрибутив Linux, основные фичи которого - статическая линковка
    всего (даже OpenGL) и очень небольшой набор зависимостей для bootstrap.
    
    Подсмотрел у него, что он делает для разворачивания среды "с нуля":
    
    https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bld/all/ix.sh
    https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bld/auto/archive/ix.sh
    https://git.sr.ht/~pg/ix/tree/main/item/pkgs/bin/auto/conf/archive/ix.sh
    https://git.sr.ht/~pg/ix/tree/main/item/pkgs/die/c/autohell.sh
    
    Стоит проверить, что на системе, где запускается ./bootstrap, есть
    autoconf-archive (/usr/share/aclocal/ax_*.m4 или где-то ещё в
    $ACLOCAL_PATH), m4 и pkg-config.
    
    > проверить и посмотреть что именно он там вообще делает и творит
    
    Он берёт очередную версию glibc и выделяет оттуда то, что влияет на ABI:
    https://raw.githubusercontent.com/ziglang/glibc-abi-tool/main/README.md
    
    выполняет некоторую постобработку заголовчных файлов:
    https://raw.githubusercontent.com/ziglang/zig/master/tools/process_headers.zig
    
    и кладёт результат себе в репозиторий в lib/libc, что и попадает в
    релизные тарболлы Zig. При первом использовании zig cc/c++ исходники
    нужной libc компилируются под нужную платформу и кешируются в
    $XDG_CACHE_DIR/zig/o/. Всё без хождения в интернет во время сборки,
    конечно же.
    
    комментарий 3:
    From: Sergey Matveev
    Date: 2022-08-18 21:02:37Z
    
    *** kmeaw [2022-08-18 22:47]:
    >Так что с воспроизводимостью всё вроде бы хорошо, и можно получить
    >свежий nix на своей системе, без всяких curl|sh.
    
    Ну curl|sh это вообще не вариант. Так то я верю что на 99.9% в nix всё
    делается как-раз воспроизводимо и честно, но крайне отталкивающие вещи
    тоже имеются, типа попытки собрать его из git-а. Не смотрел как сейчас,
    но коллеги говорили что там и жёстко bash он везде прописывает, что
    лично меня крайне напрягает и подобное не будет нравится. Но верю что
    многое, включая сборку, можно будет побороть. В отличии например от
    Rust -- его разработчикам у меня прям ни йоты доверия нет.
    
    Вижу что в самых свежих портах FreeBSD есть только nix 2.3.10 версии. И
    то с патчами добавляющими всякие #ifdef-ы, без которых бы у меня всё
    равно ничего не собралось из-за purely GNU/Linux-specific include-ов.
    Может быть и можно будет его обновить уже через сам nix, но точно не
    хочу пробовать.
    
    >в свой дистрибутив Linux, основные фичи которого - статическая линковка
    >всего (даже OpenGL) и очень небольшой набор зависимостей для bootstrap.
    
    Каждый пункт его README выглядит как просто идеальный пакетный менеджер.
    Здорово!
    
    >Стоит проверить, что на системе, где запускается ./bootstrap, есть
    >autoconf-archive (/usr/share/aclocal/ax_*.m4 или где-то ещё в
    >$ACLOCAL_PATH), m4 и pkg-config.
    
    Хм, не знал про существование autoconf-archive -- никогда не ставил.
    Видимо, просто везло что и без этих макросов попадались проекты.
    
    В Zig всё выглядит очень грамотно. Попробовал его собрать. Документация
    по сборке нравится. Но правда всё упало, видимо уже из-за моего зоопарка
    непонятного с LLVM и прочим, вызвавшим: https://lld.llvm.org/missingkeyfunction
    В портах FreeBSD его самая последняя версия имеется, причём вообще без
    каких-либо патчей -- но потом увидел что порт качает просто бинарную
    сборку какую-то (причина недоверия к портам).