21

I know you can use if statements like the following in makefiles:

foo: $(objects)
ifeq ($(CC),gcc)
        $(CC) -o foo $(objects) $(libs_for_gcc)
else
        $(CC) -o foo $(objects) $(normal_libs)
endif

Is there a way to do a conditional replacement like possibly a ternary type operator.

(condition?$(CC):$(CC2)) -o foo $(objects) $(libs_for_gcc)  

And if there isn't what would be the most idiomatic way to achieve the example

I added the c++ tag because the question had only 7 views and I figured someone who used c++ might be likely to know the answer,I know this isn't strictly a c++ question(though I am planning to compile c++ with it)

EDIT: looks like there is an if function using this syntax
$(if condition,then-part[,else-part])
I'm still a little confused on how it works though

aaronman
  • 18,343
  • 7
  • 63
  • 78

2 Answers2

26

The $(if ...) function can serve as a ternary operator, as you've discovered. The real question is, how do conditionals (true vs. false) work in GNU make? In GNU make anyplace where a condition (boolean expression) is needed, an empty string is considered false and any other value is considered true.

So, to test whether $(CC) is the string gcc, you'll need to use a function that will return an empty value when it isn't, and a non-empty value when it is.

Typically the filter and filter-out functions are used for this. Unfortunately it's easiest to use these in such a way that you get the "not equal" result; in other words, using these functions it's much simpler to accurately generate a non-empty string (true) if the string is not gcc, and an empty string (false) if the value is gcc. For example:

$(if $(filter-out gcc,$(CC)),$(info is not gcc),$(info is gcc))
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • I figured there would be a way to achieve what I wanted, is this considered idiomatic when writing a makefile, also I would upvote but I have to wait 42 mins, ran outa votes – aaronman Jul 31 '13 at 23:25
  • I think that actually Chris is correct: this kind of thing is just rarely done in makefiles. Usually other methods are used, such as recursive variable naming (something like `gcc_LIBS = $(libs_for_gcc)`, then in the rule you use `$($(CC)_LIBS)`, or including different makefiles to set up variables for different compilers, etc. So I wouldn't really call it idiomatic. But it's not unheard of. – MadScientist Aug 01 '13 at 04:20
  • ok, the only reason I didn't like Chris' answer is because it provided nothing I didn't already know. I have now UV'd him – aaronman Aug 01 '13 at 04:23
5

If the only effect you are trying to achieve is to use either the one or the other compiler, I think the best way is to use a variable for that special compilation step and set this depending on your condition.

ifeq (condition)
    MYCC=$(CC2)
    LIBS=$(LIBS_FOR_CC2)
else
    MYCC=$(CC)
    LIBS=$(LIBS_FOR_CC)
endif

and then later in the rule to compile use

$(MYCC) -o foo $(objects) $(LIBS)

At least this is how I remember structuring the makefiles into a) configuration and b) the rule sets.

Sorry if that doesn't answer your question, but I am not aware of a ternay operator for GNU make (and I presume you are referring to GNU make?).

Chris
  • 91
  • 6
  • No offense but if the answer is going essentially tell me what I want is impossible and provides very little new info, I would prefer either you back it up with an article of some sort or it comes from someone who has a high rep in [tag:make] and not a user to the site who has joined today – aaronman Jul 31 '13 at 21:50
  • just to be clear if you can back up your answer I am perfectly happy to accept it – aaronman Jul 31 '13 at 21:52
  • 1
    I would suggest you run 'info make "Conditional Syntax"' and 'info make "Conditional Functions"' and read the manual. For your question, I am not really sure what you are trying to achieve. If you are working towards a more canoncial style in the makefile, I still would recommend my first suggestion. – Chris Jul 31 '13 at 22:07