2
votes

I originally had two implicit rules(simplified for clarity):

%$(EXESUFFIX) : %.c
    $(CC) -o $* $< 

%$(EXESUFFIX) : %.cpp
    $(CXX) -o $* $< 

But the problem is that on OS X and Linux $(EXESUFFIX) is blank which leads the rule to match the wrong things. So I am trying to use the static pattern rule as follows:

$(EXECS) : %$(EXESUFFIX) : %.c
    $(CC) -o $* $< 

$(EXECS) : %$(EXESUFFIX) : %.cpp
    $(CXX) -o $* $< 

Where $(EXECS) is the target and therefore devoid of the extension. But now, the top rule is being run for sources which end in .cpp. How do I fix this?

For a complete example:

Makefile:

EXESUFFIX = 
EXECS = test

$(EXECS) : %$(EXESUFFIX) : %.c
    $(CC) -o $* $< 

$(EXECS) : %$(EXESUFFIX) : %.cpp
    $(CXX) -o $* $< 

test.cpp:

#include <stdio.h>

int main(int argc, char *argv[]){
  printf("Hello World\n");
  return 0;
}

This prints out the errors:

Makefile:8: warning: overriding commands for target `test'
Makefile:5: warning: ignoring old commands for target `test'
make: *** No rule to make target `test.c', needed by `test'.  Stop.
2
You might want to paste the whole makefile and an ls of your source dir.user657267
What "wrong things" does that rule incorrectly match? That might be a more easily solvable problem than this one.Etan Reisner
@user657267 I am trying to make it so that if there exists a file which ends with .cpp and the filename without the extension is in the $(EXECS) list do the bottom rule, if it ends with .cpp do the top rule. That idea holds in the top case (without the static pattern rule), but not with the static pattern rule.chacham15
Rewriting my comments for clarity: you have two rules to make test, with two prerequisites, but test.c does not exist and make doesn't know how to create it. Why do you need separate rules for test in the first place?user657267
@user657267 it isnt specifically for just test, what if there is a second executable whose source is a c file? Yes, I could separate out "C executables" and "c++ executables" but I would rather not if I dont have to.chacham15

2 Answers

3
votes

The GNU Make manual you linked to is quite clear about the difference between static rules and implicit rules.

4.12.2 Static Pattern Rules versus Implicit Rules

A static pattern rule has much in common with an implicit rule defined as a pattern rule > (see Defining and Redefining Pattern Rules). Both have a pattern for the target and patterns for constructing the names of prerequisites. The difference is in how make decides when the rule applies.

An implicit rule can apply to any target that matches its pattern, but it does apply only when the target has no recipe otherwise specified, and only when the prerequisites can be found. If more than one implicit rule appears applicable, only one applies; the choice depends on the order of rules.

By contrast, a static pattern rule applies to the precise list of targets that you specify in the rule. It cannot apply to any other target and it invariably does apply to each of the targets specified. If two conflicting rules apply, and both have recipes, that's an error.

I suggest splitting your executables between C and C++ programs and defining independent rules for each.

0
votes

I cannot reproduce your error, but this works in GNUMake 3.81:

%$(EXESUFFIX) : %.c
    $(CC) -o $* $<

%$(EXESUFFIX) : %.cpp
    $(CXX) -o $* $<

Having two different rules that fit the same target is legal with ordinary pattern rules, but not with static pattern rules.