I'd like to do a Makefile that runs either with gnumake or makepp that packs all the files under given directiories:
DIRS:=$(shell find . -mindepth 2 -maxdepth 2 -not -name mp3 -not -name ".*" -type d)
PACKAGES = $(DIRS:%=%.npk)
all: packages
packages: $(PACKAGES)
%.npk: %/*
npack c $@ @^
.PHONY: all packages
the problem is that there's no such thing as %/* in the dependencies. I need the targets (X.npk) to depend on every file in directory X, but I don't know what the files are when I write the Makefile, 'cause they're generated later.
An example:
./dirA/x
./dirA/y
./dirB/e
./dirB/f
I'd like to create ./dirA.npk (depending on x,y), ./dirB.npk (e,f) There's nothing I know about the dirs or the files in advance except that the find used in the 1st line finds all the dirs.
A dependency is a file that is used as input to create the target. A target often depends on several files. A command is an action that make carries out. A rule may have more than one command, each on its own line.
Yes, a Makefile can have a directory as target. However, you shouldn't. When a file is added or removed from a directory, its mtime is updated. This can cause weird behaviour by causing multiple targets depending on a single directory to become implicitly rebuilt by one another.
The order of rules is not significant, except for determining the default goal: the target for make to consider, if you do not otherwise specify one. The default goal is the target of the first rule in the first makefile. If the first rule has multiple targets, only the first target is taken as the default.
This means that when you do a "make all", make always thinks that it needs to build it, and so executes all the commands for that target. Those commands will typically be ones that build all the end-products that the makefile knows about, but it could do anything.
Try using the wildcard
directive:
DEPS := $(foreach dir, $(DIRS), $(wildcard $(dir)/*))
%.npk: $(DEPS)
npack c $@ $^
EDIT:
The above is just an example of using wildcard
and makes each .npk file dependent on the files in all of the other folders. Your usage would be slightly different.
I think there may be an easier way to go about this. Why are you wanting to have a dependency on all of the files in the folder? Is it just to use the $^
operator? Or do you need to rebuild the .npk if any of the files changed?
One alternate (and possibly cleaner) solution would be to use the find
utility in your recipe instead of $^
and use the .FORCE
directive to always force the .npk file to be rebuilt. The downside is that .npk files may be rebuilt unnecessarily.
EDIT 2:
If there's not a way to do this cleanly with make
commands, you can work around it by using .FORCE
to ensure that the recipe is always run and move the "should I rebuild this file" check into the body of the recipe:
%.npk: .FORCE
check_for_rebuild.sh $@ && npack c $@ $^
where check_for_rebuild.sh
is a shell script that does something like this:
#!/bin/bash
# Returns non-zero if the archive needs to be rebuilt
if [ -e $1 ]; then
folder_name=$(basename $1 .npk)
[ -z "$(find $folder_name -newer $1 -not -type d)" ] && return 0
fi
return 1
I don't really like that solution because it works around the problem instead of solving it directly, but it may be able to get you going in the meantime. If you are going to go that route, it's probably cleaner and easier to do everything in the shell script and either have the makefile simply invoke the script or get rid of the makefile entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With