The standard predefined macro __FILE__ available in C shows the full path to the file. Is there any way to shorten the path and get just the filename? 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 '/'.
/ is a valid path separator in Windows./ is a valid path separator in file names passed to CreateFile() and so forth. However, that doesn't always mean that you can use / just anywhere in Windows since there is a tradition (inherited from CPM) of using / as the argument lead in at the command prompt. But a quality tool would be careful to split file names at both slash and backslash characters to avoid any problems for folks that do manage to use /.strrchr("/" __FILE__, '/') + 1. By prepending "/" to __FILE__, strrchr is be guaranteed to find something, and thus the conditional ?: is no longer needed.strchr and strrchr. Not to mention references to the __FILENAME__ macro. If not, this solution is 100% bloat.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__.
__FILE__ is not a simple preprocessor symbol, it changes to the current file is often used for emitting the name of the current file (header or source module). This __FILENAME__ would only have the outermost source__FILE__ everywhere is blowing out of code-space.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-mapoptions. This can be used to make reproducible builds that are location independent. See also-fmacro-prefix-mapand-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__.
-ffile-prefix-map indeed implies both -fdebug-prefix-map and -fmacro-prefix-map options. See also the references at reproducible-builds.org/docs/build-path The GCC bug that tracks -fmacro-prefix-map and -ffile-prefix-map is gcc.gnu.org/bugzilla/show_bug.cgi?id=70268I 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.
__FILE__ is a pointer to an array of bytes. So adding a numeric literal is just pointer addition. Very clever @RenatoUtsch#define __FILENAME__ ((__FILE__) + (SOURCE_PATH_SIZE)) to eliminate the clang complaint about integers being added to strings. Also added a #ifndef SOURCE_PATH_SIZE #define SOURCE_PATH_SIZE 0 #endif to keep clang from thinking there is no definition. Now code shows up clean in the ide.C++11
msvc2015u3,gcc5.4,clang3.8.0
template <typename T, size_t S>
inline constexpr size_t get_file_name_offset(const T (& str)[S], size_t i = S - 1)
{
return (str[i] == '/' || str[i] == '\\') ? i + 1 : (i > 0 ? get_file_name_offset(str, i - 1) : 0);
}
template <typename T>
inline constexpr size_t get_file_name_offset(T (& str)[1])
{
return 0;
}
'
int main()
{
printf("%s\n", &__FILE__[get_file_name_offset(__FILE__)]);
}
Code generates a compile time offset when:
gcc: at least gcc6.1 + -O1
msvc: put result into constexpr variable:
constexpr auto file = &__FILE__[get_file_name_offset(__FILE__)];
printf("%s\n", file);
clang: insists on not compile time evaluation
There is a trick to force all 3 compilers does compile time evaluation even in the debug configuration with disabled optimization:
namespace utility {
template <typename T, T v>
struct const_expr_value
{
static constexpr const T value = v;
};
}
#define UTILITY_CONST_EXPR_VALUE(exp) ::utility::const_expr_value<decltype(exp), exp>::value
int main()
{
printf("%s\n", &__FILE__[UTILITY_CONST_EXPR_VALUE(get_file_name_offset(__FILE__))]);
}
#define LEAF(FN) (&FN[UTILITY_CONST_EXPR_VALUE(get_file_name_offset(FN))]) and use it like this printf("%s\n", LEAF(__FILE__));#define __FILENAME__ (__FILE__ + get_file_name_offset(__FILE__))::utility... as a global namespace reference and had no problems with that. Can you introduce a minimal example?std::utility, but I could not find any. So I wonder why it should not work in previous C++ standards? The old MSVC has nothing special about the namespace usage rules. I always used :: prefix and had no problems with namespace intersection. May be you tried to include an include into opened std namespace? Or used using namespace std somewhere in the code? These are usual mistakes in the code.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.
__LINE__ value by one. So __LINE__ written in line x gest evaluated to x-1. At least with gcc 5.4.#line __LINE__-1, "file.c". I'll update my answer.#line 2 "name.cpp". Also as a side note it is nice to know that it does not contaminate other files that #include it (at least on MSVC)Purely compile time solution here. It's based on the fact that sizeof() of a string literal returns its length+1.
#define STRIPPATH(s)\
(sizeof(s) > 2 && (s)[sizeof(s)-2] == '/' ? (s) + sizeof(s) - 1 : \
sizeof(s) > 3 && (s)[sizeof(s)-3] == '/' ? (s) + sizeof(s) - 2 : \
sizeof(s) > 4 && (s)[sizeof(s)-4] == '/' ? (s) + sizeof(s) - 3 : \
sizeof(s) > 5 && (s)[sizeof(s)-5] == '/' ? (s) + sizeof(s) - 4 : \
sizeof(s) > 6 && (s)[sizeof(s)-6] == '/' ? (s) + sizeof(s) - 5 : \
sizeof(s) > 7 && (s)[sizeof(s)-7] == '/' ? (s) + sizeof(s) - 6 : \
sizeof(s) > 8 && (s)[sizeof(s)-8] == '/' ? (s) + sizeof(s) - 7 : \
sizeof(s) > 9 && (s)[sizeof(s)-9] == '/' ? (s) + sizeof(s) - 8 : \
sizeof(s) > 10 && (s)[sizeof(s)-10] == '/' ? (s) + sizeof(s) - 9 : \
sizeof(s) > 11 && (s)[sizeof(s)-11] == '/' ? (s) + sizeof(s) - 10 : (s))
#define __JUSTFILE__ STRIPPATH(__FILE__)
Feel free to extend the conditional operator cascade to the maximum sensible file name in the project. Path length doesn't matter, as long as you check far enough from the end of the string.
I'll see if I can get a similar macro with no hard-coded length with macro recursion...
-O1 to use this to be compile-time.sizeof(s) > 2 check first. Also, this did not work at compile-time for me, at -Os. The full path strings were present in the output binary.For Visual Studio, you can use the (undocumented/experimental) /d1trimfile compiler option. It takes a case-insensitive prefix argument and has the effect of stripping this prefix from __FILE__ whenever this macro is evaluated.
Applying the /d1trimfile:"$(SolutionDir)\" option effectively changes all __FILE__ evaluations to become solution directory relative:
NB: Explanation for the trailing \ right before the ":
To escape the first one (
$(SolutionDir)ends in a backslash), otherwise the quote is escaped. You need an even amount of backslashes before the quote.
I have use the same solution with @Patrick 's answer for years.
It has a small issue when the full path contains symbol-link.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
-Wno-builtin-macro-redefined to mute the compiler warnings for redefining __FILE__ macro.
For those compilers do not support this, refer to the Robust way below.
Strip the project path from the file path is your real requirement. You won't like to waste the time to find out where is a header.h file, src/foo/header.h or src/bar/header.h.
We should strip the __FILE__ macro in cmake config file.
This macro is used in most exists codes. Simply redefine it can set you free.
Compilers like gcc predefines this macro from the command line arguments. And the full path is written in makefiles generated by cmake.
Hard code in CMAKE_*_FLAGS is required.
There is some commands to add compiler options or definitions in some more recently version, like add_definitions() and add_compile_definitions(). These commands will parse the make functions like subst before apply to source files. That is not we want.
-Wno-builtin-macro-redefined.include(CheckCCompilerFlag)
check_c_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
Remember to remove this compiler option from the
set(*_FLAGS ... -D__FILE__=...)line.
__FILE__ with your definition to produce a diagnostic in an inline function defined in a header file, the runtime diagnostic will report the name of the file passed to the compiler instead of the name of the include file, whereas the line number would refer to the include file.#define LOG(fmt, args...) printf("%s " fmt, __FILE__, ##args). when using the LOG() macro, you do not really want to see log.h in messages. after all, the __FILE__ macro is expanded in every C/Cpp file (compile unit) instead of the included files.In VC, when using /FC, __FILE__ expands to the full path, without the /FC option __FILE__ expands file name. ref: here
__FILE__ uses the relative path instead of the absolute path. Although it is shorter, it is not a "file name without path" solution.UseFullPaths) defaults to true unless overridden at a more local level (such as in the project file). See Microsoft.Cl.Common.props ...This behaviour has been implemented in some compilers, you can get basename of the compiled file by using:
__FILE_NAME__ (since GCC 12)__FILE_NAME__ (since CLANG 9.0.0)Here is the solution available with C++14 or newer that uses compile-time calculation:
constexpr auto* getFileName(const char* const path)
{
const auto* startPosition = path;
for (const auto* currentCharacter = path;*currentCharacter != '\0'; ++currentCharacter)
{
if (*currentCharacter == '\\' || *currentCharacter == '/')
{
startPosition = currentCharacter;
}
}
if (startPosition != path)
{
++startPosition;
}
return startPosition;
}
std::cout << getFileName(__FILE__);
There's no compile time way to do this. Obviously you can do it at runtime using the C runtime, as some of the other answers have demonstrated, but at compile time, when the pre-procesor kicks in, you're out of luck.
strrchr answer could plausibly be computed at compile-time, although of course still not by the preprocessor. I don't know whether gcc actually does it, I haven't checked, but I'm pretty sure that it does compute strlen of string literals at compile-time.__FILE__ is invoked implicitly by assert(), this leak can occur without any other overt act.__FILE__ itself may also reveal things the customer might prefer not to, so using __FILE__ anywhere at all -- whether it contains the full absolute pathname or just the basename -- has the same issues that you pointed out. In this situation all output will need to be scrutinized and a special API should be introduced for output to customers. The rest of the output should be dumped to /dev/NULL or stdout and stderr should be closed. :-)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.
char file_copy[] = __FILE__; const char *filename = basename(__FILE__);. The reason for the copy is that basename can modify the input string. You also have to watch out that the result pointer is only good until basename is called again. This means it isn't thread-safe.basename in fact will not modify the input string that results from __FILE__, because the input string doesn't have a / at the end and so there's no need for modification. So you might get away with it, but I figure the first time someone sees basename, they should see it with all the restrictions./ at the end of the string means basename may have a good reason to modify its argument.A slight variation on what @red1ynx proposed would to be create the following macro:
#define SET_THIS_FILE_NAME() \
static const char* const THIS_FILE_NAME = \
strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__;
In each of your .c(pp) files add:
SET_THIS_FILE_NAME();
Then you can refer to THIS_FILE_NAME instead of __FILE__:
printf("%s\n", THIS_FILE_NAME);
This means the construction is performed once per .c(pp) file instead of each time the macro is referenced.
It is limited to use only from .c(pp) files and would be unusable from header files.
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.
FILE is a really bad idea if you include <stdio.h>.__FILE__ contains mixed separators e.g. c:\abc/xyz\file.h.I did a macro __FILENAME__ that avoids cutting full path each time. The issue is to hold the resulting file name in a cpp-local variable.
It can be easily done by defining a static global variable in .h file. This definition gives separate and independent variables in each .cpp file that includes the .h. In order to be a multithreading-proof it worth to make the variable(s) also thread local (TLS).
One variable stores the File Name (shrunk). Another holds the non-cut value that __FILE__ gave. The h file:
static __declspec( thread ) const char* fileAndThreadLocal_strFilePath = NULL;
static __declspec( thread ) const char* fileAndThreadLocal_strFileName = NULL;
The macro itself calls method with all the logic:
#define __FILENAME__ \
GetSourceFileName(__FILE__, fileAndThreadLocal_strFilePath, fileAndThreadLocal_strFileName)
And the function is implemented this way:
const char* GetSourceFileName(const char* strFilePath,
const char*& rstrFilePathHolder,
const char*& rstrFileNameHolder)
{
if(strFilePath != rstrFilePathHolder)
{
//
// This if works in 2 cases:
// - when first time called in the cpp (ordinary case) or
// - when the macro __FILENAME__ is used in both h and cpp files
// and so the method is consequentially called
// once with strFilePath == "UserPath/HeaderFileThatUsesMyMACRO.h" and
// once with strFilePath == "UserPath/CPPFileThatUsesMyMACRO.cpp"
//
rstrFileNameHolder = removePath(strFilePath);
rstrFilePathHolder = strFilePath;
}
return rstrFileNameHolder;
}
The removePath() can be implemented in different ways, but the fast and simple seems to be with strrchr:
const char* removePath(const char* path)
{
const char* pDelimeter = strrchr (path, '\\');
if (pDelimeter)
path = pDelimeter+1;
pDelimeter = strrchr (path, '/');
if (pDelimeter)
path = pDelimeter+1;
return path;
}
Try
#pragma push_macro("__FILE__")
#define __FILE__ "foobar.c"
after the include statements in your source file and add
#pragma pop_macro("__FILE__")
at the end of your source file.
push_macro and pop_macro are non-standard. (gcc supports them for compatibility with Microsoft Windows compilers.) In any case, there's no point in pushing and popping the definition of __FILE__; the restored value won't be used after the end of the source file anyway. A cleaner way to change the value of __FILE__ is #line __LINE__ "foobar.c"Here is a portable function that works for both Linux (path '/') and Windows (mix of '\' and '/').
Compiles with gcc, clang and vs.
#include <string.h>
#include <stdio.h>
const char* GetFileName(const char *path)
{
const char *name = NULL, *tmp = NULL;
if (path && *path) {
name = strrchr(path, '/');
tmp = strrchr(path, '\\');
if (tmp) {
return name && name > tmp ? name + 1 : tmp + 1;
}
}
return name ? name + 1 : path;
}
int main() {
const char *name = NULL, *path = NULL;
path = __FILE__;
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path ="/tmp/device.log";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:\\Downloads\\crisis.avi";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:\\Downloads/nda.pdf";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:/Downloads\\word.doc";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = NULL;
name = GetFileName(NULL);
printf("path: %s, filename: %s\n", path, name);
path = "";
name = GetFileName("");
printf("path: %s, filename: %s\n", path, name);
return 0;
}
Standard output:
path: test.c, filename: test.c
path: /tmp/device.log, filename: device.log
path: C:\Downloads\crisis.avi, filename: crisis.avi
path: C:\Downloads/nda.pdf, filename: nda.pdf
path: C:/Downloads\word.doc, filename: word.doc
path: (null), filename: (null)
path: , filename:
If you ended up on this page looking for a way to remove absolute source path that is pointing to ugly build location from the binary that you are shipping, below might suit your needs.
Although this doesn't produce exactly the answer that the author has expressed his wish for since it assumes the use of CMake, it gets pretty close. It's a pity this wasn't mentioned earlier by anyone as it would have saved me loads of time.
OPTION(CMAKE_USE_RELATIVE_PATHS "If true, cmake will use relative paths" ON)
Setting above variable to ON will generate build command in the format:
cd /ugly/absolute/path/to/project/build/src &&
gcc <.. other flags ..> -c ../../src/path/to/source.c
As a result, __FILE__ macro will resolve to ../../src/path/to/source.c
Beware of the warning on the documentation page though:
Use relative paths (May not work!).
It is not guaranteed to work in all cases, but worked in mine - CMake 3.13 + gcc 4.5
A short, working answer for both Windows and *nix:
#define __FILENAME__ std::max<const char*>(__FILE__,\
std::max(strrchr(__FILE__, '\\')+1, strrchr(__FILE__, '/')+1))
std::max<const char*> instead of just std::max?std::max requires <algorithm> which I would rather not include in a header file. Another option can be checking platform by #ifdef _WIN32 since __FILE__ will have consistent separator characters.In MSVC, add FILENAME macro as FILENAME=%(FileName)%(Extension) to the Preprocessor Definitions of the C++ project. I'm afraid this is completely a compiler killer. Somehow it breaks parallel build.
Here's a solution that works for environments that don't have the string library (Linux kernel, embedded systems, etc):
#define FILENAME ({ \
const char* filename_start = __FILE__; \
const char* filename = filename_start; \
while(*filename != '\0') \
filename++; \
while((filename != filename_start) && (*(filename - 1) != '/')) \
filename--; \
filename; })
Now just use FILENAME instead of __FILENAME__. Yes, it's still a runtime thing but it works.
A tweaked, even more "bloated" version of red1ynx's answer:
#define __FILENAME__ \
(strchr(__FILE__, '\\') \
? ((strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)) \
: ((strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)))
If we find backslashes, we split on backslashes. Otherwise, split on forward slash. Simple enough.
Just about any alternative would be cleaner (A C++ constexpr is really the gold standard here, in my opinion). However, this may be helpful if you're using some compiler where __BASE_FILE__ isn't available.
__FILE__ contains mixed separators, e.g. c:\abc\xyz/file.h, then the macro does not work.I think this is better than using strrchr function.
strfnchr will search last delemeter '/' and get filename from __FILE__
and you can use __FILE__NAME__ instead __FILE__ for get file name without full file path.
strrchr solution searching filename twice per use. but this code is just 1 time search.
And it works effectively even if there is no seperater '/' in __FILE__.
You can use it by replacing it with \ as needed.
The source code of strfnchr was improved by using the source code of strrchr below. I think it will work more effectively than strrchr.
https://code.woboq.org/userspace/glibc/string/strrchr.c.html
inline const char* strfnchr(const char* s, int c) {
const char* found = s;
while (*(s++)) {
if (*s == c)
found = s;
}
if (found != s)
return found + 1;
return s;
}
#define __FILE_NAME__ strfnchr(__FILE__, '/')
The top answer is not good enough for it's not a compile-time const expression Here is a really simple solution:
#define FILESTEM(x) \
std::string_view(x).substr(std::string_view(x).rfind(OS_PATH_SLASH) + 1, \
std::string_view(x).rfind('.') - \
std::string_view(x).rfind(OS_PATH_SLASH) - 1)
it's a constexpr and can use in header file.
This solution is based on @RenatoUtsch answer:
CMake list:
string(LENGTH "${PROJECT_SOURCE_DIR}/" SOURCE_PATH_SIZE)
add_definitions("-DSOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}")
add_definitions("-DSOURCE_PATH=\"${PROJECT_SOURCE_DIR}\"")
C/C++ header
#define __FILENAME__ strstr(__FILE__, SOURCE_PATH) + SOURCE_PATH_SIZE
__FILE__contains by changing the filename you pass on the command line. So instead ofgcc /full/path/to/file.c, trycd /full/path/to; gcc file.c; cd -;. Of course there's a bit more to it than that if you're relying on gcc's current directory for the include path or output file location. Edit: the gcc docs suggest that it's the full path, not the input file name argument, but that's not what I'm seeing for gcc 4.5.3 on Cygwin. So you may as well try it on Linux and see.__FILE__printed as../../../../../../../../rtems/c/src/lib/libbsp/sparc/leon2/../../shared/bootcard.cand I want to know where gcc compiled the file such that this file is relatively located like it is shown.