Makefile如何检测本地计算机上是否有命令?


11

我开始使用org-modeGTD风格的系统中计划任务。将每个组织文件放在Dropbox文件夹的目录中,我运行emacs来从三个不同的本地计算机(Cygwin,Mac OS X和Debian)编辑/管理这些文件。由于我也使用MobileOrg从iPad访问这些组织文件,因此,进行checksums.dat任何更改时,文件必须保持最新状态。这可以通过运行来完成md5sum *.org > checksums.dat

问题是有三种不同的命令md5sum命令:md5sum.exe在Cygwin,md5Mac OS X和md5sumDebian中。最理想的情况是将Makefile存储在Dropbox foder中,该文件检测当前计算机中可用的命令并运行该命令以执行md5校验和操作。



1
@Kevin听起来太过分了。我不想在三个不同的系统中安装程序。在每个系统中,可以将Dropbox文件夹作为本地目录访问。当我运行make checksum以在Dropbox文件夹下生成校验和数据时,我希望Makefile在检测到当前计算机中可用的校验和命令后使用适当的命令。
Federico Magallanez 2012年

如果您要进行大量脚本编写,并且项目很小,我建议您使用scons。
Faheem Mitha 2012年

Answers:


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,因此,如果您担心该脚本无处不在,可以将该脚本与makefile捆绑在一起。

为您的系统选择正确的命令

好的,假设您真的找不到在任何地方都可以使用的命令。

在壳

使用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

可以在加载makefile时使用该shell函数运行shell片段,并将输出存储在变量中。

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

便携式(POSIX)品牌

您只能在rule中运行shell命令,因此每个计算校验和的规则都必须包含查找代码。您可以将代码段放入变量中。请记住,规则中的单独行是独立评估的。还要记住,$要传递给外壳的符号需要转义到$$

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仅在shell为bash的情况下才有效,而在ksh或dash的情况下则无效(在Ubuntu等系统中就是这种情况)。您可以使用它command -v的可移植性。
吉尔(Gilles)'所以

您似乎已从使用切换type为使用command。其他方法也应该更新吗?
肖恩

@Sean其他方法也很好:这type是一种测试命令是否存在的正确,可移植的方法,它的问题在于它产生的输出类似于sha1sum is /usr/bin/sha1sum而不是程序名称。这是我唯一使用输出type而不是返回值的地方。
吉尔斯(Gillles)“所以-别再邪恶了”

5

这是一个hack,但是您可以测试每个对象是否存在,并在存在的情况下执行它们:

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

我非常确定cygwin可以识别md5sum不带的命令(包括).exe,但如果需要的话可以包括它。


4
which退出值不可移植。使用type代替(您可能要使用它if; then; elif来避免在多个可执行文件中出现问题)。which而且type无论如何都只寻找可执行文件,因此使用-x进行测试毫无意义。
克里斯·唐纳

使用“ type”的更多信息:cmd = $(对于foo md5 md5sum bar中的cmd;输入$ cmd> / dev / null 2>&1 && echo $ cmd && break; done);$ cmd file1 file2 file3> md5.txt
michael


1

可以选择使用 GNU自动工具(如注释中所述),也可以选择CMake

GNU自动工具是更传统的方法,但是(也许只是为我自己说话)我认为人们对于最初使用它们来建立项目的前景并不感到太兴奋。好吧,无论如何,这是一条学习曲线。CMake是新手,可能不太常见(仍然有学习曲线)。它具有自己的语法,并为您的平台生成makefile。CMake确实具有不那么以非中心为中心的明显优势。它也可以在UNIX,Windows和Mac上可靠地运行(例如,它可以生成msvc项目,而不是makefile。)

编辑:当然,由于建议使用“ makefiles”,因此该答案也与该假设一致。但是也许仅仅是python脚本或简单的Java程序会更适合此任务;脚本/编程语言在各个平台上都可以做到这一点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.