I\'m using GCC; __FILE__ returns the current source file\'s entire path and name: /path/to/file.cpp
. Is there a way to get just the file\'s name file.cpp<
Consider this simple source code:
#include <stdio.h>
int main(void)
{
puts(__FILE__);
return(0);
}
On Solaris, with GCC 4.3.1, if I compile this using:
gcc -o x x.c && ./x
the output is 'x.c
' If I compile it using:
gcc -o x $PWD/x.c && ./x
then __FILE__ maps to the full path ('/work1/jleffler/tmp/x.c
'). If I compile it using:
gcc -o x ../tmp/x.c && ./x
then __FILE__ maps to '../tmp/x.c
'.
So, basically, __FILE__ is the pathname of the source file. If you build with the name you want to see in the object, all is well.
If that is impossible (for whatever reason), then you will have to get into the fixes suggested by other people.
You can assign __FILE__
to a string, and then call _splitpath() to rip the pieces out of it. This might be a Windows/MSVC-only solution, honestly I don't know.
I know you were looking for a compile-time solution and this is a run-time solution, but I figured since you were using the filename to do (presumably run-time) error logging, this could be a simple straightforward way to get you what you need.
You can take __FILE__ and the strip off the part of path you don't want (programatically). If basedir satisfies your needs, then fine. Otherwise, get source dir root from your build system, and the rest should be doable.
What does your error logging macro do? I would presume at some point the macro eventually calls a function of some kind in order to do the logging, why not have the called function strip off the path component at runtime?
#define LOG(message) _log(__FILE__, message)
void _log(file, message)
{
#ifndef DEBUG
strippath(file); // in some suitable way
#endif
cerr << "Log: " << file << ": " << message; // or whatever
}
The question is already 18 years old and back in 2008 this solution wasn't available, but
Starting with GCC 8 and CLANG 10, one can use the option -fmacro-prefix-map.
Acording to GCC Manual:
-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’.
For instance, the makefile in my IDE (Eclipse) includes the following parameter for GCC for some files: -fmacro-prefix-map="../Sources/"=.
Thus, my debug logs always show only the filenames, without the paths.
Note: GCC 8.1 and Clang 10 were released in May 2018 and March 2020, respectively. So, currently, in September of 2020, only some of my environments support -fmacro-prefix-map.
If you're using a make
program, you should be able to munge the filename beforehand and pass it as a macro to gcc
to be used in your program. For example, in your makefile
, change the line:
file.o: file.c
gcc -c -o file.o src/file.c
to:
file.o: src/file.c
gcc "-DMYFILE=\"`basename $<`\"" -c -o file.o src/file.c
This will allow you to use MYFILE
in your code instead of __FILE__
.
The use of basename
of the source file $<
means you can use it in generalized rules such as .c.o
. The following code illustrates how it works. First, a makefile
:
mainprog: main.o makefile
gcc -o mainprog main.o
main.o: src/main.c makefile
gcc "-DMYFILE=\"`basename $<`\"" -c -o main.o src/main.c
Then a file in a subdirectory, src/main.c
:
#include <stdio.h>
int main (int argc, char *argv[]) {
printf ("file = %s\n", MYFILE);
return 0;
}
Finally, a transcript showing it running:
pax:~$ mainprog
file = main.c
Note the file =
line which contains only the base name of the file, not the directory name as well.