Я щойно подумав про чудове рішення цього питання, яке працює як з вихідними, так і з файлами заголовків, є дуже ефективним і працює на час компіляції на всіх платформах без конкретних розширень для компілятора. Це рішення також зберігає відносну структуру каталогів вашого проекту, тому ви знаєте, в якій папці знаходиться файл, і лише відносно кореня вашого проекту.
Ідея полягає в тому, щоб отримати розмір вихідного каталогу за допомогою інструменту збирання та просто додати його до __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.