Search code examples
cautotoolsautoconfautomakecflags

How to change VAR name without getting the undeclared error after 'make install'?


My configure.in file has:

VAR=yo
AC_SUBST(VAR)

Makefile.am has:

bin_PROGRAMS = hello
hello_SOURCES = hello.c 
hello_CFLAGS =-DVAR=@VAR@

C file is:

#include <stdio.h>
int main()
{
    printf("%s\n",VAR);
    return 0;
}

When I do 'make install' there is error

Making install in src
make[1]: Entering directory `/home/albertpod/hello/src'
if gcc -DPACKAGE_NAME=\"hello\" -DPACKAGE_TARNAME=\"hello\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"hello\ 1.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I.    -DVAR=yo -g -O2 -MT hello-hello.o -MD -MP -MF ".deps/hello-hello.Tpo" -c -o hello-hello.o `test -f 'hello.c' || echo './'`hello.c; \
    then mv -f ".deps/hello-hello.Tpo" ".deps/hello-hello.Po"; else rm -f ".deps/hello-hello.Tpo"; exit 1; fi
hello.c: In function ‘main’:
hello.c:8:13: error: ‘yo’ undeclared (first use in this function)
hello.c:8:13: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [hello-hello.o] Error 1
make[1]: Leaving directory `/home/albertpod/hello/src'
make: *** [install-recursive] Error 1

So name of VAR becomes yo, but it is undeclared. My goal is to print yo, but how to solve this case?


Solution

  • I'm assuming you want the program to deliver the output

    yo
    

    Proper Quoting in configure.in

    You also probably noticed that you are missing quotes, to make the replacement text of the define VAR a string literal. The difficulty is that you are passing this value through two instances of the shell that will strip quotes: the one that executes configure and the one that is invoked by make to run the compiler. So you need three levels of quoting, with appropriate escaping:

    VAR="\"\\\"yo\\\"\""
    AC_SUBST(VAR)
    

    (You can try using single quotes in there to reduce the number of \, but it will probably become even more ugly.)

    Proper Quoting in Makefile.am

    You can also do the quoting in Makefile.am. This is especially useful if you need the value of VAR in the Makefile for other purposes too. You need two levels of qoutes, one to make the value a string literal and one that gets eaten by the shell:

    hello_CFLAGS =-DVAR='"@VAR@"'
    

    This works even if VAR contains (single) spaces or other funny characters, the only problematic characters are ', ", and \.

    Stringification

    Alternatively you can let the preprocessor add the quotes using the stringify operator #:

    #include <stdio.h>
    
    #define STR2(arg) #arg
    #define STR(arg) STR2(arg)
    
    int main()
    {
        printf("%s\n",STR(VAR));
        return 0;
    }
    

    The indirection in the macros is necessary due to a quirk how the # operator works. If you would only use one level of macros, the output would be VAR.

    Of course, this only works as long as the value does not contain any funny characters, like spaces.

    Using AC_DEFINE

    With AC_DEFINE it is slightly easier to define VAR to a value surrounded by quotes. Use

    AC_DEFINE([VAR], ["yo"])
    

    in configure.in and remove hello_CFLAGS =-DVAR=@VAR@ from Makefile.am. Alternatively, if you need to compute the value of VAR in configure, use

    VAR=yo
    AC_DEFINE_UNQUOTED([VAR], ["$VAR"])
    

    which will interpret shell substitutions in the value.

    In both cases, you don't have access to VAR in the Makefile.