[О блоге] [наверх] [пред] [2026-01-13 14:01:27+03:00] [8ba45603ac27c73bf48f2dafb920f174c88fe3fb]
Темы: [c]

perfect-helloworld

https://github.com/synalice/perfect-helloworld
https://www.gnu.org/software/hello/
В комментарии к d77a4c36db19e704ef1ed9e81720389e65efe916
увидел идеальный helloworld проект. Уже вроде не для стёба.
А как осовремененный пример GNU Hello World.

В нём мне много чего не нравится, даже GNU версия как-будто получше, но
если мочь закрыть глаза на autotools.

* факт использования Markdown. Не табу, но лично я никогда не стал бы
  его применять, как и многие проекты и хакеры. Мне кажется, факт
  использования MD сразу выдаёт не то чтобы опытного разраба. Впрочем,
  многим пофиг и они не придают значения формату документаций.
* Meson. Считаю ужасом факт требования Python для сборки. Впрочем,
  наверное соглашусь что уж лучше так, чем autotools. Но зачем выбирать
  среду двух как? Хотя я наверное даже посчитаю, что это лучше и чем
  CMake бы было.
* "Prioritizes Clang instead of GCC" -- не вдавался в подробности о чём
  речь. Наверное когда кросс-компиляция идёт. По идее в идеале проект
  должен быть CC-agnostic. Вызывая "cc" его не должно колебать кто стоит
  за этой командой. Хотя, если есть выбор, то я бы тоже предпочёл Clang,
  из-за tooling ему сопутствующего. Хотя это (Clang vs GCC) тоже выбор
  среди двух как. Судя по meson.build, действительно форсируется намёк
  на использование Clang.
* Nix -- значит уже не портабельно, так как Nix давно забил на не
  GNU/Linux системы.
* "MIT license" -- 499d8afd7741e9056f0d4c9f969386f49a6a293f, такой
  лицензии не было.
* "GitHub Actions" -- Microsoft централизованная штука, без IPv6,
  соблюдающая санкции и всякую цензуру. Не портабельно. Но... автор
  вправе тестировать это всё на чём хочет, его выбор.
* Разделение src и include? Лютейшая ненависть. Глупейшая вещь.
  Добавляющая геморрой.
* Doxygen. Лучше чем ничего, чем никакой бы документации не было. Но
  (уже субъективно) он же ужасен! Но сильных аргументов против не могу с
  ходу привести, сам я его не использовал (только чуть правил доку и
  собирал).
* Генерирование .pc файлов -- вот тут однозначно приветствую!
  Собственно, pkgconf + redo и является на 90%+ заменой autotools.
* Unity test framework -- ничего не могу сказать. Пишут что ANSI C, что
  хорошо. Я везде использую libtap для TAP-протокола тестирования,
  который по сути ничего кроме стандартизованного вывода и не помогает
  делать. Для shell кода -- поклонник sharness.

clang-format, clang-tidy -- одобряю, сам использую. Закоммитить их
конфигурационные файлы в репозиторий -- правильно, чтобы у других была
общая точка отсчёта. Это создаст проблемы тем, кто не использует Clang
toolchain, но и с GCC бы было обратное верно. Что-то же надо использовать.

IWUY -- тоже использую эту штуку. Хотя она частенько "сбоит" и колбасит.
Но всё равно с ней лучше чем без.

cppcheck -- недавно стал тоже использовать, увидев что она может
находить реальные недостатки в коде, которые не обнаруживаются clang-*.

REUSE -- вообще впервые вижу. Очередная штука про метаинформацию о
copyright и условиях распространения. Честно говоря, вообще не
вчитывался ни в SPDY, ни во что-то подобное. Кому это может помочь? Это
по сути всё нужно для конечного человеческого существа: а для него, как
многие проекты и делают, достаточно arbitrary текстом написать что всё
под XXX, но вот эти файлы под YYY или сам читай чего в них. Фатальнее
будет ошибка в метаинформации, как по мне. Но тут у меня никакого
сильного мнения нет.

jq -- форматировать JSON это хорошо. Лично я предпочитаю gojq, так как
на Go и куда быстрее собирается и минималистичнее. jq в последних
версиях стал каким-то громоздким. Но это вопрос избыточности инструмента.

