I have a bunch of files (*.txt
) that I use a python script to analyze and generate code (*.cpp
) from. Once code generation is complete, I want the generated code to be compiled into object files (*.o
).
I want to use gnu-make to set this up. My problem is that I can't figure out a working Makefile syntax to accomplish this.
Here are some additional details that makes this harder:
Since I don't know how many *.txt-files exists in the first place, I want to discover them using a shell find
command.
files := $(shell find $(TXT_FILE_DIR) -type f -name '*.txt')
However, I still want gnu-make's fine dependency features to work here. That is, if any of the txt-files change, I want make
to automatically discover these and only these changes, and generate new .cpp
files for them and recompile them into .o
files.
I am looking for a solution where make
can run in parallel (and respect the -j flag) and call the python script that translates the *.txt
files into *.cpp
files.
My OS is Linux.
[new information]
Thank you Grexis, for your answer! However, because I have a somewhat odd mapping between src and dst-paths, I am actually looking for a different solution.
Here is an example of "the oddity" when translating my src and dst-paths:
$(TXT_DIR)/a/XXX.*XXX/b/c/file1.txt -> $(CPP_DIR)/a/YYY/b/c/file1.cpp
$(TXT_DIR)/a/XXX.*XXX/b/c/file2.txt -> $(CPP_DIR)/a/YYY/b/c/file2.cpp
$(TXT_DIR)/b/XXX.*XXX/c/d/file3.txt -> $(CPP_DIR)/b/YYY/c/d/file3.cpp
Notice here that the path is manipulated twice. Hence, both:
$(TXT_DIR)
is replaced with$(CPP_DIR)
and- The regular expression
XXX.*XXX
is replaced with the fixed stringYYY
However, due to that its hard to do a multiple string replacement in gnu-make, e.g., gnu-make only supports a single % (stem) string replacement at a time, I think I have to use a more advanced gnu-make syntax. Because of this, I am looking for a way to define a "distinct recipe for each .txt
-> .cpp
pair". I have tried the following:
cleanPath = $(shell echo $(1) | sed s/XXX.*XXX/YYY/g)
txt2cpp = $(subst $(TXT_DIR),$(CPP_DIR),$(patsubst %.txt,%.cpp,$(call cleanPath,$(1))))
txt2obj = $(subst $(TXT_DIR),$(OBJ_DIR),$(patsubst %.txt,%.o,$(call cleanPath,$(1))))
define analyse =
$(2): $(1)
python.py $(2) $(3)
endef
txt_files := $(shell find $(TXT_DIR) -type f -name '*.txt')
cpps := $(foreach file,$(txt_files),$(eval $(call analyse,$(file),$(call txt2cpp,$(file)),$(call txt2obj,$(file)))))
all: $(cpps)
However, it seems my python.py
script is never called. Why is that?
If I enclose the calling to the python.py
in a shell
-command, e.g.,$(shell python.py $(2) $(3))
, the python.py
script is actually called. However, using a shell
-command makes parallelism impossible. Unfortunately, not being able to execute the python.py
script in parallel is not an option for me.