Reputation: 22675
Could someone clarify how this code works?
PRE_PROC_EXE := $(shell which pre_proc.pl)
PRE_PROC2_EXE := $(shell which pre_proc2.pl)
$(filter $(TMP_DIR)/%.c,$(FILES)):$(TMP_DIR)/%.c: $(SRC_DIR)/%.c
$(PRE_PROC_EXE) < $< > $@
I was trying to add one more step of pre processing on the files generated by step one (using PRE_PROC2_EXE
). How do I do that?
Upvotes: 0
Views: 63
Reputation: 80921
$(shell)
is a make function which runs a shell command and returns its output.
So PRE_PROC_EXE
contains the output from running which pre_proc.pl
and PRE_PROC2_EXE
contains the output from running which pre_proc2.pl
. (I'll point out that which
isn't portable, isn't guaranteed to exist and doesn't have a specification for its behavior so you can't rely on its output so using it like this isn't a great idea.)
The rest is a Static Pattern Rule which operates on the entries in $(FILES)
that match the $(TMP_DIR)/%.c
pattern (from $(filter $(TMP_DIR)/%.c,$(FILES))
) and applies the recipe to them using the matching $(SRC_DIR)/%.c
file as the prerequisite ($<
) and the matching $(TMP_DIR)/%.c
file as the target ($@
).
As to how to apply PRE_PROC2_EXE
to this that isn't easily answerable as you haven't explained how that script works or how you need to apply it.
Upvotes: 1
Reputation: 12514
How does that work? It works by magic! – in my opinion, that's an awful bit of Makefile (practical remarks at the end).
make
is a simple system, with simple syntax, which does one thing well. Over the years, however, it has acquired (and yes, I'm looking at you, GNU Make) a crust of elaborate functions, with compressed syntax, and a vast manual, which together make some Makefiles look like line-noise. Such as here.
Sometimes you have to do more-or-less clever things to build a bit of software, but (in my opinion and experience) these are much more naturally and comprehensibly handled by adding sophistication to the rules, not the Makefile syntax itself. That way, you leave the structure of the Makefile reasonably intelligible, which is important if you need to understand and adjust how the software is built.
I write quite complicated Makefiles, but only occasionally use a filter as complicated as patsubst
(but I do generally use GNU Make – BSD/POSIX Make is an asceticism too far).
Also, you could use auxiliary tools to do certain parts of the heavy lifting. For example, you might use autoconf to do the tool-searching, write
PRE_PROC_EXE=@PRE_PROC_EXE@
PRE_PROC_EXE2=@PRE_PROC_EXE2@
in a Makefile.in
, and write a configure.ac
which includes
dnl Process this file with autoconf
AC_INIT(fooprog, 0.1-SNAPSHOT, [email protected])
AC_PATH_PROG(PRE_PROC_EXE, pre_proc.pl, NOT_FOUND)
AC_PATH_PROG(PRE_PROC_EXE2, pre_proc2.pl, NOT_FOUND)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
Then autoconf; ./configure
would find pre_proc{,2}.pl
and substitute them into a new Makefile
. autoconf
takes a little getting used to, first time, but is pretty natural once you get used to it.
Returning to your particular example, I have little idea what that target does (two colons? I don't want to know...), but you might be able to adjust the rule to
$(PRE_PROC_EXE) < $< | $(PRE_PROC_EXE2) > $@
to pass the input *.c
files through both preprocessors.
Upvotes: 1