A __FILE__ Macro Which Does Not Contain the Whole Source File Path. The __FILE__ macro expands to the current source file name at compile time. It is not really useful if the source file paths which the build system uses, are very long, as this would bloat log output with long path names.
The __FILE__ macro expands to a string whose contents are the filename, surrounded by double quotation marks ( " " ). If you change the line number and filename, the compiler ignores the previous values and continues processing with the new values. The #line directive is typically used by program generators.
Click the Start button and then click Computer, click to open the location of the desired file, hold down the Shift key and right-click the file. Copy As Path: Click this option to paste the full file path into a document. Properties: Click this option to immediately view the full file path (location).
__LINE__ is a preprocessor macro that expands to current line number in the source file, as an integer. __LINE__ is useful when generating log statements, error messages intended for programmers, when throwing exceptions, or when writing debugging code.
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.
GCC 8 now has the -fmacro-prefix-map
and -ffile-prefix-map
options:
-fmacro-prefix-map=old=new
When preprocessing files residing in directory old, expand the
__FILE__
and__BASE_FILE__
macros as if the files resided in directory new instead. This can be used to change an absolute path to a relative path by using.
for new which can result in more reproducible builds that are location independent. This option also affects__builtin_FILE()
during compilation. See also-ffile-prefix-map
.
-ffile-prefix-map=old=new
When compiling files residing in directory old, record any references to them in the result of the compilation as if the files resided in directory new instead. Specifying this option is equivalent to specifying all the individual
-f*-prefix-map
options. This can be used to make reproducible builds that are location independent. See also-fmacro-prefix-map
and-fdebug-prefix-map
.
Setting an invalid path for -ffile-prefix-map
(-fdebug-prefix-map
) will break debugging unless you tell your debugger how to map back. (gdb: set substitue-path
, vscode: "sourceFileMap"
).
If your intent is to only clean up __FILE__
just use -fmacro-prefix-map
.
Example:
So for my Jenkins builds I will add -ffile-prefix-map=${WORKSPACE}/=/
, and another to remove the local dev package install prefix.
NOTE Unfortunately the -ffile-prefix-map
and -fmacro-prefix-map
options are only available in GCC 8 onwards. For, say, GCC 5, we only have -fdebug-prefix-map
which does not affect __FILE__
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With