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
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.
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.
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.
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.
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) $< $(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) $< $(C_OPTIONS) -c -o $@
EDIT: corrected OBJECTS assignment, thanks to Jonathan Leffler.
Not really just copy to
$(OBJECTS): %.o: %.m
$(CC) $< $(C_OPTIONS) -c -o $@
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With