Search code examples
cgccmakefileconfigureautoconf

#define getting cleared between file loads?


I'm working on some open source code; I have a configure.ac, in which I've added the following:

: ${FFT_MODE=1}
AC_ARG_VAR([FFT_MODE], [1 for fftw3, 2 for kiss_fft])
AC_DEFINE_UNQUOTED([FFTMODE], [$FFT_MODE],
                   [1 for fftw3, 2 for kiss_fft])

The idea is that (after calling autoconf --install), the user can run e.g. ./configure FFT_MODE=2 to switch modes. Now, I thought it was working - the status check at the end of the configuration file output the correct value, and an if/elif/endif in my code showed the correct block was executing. However - at some point I added an else, and discovered that both the if AND else blocks were running. First I thought my compiler was possessed, then I realized the file was getting loaded twice, and the second time, for some reason, FFTMODE is unset (or set to zero or something). I don't understand how, though. FTR, the check is in a file fsk.h, like so:

#warning before
#if(FFTMODE == 1)
#warning FFTMODE 1
#include <fftw3.h>
#elif(FFTMODE == 2)
#warning FFTMODE 2
#include <kiss_fftr.h>
#else
#warning FFTMODE ???
#error Unsupported FFTMODE
#endif
#warning after

The output of make is as follows:

make  all-recursive
make[1]: Entering directory '/home/erhannis/mods/minimodem'
Making all in src
make[2]: Entering directory '/home/erhannis/mods/minimodem/src'
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT minimodem.o -MD -MP -MF .deps/minimodem.Tpo -c -o minimodem.o minimodem.c
In file included from minimodem.c:43:
fsk.h:20:2: warning: #warning before [-Wcpp]
   20 | #warning before
      |  ^~~~~~~
fsk.h:22:2: warning: #warning FFTMODE 1 [-Wcpp]
   22 | #warning FFTMODE 1
      |  ^~~~~~~
In file included from minimodem.c:43:
fsk.h:31:2: warning: #warning after [-Wcpp]
   31 | #warning after
      |  ^~~~~~~
mv -f .deps/minimodem.Tpo .deps/minimodem.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT databits_ascii.o -MD -MP -MF .deps/databits_ascii.Tpo -c -o databits_ascii.o databits_ascii.c
mv -f .deps/databits_ascii.Tpo .deps/databits_ascii.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT databits_binary.o -MD -MP -MF .deps/databits_binary.Tpo -c -o databits_binary.o databits_binary.c
mv -f .deps/databits_binary.Tpo .deps/databits_binary.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT databits_callerid.o -MD -MP -MF .deps/databits_callerid.Tpo -c -o databits_callerid.o databits_callerid.c
mv -f .deps/databits_callerid.Tpo .deps/databits_callerid.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT databits_baudot.o -MD -MP -MF .deps/databits_baudot.Tpo -c -o databits_baudot.o databits_baudot.c
mv -f .deps/databits_baudot.Tpo .deps/databits_baudot.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT baudot.o -MD -MP -MF .deps/baudot.Tpo -c -o baudot.o baudot.c
mv -f .deps/baudot.Tpo .deps/baudot.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT databits_uic.o -MD -MP -MF .deps/databits_uic.Tpo -c -o databits_uic.o databits_uic.c
mv -f .deps/databits_uic.Tpo .deps/databits_uic.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT uic_codes.o -MD -MP -MF .deps/uic_codes.Tpo -c -o uic_codes.o uic_codes.c
mv -f .deps/uic_codes.Tpo .deps/uic_codes.Po
gcc -DHAVE_CONFIG_H -I. -I..  -D_REENTRANT  -Wall  -g -O2 -MT fsk.o -MD -MP -MF .deps/fsk.Tpo -c -o fsk.o fsk.c
In file included from fsk.c:30:
fsk.h:20:2: warning: #warning before [-Wcpp]
   20 | #warning before
      |  ^~~~~~~
fsk.h:28:2: warning: #warning FFTMODE ??? [-Wcpp]
   28 | #warning FFTMODE ???
      |  ^~~~~~~
fsk.h:29:2: error: #error Unsupported FFTMODE
   29 | #error Unsupported FFTMODE
      |  ^~~~~
fsk.h:31:2: warning: #warning after [-Wcpp]
   31 | #warning after
      |  ^~~~~~~
fsk.c: In function ‘fsk_bit_analyze’:
fsk.c:200:10: error: ‘mag_mark’ undeclared (first use in this function)
  200 |     if ( mag_mark > mag_space ) {
      |          ^~~~~~~~
fsk.c:200:10: note: each undeclared identifier is reported only once for each function it appears in
fsk.c:200:21: error: ‘mag_space’ undeclared (first use in this function)
  200 |     if ( mag_mark > mag_space ) {
      |                     ^~~~~~~~~
fsk.c:166:11: warning: unused variable ‘magscalar’ [-Wunused-variable]
  166 |     float magscalar = 2.0f / (float)bit_nsamples;
      |           ^~~~~~~~~
fsk.c: In function ‘fsk_detect_carrier’:
fsk.c:628:1: warning: control reaches end of non-void function [-Wreturn-type]
  628 | }
      | ^
make[2]: *** [Makefile:470: fsk.o] Error 1
make[2]: Leaving directory '/home/erhannis/mods/minimodem/src'
make[1]: *** [Makefile:361: all-recursive] Error 1
make[1]: Leaving directory '/home/erhannis/mods/minimodem'
make: *** [Makefile:302: all] Error 2

So, what's going on? There IS one instance of #undef FFTMODE in config.h.in - but while I can guess that file's for cleaning up after the build is done, the build isn't done yet, so why's it cleaning up the definitions I'm still using?

The source code is at https://github.com/erhannis/minimodem/tree/feature/alternate_fft; the relevant file is src/fsk.h.


Solution

  • I think you're confusing yourself with this idea that the file is getting loaded twice. That doesn't seem to be the case, from the output you show.

    Instead, the file is getting loaded one time each, in two different compile commands. Once when compiling minimodem.c and once when compiling fsk.c. Those are totally different compile operations.

    In minimodem.c, the value of FFTMODE is 1. In fsk.c, FFTMODE is unset.

    This is easily explained: in minimodem.c you #include "config.h" before you #include "fsk.h", and so when fsk.h is parsed you have a value for FFTMODE. In fsk.c you don't #include "config.h", so there is no value for FFTMODE.

    If your fsk.h file needs values from config.h, then it may be best to #include "config.h" in fsk.h. If you don't want to do that you need to make sure it's included by all the .c files, before fsk.h.