Reputation: 1885
I am currently working on a project that requires translating a list of files in a directory into a c++ header to store info about the resources. For example:
/
update.py
resources.h
Makefile
/resources
resource1.png
/sub1
/sub2
resource2.png
What I want is for Makefile to run update.py only when one of the resources anywhere in the directory tree is changed. No other makefiles are going to touch the resources, only resources.h. What kind of makefile do I need to do this?
PS From what I have read, recursively searching with make is a bad idea, but if nothing else is touching the same file, would it be a problem?
Upvotes: 11
Views: 6586
Reputation: 61
Notice that you can also use the $(shell find)
command for the dependencies without a variable:
resources.h: $(shell find . -name 'resource*.png')
./update.py $^
As such, it's like the answer by @MadScientist, but you get the list of dependencies in the $^
automatic variable. (Can't include the update.py
in the dependencies in this case so easily though.)
What makes this powerful is that you can use patterns with it, for example if you need to compile to multiple target files (resourcesN.h
) from multiple matching directories (resourcesN/
):
targets: resources1.h resources2.h
%.h: $(shell find $*/ -name 'resource*.png')
./update.py $^
Here $*
gets the values resources1
and resources2
, and then the $^
holds the list of dependencies found in the respective directory.
Upvotes: 4
Reputation: 500
I think you got that wrong: Recursive Make Considered Harmful explains that you should not call one make from within another, because neither will have the full overview of dependencies. This sooner or later leads to wrong builds which you can only sort out with make clean
.
makepp is an alternative that helps you to avoid that pitfall. It also solves your problem with a recursive (nothing to do with above recursion) wildcard:
RESOURCES := **/resource\*.png
resources.h: $(RESOURCES)
.$/update.py $(inputs)
This even works if the files are not there yet, because makepp's wildcards take into account what could be built according to your rules. Note how it notices the program dependency automatically. The funny $/
will lean either way depending on what system it runs on, so its more portable.
There is much more to makepp. Besides doing almost all that GNU make can, there are lots more useful things, and you can even extend your makefiles with some Perl programming.
Upvotes: 4
Reputation: 100781
I'm not sure what you've read, but there's no problem writing a rule like this in make:
RESOURCES := $(shell find . -name resource\*.png -print)
resources.h: update.py $(RESOURCES)
./update.py $(RESOURCES)
or whatever.
Upvotes: 22