Rob Latham
Rob Latham

Reputation: 5223

autotools add rule to generate preprocessed files

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

Answers (2)

Mike Kinghan
Mike Kinghan

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.ams

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

John Bollinger
John Bollinger

Reputation: 180141

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

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

Related Questions