1
votes

Is there a way to override the prerequisites of a target in later part of Makefile?

A common Makefile is used by multiple users. To accommodate individual unique usage, an include directive is added at the end.

E.g. in common.make

SomeVar1 =

all: step5

step1:
    recipe1

step2: step1
    recipe2

step3: step2
    recipe3

step4: step3
    recipe4

step5: step4
    recipe5

-include local.make

Whenever necessary, individual user can override variables or even recipes from common.make in his/her own local.make.

However, it seems prerequisite from common.make can't be overridden in local.make.

E.g. if a user needs to skip step3 & step4, adding the following in local.make doesn't remove step4 as prerequisite for step5 target.

step5: step2

Does GNU make have some syntax to force override prerequisites of targets defined in earlier part of Makefile?

Perhaps, something like:

.OVERRIDE: step5: step2

The only way I can think of is to define prerequisites of each rule in common.make as variables. But it will be unwieldy for large numbers of steps -- lots of variables to define and association/mapping of variable names to their steps requires separate documentations.

I would like to avoid the prerequisite-variable approach if possible. Hopefully, GNU make has some syntax that can do so better.

Thank you for your help.

HCN

3
If the dependencies aren't common to the users, why have them in the common makefile?Beta
@Beta, the dependencies are common for most users. For them, common.make will be used as is. But occasionally, a few users may need slightly different dependencies. In other words, common.make is sufficiently good most of the time to most users, but may not be so all the time to all users.HCN
There is another way, but it doesn't look any better than the prerequisite-variable approach, which frankly doesn't look any better than the desired .OVERRIDE: approach; you still need one statement specific to each rule you want to override, containing a description of the dependency relationship you want.Beta

3 Answers

0
votes

Make has ?= for overriding behavior:

-include local.make

# local.make definition of STEPX_PREREQS "overrides" below defaults
STEP1_PREREQS ?=
STEP2_PREREQS ?= step1
STEP3_PREREQS ?= step2

step1: $(STEP1_PREREQS)
    recipe1

step2: $(STEP2_PREREQS)
    recipe2

step3: $(STEP3_PREREQS)
    recipe3
0
votes

I just thought of a workaround that is not quite elegant as the desired hypothetical .OVERRIDE: but it doesn't require defining variable for each prerequisite in common.make.

Using the same common.gmake example, if a user needs to skip step3 & step4, but needs to add step1b & step1c between step1 & step2, his/her local.make will look as followed.

step1b: step1
    recipe1b

step1c: step1b
    recipe1c

step2: step1c

step3:
    :

step4:
    :

In addition, GNU make will also display warning messages about step3 & step4 targets being overridden, which is helpful.

local.make:10: warning: overriding commands for target `step3'
local.make:13: warning: overriding commands for target `step4'
common.make:12: warning: ignoring old commands for target `step3'
common.make:15: warning: ignoring old commands for target `step4'

Nevertheless, since this doesn't actually override dependencies, user has to force no-op to all dependencies to be skipped. In this case, no-op is necessary for both step3 & step4 targets, where in real common.make, each skipped target may have multiple prerequisites.

This is the only gotcha I can think of. I believe it'll work even with -j option for parallel execution.

Any potential pitfall in such local.make override usage that I haven't thought of, since I can't predict all possible GNU make options users may combine with local.make override?

HCN

0
votes

One way to get that override-like behavior is exploiting the pattern matching preferring "the most exact match". Making the original targets just a little ambiguous by a little pattern allows local.make to override with an exact match.

SomeVar1 =

all: step5

s%ep1:
    recipe1

s%ep2: step1
    recipe2

s%ep3: step2
    recipe3

s%ep4: step3
    recipe4

s%ep5: step4
    recipe5

-include local.make

If having step5 in local.make it is more exact than s%ep5.

(I do not actually like this solution, but you do you, I just bring the tech.)