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.*XXXis 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.