Я только что подумал о прекрасном решении, которое работает как с исходными файлами, так и с заголовочными файлами, очень эффективно и работает во время компиляции на всех платформах без специфичных для компилятора расширений. Это решение также сохраняет относительную структуру каталогов вашего проекта, поэтому вы знаете, в какой папке находится файл, и только относительно корня вашего проекта.
Идея состоит в том, чтобы получить размер исходного каталога с помощью инструмента сборки и просто добавить его в макрос __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__
всегда начинается с пути к вашему исходному каталогу CMake. Удалив его из строки __FILE__
, препроцессор позаботится об указании правильного имени файла, и все это будет относиться к корню вашего проекта CMake.
Если вы заботитесь о производительности, это так же эффективно, как и использование __FILE__
, поскольку и __FILE__
, и SOURCE_PATH_SIZE
являются известными константами времени компиляции, поэтому компилятор может оптимизировать их.
Единственное место, где это может потерпеть неудачу, - это если вы используете это для сгенерированных файлов, а они находятся в папке сборки вне исходного кода. Тогда вам, вероятно, придется создать еще один макрос, используя переменную CMAKE_BUILD_DIR
вместо CMAKE_SOURCE_DIR
.