0
votes

I would like to create a Makefile with multiple ways to produce a file:

.PHONY: app bin tgt

app file: app-dependency ; touch file

bin file: bin-dependency ; touch file

tgt: file ; touch tgt

Such that I could run make tgt and depending on whether the file app-dependency or bin-dependency was present would decide which to targets to run.

When I write something like the above, I get the following warnings:

warning: overriding recipe for target 'file'
warning: ignoring old recipe for target 'file'

2
Are app and bin directories? "app file" doesn't look like valid syntax. It would help to have a working example, perhaps using "touch" to create file. - Alcamtar
You need to rewrite your question to use consistent naming or we can't tell what you're doing. Your error messages show "target" but there's no "target" in example makefile. Please consider creating a MCVE stackoverflow.com/help/mcve - MadScientist
Ah nevermind, I see what you are doing. - Alcamtar

2 Answers

1
votes

Your specification is not 100% complete so let's invent what's missing: if app-dependency exists, use app-rule else if bin-dependency exists, use bin-rule, else raise an error. If it is not what you want, please edit your question and try to add the missing bits of specification.

Make conditionals are a way to do what you want:

.PHONY: app bin tgt

ifeq ($(wildcard app-dependency),app-dependency)

app file: app-dependency
    app-rule

else ifeq ($(wildcard bin-dependency),bin-dependency)

bin file: bin-dependency
    bin-rule

else

app bin file:
    $(error app-dependency and bin-dependency not found)

endif

tgt: file
    tgt-rule
0
votes

Since app, bin, and tgt are phony then the dependencies won't be used anyway, except to prevent a rule from building if it is missing.

There is no way for tgt to know which version of file to build. If file is created identically by both app and bin, then factor it out:

file: ; touch file
app: file ; ...
bin: file ; ...
tgt: file ; ...

If app and bin build different versions of file, then there is no need to make it a target. Tgt won't know which one to build anyway:

app: ; touch file
bin: ; touch file
tgt: file ; ...

If the intent is that tgt should build both app and bin if file is missing (it acts as an "or" dependency), you can factor it out:

app: ; touch file
bin: ; touch file
file: app bin
tgt: file ; ...