Search code examples
c++interfacec-preprocessorconditional-compilationtranslation-unit

Prevent same macro having different definitions in multiple translation units


I'm creating a library that will need different command-line defined macros (-D option) per resulting binary (.exe, .so, .dll) that uses it. I would like to ensure each translation unit that will be a part of resulting binary, was compiled with the same macro definition. This is to e.g. prevent accidental ODR violations and other unexpected behavior.

For instance, this should be prevented:

g++ -DMY_MACRO=5 a.cpp
g++ -DMY_MACRO=7 b.cpp
ld a.o b.o -o result

The library will provide header - library.hpp - that will be included in all translation units using it. My idea is to use that header as a place to create checks for misuse.

The question is, what's the best way to do it?

Preferably misuse would be detected, in order of preference, during:

  • compilation
  • linking
  • runtime

It's likely not possible during compilation due to way how C/C++ compilers work. But maybe at least during linking?

I would like to avoid using external tools/scripts. I know one could write a script that goes through all object files and checks if all used the same value. But maybe there is a way less intrusive for the buildsystem, just reusing how C++ linker or compiler works.

Platform independent solution would be best, but ways for doing it independently for gcc/clang and msvc would also be useful.

Macro definition will always be an integral number.


Solution

  • How about something along these lines:

    main.cpp:

    int checkMyMacro#MY_MACRO;

    a.cpp and b.cpp:

    static int *checkMyMacro = &checkMyMacro#MY_MACRO;

    resulting in a unresolved external error from linker on misuse.

    You could insert the second part into the header defining that macro.