我们有一个库项目,它从旧的i386 / i686 / x86_64中常见的未对齐数据访问转换为对齐数据访问。推动力是GCC和矢量化,它导致-O3
崩溃(GCC甚至是矢量化字符串与SSE4基元的比较)。
如果有人运行make并且没有特定的定义,那么我们要打印一条警告他们的info
消息。我在制作食谱时遇到了麻烦。
以下配方在运行时会产生错误(它使用 TAB ,而不是空格):
.PHONY check_defines
check_defines:
CONFIG_ALIGNED := $(shell $(EGREP) -i -c "[[:space:]]*#[[:space:]]*define[[:space:]]*NO_UNALIGNED_DATA_ACCESS" config.h)
CXX_ALIGNED := $(shell echo $(value CXXFLAGS) | $(EGREP) -i -c "-DNO_UNALIGNED_DATA_ACCESS")
ifeq ($(CONFIG_ALIGNED)$(CXX_ALIGNED),00)
$(info Warning: NO_UNALIGNED_DATA_ACCESS is not defined)
endif
错误是:
$ make check_defines
GNUmakefile:383: *** missing separator. Stop.
第383行是CONFIG_ALIGNED := ...
。 5.1 Recipe Syntax上的手册对我没有帮助。
如何制定规则以在食谱中执行测试?
答案 0 :(得分:2)
Makefile不像脚本一样被解析并且必须执行。食谱不是一个子程序。
您链接的页面明确告诉您配方的主体被视为shell命令,而不是声明/表达式:
- “规则上下文”中的变量定义,由制表符缩进为行的第一个字符,将被视为配方的一部分,而不是make变量定义,并传递给shell。
- 条件表达式(ifdef,ifeq等,请参阅条件语法的语法)在“规则上下文”中,由制表符缩进作为该行的第一个字符,将被视为配方的一部分并传递给壳。
所以你不能声明make变量或使用make conditionals。您只能使用shell命令。
尝试类似:
CONFIG_ALIGNED := $(shell $(EGREP) -i -c "[[:space:]]*#[[:space:]]*define[[:space:]]*NO_UNALIGNED_DATA_ACCESS" config.h)
CXX_ALIGNED := $(shell echo $(value CXXFLAGS) | $(EGREP) -i -c "-DNO_UNALIGNED_DATA_ACCESS")
ifeq ($(CONFIG_ALIGNED)$(CXX_ALIGNED),00)
CHECK_FAILED := 1
endif
.PHONY check_defines
check_defines:
if [ $(CHECK_FAILED) = 1 ]; then echo Warning: NO_UNALIGNED_DATA_ACCESS is not defined; exit 1; fi
或者使用shell检查条件:
CONFIG_ALIGNED := $(shell $(EGREP) -i -c "[[:space:]]*#[[:space:]]*define[[:space:]]*NO_UNALIGNED_DATA_ACCESS" config.h)
CXX_ALIGNED := $(shell echo $(value CXXFLAGS) | $(EGREP) -i -c "-DNO_UNALIGNED_DATA_ACCESS")
.PHONY check_defines
check_defines:
if [ $(CONFIG_ALIGNED)$(CXX_ALIGNED) = 00 ]; then echo Warning: NO_UNALIGNED_DATA_ACCESS is not defined; exit 1; fi
或者使用shell完成所有操作,声明shell变量而不是make变量:
.PHONY check_defines
check_defines:
config_aligned=`$(EGREP) -i -c "[[:space:]]*#[[:space:]]*define[[:space:]]*NO_UNALIGNED_DATA_ACCESS" config.h`
cxx_aligned=`echo $(value CXXFLAGS) | $(EGREP) -i -c "-DNO_UNALIGNED_DATA_ACCESS")`
if [ $${config_aligned}$${cxx_aligned} = 00 ]; then echo Warning: NO_UNALIGNED_DATA_ACCESS is not defined; exit 1; fi
(如果CXXFLAGS包含`pkg-config --cflags foo`
之类的任何外壳,那么此版本可能无效,因为这会混淆shell)
答案 1 :(得分:1)
在配方中,您需要使用任何$(...)
表达式将make的解析器置于shell模式之外。
.PHONY: check_defines
check_defines:
$(eval CONFIG_ALIGNED := $(shell echo 0))
$(eval CXX_ALIGNED := $(shell echo 0))
$(if $(filter 00,$(CONFIG_ALIGNED)$(CXX_ALIGNED)), \
$(warning Warning: NO_UNALIGNED_DATA_ACCESS is not defined) \
)
请注意,声明的变量不是规则的局部变量,因此您最好不要声明它们,而将shell表达式直接放在if表达式中。