tpm - trivial package manager. Написан 2017-07-29. Trivial, потому что сейчас, временно, написал тривиальный менеджер пакетов. Может быть, когда-нибудь напишу настоящий. Для всех UNIX-подобных систем и всех языков программирования. Я его написал для распространения своих программ, т. е. чтобы автоматически устанавливалась моя программа, а к ней зависимости, возможно, тоже мои. Малофункциональный. Написан по-быстрому, для себя. Пакеты лежат на гитхабе (в виде исходных кодов), оттуда я могу их собирать и выкладывать (в бинарном виде) на http://safinaskar.com/tpm (это место для бинарных пакетов). Для установки tpm на новую систему можно собрать его из сорцов или набрать команду wget -O - http://tinyurl.com/tpm-sh | sudo sh -s bootstrap
. После этого на систему можно устанавливать пакеты. Они будут скачиваться с http://safinaskar.com/tpm , если они там есть, либо сразу же собираться на вашей машине, если их там нет.
Возможно, прежде чем читать этот README, вам пригодится моя статья https://habrahabr.ru/post/321468 , рассказывающая про распространение софта в виде сорцов в UNIX-подобных системах вообще, без всякого упоминания tpm.
И ещё одно предупреждение - стиль этого README намеренно ироничен, я просто не заморачивался с написанием нормальной документации, на самом деле программа действительно существует и работает, просто недостаточно функциональная для гордого звания менеджера пакетов. Дальше README будет становится всё более серьёзным и всё менее понятным.
Итак, пакет. Пакет - это репозиторий на гитхабе. Необязательно на моём аккаунте. В нём должен быть файл tpm-control, который устанавливает свойства пакета, такие как зависимости и т. д.
tpm умеет собирать пакет. Для этого tpm скачивает пакет, собирает его, указав DESTDIR, результат запаковывает в архив в .tar.gz. Далее этот пакет можно выложит на http://safinaskar.com/tpm либо сразу же установить на систему путём его распаковки.
Когда tpm хочет установить пакет, он ищет его на http://safinaskar.com/tpm . Если находит, то устанавливает путём распаковки в корень (предварительно установя зависимости). Если нет - скачивает сорцы с гитхаба, устанавливает DEPENDS и BUILD_DEPENDS, собирает и устанавливает.
Зачем нужен tpm если есть dpkg/apt/rpm/yum/dnf и так далее? Потому что мой tpm работает как на debian'е, так и на fedora'е, так и вообще везде. Он просто устанавливается параллельно с основным пакетным менеджером, вы не привязаны к dpkg или, скажем, к rpm. Разные пакетные менеджеры для программ на C/C++ меня тоже не устраивали, т. к. мой пакет может зависеть от пакета на другом языке, тот - от пакета ещё на каком-нибудь языке и т. д. Так что нужен пакетный менеджер сразу для всех (UNIX-подобных) систем и всех языков. Может быть даже такой и есть, я не проводил хорошего поиска альтернатив.
Сам tpm - это тоже tpm-пакет. Как же его тогда установить изначально? Первый путь - собрать из сорцов. Скачиваем сорцы tpm, собираем и устанавливаем так же, как и любой другой проект, основанный на cmake (tpm написан на shell, поэтому понятие "сборка", как и для многих других пакетов, условно, ничего при этом не компилируется). При установке рекомендуется установить в префикс /opt/tpm-store, т. к. этот путь захардкожен в сорцах tpm. То есть запускать tpm можно откуда угодно, но если tpm считает, что он уже установлен, то он считает, что установлен именно туда. Путь к самому скрипту tpm при этом будет /opt/tpm-store/bin/tpm .
Установка при помощи cmake - это ещё не всё. Далее вам нужно инициализировать базу данных пакетов командой "/opt/tpm-store/bin/tpm init". Тем самым вы создадите пустую базу данных пакетов. Количество пакетов теперь равно нулю.
Но и это ещё не всё. Нужно попросить tpm установить себя. Чтобы он понял, что он установлен. Это делается так: "/opt/tpm-store/bin/tpm install safinaskar/tpm".
Вот теперь всё готово.
Второй способ установки: просто сделать wget -O - http://tinyurl.com/tpm-sh | sudo sh -s bootstrap
. Это сделает всё вышеперечисленное сразу.
Так или иначе, вы его теперь установили. Теперь можно устанавливать разные пакеты. Каждый мой репозиторий на гитхабе, в котором есть файл tpm-control - это пакет tpm, его можно установить. Вы тоже можете создать репозиторий и положить туда такой файл. Устанавливать такой пакет можно будет без проблем, разве что каждому пользователю придётся собирать его на своей системе заново, т. к. заливать на http://safinaskar.com/tpm имею право только я. То есть фактически мы имеем распределённый неограниченный репозиторий пакетов, куда любой может без всяких ограничений добавлять пакет.
Для начала замечу, что у tpm нет базовой функциональности, которая предполагается у любого менеджера пакетов. У него нет версионности. Вот так вот. Пакеты можно обновлять. Обновление всегда гарантированно обновит пакет, при этом tpm не будет знать, действительно ли только что установленный пакет новее того, который был, т. е. действительно ли в обновлении был какой-то смысл. Да, глупо. Пакетный менеджер писался для себя, для удобства распространения своего софта, скорее для того, чтобы одной командой можно было установить на какой-нибудь хост все свои программы, желательно не собирая их (но при необходимости и собирая, т. е. tpm сам решает надо собирать или можно просто скачать). Вон посмотрите, как я в своём https://github.com/safinaskar/init-vps смог парой команд установить мой софт в свежесозданную VPS'ку. Разнообразной другой функциональности, которую вы, скорее всего, ожидаете, тоже нет. tpm не разрешает зависимости полностью, прежде чем начать что-либо ставить. Там тупой рекурсивный алгоритм установки. Т. е. функция "установить" (условно) читает список зависимостей, вызывает для них рекурсивно "установить", а потом устанавливает сам пакет. Да, это приведёт к зависанию tpm в случае циклических зависимостей.
Теперь о том, что есть.
- Пакеты всегда устанавливаются в отдельную папку /opt/tpm-store, т. е. они всегда собираются с префиксом /opt/tpm-store. Это хорошо, т. к. они лежат отдельно от вашей основной системы в /usr. Это плохо, т. к. этот путь захардкожен в скрипт tpm (ну, для себя же), а значит, с tpm невозможно работать не от рута. Ещё это плохо, т. к. /opt/tpm-store/bin и /opt/tpm-store/sbin нужно прописать в PATH (и конфиг sudo), а /opt/tpm-store/lib - ещё и в конфиг ld.so. К счастью, при установке (а точнее, в момент инициализации базы данных, т. е. когда вы набираете
tpm init
илиtpm bootstrap
илиwget -O - tinyurl.com/tpm-sh | sudo sh -s bootstrap
) все необходимые изменения в конфиге прописываются сами. Таким образом, при следующем логине в систему ваш PATH уже будет изменён, а ещё до этого момента sudo будет искать программы в том числе в /opt/tpm-store - Поддерживаются зависимости
- Есть база данных установленных пакетов
- Пакеты можно удалять. :) А ещё можно набрать
tpm deinit
, это приведёт к полной отмене всех изменений на системе, сделанных tpm'ом. Будут удалены все пакеты (включая tpm), у них будут выполнены prerm скрипты (о них позже), затем будут удалены созданные конфиги (ну там, конфиги для PATH) и будет удалена папка /opt/tpm-store. Это хорошо, это очень хорошо, до этого у меня были предыдущие системы распространения моих программ, они были менее функциональны. Они распаковывали мои программы сразу в /usr, где они перемешивались с системными программами, понять, как их удалить (не трогая системные программы), было нельзя. Установить можно было лишь путём распаковки готового архива бинарей, сборки на ходу не было. Зависимостей не было, т. е. если моя программа зависела от какой-нибудь системной либы, эта либа не ставилась. Архитектуры не поддерживались. Приходилось на i386 распаковывать архив, предназначенный для amd64 и говорить себе "ну хотя бы скрипты работать будут" - Как вы уже поняли, tpm умеет работать как с бинарными, так и с сорцевыми пакетами (ну, сорцевым пакетом я называю репу на гитхабе). В общем, он умеет как устанавливать бинарный пакет, так и собирать его на лету
- Поддерживаются разные архитектуры! Неожиданно для такой раздолбайской поделки? Итак, у пакета в конфиге должно быть написано ARCH="all" или ARCH="any" (термины позаимствованы мной из менеджера пакетов дебиана, вообще оттуда позаимствовано очень много, tpm-control взят от debian/control, /opt/tpm-store/var/lib/tpm/info от /var/lib/dpkg/info, файлы
info/*.list
,info/*.postinst
,info/*.prerm
тоже позаимствованы оттуда, позаимствован даже точный вид файлаinfo/*.list
, для этого я его хорошенько про'sed'ил). ARCH="all" означает, что пакет в "собранном" виде на самом деле никакой не "собранный", никаких бинарников в нём нет, а лежат одни, скажем, скрипты, а потому его можно установить на любую архитектуру. ARCH="any" означает, что пакет, в принципе, поддерживает любую архитектуру (подразумевается UNIX-подобная ОС), но для каждой архитектуры бинарный пакет свой. Для названий архитектур используются multiarch-идентификаторы архитектур (они почти ничем не отличаются от GNU триплетов), например, x86_64-linux-gnu. При инициализации tpm он пытается выяснить архитектуру системы, в которую устанавливается (в том числе путём скачивания и запуска известного файла config.guess). При заливке пакетов на http://safinaskar.com/tpm они заливаются в all, либо в папку, соответствующую архитектуре. При установке tpm смотрит - если пакет ARCH="all", то можно просто взять его из all, если ARCH="any", нужно искать только в папке со своей архитектурой. Если найти не получилось - собираем сами - У пакетов могут быть postinst и prerm скрипты. То есть скрипты, запускаемые сразу после установки или перед удалением. Я этим пользуюсь в своей программе http://github.com/safinaskar/my-config . Она настраивает систему по моему вкусу сразу в момент установки (в своём postinst скрипте), при этом записывая внесённые изменения в специальные файлы. А prerm скрипт может всё откатить обратно
- У меня пофиксена следующая проблема. Собрал программу на новой системе, запустил на старой и получил, скажем,
/opt/tpm-store/lib/libsh.so: /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.17' not found (required by /opt/tpm-store/lib/libsh.so)
. (При старой системе распространения моего софта такое происходило постоянно.) tpm при установке проверяет все установленные бинарники (при помощи ldd) и при наличии подобных проблем удаляет пакет обратно. Да, тупо. Да, нужно было, чтобы, как в дебиане, можно было заранее сказать, имеет смысл устанавливать пакет на систему, или нет, и чтобы пакет знал, от каких именно версий либ он зависит, с которыми такого не будет. (Бгг, у меня даже нет при таком случае варианта форсировать сборку из сорцов на локальной машине, разве что снести REPO из конфига) - Умеет работать с chroot-окружением снаружи при помощи опции --root
- В качестве зависимости к пакету tpm можно указать не только пакет tpm, но и наличие на системе какого-нибудь бинарника. В случае его наличия никакого действия не будет. В случае отсутствия tpm попытается установить его при помощи apt-get. Обратите внимание, это не значит, что tpm требует для работы Debian. Нет, если вы установите нужную программу сами, то tpm не будет вызывать apt-get. Получаем вообще идеальный способ распространения софта - указываем, от каких tpm-ных пакетов он зависит и указываем, от каких "общеизвестных" пакетов он зависит. Первые tpm всегда поставит сам, а если дело происходит на Debian'е, то и вторые он тоже сможет поставить сам! Разумеется, tpm не ведёт учёт установленных на вашей системе Debian-пакетов, это задача пакетного менеджера Debian. Так что вы можете сперва установить какой-нибудь tpm-пакет, который зависит от какого-нибудь Debian'ового, а потом этот Debian'овый при помощи apt-get снести, tpm ничего не заметит. :) Итак, tpm может "пнуть" apt-get, теоретически в него можно добавить поддержку пинать другие пакетные менеджеры, ну, там, yum/dnf и так далее.
Написанные скорее для себя.
- У меня две стадии кода - сорцы и собранные сорцы. Нет разделения, как у многих пакетов, содержащих скрипты configure или сгенерированные bison'ом парсеры - на (1) абсолютные сорцы (только код, написанный человеком), (2) немного сгенерированные сорцы (сгенерированы скрипты configure, парсеры, словом, то, что портируемо) и (3) окончательный собранный код. Я не стал так делать для упрощения
- На всех UNIX-подобных системах, которые были в моём распоряжении, был gzip. xz не было на OpenBSD 5.5 в той инсталяции, которую я сделал. Так что в качестве компрессора выбираем gzip
- Считаю зависимость от mktemp нормальной, его обычно можно достать
- Не важно, если trap неправильно работает в target shell, речь идёт всего лишь об удалении временных файлов
- Весь код предполагается выполняющимся в режиме
set -e
. Значит, функции из shell library нельзя вызывать из set +e environment'а. Shell library ставит set -e. В случае использования как shell library нельзя юзать $TARGET. Также это значит, что никакие функции нельзя писать перед ||, && и if'е и так далее, это включает неотключаемый set +e. Исключения: функции: специально помеченные "is". Всё это относится как к экспортируемым функциям, так и нет. Раз уж всё равно обычные функции нельзя вызывать перед ||, то я смело делаю в них exit в случае проблем (но лишь в случае проблем, в случае успеха всё равно нужно сделать return, да и вообще нужно написать shell code style, по которому весь код должен быть в одной большой функции, из которой можно делать return). После каждого && или || в конце функции или скрипта ставлю :, чтобы получить нулевой код возврата - Функции с tpm_ считаются exported из shell library и не относящимися к TARGET'у. Начинающиеся с _ - внутренними, они могут как-то манипулировать TARGET'ом
- Shell library плохая, т. к. имеет слишком много зависимостей (хоть она их всех и проверяет). Надо было разбить на несколько поменьше. Но мне просто захотелось всё запихнуть в один bootstrap-файл
- Ещё разок: хотелось иметь bootstrap-скрипт, который можно запустить первым на "чистой" машине. Но тогда он должен либо уметь устанавливать пакеты, либо догружать части, которые умеют. Второй способ не слишком подходит, т. к. на машине может не быть wget, а чтобы его установить, опять-таки нужно что-то устанавливать. Так что некую минимальную функциональность (как минимум, чтобы добиться работающего wget) нужно включить в сам bootstrap-скрипт. Эта же функциональность может потребоваться в самом tpm. Поэтому, в идеале нужна была shell library, bootstrap-скрипт, её использующий, и tpm, использующий её же. Но bootstrap-скрипт нельзя отделять от своей shell library, он должен быть единым, чтобы одним скриптом загружаться на "чистую" машину. Значит, bootstrap-скрипт должен быть одновременно shell library для tpm. Затем было принято решение "а давайте тогда вообще всё объединим в одну кучу". В результате имеем один скрипт, который является tpm, умеет делать bootstrap и при этом является shell library, которую можно подключать снаружи. Да, возможно, это не самое лучшее решение
- В tpm и tpm-dev мы не делаем защиты от перезаписи файла, то есть не помещаем всё в { ... exit }. Это сделало бы невозможным использовать tpm в качестве shell library. Тем не менее всё хорошо, т. к. при распаковке поверх скрипта с помощью tar, старая версия скрипта продолжает работу
- tpm (в любом режиме работы) сам по мере необходимости устанавливает (или пытается установить) зависимости для себя (но только в TARGET), поэтому его можно сразу запускать на любой машине, даже если там ещё не установлено зависимостей для tpm. Тем не менее DEPENDS в tpm-control пакета tpm всё равно указано. Если, скажем, запустить
tpm bootstrap
на любой машине, где ещё не установлен tpm, то этот скрипт сам установит (или попытается) установить все зависимости для tpm, затем установит сам tpm, даже если для этого этот tpm придётся ещё и собрать (в этом случае tpm ещё и установит зависимости для своей сборки). tpm может работать даже в режиме wget -O - ... | sh, поэтому он не опирается на содержимое переменной $0 (использует её только в выводе сообщений об ошибках) и не перезапускает себя. tpm можно запустить из любого места, но вот установит он себя только в /opt/tpm-store, и, если он считает, что он уже установлен, то будет искать установленную версию себя только там - Файлы и папки, созданные mktemp (и mktemp_directory) имеют странные права. Поэтому мы работаем не с ними непосредственно, а с файлами и папками внутри папок, созданных mktemp. Если создать с помощью mktemp папку, использовать её в качестве DESTDIR, затем запаковать в tar-архив, а затем распаковать в /, то / получит права drwx------, а это приведёт к неработоспособности sudo. Также я следил, чтобы не сделать случайно юзера владельцем /
- Считаю плохой ситуацию, когда скрипт по необходимости вызывает sudo. Так что любая операция, которая может потребовать прав root, сразу запускается с правами root. Для tpm-dev делаем исключение, т. к. ему нужно залить на ssh с ключами пользователя
- В скриптах tpm и tpm-dev в единственных местах (?) захардкодено нечто, имеющее отношение конкретно к моей инфраструктуре: в местах, помеченных HARD
И которые поэтому он может не указывать в DEPENDS и BUILD_DEPENDS.
Предполагаем, что мы находимся в UNIX-подобном окружении (это может быть, например, cygwin). Наличие программ для разработки на C, ровно как и на любом другом языке, не предполагается. Не предполагается наличие каких бы то ни было программ и команд, кроме явно указанных в этом файле. Это может быть, например, минимальное chroot-окружение, созданное debootstrap'ом. Не предполагается наличие, скажем, sed, т. к. sed находится в Debian в отдельном пакете, и, в принципе, можно представить себе Debian-chroot-окружение, где нет sed. Наличие bash не предполагается. Предполагается наличие sh и /bin/sh (при этом не предполагается, что sh и /bin/sh - это одна и та же программа). Предполагается, что shebang работает. Разумеется, предполагается, что в sh есть портируемые синтаксические конструкции (например, if). Разумеется, есть всё для того, чтобы sh работал (например, работающее ядро). Предполагается, что есть следующие команды: [ basename cat chmod chown cp cut date dd df dirname echo env expr false head id ln ls mkdir mv printf pwd rm rmdir sh sleep sort tail test touch tr true tty uname uniq wc
. Предполагается, что они доступны в виде отдельных бинарников. Предполагается, что в sh также доступны следующие команды: : . bg break cd command continue eval exec exit export fg getopts hash jobs kill local read readonly return set shift times trap type ulimit umask unset wait
. При этом они могут быть реализованы как в виде внутренних команд, так и в виде внешних. Эти же списки захардкожены в tpm.
Объясню, откуда получились списки команд. Можно создать chroot с debian slink i386, в котором будут установлены только пакеты fileutils, ldso, libc6, shellutils, textutils. (Выбран slink, т. к. это самый ранний, в котором есть apt.) Тогда (по выводу dpkg -L) в нём в папках /bin и /usr/bin будут (с добавлением sh): [ basename bin cat chgrp chmod chown cksum comm cp csplit cut date dd df dir dircolors dirname du echo env expand expr factor false fmt fold glibcbug groups head id install join ldd ln logname ls makedb mkdir mkfifo mknod mv nice nl nohup od paste pathchk pr printenv printf pwd rm rmdir seq sh sleep sort split stty su sum sync tac tail tee test touch tr true tty uname unexpand uniq users vdir wc who whoami yes
. (Идеально.)
POSIX 2001, кроме special builtin utilities (да, POSIX 2001 действительно говорит, что read - это не special builtin utility, а потому должен быть доступен для execve): [ admin alias ar asa at awk basename batch bc bg c99 cal cat cd cflow chgrp chmod chown cksum cmp comm command compress cp crontab csplit ctags cut cxref date dd delta df diff dirname du echo ed env ex expand expr false fc fg file find fold fort77 fuser gencat get getconf getopts grep hash head iconv id ipcrm ipcs jobs join kill lex link ln locale localedef logger logname lp ls m4 mailx make man mesg mkdir mkfifo more mv newgrp nice nl nm nohup od paste patch pathchk pax pr printf prs ps pwd qalter qdel qhold qmove qmsg qrerun qrls qselect qsig qstat qsub read renice rm rmdel rmdir sact sccs sed sh sleep sort split strings strip stty tabs tail talk tee test time touch tput tr true tsort tty type ulimit umask unalias uname uncompress unexpand unget uniq unlink uucp uudecode uuencode uustat uux val vi wait wc what who write xargs yacc zcat
. (Идеально, но осмотреть, не затесалось ли здесь неправильное имя команды типа colon.)
Окружение внутри debian installer stretch amd64 (папки /bin и /usr/bin): [ [[ anna anna-install apt-install ar archdetect ash basename block-attr bterm busybox cat check-missing-firmware chmod choose-mirror chown ckbcomp ckbcomp-mini cmp cp cut date dd debconf debconf-copydb debconf-disconnect debconf-dumpdb debconf-get debconf-loadtemplate debconf-set debconf-set-selections df dirname dmesg dnsdomainname echo egrep env env2debconf ethdetect expr false fetch-url find free getopt gpgv grep groups gunzip head hostname hotplug-pcmcia httpd hw-detect id in-target kbd_mode kill kill-all-dhcp kmod languagemap list-devices ln loadkeys localechooser logger log-output lowmem_debconf ls lsmod lspci main-menu md5sum mkdir mknod mktemp more mount mountmedia mv nano nc netcfg pidof ping ping6 preseed_command preseed_fetch printf ps ptom pwd rdisc6 readlink realpath register-module report-hw resolv rm rmdir screen search-path sed seq setfont setupcon sh sha1sum sha256sum sha512sum sleep sort start-shell sync sysfs-update-devnames tail tar test tftp touch tr translation-check trimtemplates true tty udevadm udpkg umount uname uniq unxz update-dev usb-list user-params wc wget xzcat zcat
. (Идеально.)
Пересекаем всё вышеназванное. Получаем список, который логично установить в качестве обязательно присутствующих бинарников (именно в виде внешних программ): [ basename cat chmod chown cp cut date dd df dirname echo env expr false head id ln ls mkdir mv printf pwd rm rmdir sh sleep sort tail test touch tr true tty uname uniq wc
.
Упомянутый slink. Наберём help в bash'е, преобразуем в один столбец:
%[DIGITS | WORD] [&]
. filename
:
[ arg... ]
alias [-p] [name[=value] ... ]
bg [job_spec]
bind [-lpvsPVS] [-m keymap] [-f fi
break [n]
builtin [shell-builtin [arg ...]]
case WORD in [PATTERN [| PATTERN].
cd [-PL] [dir]
command [-pVv] command [arg ...]
continue [n]
declare [-afFrxi] [-p] name[=value
dirs [-clpv] [+N] [-N]
disown [-h] [jobspec ...]
echo [-neE] [arg ...]
enable [-pnds] [-a] [-f filename]
eval [arg ...]
exec [-cl] [-a name] file [redirec
exit [n]
export [-nf] [name ...] or export
false
fc [-e ename] [-nlr] [first] [last
fg [job_spec]
for NAME [in WORDS ... ;] do COMMA
function NAME { COMMANDS ; } or NA
getopts optstring name [arg]
hash [-r] [-p pathname] [name ...]
help [pattern ...]
history [-c] [n] or history -awrn
if COMMANDS; then COMMANDS; [ elif
jobs [-lnprs] [jobspec ...] or job
kill [-s sigspec | -n signum | -si
let arg [arg ...]
local name[=value] ...
logout
popd [+N | -N] [-n]
pushd [dir | +N | -N] [-n]
pwd [-PL]
read [-r] [-p prompt] [-a array] [
readonly [-anf] [name ...] or read
return [n]
select NAME [in WORDS ... ;] do CO
set [--abefhkmnptuvxBCHP] [-o opti
shift [n]
shopt [-pqsu] [-o long-option] opt
source filename
suspend [-f]
test [expr]
time [-p] PIPELINE
times
trap [arg] [signal_spec ...] or tr
true
type [-apt] name [name ...]
typeset [-afFrxi] [-p] name[=value
ulimit [-SHacdflmnpstuv] [limit]
umask [-S] [mode]
unalias [-a] [name ...]
unset [-f] [-v] [name ...]
until COMMANDS; do COMMANDS; done
variables - Some variable names an
wait [n]
while COMMANDS; do COMMANDS; done
{ COMMANDS }
Убрали запуск job'а, синтаксическую конструкцию { ... }, очевидно синтаксические конструкии case, for, function, if, select, until, while. Убрал variables (это в help затесалось нечто, не являющееся builtin'ом, баг зарепорчен: https://savannah.gnu.org/support/index.php?109359 , закрыт как "Wont Do"). Имеем: : . [ alias bg bind break builtin cd command continue declare dirs disown echo enable eval exec exit export false fc fg getopts hash help history jobs kill let local logout popd pushd pwd read readarray readonly return set shift shopt source suspend test time times trap true type typeset ulimit umask unalias unset wait
. (Идеально.)
Squeeze (версия debian, где перешли на dash). amd64. dash builtins (из сорцов dash). С #if'ами разобрался в зависимости от того, есть ли builtin в реальном бинарном dash из squeeze. Имеем: : . [ alias bg break cd chdir command continue echo eval exec exit export false fg getopts hash jobs kill local printf pwd read readonly return set shift test times trap true type ulimit umask unalias unset wait
. (Идеально.)
Тот же posix, но со special builtin utilities. : . [ admin alias ar asa at awk basename batch bc bg break c99 cal cat cd cflow chgrp chmod chown cksum cmp comm command compress continue cp crontab csplit ctags cut cxref date dd delta df diff dirname du echo ed env eval ex exec exit expand export expr false fc fg file find fold fort77 fuser gencat get getconf getopts grep hash head iconv id ipcrm ipcs jobs join kill lex link ln locale localedef logger logname lp ls m4 mailx make man mesg mkdir mkfifo more mv newgrp nice nl nm nohup od paste patch pathchk pax pr printf prs ps pwd qalter qdel qhold qmove qmsg qrerun qrls qselect qsig qstat qsub read readonly renice return rm rmdel rmdir sact sccs sed set sh shift sleep sort split strings strip stty tabs tail talk tee test time times touch tput tr trap true tsort tty type ulimit umask unalias uname uncompress unexpand unget uniq unlink unset uucp uudecode uuencode uustat uux val vi wait wc what who write xargs yacc zcat
. (Идеально, но опять-таки осмотреть так же, как и предыдущий POSIX.)
Упомянутый Debian Installer. Builtin'ы busybox sh. : . [ bg break cd chdir command continue echo eval exec exit export false fg getopts hash help history jobs kill let local printf pwd read readonly return set shift test times trap true type ulimit umask unset wait
. (Идеально.)
Пересекаем это всё, получаем. : . [ bg break cd command continue echo eval exec exit export false fg getopts hash jobs kill pwd read readonly return set shift test times trap true type ulimit umask unset wait
. Затем добавляем local
просто потому что я этого хочу.
Вычитаем то, что установили в качестве обязательных бинарников: : . bg break cd command continue eval exec exit export fg getopts hash jobs kill local read readonly return set shift times trap type ulimit umask unset wait
. Получили список команд, которые всегда есть в дополнение к бинарникам, но они могут быть как внутренними, так и внешними командами.
Компилируемая программа должна иметь в BUILD_DEPENDS свой компилятор (C - prog:cc:gcc, C++ - prog:c++:g++).
Компилируемая программа должна иметь в LIBS все не-tpm библиотеки, от которых она зависит. В том числе для C - libc:6, для C++ - libc:6 и libstdc++:6:g++.
Библиотека считается соответствующей -dev пакету в Debian, а потому её LIB должен быть пустым, и всё, что там было бы, должно быть в DEPENDS с префиксом libdev:. В остальном правила те же.
Если библиотека содержит только хедеры C или только хедеры C++, то соответствующий компилятор писать в BUILD_DEPENDS не нужно. Однако остальные правила те же.
В виде исключения header-only library может не писать в зависимости libc или libstdc++, т. к. та либа или программа, которая реально должна будет что-то собрать (если она их (и соотвествующий компилятор) реально заюзает), обязана будет их указать.
Да, все эти правила приводят к тому, что либы, которые ты собираешься всего лишь ИСПОЛЬЗОВАТЬ, тащат за собой хедеры, да ещё и другие либы, тоже с хедерами и так далее. Это баг tpm.
Если где-либо написано g++, то gcc можно не писать. Если написано libstdc++ (dev или не dev), то соответствующий libc тоже можно не писать.
INSTALL должен не только устанавливать, но ещё и собирать.
Что делать, если захочу написать по-нормальному.
- Поискать аналоги. Может быть, просто git submodules?
- Определиться с целями
- Правильно зависеть от разделяемых библиотек - это, видимо, слишком сложно (для бинарных пакетов). Наверное, нужно поручить это dpkg. То есть из сорцевых пакетов генерятся обычные бинарные пакеты dpkg, а он уже отвечает за их установку
- Нужно иметь возможность работать над секретным проектом, при этом пользуясь tpm. Т. е. держать папку со своим проектом на компьютере и с помощью tpm устанавливать к нему зависимости. В идеале ещё и иметь возможность развернуть этот проект на другой машине
- Хорошо бы ещё редактировать /etc/login.defs, чтобы правильно выставлялся PATH в su. Но тогда нужно прямо в tpm, а не в отдельном пакете my-config уметь ревертить конфиги при удалении. (Workaround: всегда используйте su -l вместо обычного su)
- tpm - плохое название, потому что легко перепутать с tmp. Такая путаница уже возникала в процессе написания (устанавливал что-то в /opt/tmp-store вместо /opt/tpm-store), вдобавок только что случайно попытался открыть файл /dr/github/tmp/tmp, что и побудило добавить этот пункт
//этот readme про tpm