__FILE__ macro shows full path

2019-01-04 17:33发布

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

标签: c file macros path
18条回答
Evening l夕情丶
2楼-- · 2019-01-04 17:38

A bit late to the party, but for GCC have a look at the -ffile-prefix-map=old=new option:

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.

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 option is only avalable in GCC 8 onwards, as is -fmacro-prefix-map which, I think, does the __FILE__ part. For, say, GCC 5, we only have -fdebug-prefix-map which does not (appear to) affect __FILE__.

查看更多
时光不老,我们不散
3楼-- · 2019-01-04 17:39

in vs, when with /FC, FILE equals full path, without /FC FILE equals file name. ref here

查看更多
放我归山
4楼-- · 2019-01-04 17:39

just hope to improve FILE macro a bit:

#define FILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)

this catches / and \, like Czarek Tomczak requested, and this works great in my mixed environment.

查看更多
Bombasti
5楼-- · 2019-01-04 17:41

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.

查看更多
6楼-- · 2019-01-04 17:41

Use the basename() function, or, if you are on Windows, _splitpath().

#include <libgen.h>

#define PRINTFILE() { char buf[] = __FILE__; printf("Filename:  %s\n", basename(buf)); }

Also try man 3 basename in a shell.

查看更多
唯我独甜
7楼-- · 2019-01-04 17:41

If you are using CMAKE with GNU compiler this global define works fine:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__MY_FILE__='\"$(notdir $(abspath $<))\"'")
查看更多
登录 后发表回答