Declare all targets PHONY
Asked Answered
T

4

47

Consider a long makefile with numerous targets, all of which are PHONY (meaning that the target name does not represent an existing file).

I can do either:

.PHONY: a
a:
    do someting a

.PHONY: b
b:
    do someting b

.PHONY: c
c:
    do someting c

Or:

.PHONY: a b c
a:
    do someting a

b:
    do someting b

c:
    do someting c

The first option is cumbersome, and the second option is prone to error, when future me adds a target and forget to declare it as PHONY.

Is there a standard way to declare all targets in a makefile as PHONY?

Torrey answered 12/6, 2017 at 6:36 Comment(16)
If all targets are PHONY, make is not the correct tool because it has no advantage whatsoever over a plain script... .PHONY: $(MAKECMDGOALS) would make exactly the targets given at the command-line phony, which would work for you if none of your targets depend on other targets.Opulent
I agree with Felix. And I think the second version is more standard than the first one. I don't think it's that error prone, you should somehow keep control over what you have in your Makefile regardless of its size.Alyse
I will be more than happy to have these comments as answersTorrey
I disagree with Felix and TimF. Make does have advantages over "plain scripts" in that you can use make to specify the order in which recipes and external scripts are run by using dependencies. You can also use the Makefile as a clean way to store and call multiple recipes/scripts from a single file. That way the Makefile is essentially a directory of commands and that you'd probably rather not have to type over and over. The target names can be used as aliases to the actual command/script name.Frizzell
@ShammelLee You know about the case statement and functions in scripts, do you? The whole idea about make is that it decides based on timestamps, so if all your targets are PHONY, make is pointless.Opulent
@FelixPalmen So pointless, I use it for this very reason all the time. Make's syntax is much simpler than passing arguments to a script that then have to be interpreted by the ugly syntax of a switch statement. So why not use .PHONY for exactly what it was intended?-which is to trigger a target every time, regardless of whether or not it's out of date. Regarding the "whole idea" of Make, you forgot to mention the other part of the "whole idea"… dependency management. Which, in my case, is why I prefer to use Make than rewriting (and debugging) dependency logic in a shell script.Frizzell
@ShammelLee dependencies between PHONY targets are very simple: unconditionally execute the recipes for these other targets before your own. This has to be stated explicitly and is completely functionally equivalent to first calling some other functions in a (shell) script. I rest my case, this misses the point of make. Sure it works, it's just like using pincers to pull a screw.Opulent
@FelixPalmen if they're equivalent, then your argument is basically that you prefer to use scripts. The OP obviously sees the usefulness of using Make to run commands.Frizzell
@ShammelLee yes, they're equivalent in functionality. But only make has all sorts of bells and whistles to support a real building process based on file timestamps. This goes to great lengths with GNU make. It just doesn't make sense to even depend on make here.Opulent
Let's call it a peculiar use of Make.Frizzell
Here's an example of companies like Facebook using Makefiles in the exact way I described => github.com/graphql-python/graphene/blob/master/docs/MakefileFrizzell
Old discussion, but I think 2 years later this question is more relevant than ever. I am trying to use make to setup an application that relies on some dozen microservices running on docker containers. I want to be able to start each service individually, so during development, I can just start one of them, develop something and test, without running the whole application. But the services have some common dependencies, and declaring them as make targets make it very convenient to start any number of services, being sure that all the dependencies are ran in the right order, and only once.Kidd
Does .PHONY: % work in this situation? IIRC % matches all targets when used as a dependency. You could put that at the bottom of each Makefile.Phalansterian
You can use just. It's similar to make but all the rules are PHONY by default. github.com/casey/justPartial
@JuliusEcker: .PHONY: % does not work for me, neither at the top nor at the bottom of a file.Inflight
After careful consideration, I think your first approach with .PHONY right before each target is the best way. Wildcards like .PHONY: * are good for DRY but will become useless if one day you will need non-phony target. And between DRY and flexibility I would choose flexibility.Mesenchyme
O
16

