我正在处理下面描述的问题。在研究它时,GNU Make 手册第 6.11 节说:
make 中的变量值通常是全局的;也就是说,无论它们在哪里计算,它们都是相同的......自动变量是一个例外(请参阅自动变量)。
另一个例外是特定于目标的变量值。此功能允许您根据 make 当前正在构建的目标为同一变量定义不同的值。与自动变量一样,这些值仅在目标配方的上下文中可用(以及在其他特定于目标的分配中)。
设置特定于目标的变量值,如下所示:
target … : variable-assignment
多个目标值分别为目标列表的每个成员创建一个特定于目标的变量值。
...
特定于目标的变量还有一个特殊功能:当您定义特定于目标的变量时,该变量值也对该目标的所有先决条件及其所有先决条件等有效(除非这些先决条件以其自己的目标特定变量值)。因此,例如,像这样的语句:
prog : CFLAGS = -g prog : prog.o foo.o bar.o
...
在上面 GNU Make 示例的上下文中,我需要类似的内容:
带有 SSE4.2 的英特尔机器:
crc-simd.o: CRC_FLAG = -msse4.2
crc-simd.o:
$(CXX) $(CXXFLAGS) $(CRC_FLAG) -c $<
带有 CRC32 的 ARMv8a 机器:
crc-simd.o: CRC_FLAG = -march=armv8-a+crc
crc-simd.o:
$(CXX) $(CXXFLAGS) $(CRC_FLAG) -c $<
我认为在规则执行时定义 make 变量可能是相关的,但细节对我来说仍然是模糊的。我不确定它是基石还是另一种选择。
特定于目标的变量是有条件地设置变量的合适工具CRC_FLAG
吗?如果是,那么我们如何使用它来有条件地设置变量?
如果没有,那么有没有办法CRC_FLAG
仅在crc-simd.o
需要构建时为其赋值?如果有,那我们怎么做呢?
这是我们的 GNUmakefile 包含的内容。尽管显示了 ARMv8a,但 x86/x32/x64 是相似的。我们对 SSE4.2、NEON、AES、SHA、CLMUL、AVX 和 BMI 做了类似的处理。
测试编译后,CRC_FLAG
在MIPS上为空,-msse4.2
在SSE4.2可用时取,-march=armv8-a+crc
在ARMv8a上。问题是,它使食谱make clean
需要太多时间来运行。即使构建一个脏对象文件也会招致所有编译的愤怒。滞后是明显的。
TEMPDIR ?= /tmp
EGREP ?= egrep
IS_ARMV8 ?= $(shell uname -m | $(EGREP) -i -c 'aarch32|aarch64')
...
ifeq ($(IS_ARMV8),1)
HAS_CRC := $(shell $(CXX) $(CXXFLAGS) -march=armv8-a+crc -o $(TEMPDIR)/t.o -c crc-simd.cpp; echo $$?)
ifeq ($(HAS_CRC),0)
CRC_FLAG := -march=armv8-a+crc
endif
endif
...
# SSE4.2 or ARMv8a available
crc-simd.o : crc-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(CRC_FLAG) -c) $<
如果您只需要为单个 .o 文件(如 )crc-simd.o
使用此标志,那么为什么要:=
在 的分配中使用CRC_FLAG
?如果您使用=
它,那么它在使用之前不会被扩展,如果您只使用它一次,它只会被扩展一次。
就像是:
ifeq ($(IS_ARMV8),1)
CRC_FLAG = $(shell $(CXX) $(CXXFLAGS) -march=armv8-a+crc -o $(TEMPDIR)/t.o -c crc-simd.cpp 2>/dev/null && printf %s -march=armv8-a+crc)
endif
# SSE4.2 or ARMv8a available
crc-simd.o : crc-simd.cpp
$(CXX) $(strip $(CXXFLAGS) $(CRC_FLAG) -c) $<
这仍然编译文件两次;似乎应该有一种更快的方法来确定是否支持该标志,但无论如何。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句