57

I would like to use some gcc warning switchs that aren't available in older gcc versions (eg. -Wtype-limits).

Is there an easy way to check the gcc version and only add those extra options if a recent gcc is used ?

2
  • What's wrong with gcc --version? Commented Mar 4, 2011 at 0:29
  • 2
    @rlibby: gcc --version or gcc -dumpversion are fine. I'm looking for a "version is greater" comparison in the Makefile. Commented Mar 4, 2011 at 0:58

8 Answers 8

62

I wouldn't say its easy, but you can use the shell function of GNU make to execute a shell command like gcc --version and then use the ifeq conditional expression to check the version number and set your CFLAGS variable appropriately.

Here's a quick example 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

Edit: There is no ifgt. However, you can use the shell expr command to do a greater than comparison. Here's an example

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
Sign up to request clarification or add additional context in comments.

8 Comments

Use := instead of =, or else that $(shell) is going to get run every time $(GCCVERSION) is expanded.
I would like to check for greater than a certain version. Is the there a ifgt equivalent to ifeq ?
thanks - very useful - I was just about to post a question asking how to test for gcc version >= 4.3 but I worked it out myself using your expr method.
I fixed the reversed logic of the greater than comparison. Thanks.
I used GCCVERS := $(shell gcc --version | grep ^gcc | awk '{print $$3}')
|
25

To transform full 3-part gcc version (not only first digit) into numerical format, suitable for comparison (e.g. 40701) use

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/'

Which addresses the possibility of double-digit numbers in any of the version part, and possibility of missing 3-rd part of the version in output of gcc -dumpversion (which is the case in some earlier gcc versions).

So to test the version in makefile, use something like (note $$ inside last sed command)

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

Comments

9

I just encountered this problem where I needed to test the first two digits of gcc and wanted a more readable option than the clever sed hackery above. I used bc to do the comparison since it supports floating point (expr treats non-integers as strings):

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

If they release gcc 4.10 after gcc 4.9, then a bit of sed hacking is necessary, but this is still pretty readable:

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

Comments

6

I found this and thought it was really clever. It implements >, >=, <, and <= with fewer shell calls:

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

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

This example shows >=. You can implement >, <=, or < using combinations of ifneq and $(lastword).

References:

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

2 Comments

Has been nice for over 10 years but fails with double-digit version elements... such as in GCC 10, which has already been released. Example: "9.0 8.0 10.0" is sorted into "10.0 8.0 9.0".
sort -n might fix that
2

Are you using something like autoconf?

It might be worth invoking a 'dummy' compile via gcc with the flag enabled and if that one fails because the compiler doesn't recognise the flag, you can fall back to the command line that doesn't use the newer warning options.

Comments

2

I've made a ready-to-use IF_GCC macro, based on the answers above:

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')) 

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

As the second argument, you can use any operator of those supported by test(1): eq, gt, lt, ge, le etc.

If cc -V doesn't work for you, replace it with gcc -dumpversion or whatever suitable

Hope that helps.

Comments

2

Following Chris, but using awk

GCC_VER_GTE44 := $(shell expr $$(gcc -dumpversion | awk -F. '{print $$3+100*($$2+100*$$1)}') \>= 40400)

note $ needs to be escaped in Makefile with another $.

Comments

1

I think awk is a better tool for this purpose, as it can both split the the version string into $1 $2 and $3 and then do the comparison with >, <, >= etc. in one command. The whole line is omitted from awk output if the expression is false.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.