Запретить один и тот же макрос с разными определениями в нескольких единицах перевода

Я создаю библиотеку, которая будет нуждаться в различных макросах, определенных в командной строке (опция -D) для каждого полученного двоичного файла (.exe, .so, .dll), который ее использует.
Я хотел бы, чтобы каждая единица перевода, которая будет частью результирующего двоичного файла, была скомпилирована с тем же макроопределением. Это, например, предотвратить случайные нарушения ODR и другое непредвиденное поведение.

Например, это должно быть предотвращено:

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

Библиотека предоставит заголовок — library.hpp, который будет включен во все блоки перевода, использующие его. Моя идея состоит в том, чтобы использовать этот заголовок как место для создания проверок на неправильное использование.

Вопрос в том, как лучше это сделать?

Предпочтительно злоупотребление будет обнаружено в порядке предпочтения во время:

  • сборник
  • соединение
  • время выполнения

Это вероятно невозможно во время компиляции из-за способа работы компиляторов C / C ++. Но, может быть, хотя бы во время ссылки

Я хотел бы избежать использования внешних инструментов / скриптов. Я знаю, что можно написать скрипт, который просматривает все объектные файлы и проверяет, все ли используют одно и то же значение. Но, может быть, есть способ менее навязчивый для системы сборки, просто повторное использование компоновщика C ++ или компилятора.

Независимое от платформы решение было бы наилучшим, но способы сделать это независимо для gcc / clang и msvc также были бы полезны.

Определение макроса всегда будет целым числом.

1

Решение

Как насчет чего-то такого:

main.cpp:

int checkMyMacro # MY_MACRO;

a.cpp и b.cpp:

static int * checkMyMacro = &checkMyMacro # MY_MACRO;

приводя к неразрешенной внешней ошибке компоновщика при неправильном использовании.

Вы можете вставить вторую часть в заголовок, определяющий этот макрос.

1

Другие решения

Если вы просто хотите защитить себя от случайного неправильного использования, вам может быть достаточно что-то вроде следующего:

#if defined(MY_MACRO) && MY_MACRO_MIN > MY_MACRO || MY_MACRO_MAX < MY_MACRO
#error MY_MACRO is out of range
#endif

Защита от злонамеренного неправильного использования в любой момент до времени выполнения в принципе невозможна в описанных вами обстоятельствах.

-1

По вопросам рекламы [email protected]