This seems slightly related to How to write Makefile where target and source files have the same extension?. In that question the extensions are the same, but the input and output files seem to be in the same directory and filenames are being conditionally renamed.
I have a large collection of .txt
files in ../src/
that need to be processed, and dumped into ./
(which is a directory called target/
) as txt files of the same name. I want to use make
, so that only files in ../src/
that have been changed get updated in ./
. I would like to get the prototype working before I put the real code in.
My Makefile
in ./
is as follows:
DIR = ../src
INPUTS = $(wildcard $(DIR)/*.txt)
OUTPUTS = $(patsubst $(DIR)/%.txt,%.txt,$(INPUTS))
all: $(OUTPUTS)
.PHONY: $(INPUTS)
check:
@echo "DIR = $(DIR)"
@echo "INPUTS = $(INPUTS)"
@echo "OUTPUTS = $(OUTPUTS)"
%.txt: $(DIR)/%.txt
sed -e "s/test/cat/g" "$<" > $@
For now, the contents of ../src/
are test1.txt
and test2.txt
.
As the Makefile stands now, running make test2.txt
generates the file as expected.
target/ $ make test2.txt
sed -e "s/test/cat/g" "../src/test2.txt" > test2.txt
Running make check
shows the INPUTS
and OUTPUTS
correctly.
target/ $ make check
DIR = ../src
INPUTS = ../src/test1.txt ../src/test2.txt
OUTPUTS = test1.txt test2.txt
If I run make all
, it generates every file, every time. This is expected with the .PHONY $(INPUTS)
line in there.
If I remove the .PHONY $(INPUTS)
target, Make gets all bound up in itself trying to find the target to make ../src/test1.txt
and keeps prefixing $(DIR)
in front of it until it makes too long of a filename and gives up.
make: stat: ../src/../src/../src/ [repeat for a few pages] ../src/../src/test1.txt: File name too long
make: stat: ../src/../src/../src/ [repeat for a few pages] ../src/../src/../src/test1.txt: File name too long
make: *** No rule to make target `../src/../src/../src/[repeat]../src/../src/test1.txt', needed by `../src/[repeat]../src/../src/test1.txt'. Stop.
It never does get to processing test2.txt
.
As I was drafting this, I had the idea to remove the ../
from the DIR,
and relocate the Makefile so it was parent to both src/
and target/
. That approach seems to work, but isn't ideal. Eventually there would be a chain of these Makefiles, each pulling from one directory to another.
Is there a way to keep the Makefile
in 'target/' along with the generated destination files, and base those destination files off of something in a relative path?
Replace
%.txt: $(DIR)/%.txt
with:
${CURDIR}/%.txt: $(DIR)/%.txt
This way %.txt
does not match any .txt
file in any directory. In other words, you limit this rule's scope to files in ${CURDIR}/
only and this prevents that endless recursion.
See §10.5.4 How Patterns Match for more details.
It is also good practice to avoid relative paths:
DIR = $(abspath ../src)
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