Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In gnu make, can the prerequisites in a static pattern rule have different suffixes

Our make file compiles .c source files with a static pattern rule like this:

OBJECTS = foo.o bar.o baz.o

$(OBJECTS): %.o: %.c
    $(CC) $< $(C_OPTIONS) -c -o $@

I need to change one of the .c files to an Objective-C .m file. Invoking the compiler is the same for both source types, so I'd like to use the same rule and just tweak it to be more flexible. I'd rather not change the OPTIONS variable because it's also used for the linking step, etc.

Is there a way to make the rule above more flexible to accommodate both .c and .m files?

Thanks

like image 413
Greg Sanborn Avatar asked Oct 21 '09 21:10

Greg Sanborn


People also ask

What is pattern rule in makefile?

A pattern rule looks like an ordinary rule, except that its target contains the character ' % ' (exactly one of them). The target is considered a pattern for matching file names; the ' % ' can match any nonempty substring, while other characters match only themselves.

What is a suffix rule C?

A single-suffix rule whose source suffix is ' . c ' is equivalent to the pattern rule ' % : %. c '. Suffix rule definitions are recognized by comparing each rule's target against a defined list of known suffixes.

How does GNU Make work?

GNU Make is a program that automates the running of shell commands and helps with repetitive tasks. It is typically used to transform files into some other form, e.g. compiling source code files into programs or libraries. It does this by tracking prerequisites and executing a hierarchy of commands to produce targets.

What are static rules?

Static pattern rules are rules which specify multiple targets and construct the prerequisite names for each target based on the target name. They are more general than ordinary rules with multiple targets because the targets do not have to have identical prerequisites.


2 Answers

We can add this either-or behavior to the list of things Make should be able to do easily, but isn't. Here's a way to do it, using "eval" to create a seperate rule for each object.

define RULE_template
$(1): $(wildcard $(basename $(1)).[cm])
endef

OBJECTS = foo.o bar.o baz.o

$(foreach obj,$(OBJECTS),$(eval $(call RULE_template,$(obj))))

$(OBJECTS):
    $(CC) $&lt $(C_OPTIONS) -c -o $@ 

Note that this depends on the source files already existing before you run Make (foo.c or foo.m, but not both). If you're generating those sources in the same step, this won't work.

Here's a less clever, more robust method.

CPP_OBJECTS = foo.o bar.o
OBJECTIVE_OBJECTS = baz.o
OBJECTS = $(CPP_OBJECTS) $(OBJECTIVE_OBJECTS)

$(CPP_OBJECTS): %.o: %.c 

$(OBJECTIVE_OBJECTS): %.o: %.m 

$(OBJECTS):
    $(CC) $&lt $(C_OPTIONS) -c -o $@ 

EDIT: corrected OBJECTS assignment, thanks to Jonathan Leffler.

like image 79
Beta Avatar answered Jun 25 '23 05:06

Beta


Not really just copy to

$(OBJECTS): %.o: %.m
  $(CC) $< $(C_OPTIONS) -c -o $@
like image 27
mmmmmm Avatar answered Jun 25 '23 05:06

mmmmmm