我正在处理下面描述的问题。研究时,GNU Make manual,第6.11节说:
make中的变量值通常是全局的;也就是说,它们是一样的 无论他们在哪里被评估......一个例外是 自动变量(参见自动变量)。
另一个例外是特定于目标的变量值。此功能 允许您根据相应变量定义不同的值 目前建立的目标。和自动一样 变量,这些值仅在a的上下文中可用 目标的配方(以及其他特定于目标的分配)。
设置特定于目标的变量值,如下所示:
target … : variable-assignment
多个目标值为其创建特定于目标的变量值 目标列表中的每个成员。
...
目标特定变量还有一个特殊功能:何时 您定义了一个特定于目标的变量,变量值也在其中 影响该目标的所有先决条件及其所有先决条件 先决条件等(除非这些先决条件覆盖该变量 用他们自己的特定目标变量值)。所以,例如,a 声明如下:
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 $<
我认为Define make variable at rule execution time可能是相关的,但细节对我来说仍然模糊不清。我不确定它是否是关键或只是另一种选择。
特定于目标的变量是否有条件地设置CRC_FLAG
变量?如果是,那么我们如何使用它来有条件地设置变量?
如果没有,那么只有在需要构建CRC_FLAG
时才能为crc-simd.o
分配值吗?如果有,那我们该怎么做呢?
这是我们的GNUmakefile包含的内容。虽然显示了ARMv8a,但x86 / x32 / x64类似。我们对SSE4.2,NEON,AES,SHA,CLMUL,AVX和BMI做了类似的工作。
测试编译后,MIPS上的CRC_FLAG
为空,SSE4.2可用时为-msse4.2
,ARMv8a为-march=armv8-a+crc
。问题是,它使像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) $<
答案 0 :(得分:1)
如果您只需要{。1}}这样的单个.o文件的此标记,那么为什么在crc-simd.o
的分配中使用:=
?如果您使用CRC_FLAG
代替它,那么在它被使用之前它不会被展开,如果您只使用它一次它将只展开一次。
类似的东西:
=
这仍然会编译文件两次;似乎应该有一种更快的方法来确定是否支持该标志,但无论如何。