Я создаю библиотеку, которая будет нуждаться в различных макросах, определенных в командной строке (опция -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 также были бы полезны.
Определение макроса всегда будет целым числом.
Как насчет чего-то такого:
main.cpp:
int checkMyMacro # MY_MACRO;
a.cpp и b.cpp:
static int * checkMyMacro = &checkMyMacro # MY_MACRO;
приводя к неразрешенной внешней ошибке компоновщика при неправильном использовании.
Вы можете вставить вторую часть в заголовок, определяющий этот макрос.
Если вы просто хотите защитить себя от случайного неправильного использования, вам может быть достаточно что-то вроде следующего:
#if defined(MY_MACRO) && MY_MACRO_MIN > MY_MACRO || MY_MACRO_MAX < MY_MACRO
#error MY_MACRO is out of range
#endif
Защита от злонамеренного неправильного использования в любой момент до времени выполнения в принципе невозможна в описанных вами обстоятельствах.