作为我makefile
的一部分,我需要下载并构建ZLib。但是我想确保在下载ZLib时,将下载的.tar.gz的sha256与已知的正确sha256值进行比较是正确的。这需要在多个平台上工作。
到目前为止我的内容类似于以下内容,但是当我将ZLIB_SHA256_ACTUAL
与ZLIB_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"}
答案 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
。