I can't seem to find any examples of this online, and it doesn't seem to work for me. Can you have a pattern rule in a make file that has two matching dependencies?
For example
%.sas7bdat: %.sas %.dat
# build %.sas7bdat using %.sas and %.dat
Specifically, if I run make, it states...
make: *** No rule to make target `sip84fp.sas7bdat', needed by `sipp84'. Stop.
Even though the rule is clearly defined as above.
However, reducing the rule to this...
%.sas7bdat: %.sas
seems to work?
Yes, both static pattern rules and implicit pattern rules can have multiple prerequisites that contain a %
reference to the pattern stem.
Implicit pattern rules are different from static pattern rules, or ordinary non-pattern rules in that they only apply when they either have no prerequisites ("unconditionally make this thing") or else the prerequisites exist.
That is to say, if a target that needs to be built, like sip84fp.sas7bdat
needs to be updated, then indeed the pattern rule %.sas7bdat: %.sas %.dat
is a candidate. But a check is made: the sip84fp
stem is inserted into the prerequisite patterns to generate sip84fp.sas sip84fp.dat
. These both have to exist. If they do not exist, then the rule is removed from consideration, and the search continues for some other rule.
This is why in the end you get a message about "no rule": it really means that no rule was left after ignoring all the implicit rules that didn't apply.
By contrast, under a static pattern rule or ordinary rule, if a target matches a rule, and a prerequisite doesn't exist, the prerequisite must be updated. For instance if you have foo.o: foo.c
and foo.c
doesn't exist, the rule cannot be thrown away because it's not implicit: that rule must be used for foo.o
. Make will then look for a rule which builds foo.c
(and probably not find one: the error will then be that there is no rule to make foo.c
, not foo.o
).
See the topic Implicit Rule Search Algorithm in the GNU Make Manual.
If it is an expected behavior that the .dat
file might not exist, you have to express that in some other way. For instance, one way is to use some external dependency generation to make numerous concrete rules of the form:
foo.sas7bdat: foo.dat
Put that into a foo.d
file, and include
it into the Makefile
. If you have a variable called TARGETS
which holds the names of all .sas7bdat
files, you can include all their .d
dependency files like this:
-include $(patsubst %.sas7bdat,%.d,$(TARGETS))
This is the same as for compiling C. We wouldn't write a pattern rule like this for C programs:
%.o: %.c %.h
# ... build steps
This is because not every foo.c
has a foo.h
, and so the rule would not apply to such cases. Rather, we have:
%.o: %.c
and then any additional dependencies, like foo.o
depending on foo.h
are expressed elsewhere. The implicit rule only matches the principal deliverables: the object file and the "root" file of the translation unit.
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