Skip to content

Stringizing / stringify name mangling

I load a path name with cmake

add_definitions(-DMY_PATH =${CMAKE_INSTALL_FULL_DATADIR}/path)

and want to use as a string in my C++ program to load some data. For this the stringification operator # is really handy – I use the macro provided in this answer which is the same as here. Now when I have “linux” or “unix” in my path, this goes horribly wrong (at least with gcc), as these names are simply replaced by “1”:

#include <stdio.h>

#define xstr(a) str(a)
#define str(a) #a

#ifndef MY_PATH
    #define MY_PATH /path/x86-unix/linux/path

int main()
    char my_path_str[] = xstr(MY_PATH);
    printf("my path is %s", my_path_str);

    return 0;

Try it out

Can anyone give a hint why is this happening and how I can prevent it? There is a similar question here, but there is no suitable answer to use it with cmake.



why is this happening

Macros unix and linux are legacy defined to 1 on UNIX platforms.

Part of the program /path/x86-unix/linux/pat consists of tokens unix and linux, so as part of macro expansion in xstr these macros are substituted for 1.

how I can prevent it?

#undef linux and unix macros. Or disable gnu extensions, for example, use c11 standard. With GCC compiler on Linux:

$ gcc  -E -dM - </dev/null | grep linux
#define __linux 1
#define __gnu_linux__ 1
#define linux 1  // here it is
#define __linux__ 1
$ gcc -std=c11 -E -dM - </dev/null | grep linux
#define __linux 1
#define __gnu_linux__ 1
#define __linux__ 1
// now there's no #define linux

how I can prevent it?

I load a path name with cmake and want to use as a string in my C++ program

Adapting example from Example section from CMake documentation of configure_file, create a file named with content:

#cmakedefine MY_PATH "@MY_PATH@"

Add the following to your cmake configuration:

set(MY_PATH "/path/x86-unix/linux/path") 
# Generate the file
# add the path to your target

And use #include <my_path.h> in your program to get MY_PATH definitions.

I see no reason to use a macro – maybe it would be better to do static const char MY_PATH[] = "@MY_PATH@"; instead.

I load a path name with cmake

 add_definitions(-DMY_PATH =${CMAKE_INSTALL_FULL_DATADIR}/path)

Do not use add_definitions. Prefer target_compile_definitions instead. See CMake add_definitions documentations.

As a crude workaround, you can add quotes, assuming the shell and compiler will properly parse them:

target_compile_definitions(your_target PRIVATE 

(Note that quotes in the above are preserved literally and passed to the compiler (or build system). CMake quoting does not work like shell quoting. In CMake language, to quote a word, quotes " have to be exactly the first and last characters of the word. If one of them is in the middle, they are interpreted literally)

However, I think using configure_file would be preferred, because of ESCAPE_QUOTES.

7 People found this is helpful