Как make-файл может определить, доступна ли команда на локальном компьютере?

11

Я начал использовать org-mode для планирования своих задач в GTD- стиле. Помещая все файлы org в каталог папки Dropbox , я запускаю emacs для редактирования этих файлов и управления ими с трех разных локальных компьютеров: Cygwin, Mac OS X и Debian. Поскольку я также использую MobileOrg для доступа к этим файлам org с моего iPad, checksums.datфайл должен постоянно обновляться при внесении любых изменений. Это можно сделать, запустив md5sum *.org > checksums.dat.

Проблема в том, что для команды есть три разные команды md5sum: md5sum.exeв Cygwin, md5в Mac OS X и md5sumв Debian. Наиболее идеальная ситуация - это make-файл, хранящийся в фодере Dropbox, который определяет, какая команда доступна на текущем компьютере, и запускает эту команду для выполнения операции контрольной суммы md5.

Федерико Магалланез
источник
GNUautotools
Кевин
1
@Kevin Это звучит как излишество. Я не хочу устанавливать программу в трех разных системах. В каждой системе папка Dropbox доступна как локальный каталог. Когда я запускаю make checksumдля генерации данных контрольной суммы в папке Dropbox, я хочу, чтобы make-файл использовал соответствующую команду после определения, какая команда контрольной суммы доступна на текущем компьютере.
Федерико Магалланез
Если вы собираетесь делать значительное количество сценариев, а проект небольшой, я бы предложил scons.
Фахим Митха

Ответы:

7

Возможные команды для генерации контрольной суммы

К сожалению, нет стандартной утилиты для генерации криптографической контрольной суммы. Существует стандартная утилита для генерации CRC: cksum; этого может быть достаточно для обнаружения изменений в не враждебной среде.

Я бы рекомендовал использовать SHA1, а не MD5. Существует не так много систем, в которых есть утилита MD5, но нет SHA1, и если вы собираетесь использовать криптографические контрольные суммы, вы могли бы также использовать алгоритм без известного метода для обнаружения коллизий (при условии, что вы также проверяете размер).

OpenSSL - это инструмент, который не является стандартным, но распространенным и может рассчитывать дайджесты . Он доступен для Cygwin, Debian и OSX, но, к сожалению, не является частью установки по умолчанию на OSX.

openssl dgst -sha1

В OSX 10.6 есть shasumутилита, которая также присутствует в Debian (она входит в perlпакет), и я верю и в Cygwin. Это скрипт на Perl. В большинстве Unix-систем установлен Perl, поэтому вы можете связать этот скрипт с вашим make-файлом, если вы беспокоитесь о том, что этот скрипт не будет доступен везде.

Выбор правильной команды для вашей системы

Хорошо, скажем, вы действительно не можете найти команду, которая работает везде.

В оболочке

Используйте typeвстроенный, чтобы увидеть, если команда доступна.

sum=
for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do
  if type "${x%% *}" >/dev/null 2>/dev/null; then sum=$x; break; fi
done
if [ -z "$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi
$sum *.org

GNU make

Вы можете использовать shellфункцию для запуска фрагмента оболочки при загрузке make-файла и сохранения результатов в переменной.

sum := $(shell { command -v sha1sum || command -v sha1 || command -v shasum; } 2>/dev/null)
%.sum: %
        $(sum) $< >$@

Портативная (POSIX) марка

Вы можете запускать только команды оболочки в правиле, поэтому каждое правило, которое вычисляет контрольную сумму, должно содержать код поиска. Вы можете поместить фрагмент в переменную. Помните, что отдельные строки в правилах оцениваются независимо. Также помните, что $знаки, которые должны быть переданы в оболочку, должны быть экранированы $$.

determine_sum = \
        sum=; \
        for x in sha1sum sha1 shasum 'openssl dgst -sha1'; do \
          if type "$${x%% *}" >/dev/null 2>/dev/null; then sum=$$x; break; fi; \
        done; \
        if [ -z "$$sum" ]; then echo 1>&2 "Unable to find a SHA1 utility"; exit 2; fi

checksums.dat: FORCE
    $(determine_sum); \
    $$sum *.org
Жиль "ТАК - прекрати быть злым"
источник
Мне пришлось использовать -Pопцию typeкоманды, чтобы заставить описанный выше метод «GNU make» работать должным образом, поэтому я закончил sum := $(shell { type -P sha1sum || type -P sha1 || type -P shasum; } 2>/dev/null).
Шон
@Sean Спасибо за сообщение об ошибке. type -Pработает только если ваша оболочка bash, а не, например, ksh или dash (как, например, в Ubuntu). Вы можете использовать command -vдля мобильности.
Жиль "ТАК ... перестать быть злым"
Похоже, вы переключились с использования typeна использование command. Нужно ли обновлять и другие методы?
Шон
@Sean Остальные методы хороши: typeэто правильный, переносимый способ проверить наличие команды, проблема в том, что она выдает вывод, sha1sum is /usr/bin/sha1sumа не только имя программы. Это было единственное место, где я использовал вывод, typeа не только его возвращаемое значение.
Жиль "ТАК - перестань быть злым"
5

Это что-то вроде хака, но вы можете проверить, существуют ли каждый из них, и выполнить их, если они есть:

[ -x "`which md5 2>/dev/null`" ] && md5 newfile >>sums
[ -x "`which md5sum 2>/dev/null`" ] && md5sum newfile >>sums

Я вполне уверен, что Cygwin распознает команды (в том числе md5sum) без .exe, но включите его, если нужно.

Kevin
источник
4
whichВыходные значения не являются переносимыми. Используйте typeвместо этого (и вы, вероятно, захотите использовать, if; then; elifчтобы избежать проблем с несколькими исполняемыми файлами). whichи typeвсе равно ищите только исполняемые файлы, так что ваш тест с -x не имеет смысла.
Крис Даун
подробнее об использовании "type": cmd = $ (для cmd в строке foo md5 md5sum; введите $ cmd> / dev / null 2> & 1 && echo $ cmd && break; done); $ cmd file1 file2 file3> md5.txt
майкл
1

Либо GNU autotools (как упомянуто в комментарии), либо CMake - вариант.

GNU autotools - более традиционный подход, но (и, может быть, я говорю только о себе), я не думаю, что люди действительно слишком взволнованы перспективой первоначальной настройки проекта с их использованием. Ну, в любом случае, это кривая обучения. CMake - более новый ребенок в блоке, и, возможно, менее распространенный (и все еще имеет кривую обучения). Он имеет собственный синтаксис и генерирует make-файлы для вашей платформы. CMake имеет явное преимущество в том, что он не настолько не * х-центричен; он также надежно работает на Unix, Windows и Mac (например, он может генерировать проекты msvc, например, вместо make-файлов).

Изменить: и, конечно, так как были предложены «make-файлы», этот ответ согласуется с этим предположением. Но, возможно, для этой задачи больше подойдет простой скрипт на python или (простое дыхание) простая Java-программа; язык сценариев / программирования будет делать то же самое на разных платформах.

Майкл
источник