在Makefile中生成并检查下载文件校验和

时间:2017-02-08 20:33:52

标签: makefile sha256

作为我makefile的一部分,我需要下载并构建ZLib。但是我想确保在下载ZLib时,将下载的.tar.gz的sha256与已知的正确sha256值进行比较是正确的。这需要在多个平台上工作。

到目前为止我的内容类似于以下内容,但是当我将ZLIB_SHA256_ACTUALZLIB_SHA256进行比较时,ZLIB_VER = 1.2.11 ZLIB_SHA256 = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 SHA256_CMD = sha256sum ifeq ($(PLATFORM), OS_MACOSX) SHA256_CMD = openssl sha256 -r endif ifeq ($(PLATFORM), OS_SOLARIS) SHA256_CMD = digest -a sha256 endif libz.a: -rm -rf zlib-$(ZLIB_VER) curl -O -L http://zlib.net/zlib-$(ZLIB_VER).tar.gz ZLIB_SHA256_ACTUAL = $(SHA256_CMD) zlib-$(ZLIB_VER).tar.gz ifneq ($(ZLIB_SHA256), $(ZLIB_SHA256_ACTUAL)) $(error zlib-$(ZLIB_VER).tar.gz checksum mismatch, expected="$(ZLIB_SHA256)" actual="$(ZLIB_SHA256_ACTUAL)") endif tar xvzf zlib-$(ZLIB_VER).tar.gz cd zlib-$(ZLIB_VER) && CFLAGS='-fPIC' ./configure --static && make cp zlib-$(ZLIB_VER)/libz.a . 的值似乎总是空白,因此我的makefile总是退出时出错,因为校验和不是相同。我对Makefiles很新,有人可以告诉我,我做错了吗?

Object {readyState: 4, responseText: "", status: 200, statusText: "OK"}

1 个答案:

答案 0 :(得分:3)

makefile在一个文件中包含两种不同的编程语言。大多数文件使用makefile语法,这使得理解和解析。但是规则的配方使用shell语法,make不会尝试解释:它只是将配方的内容传递给shell来解释。

配方是makefile的一部分,在目标定义之后用TAB字符缩进。因此,在上面的示例中,目标定义为libz.a:,之后用TAB缩进的所有行都是配方行。它们被传递给shell,而不是由make运行。

配方是一个单行的线;你不能在makefile行中散布配方行。一旦make看到第一个非配方行,那就是配方的结束,并开始将剩余的行视为makefile行。

让我们来看看你的规则:

libz.a:
        -rm -rf zlib-$(ZLIB_VER)
        curl -O -L http://zlib.net/zlib-$(ZLIB_VER).tar.gz

好的,没关系:你已经创建了一个目标libz.a,并在你的食谱中提供了两个命令行,它们是有效的shell命令。

        ZLIB_SHA256_ACTUAL = $(SHA256_CMD) zlib-$(ZLIB_VER).tar.gz
好的,现在你有问题;这是一个 make 变量赋值,而不是shell命令,但是因为你用TAB make缩进它不会解释它:make会将它传递给shell。这不是一个有效的shell命令(在shell中,变量赋值不能在等号周围有空格);这是尝试运行一个名为字面ZLIB_SHA256_ACTUAL的程序,并传递参数=SHA256_CMD变量的扩展。即使这被认为是make赋值,它也不会做你想要的,因为它只是将变量的值设置为字符串openssl sha256 -r zlib-1.2.11.tar.gz:你想运行该命令并将变量设置为输出。

然后是下一行:

        ifneq ($(ZLIB_SHA256), $(ZLIB_SHA256_ACTUAL))
                $(error zlib-$(ZLIB_VER).tar.gz checksum mismatch, expected="$(ZLIB_SHA256)" actual="$(ZLIB_SHA256_ACTUAL)")
        endif

同样,这是错误的,因为这些是 make 命令,但是你已经将它们放入一个配方中,这意味着它们将被传递给shell,但shell对它们一无所知

但是,它们永远不会有机会被传递给shell,因为在将它发送到shell之前,一个事情就是使用一个配方来扩展所有make变量和函数。因此,当make扩展它时,它运行error函数,并立即失败,并且永远不会有机会尝试运行配方。

这是make的棘手部分。也许我只是把你和以上所有的东西搞糊涂了。

简短的答案是:您必须使用 shell 命令在配方中执行操作。您不能使用 make 命令(如ifeq等),如果您想在配方中设置变量,则必须是 shell 变量,而不是 make 变量。

所以,你想要这样的东西,它使用shell语法而不是为变量赋值和测试制作语法。

编辑请注意,您的SHA生成命令不会仅打印SHA,它还会打印文件的名称,因此您无法将它们作为字符串进行比较:它们永远不会相同。你需要做一些比较漂亮的事情;有很多方法可以解决这个问题。在这里,我决定使用case进行比较:

libz.a:
        -rm -rf zlib-$(ZLIB_VER)
        curl -O -L http://zlib.net/zlib-$(ZLIB_VER).tar.gz
        ZLIB_SHA256_ACTUAL=`$(SHA256_CMD) zlib-$(ZLIB_VER).tar.gz`; \
        case "$$ZLIB_SHA256_ACTUAL " in \
            ($(ZLIB_SHA256)\ *) : ok ;; \
            (*) echo zlib-$(ZLIB_VER).tar.gz checksum mismatch, expected=\"$(ZLIB_SHA256)\" actual=\"$$ZLIB_SHA256_ACTUAL\"; \
            exit 1 ;; \
        esac
        tar xvzf zlib-$(ZLIB_VER).tar.gz
        cd zlib-$(ZLIB_VER) && CFLAGS='-fPIC' ./configure --static && $(MAKE)
        cp zlib-$(ZLIB_VER)/libz.a .

请注意,配方中的每个逻辑行都会传递给shell的新实例,因此,如果要设置shell变量并测试其值,则必须使用反斜杠/换行符语法将物理行组合为一个逻辑行

此外,在配方中运行子品牌时,您应始终使用变量$(MAKE),而不要仅使用make