信息中的条件保护信息?

时间:2015-09-30 11:23:58

标签: gnu-make

我们有一个库项目,它从旧的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上的手册对我没有帮助。

如何制定规则以在食谱中执行测试?

2 个答案:

答案 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表达式中。