Я щойно подумав про чудове рішення цього питання, яке працює як з вихідними, так і з файлами заголовків, є дуже ефективним і працює на час компіляції на всіх платформах без конкретних розширень для компілятора. Це рішення також зберігає відносну структуру каталогів вашого проекту, тому ви знаєте, в якій папці знаходиться файл, і лише відносно кореня вашого проекту.
Ідея полягає в тому, щоб отримати розмір вихідного каталогу за допомогою інструменту збирання та просто додати його до __FILE__
макросу, повністю видаливши каталог і лише показавши ім’я файлу, починаючи з вихідного каталогу.
Наступний приклад реалізований за допомогою CMake, але немає причин, щоб він не працював з будь-якими іншими інструментами побудови, тому що трюк дуже простий.
У файлі CMakeLists.txt визначте макрос, який має довжину шляху до вашого проекту в CMake:
# The additional / is important to remove the last character from the path.
# Note that it does not matter if the OS uses / or \, because we are only
# saving the path size.
string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE)
add_definitions("-DSOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}")
У вихідному коді визначте __FILENAME__
макрос, який просто додає розмір вихідного шляху до __FILE__
макросу:
#define __FILENAME__ (__FILE__ + SOURCE_PATH_SIZE)
Тоді просто використовуйте цей новий замість __FILE__
макросу. Це працює, тому що __FILE__
шлях завжди починатиметься із шляху до вашого dir-джерела CMake. Видаляючи його з __FILE__
рядка, препроцесор подбає про те, щоб вказати правильне ім'я файлу, і все це буде відносно кореня вашого проекту CMake.
Якщо ви дбаєте про продуктивність, це настільки ж ефективно, як і використання __FILE__
, оскільки обидва __FILE__
і SOURCE_PATH_SIZE
відомі константи часу компіляції, тому компілятор може бути оптимізований.
Не вдалося це зробити, якщо ви використовуєте це для створених файлів, і вони знаходяться в папці збірки без вихідного коду. Тоді вам, мабуть, доведеться створити інший макрос, використовуючи CMAKE_BUILD_DIR
змінну замість CMAKE_SOURCE_DIR
.