If really all targets are PHONY, this is a bit pointless. make is meant for "do what is necessary to update my output", and if the answer to what is necessary? is always the same, simple scripts would do the same job with less overhead.

That being said, I could imagine a situation where all targets intended to be given at the commandline should be PHONY -- Let's assume you want to build some documents like this:

all: doc1.pdf doc2.pdf doc3.pdf doc4.pdf doc5.pdf

manuals: doc3.pdf doc4.pdf

faqs: doc1.pdf

designdocs: doc2.pdf

apidocs: doc5.pdf

developerdocs: doc2.pdf doc5.pdf

userdocs: doc1.pdf doc3.pdf doc4.pdf

%.pdf: %.md
     $(somedocgenerator) -o $@ $<

Then you could do the following:

.PHONY: all $(MAKECMDGOALS)

This would dynamically make any target given at the command line PHONY. Note you have to include your default target here as this could be invoked without giving it explicitly, by simply typing make.

I would not recommend this approach because it has two drawbacks:

  • It's less portable to different flavors of make.
  • It will misbehave if someone decides to make a specific output file like here make doc3.pdf.
  • It will also misbehave if you decide to have one of your PHONY targets depend on another PHONY one.

So, better go with the approach to have one line declaring all the PHONY targets. If your Makefile is really huge, you could split it in several files and use include -- and have one .PHONY: line in each file.

Opulent answered 12/6, 2017 at 12:19 Comment(7)
I disagree with the premise that a Makefile with all phony targets should be replaced by arbitrary scripts. Make is an extremely prolific tool which has become the de facto standard for building most projects. Replacing it with arbitrary build scripts in a project would break from this standard and likely cause confusion among both developers and consumers.Acerate
Using Make for dep management in your project is great! Make is a wonderful tool, and given the nature of software development in 2020, building file by file is likely not the use case most people are trying to solve. .PHONY: % will do what most folks want.Phalansterian
@JuliusEcker .PHONY: % does not work for me (GNU make 4.3)Inflight
make's autocomplete and the huge chance of being already installed makes it a very convenient tool for grouping workflow scripts in a project, even if that wasn't the intended usage of the tool.Lorrianelorrie
what if I need targets to be dependent on each other? make does it so easy to write and maintain. But what will turn out from a bunch of shell scripts.Madly
I have downvoted this answer. "If really all targets are PHONY, this is a bit pointless" <- this is a false statement.Hull
I have downvoted this, because honestly I don't think it even tries to answer the question.Broncho
R
15

Just use MAKEFLAGS and set option --always-make like so:

MAKEFLAGS += --always-make
Radborne answered 1/1, 2022 at 17:28 Comment(3)
This should be at the top of the Makefile?Adagio
How to use this?Enterectomy
You define the MAKEFLAGS in the Makefile on top, its an environment variables that make looks at for options. You can read more about it here: gnu.org/software/make/manual/html_node/…Radborne
Y
14

For me .PHONY: * worked. (GNU make 4.2.1)

Yulma answered 2/4, 2022 at 23:14 Comment(3)
Doesn't work here. GNU make 4.4.1.Serai
Not working in GNU Make 3.82.Enterectomy
Thank you! Works with GNU Make 4.3 Built for x86_64-pc-linux-gnu. Tested with .PHONY: * set at the very top of Makefile.Stagner
T
3

One way to do it:

.PHONY: $(shell sed -n -e '/^$$/ { n ; /^[^ .\#][^ ]*:/ { s/:.*$$// ; p ; } ; }' $(MAKEFILE_LIST))

Works perfectly even for targets mentioned as dependencies.

Tellus answered 7/9, 2020 at 21:36 Comment(1)
Actually answers the questionPoaceous

© 2022 - 2024 — McMap. All rights reserved.