Consider the following Makefile which knows to clean and rebuild itself if the Makefile or its included configuration files config.mk or local.mk are changed:
include config.mk
-include local.mk
-include dummy.rebuild
all: ...
# other targets...
# https://stackoverflow.com/a/3892826/149138
dummy.rebuild: Makefile config.mk local.mk
touch $#
$(MAKE) -s clean
This works fine if config.mk and local.mk actually exist - if either is modified, the dummy.rebuild target fires and the project is rebuild.
However, imagine that local.mk is an optional file which may or may not exist. In the case that it doesn't exist, the dummy.rebuild rule never seems to run at all, even if the Makefile or config.mk is changed. This is different behavior than a normal rule where a dependency doesn't exist, usually you'd get an error like:
make: *** No rule to make target 'local.mk', needed by 'dummy.rebuild'. Stop.
... but in the case of the dummy.rebuild target implicitly added as a target via inclusion, you just get:
make: Nothing to be done for 'all'.
How can I implement the makefile so that if any of Makefile, config.mk or local.mk are changed, the dummy.rebuild target is executed, where the local.mk file may not exist?
I'm not entirely sure what you're trying to do, but maybe using this instead will give you the behavior you want:
local.mk := $(wildcard local.mk)
include $(local.mk)
...
dummy.rebuild: Makefile config.mk $(local.mk)
...
Using wildcard here expands to local.mk if the file exists, or the empty string if it doesn't exist so it will be ignored in all ways if it's not there.
Related
I'm learning make, and try to understand the following makefile from Prerequisite-Types
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
The first rule confuses me. It's to be firstly applied. Since $(OBJDIR) is not there, the last rule will be applied to mkdir objdir. Then, since there's nothing in the newly created directory, there's no stem.o, and correspondingly, no stem.c So the prerequisites and recipes seem to be meaningless.
The only thing that the first rule does is to make a directory, which seems to be unreal.
The first rule is a pattern rule, so it cannot be the default rule; it will not be the first applied unless you specify e.g. make thing.o.
The first rule might not do what you expect. The recipe is $(COMPILE.c) $(OUTPUT_OPTION) $<, but you don't assign a value to OUTPUT_OPTION in the makefile; unless you provide a value from outside (e.g. make thing.o OPTION_OUTPUT=...) this recipe has no special instructions about where to put the file it builds, it has never heard of objdir/, and will use the compiler's default which is probably the working directory.
The last rule will build objdir (if objdir does not already exist, and if Make invokes that rule). The command make objdir will work perfectly. If you try to build one of the object files listed in OBJS, Make will construct the directory (if the directory does not exit) -- not because it needs a place to put the file, but because $(OBJDIR) is a prerequisite of every member of $(OBJS), according to the third rule. It will not construct the directory if you try to build objdir/thing.o, because $(OBJDIR) is not a prerequisite of that target. You think Make should build it because it is obviously needed? Well, Make isn't that smart.
The first rule has a prerequisite pattern %.c, and the recipe looks for the source file in the working directory, not in any newly constructed subdirectory. If there is no such source file in the working directory, Make will not run that rule.
I don't really follow your logic.
The first rule in your makefile is this:
all: $(OBJS)
so the default goal for this makefile (if you don't specify one on the command line) is all.
all depends on all the .o files. All the .o files have an order-only dependency on the directory. So, first the directory is created, then the .o files are created, then all is done (there is no recipe here to create a program or library or anything out of those .o files).
I read this: Makefile: Copying files with a rule but couldn't do it.
To make it simple, suppose I have two directories dir1 and dir2. Under dir1 I have three files: rabbit.c, tiger.c and bus.c .
I made Makefile like this:
dir2/rabbit.c:dir1/rabbit.c
dir2/tiger.c:dir1/tiger.c
dir2/bike.c:dir1/bike.c
dir2/%:
cp -f $< $#
I specified the prerequisites in three separate lines and specified the unified recipe for the three targets. I expected when I touch any file under dir1, make will copy that file to dir2. But this happend only for rabbit.c. What is wrong?
ADD(after selecting an answer) :
After realizing what's wrong by Takkat's answer, I fixed it and later modified it further and I think this is the correct simplest Makefile for this case.
.PHONY:all
LIST:=rabbit.c tiger.c bike.c
DSTFILES:=$(addprefix dir2/, $(LIST))
all: $(DSTFILES)
dir2/%:dir1/%
cp -f $< $#
Make chooses a default target in your makefile and, unless you specify differently on the command line, it builds just that target (and all prerequisites required to build that target).
The default target in a makefile is, by default, the first explicit target listed.
So in your makefile the first rule is:
dir2/rabbit.c:dir1/rabbit.c
so the first explicit target is dir2/rabbit.c, so that's all make builds.
If you want to build multiple targets by default, you need a first target that lists all the "real" targets as prerequisites; put this line first in your makefile:
all: dir2/rabbit.c dir2/tiger.c dir2/bike.c
and it will work. It's often considered good practice to declare targets like this, which don't relate to real files on the disk, as phony:
.PHONY: all
From the docs, regarding VPATH:
After processing the prerequisites, the target may or may not need
to be rebuilt:
a. If the target does _not_ need to be rebuilt, the path to the
file found during directory search is used for any
prerequisite lists which contain this target. In short, if
'make' doesn't need to rebuild the target then you use the
path found via directory search.
b. If the target _does_ need to be rebuilt (is out-of-date), the
pathname found during directory search is _thrown away_, and
the target is rebuilt using the file name specified in the
makefile. In short, if 'make' must rebuild, then the target
is rebuilt locally, not in the directory found via directory
search.
Illustrating the above, with the following makefile - which is basically the same situation as section b. above - where the vpath-ized target turns outs to be out-of-date, we write the Makefile, as:
$(shell rm -rf all D)
$(shell mkdir D)
$(shell touch D/all)
VPATH = D
all: phony
echo '$#'
.SILENT: D/all
.PHONY: phony
Running, I get:
echo 'D/all'
D/all
Now, given that above quote that:
"if the target does need to be rebuilt (is out-of-date), the pathname found during directory search is thrown away, and the target is rebuilt using the file name specified in the makefile"
Why, then does Make build D/all, as evident by the output of the command, and not the original (before it was vpath-ized) target?
Simply make builds D/all because you have specified .SECONDARY: D/all which prevents make from "automatically deleting", i.e. throwing away, the pathname of D/all.
If you remove (or comment out) .SECONDARY: D/all and run make --debug on
$(shell rm -rf all D)
$(shell mkdir D)
$(shell touch D/all)
VPATH = D
all: phony
echo '$#'
.PHONY: phony
the output should be similar to
Reading makefiles...
Updating goal targets....
File 'phony' does not exist.
Must remake target 'phony'.
Successfully remade target file 'phony'.
Prerequisite 'phony' of target 'all' does not exist.
Must remake target 'all'.
Ignoring VPATH name 'D/all'.
echo 'all'
all
Successfully remade target file 'all'.
Here we can clearly see make now throws away the pathname of D/all and rebuilds all locally as per the documentation you've quoted.
.SECONDARY is documented in Special Targets in the GNU Make Documentation.
I understand that an "explicit" pattern rule will take precedence on its implicit counterpart when its prerequisites can be made.
all: src/foo.o
src/%.o: makefile my_haeder.h src/%.c
echo Do something with those source files
If there is a typo for "my_header.h", the implicit rule for %.o will take precedence. Not only my recipe will not be executed, but touching the prerequisites will not trigger the rule. Actually it is the second point which is of interest for me.
The make documentation offers a verification using static pattern rules:
SET_OF_FILES=src/foo.o
all: src/foo.o
$(SET_OF_FILES): src/%.o: makefile my_haeder.h src/%.c
echo Do something with those source files
This results in:
gmake: *** No rule to make target `src/my_haeder.h', needed by `src/foo.o'. Stop.
Though a larger rule, that solution is nice, as long as I don't have to add a rule for which the stem could overlap:
SET_OF_FILES=src/foo.o src/subsrc/bar.o
all: src/foo.o
$(SET_OF_FILES): src/%.o: makefile my_header.h src/%.c
echo Do something with those source files
$(SET_OF_FILES): src/subsrc/%.o: makefile my_header.h src/subsrc/%.c
echo Do something with those other source files
Which results in:
makefile:8: target `src/foo.o' doesn't match the target pattern
makefile:9: warning: overriding commands for target `src/foo.o'
makefile:6: warning: ignoring old commands for target `src/foo.o'
makefile:9: warning: overriding commands for target `src/subsrc/bar.o'
makefile:6: warning: ignoring old commands for target `src/subsrc/bar.o'
The first message is here because I didn't bother $(filter)ing SET_OF_FILES. I don't know how to solve the next warnings, which for any reviewer would mean "something's wrong".
Is there another (more elegant) way to verify that the prerequisites are actually feasible, in order to avoid dropping the explicit pattern rule?
(using GNU Make 3.79.1 win32)
Add a separate rule to check for your prerequisites
all: prereqs src/foo.o
prereqs: Makefile my_header.h
src/%.o: src/%.c Makefile my_header.h
echo Do something with those source files
src/subsrc/%.o: src/subsrc/%.c Makefile my_header.h
echo Do something with those other source files
which will give you:
make
make: *** No rule to make target 'my_header.h', needed by 'prereqs'. Stop
When I change a Makefile, its rules may have changed, so they should be reevaluated, but make doesn't seem to think so.
Is there any way to say, in a Makefile, that all of its targets, no matter which, depend on the Makefile itself?
(Regardless of its name.)
I'm using GNU make.
This looks like one more simple, useful, logical thing that Make should be able to do, but isn't.
Here is a workaround. If the clean rule is set up correctly, Make can execute it whenever the makefile has been altered, using an empty dummy file as a marker.
-include dummy
dummy: Makefile
#touch $#
#$(MAKE) -s clean
This will work for most targets, that is targets that are actual files and that are removed by clean, and any targets that depend on them. Side-effect targets and some PHONY targets will slip through the net.
Since GNU make version 4.3 it is now possible with the use of those two special variable:
.EXTRA_PREREQS
To add new prerequisite to every target
MAKEFILE_LIST
To get the path of the make file
To have every target depend on the current make file:
Put near the top of the file (before any include since it would affect the MAKEFILE_LIST) the following line:
.EXTRA_PREREQS:= $(abspath $(lastword $(MAKEFILE_LIST)))
To have every target depend on the current make file and also the make files which were included
Put the following line at the end of your file:
.EXTRA_PREREQS+=$(foreach mk, ${MAKEFILE_LIST},$(abspath ${mk}))
The only answer I know to this is to add makefile explicitly to the dependencies. For example,
%.o: %.c makefile
$(CC) $(CFLAGS) -c $<