You are not logged in.

#1 2023-04-27 01:39:12

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,742
Website

[SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

I'm getting a behavior from make (both gnu make and bmake) that doesn't make sense to me.  As it is in both implementations, there must be a reason, but I'd appreciate any clarification on why this happens.

I try to write fairly generic Makefiles that use implicit rules wherever possible.  But if an object file is to be built from a .c source and .h header the header needs to be added as a prerequisite to the recipe in order for make to trigger a rebuild of that object file if / when the header changes.  I trivial example can be seen with the minimal Makefile below:

project: project.o

project.o: project.h

This assumes two source files exist: project.c and project.h.  The latter can be an empty file, the former could be the following:

int main(void) {
   return 0;
}

With this set up, you can then run `touch project.h` and `make` will then correctly rebuild the object file and final binary.  But this is not the case with the following (diff-style) change to the Makefile:

- project.o: project.h
+ %.o: project.h

Now when `make` is called again it will report that 'project' is up to date regardless of any changes to the header file.

I'd prefer to use the wildcard target format as for my actual use I have a single project header that is used by all the source files.  Though I have found that a rule like the following also works fine:

MODULES  = project other another

project: $(MODULES:%=%.o)

$(MODULES:%=%.o): project.h

This allows my to add the header prerequisite to all the modules just fine, but I'd like to understand why the generic wildcard rule `%.o: project.h` will not.

Last edited by Trilby (2023-04-27 15:47:32)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#2 2023-04-27 03:44:06

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 245

Re: [SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

As i understand, pattern rule must contain recipe. By defining empty recipe you just delete pattern rule if such exists.

Offline

#3 2023-04-27 04:10:30

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,742
Website

Re: [SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

The implicit recipes work fine and will build the project properly when source files (e.g., project.c) have changed. Adding additional prerequisite appends to existing prerequisite list(s) while keeping the rest of the recipe/rule in place.  If this were not the case, the wildcard version of my makefile would never build the project at all - but it does so fine but it only misses the need to rebuild when the header file has been modified.

Last edited by Trilby (2023-04-27 04:11:15)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#4 2023-04-27 04:41:50

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 245

Re: [SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

Trilby wrote:

The implicit recipes work fine and will build the project properly when source files (e.g., project.c) have changed.

Because there is built-in implicit pattern rule:

%.o: %.c
#  recipe to execute (built-in):
        $(COMPILE.c) $(OUTPUT_OPTION) $<
Trilby wrote:

Adding additional prerequisite appends to existing prerequisite list(s) while keeping the rest of the recipe/rule in place. 
If this were not the case, the wildcard version of my makefile would never build the project at all - but it does so fine but it only misses the need to rebuild when the header file has been modified.

This

$(MODULES:%=%.o): project.h

is not a pattern rule. It is substituted with

project.o: project.h

before it is applied.

See Canceling Implicit Rules:

You can cancel a built-in implicit rule by defining a pattern rule with the same target and prerequisites, but no recipe.

Offline

#5 2023-04-27 13:36:31

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,742
Website

Re: [SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

Your missing my point, the implicit rule is clearly not cancelled as the makefile with the wildcard rule still builds the project just fine in all cases except when the header file has changed.  If the wildcard rule cancelled the implicit rule this would not happen.  And the specification of an additional prerequisite is not defining a new rule with the same target and prerequisites.

Last edited by Trilby (2023-04-27 13:37:11)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#6 2023-04-27 14:41:04

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 245

Re: [SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

Trilby wrote:

Your missing my point, the implicit rule is clearly not cancelled as the makefile with the wildcard rule still builds the project just fine in all cases except when the header file has changed.

I'm not saying "%.o: project.h" cancels built-in implicit rule "%.o: %.c". It doesn't because both target and prerequisites must match. It _would_ cancel another "%.o: project.h ; ..." rule if such exist (it obviously doesn't). Pattern rules without recipe make no sense except canceling existing rules.

See Implicit Rule Search Algorithm:

4. Remove from the list all rules with no recipe.

Last edited by dimich (2023-04-27 14:41:45)

Offline

#7 2023-04-27 15:47:10

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,742
Website

Re: [SOLVED] make: adding prerequsite to recipe fails w/ wildcard targets

Ah, thanks - that's what I was missing.

It does seem odd to me yet that the rule search would be different for pattern vs non-pattern rules such that specifying "these object files depend on this header" works but "all object files depend on this header" will not - but that's clearly the documented intent.

Last edited by Trilby (2023-04-27 15:53:20)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

Board footer

Powered by FluxBB