Reputation: 9003
I use make
to build a project that does not contain any C/C++ files.
I have python
directory in my project that contains some python code that I what to execute during the build process if anything in python
has changed.
Here is my Makefile
:
.PHONY: all python
all: python
python: python/
python python/code.py
However, if I just call make
two times in a row, it builds everything over and over again.
Upvotes: 0
Views: 1283
Reputation: 9003
The clear and succinct answer to my question is that it is not possible with make
if you don't want to keep the "products" of your build process on the disk. The reasons are as follows:
.PHONY
target is meant to serve as a "name for a recipe to be executed". Thus, .PHONY
targets may seem suitable for the purpose..PHONY
targets are always rerun from the scratch, regardless of whether their dependencies have changed.Instead of being insistent on using make
, I wrote a simple shell script that invokes git to learn whether the python
directory has changed and builds accordingly. Importantly, in my case, the build process does not leave any files on the local disk since all the produced files are immediately transferred to a remote.
Additional notes to those insistent on using make
:
make
needs a "product" of the build process to be present on the disk. Otherwise, make
has no mechanism to detect that the build has already been run..PHONY
targets. Instead, use your "products" of the build as targets and your source files as dependencies. However, for this to work you first need to have some build process "products" that you want to keep. It may be perfectly reasonable not to keep any "products" but still demanding the build process to run only if it has not been done before.Upvotes: 1
Reputation: 29040
"if anything in python
has changed" is not 100% unambiguous. If it means that you have a set of python source files in python
and you want to run the recipe each time one of them changes, as MadScientist explained very clearly, you cannot use python
as a prerequisite, this will not work because if an existing file changes, the timestamp of python
does not. Declaring python
as phony does not help, it just tells make to always run this recipe. And declaring python
as the prerequisite of itself does not really make sense because make compares the timestamps of the target and the prerequisites and runs recipes only if some prerequisites are newer than the target.
One option would be to declare all these python source files as prerequisites of a target that would be a real file and which timestamp would correspond to the last time the recipe was run. As you do not tell what the effect of the recipe is, we do not know on which product file we could base this. So, let's create an empty file just for this (replace it by a real product file if you have some):
PYDIR := python
PYSRC := $(wildcard $(PYDIR)/*.py)
.PHONY: all
all: .python.done
.python.done: $(PYSRC)
python $(PYDIR)/code.py
touch $@
Of course, if you have sub-directories in python
, or if your python source files have other extensions than .py
, or there are other files than python source files that should trigger the re-build, or if some source files can be created with old timestamps, or if some source files can be deleted or any other more complicated case, this simple proposal will not suffice.
For instance if files can be created or deleted in python
(but not in sub-directories of it), and you want to run the recipe when this happens, you can indeed declare python
as a prerequisite of .python.done
because its timestamp changes exactly when this happens:
.python.done: $(PYSRC) $(PYDIR)
And if you have sub-directories in python
, you will have to replace wildcard
by something like:
PYSRC := $(shell find $(PYDIR) -type f -name '*.py')
And if any file under python
shall be considered:
PYSRC := $(shell find $(PYDIR) -type f)
Upvotes: 1
Reputation: 100836
I'm not really sure what you expected to happen, but you've declared the target python
to be a phony target and the make manual clearly states that phony targets are always considered out of date and always rebuilt:
The prerequisites of the special target .PHONY are considered to be phony targets. When it is time to consider such a target, make will run its recipe unconditionally, regardless of whether a file with that name exists or what its last-modification time is.
So, obviously when you run your makefile, the recipe for the phony target python
will always be run.
Further, if you remove the phony setting this rule will NEVER be run, because you're saying that a directory python
depends on itself. It can never be the case that a file is out of date with respect to itself.
I should also point out, listing a directory as a prerequisite is not a magical shorthand that means "check every file in this directory". It literally means, check the timestamp of the directory. The timestamp of a directory is only updated when a file in that directory is renamed, removed, or created. It is not updated when a file in that directory is modified.
Upvotes: 0