1

Is it possible to configure automake to generate a Makefile which, in addition to building the .o files and linked binary, also has targets for %.s? I want to be able to review the compiler output in a text format without having to invoke binutils on the .o files.

Specifically, if I have main.c as a source file, I want to be able to run make main.s. The desired recipe would be the same as that for main.o, but using CC1 := $(CC) -S.

2 Answers2

1

The question is a little XY.

You want to be able make the intermediate assembly file foo.s, where the source file foo.c is one of the sources in an autotooled project, using a makefile that is generated by the project's ./configure script. You assume that to do this you must do something to the automake inputs - the Makefile.ams? - that will cause ./configure to generate Makefiles that include assembly targets *.s matching all object targets *.o.

Well you could, but then your project would not be a regular autotooled project as usually distributed, and there is no need to make it irregular to get what you want.

The GCC option -save-temps exists to let developers see the intermediate files of compilation - the preprocessor output, the assembly.

$ gcc -c -o foo.o foo.c

outputs foo.o

$ gcc -save-temps -c -o foo.o foo.c

outputs:

foo.o
foo.i   # preprocessed source
foo.s   # assembly

As I expect you know, GNU Make receives compiler options from the make-variable CFLAGS, and automake respects this convention, independently of and in addition to any compiler options prescribed by the project's autotooling. So, if you would otherwise generate makefiles with:

$ ./configure ...

then, to add -save-temps to the C compiler options, generate makefiles instead with:

$ ./configure CFLAGS=-save-temps ...

And if you are already using CFLAGS, e.g.

$ ./configure CFLAGS="-g -O0" ...

then append -save-temps:

$ ./configure CFLAGS="-g -O0 -save-temps" ...

Then,

$ make main.o

will make main.o, main.i and main.s up-to-date.

To disable -save-temps, of course, rerun ./configure, removing it from the CFLAGS.

If the project involves C++ compilation, then CXXFLAGS affects the C++ compiler in the same way that CFLAGS affects the C compiler. Note that the generated preprocessed C++ sources will be called *.ii, not *.i.

With -save-temps enabled, make clean will not delete the *.i and *.s files. You may not care, since compilation will always clobber them. If you do care, you may take advantage of automake's standard phony target clean-local, which is supported to let an autotooling maintainer extend the behaviour of clean. Add the following recipe to the Makefile.am of each source directory in the project:

clean-local:
    $(RM) *.i *.ii *.s

Then update the autotooling and regenerate Makefiles:

$ autoreconf
$ ./configure ...
Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • Yup, `-save-temps` is a better way to go about this than baking the `.s` step into the build system. Or as a one-off, copy the build command from a build log and run it manually from the right directory, with `-S -o- | less` at the end of the command line. (And maybe other options to make the asm more human-readable: [How to remove “noise” from GCC/clang assembly output?](https://stackoverflow.com/questions/38552116/how-to-remove-noise-from-gcc-clang-assembly-output) – Peter Cordes Feb 17 '18 at 13:16
1

While the COMPILE variable in the generated Makefile.in is technically an internal detail, and this solution relies on the compiler to understand -c -S, adding:

.c.s:
        $(COMPILE) -c -S $<

to the Makefile.am has worked for as long as I've been using the autotools. It might also be convenient to add:

clean-local:
        rm -f *.s

I find this useful in development to have a look at the assembly output for specific configure and CC, CFLAGS options.

The COMPILE variable will be defined as something like:

COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)

Similarly, for C++ source we have:

.cc.s:
        $(CXXCOMPILE) -c -S $<
Brett Hale
  • 21,653
  • 2
  • 61
  • 90
  • This is more convenient than `rm foo.o` / `make`, then copy / paste the compiler command line and edit it manually? (With `-S -o- | less` at the end, so it pipes into a pager). You do have to `cd` into the right directory, and if the build system doesn't spew the full command lines you have to go digging, but still it's what I usually do. – Peter Cordes Feb 18 '18 at 07:15