How to prevent 'make clean' from building files scheduled for removal - makefile

If I run make clean twice the second invocation will build the dependency Makefiles that are scheduled for removal. How can I get Makefile to recognize the files scheduled for removal and skip the recursive call to make for that directory? In other words, only make clean in sub directory if the makefile already exists in each sub directory, on a per sub directory basis. I don't know the GNU-Make syntax but I'm looking for something like:
Dependencies=[dependency1,dependency2,dependency3,dependency4]
DoNotMake=[bool1,bool2,bool3,bool4]
for all (i < 4):
if (! Dependencies(i)/Makefile):
DoNotMake(i)=true
The current rules for make clean are as follows:
.PHONY: clean
clean:
$(MAKE) MAKEDEPEND=off SUBDIR_ARGS=clean
rm -f dependency1/Makefile
rm -f dependency2/Makefile
rm -f dependency3/Makefile
rm -f dependency4/Makefile
rm -f dependency4/src/config.h.in

I can't give you a definite answer since there's still a lot of your makefile that you haven't posted, but here are some things that we do to solve similar problems.
The make variable MAKECMDGOALS contains the current make target. If you want to avoid doing something when you run make clean, you can do something like this:
ifeq (,$(findstring $(MAKECMDGOALS),clean))
# Whatever you place here won't be run when you run 'make clean'
endif
You can also add a bit of shell script to only invoke a sub-makefile when it exists:
some_target:
[ -f $(SUB_FOLDER)/Makefile ] && $(MAKE) -C $(SUB_FOLDER)
If your makefiles are being created implicitly, then these may not work. You may be able to use the --assume-old= option to prevent make from re-building the makefiles (I've never tried to use that on a file that doesn't exist, so YMMV).

Related

make runs command even if underlying files have not changed

I want to recompile Unix.zwc, if any of the files in Unix/ directory has changed. I have created this Makefile:
all: Unix.zwc
zsh -c 'zcompile -Uz Unix.zwc Unix/*'
Unix.zwc: Unix/*
but when I run make, it always recompiles the file Unix.zwc even when none of the files Unix/* have changed.
What am I doing wrong?
Make works by comparing timestamps of files. This rule:
all: Unix.zwc
says that the all file will be updated if either (a) it doesn't exist or (b) it exists but its last modified time is older than the file Unix.zwc.
Maybe you can now see why everything is always rebuilt: the file all never exists, and so it's always considered out of date, so the recipe is always run. I don't know what the zcompile command actually does, but either the name of this target should not be all it should be whatever file the zcompile command generates, or else you'll have to create the all target by hand using touch $# for example.
Second, this rule doesn't do what you expect:
Unix.zwc: Unix/*
You don't have a recipe here, which means that make will never update Unix.zwc, which means that all will not be out of date when a file in Unix changes. If the all target depends on both the Unix.zwc file and the files in the Unix directory (which it appears it does) then you should remove the above prerequisite statement and write all as:
all: Unix.zwc Unix/*
zsh -c 'zcompile -Uz Unix.zwc Unix/*'
touch $#
What am I doing wrong?
You are putting the command for compiling Unix.zwc into the recipe for (phony) target all, instead of the recipe for its own target.
Since all does not exist, its recipe is always run. With GNU make, it is advisable to go even farther by explicitly declaring it phony to ensure that the recipe is run even if a file named all actually is created.
What you want is this:
all: Unix.zwc
Unix.zwc: Unix/*
zsh -c 'zcompile -Uz Unix.zwc Unix/*'
.PHONY: all

Makefile: What does 'make $* clean' mean?

I know what make clean does.
But what does make $* clean do?
I'm not able to find a clear explanation anywhere.
As Ross says, we can't help because you haven't provided enough context. You need to provide at least the rule in which the make $* clean appears.
However, I'll guess it looks something like this:
%.xyz:
make $* clean
Here, $* is an automatic variable which will expand to the stem of the target (the text matching the % in the pattern). So, if you invoke make foobar.xyz, this rule would invoke make foobar clean: it would run a sub-make, build the foobar target, then build the clean target.
I've not seen anything quite like the above, although I can think of reasons for doing it. Far more common would be if you mistyped the command and it really said make -C $* clean, giving a rule like this:
%.xyz:
make -C $* clean
(note you should never use the static string make when invoking a sub-make; you should always use $(MAKE) or ${MAKE}). In this example running make foobar.xyz would run make -C foobar clean, which means change to the directory foobar and run the clean target there.
If it is invoked from a shell script, then $* is expanded to the arguments passed to the shell script.
#!/usr/bin/env bash
# filename clean.sh
make $* clean
The above shell script can be invoked like,
#./clean.sh --silent
Which will eventually pass the --silent to the make application and execute the following command.
#make --silent clean
Finally, $* in a shell-script is expanded by the shell, not by the make application.

How to call top-level make with same arguments?

I want always call top-level makefile with same command line. I tried:
.PHONY: %
%:
$(MAKE) -C ${CURDIR}/.. ${CURDIR}/$*
but its does not work :(
I'm not sure what you're trying to do. Are you saying that for any invocation of make in this directory you want to run make in a different directory, with the same arguments?
You can't quite do this, but this will get you close:
.DEFAULT:
$(MAKE) -C ${CURDIR}/.. $#
I don't know why you were prefixing the $* with $(CURDIR) in the target name...?
The big difference between this and the original invocation is that it will run a separate make process for each target; that is if you run make foo bar it will invoke the "top-level makefile" twice: once with a target of foo and then again with a target of bar. There's no way to avoid this, that I can think of.

Strange behaviour after recursively calling another makefile

I have a main makefile in the root directory of my project. There is another makefile inside the include directory. The second makefile uses the include keyword to call some other makefiles in other projects which I have no control over it. I cannot directly include this makefile as it has some targets which have the same name as the ones that I have. As a workaround, I decided to use recursive calling. When I run this makefile through the shell, using the following command, it works nicely:
my_project$ make -C include -f Second_Makefile
But when I call it through the main Makefile as follows, it does not behave normally meaning that it reports some project specific errors rooted from the included files inside the second makefile which are very hard to locate.
all:
#$(MAKE) -C include -f Second_Makefile
I also tried the following line, but it did not help:
cd include; #$(MAKE) -f Second_Makefile
I think there should be difference between recursive calling and direct calling but I don't know what it is.

`make -n` starts a config.status

I start a make -n of big project (multiple directories; Makefile and configure created with autotools); I think that nothing can be changed by this make; but it starts a config.status --recheck and regenerates some Makefiles and config.h.
Why does make -n starts anything?
Have you read the manual? If you look at this section, you will see that recipe lines that start with a + and ones containing the $(MAKE) variable are always executed. Perhaps your Makefile contains such lines.

Resources