在Makefile中检查gcc版本?

56

我想使用一些在旧版gcc中不可用的gcc警告开关(例如-Wtype-limits)。

有没有一种简单的方法来检查gcc版本并仅在使用较新版gcc时添加这些额外选项?


gcc --version 有什么问题吗? - rlibby
2
@rlibby:gcc --version 或 gcc -dumpversion 都可以。我正在寻找在 Makefile 中进行“版本更高”比较的方法。 - Gene Vincent
8个回答

61

我不会说这很容易,但你可以使用GNU make的shell函数执行像gcc --version这样的 shell 命令,然后使用ifeq条件表达式检查版本号并适当地设置你的CFLAGS变量。

以下是一个快速示例makefile:

CC = gcc
GCCVERSION = $(shell gcc --version | grep ^gcc | sed 's/^.* //g')
CFLAGS = -g

ifeq "$(GCCVERSION)" "4.4.3"
    CFLAGS += -Wtype-limits
endif

all:
        $(CC) $(CFLAGS) prog.c -o prog

编辑:没有ifgt命令。不过,你可以使用shell中的expr命令进行大于比较。下面是一个例子

CC = gcc
GCCVERSIONGTEQ4 := $(shell expr `gcc -dumpversion | cut -f1 -d.` \>= 4)
CFLAGS = -g

ifeq "$(GCCVERSIONGTEQ4)" "1"
    CFLAGS += -Wtype-limits
endif

all:
        $(CC) $(CFLAGS) prog.c -o prog

8
请使用:=代替=,否则每次扩展$(GCCVERSION)时都会运行$(shell) - Jack Kelly
3
我想检查是否有大于某个版本的内容。是否有类似ifeq的ifgt等效语句? - Gene Vincent
我修复了大于比较的逻辑错误。谢谢。 - srgerg
1
我使用了 GCCVERS := $(shell gcc --version | grep ^gcc | awk '{print $$3}') - Paul Rooney
应该是ifeq "$(GCCVERSIONGTEQ4)" "0"吗? - MKesper
显示剩余3条评论

23
将完整的gcc版本号(不仅是第一个数字)转换为数字格式,以便进行比较(例如40701),请使用:
gcc -dumpfullversion -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$/&00/'

这涉及到版本号中任何一部分出现两位数的可能性,以及在gcc -dumpversion输出中缺少第三部分版本号的情况(在某些早期的gcc版本中存在此情况)。

因此,要在makefile中测试版本号,请使用类似以下命令(请注意最后一个sed命令中的$$):

GCC_GTEQ_472 := $(shell expr `gcc -dumpfullversion -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40702)
ifeq "$(GCC_GTEQ_472)" "1"
  ...
endif

9

我遇到了这个问题,需要测试gcc的前两位数字,并希望有一个比上面巧妙的sed hackery更易读的选项。我使用了bc进行比较,因为它支持浮点数(expr将非整数视为字符串):

GCC_VER_GTE44 := $(shell echo `gcc -dumpversion | cut -f1-2 -d.` \>= 4.4 | bc )
ifeq ($(GCC_VER_GTE44),1)
...
endif

如果他们在发布gcc 4.9之后发布gcc 4.10,那么需要进行一些sed操作,但这仍然相当易读:
GCC_VER_GTE44 := $(shell echo `gcc -dumpversion | cut -f1-2 -d.` \>= 4.4 | sed -e 's/\./*100+/g' | bc )
ifeq ($(GCC_VER_GTE44),1)
...
endif

6

我发现这个方法非常聪明,可以用更少的Shell调用实现>、>=、<和<=:

GCC_VERSION := $(shell gcc -dumpversion)
VERSION := 7.4.0

ifeq ($(VERSION),$(firstword $(sort $(GCC_VERSION) $(VERSION))))
    # stuff that requires GCC_VERSION >= VERSION
endif

这个例子展示了 >=。你可以使用 ifneq 和 $(lastword) 的组合来实现 >, <=, 或者 <。
参考资料:

https://lists.gnu.org/archive/html/help-make/2006-04/msg00065.html


1
已经过了10年,一直表现不错,但在双位数版本元素方面失败了...例如在已经发布的GCC 10中。例如:"9.0 8.0 10.0"被排序为"10.0 8.0 9.0"。 - stefanct
sort -n 可能会解决这个问题。 - Charlie Reitzel

2

我已经准备好了一个可直接使用的IF_GCC宏,基于以上答案:

MY_GCC_VERSION=$(if $(GCC_VERSION),$(GCC_VERSION),$(GCC_DEFAULT_VER))
MY_GCC_TOINT=$(shell echo $(1) | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$//')
MY_IF_GCC=$(if $(shell test $(call MY_GCC_TOINT, $(MY_GCC_VERSION)) -$(1) $(2) || echo 0),$(4),$(3)) 
GCC_DEFAULT_VER:=$(firstword $(shell cc -V 2>&1 | grep default | sed -r 's/( *)([0-9.]+),(.*)/\2/g')) 

用法: $(call MY_IF_GCC,ge,30305,-fan_option_for_gcc_ge_3.3.5)

作为第二个参数,您可以使用test(1)支持的任何运算符:eq、gt、lt、ge、le等。

如果cc -V对您不起作用,请将其替换为gcc -dumpversion或适当的命令。

希望这有所帮助。


2
跟随 Chris,但使用 awk。最初的回答中提到了这种方法。
GCC_VER_GTE44 := $(shell expr $$(gcc -dumpversion | awk -F. '{print $$3+100*($$2+100*$$1)}') \>= 40400)

注意:在Makefile中,$需要用另一个$进行转义。

最初的回答:

请注意,在Makefile中,要使用两个美元符号$$来转义$


2

你是否使用类似于autoconf的工具?

值得尝试的是使用gcc调用一次“虚假”的编译,并启用该标志,如果该编译因为编译器不识别该标志而失败,则可以回退到不使用较新警告选项的命令行。


0

我认为awk是更好的工具,因为它可以将版本字符串分割成$1$2$3,然后在一个命令中使用><>=等进行比较。如果表达式为假,则整行从awk输出中省略。

GCC_VERSION_GT_75 = $(shell gcc -dumpfullversion -dumpversion | awk -F. '$$1 > 7 && $$2 > 5')
ifneq ($(GCC_VERSION_GT_75),)
    # stuff that requires gcc version > 7.5
endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接