Что: 17aa5a765f6ab4a81dc3e14bf8ecdcd5a88ac820
Когда: 2022-09-29 22:59:47+03:00
Темы: c redo
autoconf vs redo Количество проектов на Си на работе плодится. И в них я использую redo вместо Make и autoconf. Вообще конечно абсолютно некорректно сравнивать redo и autoconf, ибо у них по сути не пересекающиеся задачи, но autoconf это же ведь множество задач/целей, результат выполнения которых используется, по сути, как зависимость для команд сборки. И кучу всяких детектов как-раз можно описывать в виде redo целей. Но об этом уже писал в 401c0f635a1cdfb01068a48a4cdf40791d3db458. Если в autoconf нужно знать как этот сам framework, так ещё и основы M4, то в redo ничего не нужно дополнительно: что хочешь, то и используй. Нужно Си программу проверяющую работоспособность чего то? Делаешь цель, которая может зависеть от уже имеющихся детектов флагов, компиляторов, других команд, которая соберёт что нужно. Распараллеливание всех этих детектов из коробки (ведь известно, что ./configure может выполняться существенно дольше чем вообще вся сборка программы после него). Сегодня понял про другой плюс: redo-log команда может показать вывод связанный только и только с заданной целью. Если ./configure падает, то это очень не тривиально найти место даже самого последнего падения в config.log, ибо в конце там вывод далеко не последнего детекта. Пока просматривал свою старую запись про замену autoconf, то удивился что ещё проще у меня многое стало. Я полностью избавился от redo-stamp. Я приводил пример с conf/cmd/cc.do целью, где основное содержание было: echo "${CC:-`command -v cc`}" > $3 command -v redo-stamp > /dev/null || exit 0 redo-stamp < $3 а теперь это conf/cmd/default.do: envname=`echo "$1" | tr a-z A-Z | tr - _` eval echo '${'$envname':-`command -v '$1'`}' который применим к любой команде (это default цель), которую и через или переменные окружения или config-файл в корне можно переопределить. В моём прошлом примере было упоминание pkg-config-based цели. Но на практике регулярно pkg-config нужен не только для определения одной библиотеки и все эти цели идентичны и похожи, поэтому вместо conf/flags/libcrypto.do: redo-ifchange ../../config ../cmd/pkg-config . ../../config read PKG_CONFIG < ../cmd/pkg-config cat <<EOF ${SSL_CFLAGS:-`$PKG_CONFIG --cflags libcrypto`} ${SSL_LDFLAGS:-`$PKG_CONFIG --libs-only-L libcrypto`} ${SSL_LDLIBS:-`$PKG_CONFIG --libs-only-l libcrypto`} EOF результат которого мне надо читать чётко понимая что там три строчки флагов, я делаю conf/flags/default.pc.rc.do: redo-ifchange ../../config . ../../config libname=$2 prefix=`echo $libname | tr a-z A-Z | tr - _` eval cflags=\${prefix}_CFLAGS eval ldflags=\${prefix}_LDFLAGS eval ldlibs=\${prefix}_LDLIBS eval pkgconf=\${prefix}_PKGCONF cat <<EOF { read ${prefix}_CFLAGS read ${prefix}_LDFLAGS read ${prefix}_LDLIBS read ${prefix}_PKGCONF } <<EOF EOF export PKG_CONFIG_PATH=${PKG_CONFIG_PATH} if [ -z "$cflags" -a -z "$ldflags" -a -z "$ldlibs" ] ; then redo-ifchange ../cmd/pkgconf read PKGCONF < ../cmd/pkgconf $PKGCONF --cflags $libname $PKGCONF --libs-only-L $libname $PKGCONF --libs-only-l $libname echo $libname else cat <<EOF $cflags $ldflags $ldlibs $pkgconf EOF fi echo EOF Если мне нужно получить флаги для сборки whatever библиотеки, то достаточно выполнить redo conf/flags/whatever.pc.rc. whatever станет вторым аргументом при выполнении этого скрипта, и будет подставлятся по все эти команды, создавая .rc-файл, который если за-source-ить, то на руках получим WHATEVER_CFLAGS, WHATEVER_LDFLAGS, и т.д.. Подобные цели я таскаю из проекта в проект без изменений: они just works. Как в autoconf есть свои библиотеки детектов, так и здесь подобные цели аналогичную функцию выполняют. Но зная о default цели, мы же не знаем какие именно команды предполагается вызывать в проекте? Раньше я делал что-то-там.list файлы со списком возможных сгенерированных команд. Вот только их приходилось дублировать в .gitignore файле. Теперь я подобные списки храню в .gitignore полностью, ведь чем он хуже остальных файлов? А clean.do цель в директории может подчистить файлы просто делая: rm -f `sed "s#/##" < .gitignore` ./configure может выдать полный список опций/флагов который пользователь может задать и переопределить. Если цели для определения команд и флагов написаны аккуратно, то это и в redo-based проектах выполняется очень просто, например в conf/vars.list.do: redo-ifchange fn2env.sh cmd/.gitignore flags/.gitignore fn2env() { tr a-z A-Z | tr - _ } { sed "s#^/##" cmd/.gitignore | ./fn2env.sh sed -n 's#^/\(.*\)\.pc\.rc$#\1_CFLAGS \1_LDFLAGS \1_LDLIBS \1_PKGCONF#p' \ flags/.gitignore | ./fn2env.sh perl -ne 'print "$1\n" if /\$\{(\w+):?.*\}/' *.do flags/*.do | ./fn2env.sh } | tr " " "\n" | sort | uniq | fmt и сделав redo conf/vars.list && cat conf/vars.list можно получить красивый список типа: AR CC CFLAGS CLANG_FORMAT CLANG_TIDY DTRACE XXX_CFLAGS XXX_LDFLAGS XXX_LDLIBS XXX_PKGCONF INCDIR INCLUDE_WHAT_YOU_USE INFODIR LDFLAGS LDLIBS LIBDIR LIBTAP_CFLAGS LIBTAP_LDFLAGS LIBTAP_LDLIBS MAKEINFO PKG_CONFIG_DIR PKG_CONFIG_PATH PKGCONF PLANTUML PREFIX Детектирование glibc например делаю так: redo-ifchange ../../config ../cmd/cc . ../../config GLIBC_CFLAGS="-D_POSIX_C_SOURCE=200112L" GLIBC_CFLAGS="$GLIBC_CFLAGS -D_DEFAULT_SOURCE" read CC < ../cmd/cc src=`mktemp` trap "rm -f $src $src.c" HUP PIPE INT QUIT TERM EXIT cat > $src.c <<EOF #include <features.h> int main(int argc, char **argv) { return 0; } EOF $CC -o /dev/null $src.c > /dev/null 2>&1 && printf "%s\n" "$GLIBC_CFLAGS" || echo где факт компилирования с features.h вполне годится. А в других целях я из этого файла возьму опциональные флаги нужные для ОС с glibc. Аналогично я делаю Си программы которые уже что-то выводят (xxx.rc.do): redo-ifchange ../../config ../cmd/cc common.rc xxx.pc.rc read CC < ../cmd/cc . ./common.rc . ./xxx.pc.rc src=`mktemp` trap "rm -f $src $src.c" HUP PIPE INT QUIT TERM EXIT cat > $src.c <<EOF #include <stdio.h> #include <xxx.h> int main(int argc, char **argv) { puts("{\\nread XXX_FOO_CTX_SIZE\\nread XXX_BAR_CTX_SIZE\\n} <<EOF"); printf("%zu\\n%zu\\nEOF\\n", XXX_FOO_CTX_SIZE, XXX_BAR_CTX_SIZE); return 0; } EOF $CC $XXX_CFLAGS $CFLAGS -o $src $src.c $LDFLAGS $XXX_LDFLAGS $LDLIBS $XXX_LDLIBS $src И этот детект зависит и от default.pc.rc и cmd/default.do целей.
From: kmeaw Date: 2022-10-01 16:17:18Z > clean.do цель в директории может подчистить файлы Если используется git, то можно сделать git clean -Xf - тогда будет использоваться полноценный парсер .gitignore.
From: Sergey Matveev Date: 2022-10-02 09:28:15Z
Сгенерирован: SGBlog 0.34.0