C++ 在编译时获取源文件的基名称
我正在使用GCC__返回当前源文件的完整路径和名称:C++ 在编译时获取源文件的基名称,c++,c,makefile,macros,compiler-construction,C++,C,Makefile,Macros,Compiler Construction,我正在使用GCC__返回当前源文件的完整路径和名称:/path/to/FILE.cpp。有没有办法在编译时只获取文件名file.cpp(不带路径)?是否可以以便携方式进行此操作?模板元编程可以应用于字符串吗 我在一个错误日志宏中使用它。我真的不希望我的源代码的完整路径进入可执行文件。您可以使用模板元编程来完成,但没有内置的方法来完成 编辑:嗯,更正。根据,GCC使用为文件指定的路径。如果给出了全名,它将嵌入它;如果只给它一个相对的,它只会嵌入它。不过我自己还没有试过。我不知道直接的方法。您可以使
/path/to/FILE.cpp
。有没有办法在编译时只获取文件名file.cpp
(不带路径)?是否可以以便携方式进行此操作?模板元编程可以应用于字符串吗
我在一个错误日志宏中使用它。我真的不希望我的源代码的完整路径进入可执行文件。您可以使用模板元编程来完成,但没有内置的方法来完成
编辑:嗯,更正。根据,GCC使用为文件指定的路径。如果给出了全名,它将嵌入它;如果只给它一个相对的,它只会嵌入它。不过我自己还没有试过。我不知道直接的方法。您可以使用:
#line 1 "filename.c"
bool IsDebugBuild()
{
return !NDEBUG;
}
在源文件的顶部设置\uuuuu file\uuuu
的值,但我不确定这比硬编码好多少。或者只是使用#define创建自己的宏
另一个选项可能是使用-D和$(shell basename$从Makefile传递名称,您可以使用:
#line 1 "filename.c"
bool IsDebugBuild()
{
return !NDEBUG;
}
或者,您可以在宏中使用NDEBUG来打开/关闭这些文件路径。错误记录宏的作用是什么?我想在某个时候,宏最终会调用某种函数来进行记录,为什么不在运行时将被调用的函数从路径组件中剥离
#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
}
#定义日志(消息)(文件)(消息)
无效日志(文件、消息)
{
#ifndef调试
strippath(file);//以某种合适的方式
#恩迪夫
cerr如果您使用的是make
程序,您应该能够预先将文件名作为宏传递给gcc
,以便在程序中使用。例如,在makefile
中,更改行:
file.o: file.c
gcc -c -o file.o src/file.c
致:
然后是子目录中的文件,src/main.c
:
#include <stdio.h>
int main (int argc, char *argv[]) {
printf ("file = %s\n", MYFILE);
return 0;
}
请注意file=
行,该行仅包含文件的基本名称,不包含目录名称。您可以获取\uuuu file\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。如果basedir满足您的需要,则可以。否则,请从生成系统中获取source dir根目录,其余的都应该是可行的。考虑以下简单的源代码:
#include <stdio.h>
int main(void)
{
puts(__FILE__);
return(0);
}
如果使用以下方法编译,则输出为“x.c
”:
gcc -o x $PWD/x.c && ./x
gcc -o x ../tmp/x.c && ./x
然后uuu文件映射到完整路径(“/work1/jleffler/tmp/x.c
”)。如果我使用以下方法编译它:
gcc -o x $PWD/x.c && ./x
gcc -o x ../tmp/x.c && ./x
然后,文件映射到“。/tmp/x.c
”
因此,基本上,_FILE__是源文件的路径名。如果使用希望在对象中看到的名称进行构建,则一切正常
如果这是不可能的(无论出于何种原因),那么您将不得不使用其他人建议的修复方法。接受Glomek的想法,它可以自动执行,如下所示:
源文件x.c
#line 1 MY_FILE_NAME
#include <stdio.h>
int main(void)
{
puts(__FILE__);
return(0);
}
输出为“abcd.c
”。只能通过编程方式完成
也许这是有用的
filename = __FILE__
len = strlen(filename)
char *temp = &filename[len -1]
while(*temp!= filename)
if(*temp == '\') break;
您可以将\uuuu FILE\uuuu
分配给一个字符串,然后调用splitpath()将其拆分。老实说,这可能是Windows/MSVC唯一的解决方案,我不知道
我知道您正在寻找编译时解决方案,这是一个运行时解决方案,但我认为,由于您使用文件名进行(可能是运行时的)错误记录,这可能是一种简单直接的方法,可以满足您的需要。只是遇到了同样的问题;找到了不同的解决方案,我想与您分享一下:
在包含在所有其他文件中的头文件中:
static char * file_bname = NULL;
#define __STRIPPED_FILE__ (file_bname ?: (file_bname = basename(__FILE__)))
希望这对其他人也有用:)既然您标记了CMake,下面有一个简洁的解决方案可以添加到您的CMakeLists.txt中:
(复制自)。(注意:某些编译器不支持每文件编译定义!但它可以与gcc一起使用)
注意:对于我的应用程序,我需要像这样转义文件名字符串:
COMPILE_DEFINITIONS "MYSRCNAME=\"${b}\"")
使用cmake很容易
definererelativefilepaths.cmake
function (cmake_define_relative_file_paths SOURCES)
foreach (SOURCE IN LISTS SOURCES)
file (
RELATIVE_PATH RELATIVE_SOURCE_PATH
${PROJECT_SOURCE_DIR} ${SOURCE}
)
set_source_files_properties (
${SOURCE} PROPERTIES
COMPILE_DEFINITIONS __RELATIVE_FILE_PATH__="${RELATIVE_SOURCE_PATH}"
)
endforeach ()
endfunction ()
在CMakeLists.txt中的某个地方
set (SOURCES ${SOURCES}
"${CMAKE_CURRENT_SOURCE_DIR}/common.c"
"${CMAKE_CURRENT_SOURCE_DIR}/main.c"
)
include (DefineRelativeFilePaths)
cmake_define_relative_file_paths ("${SOURCES}")
cmake..&&make clean&&make VERBOSE=1
cc ... -D__RELATIVE_FILE_PATH__="src/main.c" ... -c src/main.c
就这样。现在你可以制作漂亮的日志消息了
#define ..._LOG_HEADER(target) \
fprintf(target, "%s %s:%u - ", __func__, __RELATIVE_FILE_PATH__, __LINE__);
func src/main.c:22-我的错误
PS最好在config.h.in
->config.h
#ifndef __RELATIVE_FILE_PATH__
#define __RELATIVE_FILE_PATH__ __FILE__
#endif
因此,您的linter wan不会提供大量错误。这个问题已经存在了18年,早在2008年,这个解决方案就不可用了,但是
从GCC 8和CLANG 10开始,可以使用-fmacro前缀映射选项。
根据GCC手册:
-fmacro prefix map=old=new
预处理驻留在目录“old”中的文件时,展开
\uuuuuuuuuuuu文件
和\uuuuuu基本文件
宏,就像文件位于
改为“新建”目录。这可用于将绝对路径更改为
使用“.”表示新的相对路径,这可能会导致
独立于位置的可复制构建。此选项也
编译期间影响\u内置文件()
。另请参阅
“-ffile前缀映射”
例如,my IDE(Eclipse)中的makefile为某些文件的GCC包含以下参数:-fmacro prefix map=“../Sources/”=。
因此,我的调试日志总是只显示文件名,而不显示路径
注意:GCC 8.1和Clang 10分别于2018年5月和2020年3月发布。因此,目前,在2020年9月,只有我的一些环境支持-fmacro前缀映射。文件名是给编译器的名称。我的源代码有一个目录结构,所以我不能只将文件名传递给编译器。此外,我正在使用CMake这个问题似乎总是给出完整的路径。我认为这个问题应该保留C++标签,因为模板元编程可能是一个有效的答案。也许@ BeNTalpPFA的复制品更像是一个复制的。
#define ..._LOG_HEADER(target) \
fprintf(target, "%s %s:%u - ", __func__, __RELATIVE_FILE_PATH__, __LINE__);
#ifndef __RELATIVE_FILE_PATH__
#define __RELATIVE_FILE_PATH__ __FILE__
#endif