Есть скрипты на bash -- лютое нет, табу. У нас во многих проектах
(особенно которые перешли с autotools/Makefile/etc) на bash строгий
запрет, как когда-то был джихад на эту тему в Debian и ALT Linux. Не
портабельно, на пустом месте требует кусок говна ставить в систему.

.envrc -- категорически не понимаю людей, которые используют эту an
enormously overengineered штуку. Блин, ну ведь все задачи (99% на 100%)
можно бы было покрыть банальными autoenv штуками написанными на *shell.
37a5f6e79cff402f892ba9b0f9d5aa52890b7e8f. И не уверен что это стоит
коммитить, но возможно именно .envrc ещё нормально.

.vscode -- фу блин, поощрать использование этого? Плюс, это же наверное
равносильно помещению .vimrc в репозиторий? Это точно должны быть личные
настройки предпочтения пользователя, не место в репе.

Не понял смысла в наличии полной копии "MIT" лицензии и в директории и в
файле. Впервые такое вижу.

    enum PERFECT_HELLOWORLD_RESULT {
        PERFECT_HELLOWORLD_RESULT_OK = 0,          //!< Success.
        PERFECT_HELLOWORLD_RESULT_STDOUT_IO_ERROR, //!< Failure.
    };

Я вот себе перестал позволять делать нулевое значение чем-то валидным.
Нуль должен быть чем-то невалидным или failure. Очистил ты память, в ней
нули -- и по умолчанию они будут интерпретироваться как успешное
значение, которое нечаянно может "прососаться" дальше по коду на выход
функции. Например при проверке криптографической подписи -- success
должен явно выставлять как-то руками/кодом, не должен быть значением по
умолчанию.

В Meson вижу намёк на использование Ninja. Ещё одна зависимость, но уж
лучше она, чем тянуть GNU Make. А ещё лучше, конечно же, делать POSIX
Makefile, который бы уже обработался везде. Но если проект здоровый, то
ninja реально шустро работает.

А вообще для сборки нужно и Python тянуть (Meson), и C++ (Doxygen,
ninja). Не очень понял зачем тянуть pkg-config (причём лично я бы тащил
pkgconf, куда более компактный) для сборки. Возможно это тащится модуль
для Meson, для генерирования .pc файла. Тогда ok. В общем, не мало всего.

    #!/usr/bin/env bash
    set -o errexit
    set -o nounset
    set -o pipefail
    for file in "$@"; do
      out="$file.fmt"
      if jq . "$file" >"$out"; then
        mv "$out" "$file"
      else
        rm -f "$out"
        exit 1
      fi
    done

Молчу про bash (выжигать просто!), но зачем так сложно то всё? За
строчки кода платят? Выставляется pipefile, а pipe-ов нет. Не будет
работать с файлами с пробелом в имени. А если на это автор готов забить,
что я тоже считаю допустимым во многих случаях типа этого, то зачем
париться с кавычками вокруг остальных переменных?. Я бы сделал так:

    #!/bin/sh -e
    tmp=$(mktemp fmt.XXXXXX)
    trap "rm -f $tmp" HUP INT QUIT TERM EXIT
    while [ $# -ne 0 ] ; do
        jq . "$1" >$tmp
        mv $tmp "$1"
        shift
    done

Но, правда, mktemp делает права доступа 600, а исходный файл мог
наверняка быть с 644. Это я у себя использую по умолчанию umask 077,
но по умолчанию все известные мне дистрибутивы и ОС имеют 022.

"Скопировать" права доступа уже не тривиально. stat на всех ОС полностью
ведёт себя по разному (разный вывод, разные аргументы). GNU chmod умеет
--reference, но не BSD версия. Как всегда, простейшим портабельным
решением я вижу использование Perl, который в преобладающем большинстве
случаев будет в системе. Или написать скрипт на zsh, где тоже есть
портабельные аналоги команд.

    perl -e 'my $perm = (stat "'$1'")[2] & 07777; chmod($perm, '$tmp');'

Ну и закрываю глаза на отсутствие (f)sync вызова, что в этой задаче
считаю допустимым.

    [оставить комментарий]