简体   繁体   中英

How do I create a static implicit rule in a Makefile?

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM