Reputation: 5223
I've got a large software project using the autotools suite. When I need to debug a complex C macro I will sometimes consult the preprocessed file.
While I can do this by hand with a "make V=1", cut and paste the output and add the -E flag, it sure seems like I should be able to add the right rule somewhere to do this for me.
e.g. I can already do make src/driver/foo/some_object.o
but I would also like to be able to do make src/driver/foo/some_object.i
Were this a simple Makefile, I could add
.%i : %c
$(CC) $(CPPFLAGS) -E -o $@
but adding that line to Makefile.am
resulted in
make: *** No rule to make target src/driver/foo/some_object.i
is libtool complicating things?
Upvotes: 1
Views: 596
Reputation: 61232
It seems you would like to statically configure your build to generate
a preprocessed .i
file per C compilation.
You can do that by adding:
AC_SUBST(AM_CFLAGS,[-save-temps])
to your configure.ac
. (Then autoreconf
and ./configure
again).
The -save-temps
compilation option
causes the preprocessed source foo.i
and assembly foo.s
to be saved alongside foo.c
when the
latter is compiled.
Since these files are not among the targets known to make
, make clean
will not
delete them automatically (though that doesn't matter for their freshness, since they're
always clobbered). If you want make clean
to remove them, then add:
clean-local:
$(RM) *.i *.s
to the relevant Makefile.am
s
As an alternative to hard-coding the configure.ac
like this, you might
consider just configuring -save-temps
whenever you want, for as long as you want, with:
./configure CFLAGS=-save-temps
Upvotes: 0
Reputation: 180141
e.g. I can already do
make src/driver/foo/some_object.o
but I would also like to be able to domake src/driver/foo/some_object.i
Obviously, you cannot do the latter without adding an appropriate rule to the Makefile
(via Makefile.am
). The Autotools do not automatically provide rules for building .i
files, nor does GNU make have an implicit rule for building them. However, if indeed you want to invoke the same recipe that is ordinarily used to build foo.o
, but passing an -E
flag to the compiler, then you ought to be able to achieve it by specifying the a value for the CFLAGS
variable on the make
command line. For example,
make src/driver/foo/some_object.o CFLAGS=-E
An Autotools build system that conforms to GNU policy and convention does not itself set options in CFLAGS
(or CPPFLAGS
) -- it is a so-called "user variable", that the project builder is supposed to be free to use to specify options. Therefore, using it this way should not clobber any other options (or if it does, then that's something you should fix).
That should still put the output in src/driver/foo/some_object.o
, however, though that's because of the (expected) form of the recipe, not the name of the target. Additionally, it will do nothing if the .o
file already exists and is up to date. You might address both of those issues by wrapping it all up in a little script, maybe something like this:
preprocess.sh
#!/bin/bash
if [ $# -lt 1 ]; then
echo Specify at least one file name 1>&2
exit 1
fi
for path; do
stem="${path%.[ioc]}"
rm -f "${stem}.o"
make "${stem}.o" CFLAGS=-E
mv "${stem}.o" "${stem}.i"
done
You might invoke that via any of these forms:
./preprocess.sh src/driver/foo/some_object.i
./preprocess.sh src/driver/foo/some_object.o
./preprocess.sh src/driver/foo/some_object.c
./preprocess.sh src/foo.i src/bar.i src/driver/baz.o src/main/frobozz.c
But perhaps you consider that a kludge. You also remark,
Were this a simple Makefile, I could add
.%i : %c $(CC) $(CPPFLAGS) -E -o $@
but adding that line to Makefile.am resulted in
make: *** No rule to make target src/driver/foo/some_object.i
Well, if you added exactly the rule that you present then that's not surprising. The correct GNU Make pattern rule for what you want would be spelled like this:
%.i : %.c
$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) -E -o $@ $<
Note the difference in both the target and prerequisite names, but do not overlook the difference in the rule either. The AM_CPPFLAGS
part is optional, but the $<
appended to the end is mandatory.
On the other hand, the Autotools are focused on producing cross-platform, cross-toolchain build systems, and pattern rules such as the above are specific to GNU make. Instead, therefore, you really ought to use a traditional suffix rule:
.c.i:
$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) -E -o $@ $<
Moreover, you must either way tell Automake that you are providing a rule for a suffix that it does not recognize by default:
SUFFIXES = .i
The Automake manual speaks to this general use case.
is libtool complicating things?
Unlikely in this case.
Upvotes: 2