__FILE__ macro shows full path
The standard predefined macro __FILE__
available in C shows the full path to the file. Is there any way to short the path? I mean instead of
/full/path/to/file.c
I see
to/file.c
or
file.c
Try
#include <string.h>
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
For Windows use '\\' instead of '/'.
Here's a tip if you're using cmake. From: http://public.kitware.com/pipermail/cmake/2013-January/053117.html
I'm copying the tip so it's all on this page:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst
${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'")
If you're using GNU make, I see no reason you couldn't extend this to your own makefiles. For example, you might have a line like this:
CXX_FLAGS+=-D__FILENAME__='\"$(subst $(SOURCE_PREFIX)/,,$(abspath $<))\"'"
where $(SOURCE_PREFIX)
is the prefix that you want to remove.
Then use __FILENAME__
in place of __FILE__
.
I have just thought of a great solution to this that works with both source and header files, is very efficient and works on compile time in all platforms without compiler-specific extensions. This solution also preserves the relative directory structure of your project, so you know in which folder the file is in, and only relative to the root of your project.
The idea is to get the size of the source directory with your build tool and just add it to the __FILE__
macro, removing the directory entirely and only showing the file name starting at your source directory.
The following example is implemented using CMake, but there's no reason it wouldn't work with any other build tools, because the trick is very simple.
On the CMakeLists.txt file, define a macro that has the length of the path to your project on 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}")
On your source code, define a __FILENAME__
macro that just adds the source path size to the __FILE__
macro:
#define __FILENAME__ (__FILE__ + SOURCE_PATH_SIZE)
Then just use this new macro instead of the __FILE__
macro. This works because the __FILE__
path will always start with the path to your CMake source dir. By removing it from the __FILE__
string the preprocessor will take care of specifying the correct file name and it will all be relative to the root of your CMake project.
If you care about the performance, this is as efficient as using __FILE__
, because both __FILE__
and SOURCE_PATH_SIZE
are known compile time constants, so it can be optimized away by the compiler.
The only place where this would fail is if you're using this on generated files and they're on a off-source build folder. Then you'll probably have to create another macro using the CMAKE_BUILD_DIR
variable instead of CMAKE_SOURCE_DIR
.
At least for gcc, the value of __FILE__
is the file path as specified on the compiler's command line. If you compile file.c
like this:
gcc -c /full/path/to/file.c
the __FILE__
will expand to "/full/path/to/file.c"
. If you instead do this:
cd /full/path/to
gcc -c file.c
then __FILE__
will expand to just "file.c"
.
This may or may not be practical.
The C standard does not require this behavior. All it says about __FILE__
is that it expands to "The presumed name of the current source file (a character string literal)".
An alternative is to use the #line
directive. It overrides the current line number, and optionally the source file name. If you want to override the file name but leave the line number alone, use the __LINE__
macro.
For example, you can add this near the top of file.c
:
#line __LINE__ "file.c"
The only problem with this is that it assigns the specified line number to the following line, and the first argument to #line
has to be a digit-sequence so you can't do something like
#line (__LINE__-1) "file.c" // This is invalid
Ensuring that the file name in the #line
directive matches the actual name of the file is left as an exercise.
At least for gcc, this will also affect the file name reported in diagnostic messages.