在编译时获取源文件的基本名称
我正在使用海湾合作委员会; __FILE__ 返回当前源文件的完整路径和名称:/path/to/file.cpp
。 有没有办法在编译时只获取文件名 file.cpp
(不带路径)? 是否有可能以便携的方式做到这一点? 模板元编程可以应用于字符串吗?
我在错误记录宏中使用它。 我真的不希望我的源代码的完整路径进入可执行文件。
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
(without its path) at compile time? Is it possible to do this in a portable way? Can template meta programming be applied to strings?
I am using this in an error logging macro. I really do not want my source's full path making its way into the executable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
如果您使用的是
make
程序,您应该能够预先修改文件名并将其作为宏传递给gcc
以在您的程序中使用。 例如,在makefile
中,将行:更改为:
这将允许您在代码中使用
MYFILE
而不是__FILE__
。使用源文件
$<
的basename
意味着您可以在.co
等通用规则中使用它。 下面的代码说明了它是如何工作的。 首先是makefile
:然后是子目录中的文件
src/main.c
:最后是显示其运行情况的记录:
注意
file =
> 行仅包含文件的基本名称,而不包含目录名称。If you're using a
make
program, you should be able to munge the filename beforehand and pass it as a macro togcc
to be used in your program. For example, in yourmakefile
, change the line:to:
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, amakefile
:Then a file in a subdirectory,
src/main.c
:Finally, a transcript showing it running:
Note the
file =
line which contains only the base name of the file, not the directory name as well.我不知道有什么直接的方法。 您可以
在源文件顶部使用:来设置 __FILE__ 的值,但我不确定这比硬编码好得多。 或者只是使用#define 创建您自己的宏。
另一种选择可能是使用 -D 和 $(shell basename $<) 从 Makefile 传递名称
编辑:如果您使用 #define 或 -D 选项,您应该创建自己的新名称,而不是尝试重新定义 <代码>__FILE__。
I don't know of a direct way. You could use:
at the top of the source file to set the value of
__FILE__
, but I'm not sure that that's much better than hard coding it. or just using a #define to create your own macro.Another option might be to pass the name from your Makefile using -D and $(shell basename $<)
Edit: If you use a #define or the -D option, you should create your own new name and not try to redefine
__FILE__
.由于您标记了 CMake,因此有一个巧妙的解决方案可以添加到您的 CMakeLists.txt 中:
(复制自 http://www.cmake.org/pipermail/cmake/ 2011-12 月/048281.html)。 (注意:有些编译器不支持每个文件 COMPILE_DEFINITIONS!但它可以与 gcc 一起使用)
注意:对于我的应用程序,我需要像这样转义文件名字符串:
Since you tagged CMake, here's a neat solution to add to your CMakeLists.txt:
(copied from http://www.cmake.org/pipermail/cmake/2011-December/048281.html ). (Note : some compilers don't support per-file COMPILE_DEFINITIONS ! but it works with gcc)
Note : For my application I needed to escape the filename string like this:
考虑这个简单的源代码:
在 Solaris 上,使用 GCC 4.3.1,如果我使用以下方式编译它:
输出为 '
xc
' 如果我使用以下方式编译它:那么 __FILE__ 映射到完整路径 ('<代码>/work1/jleffler/tmp/xc')。 如果我使用以下命令编译它:
那么 __FILE__ 映射到 '
../tmp/xc
'。所以,基本上, __FILE__ 是源文件的路径名。 如果您使用您希望在对象中看到的名称进行构建,那么一切都很好。
如果这是不可能的(无论出于何种原因),那么您将不得不接受其他人建议的修复。
Consider this simple source code:
On Solaris, with GCC 4.3.1, if I compile this using:
the output is '
x.c
' If I compile it using:then __FILE__ maps to the full path ('
/work1/jleffler/tmp/x.c
'). If I compile it using: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.
你的错误记录宏有什么作用? 我假设在某个时候宏最终会调用某种函数来进行日志记录,为什么不让被调用的函数在运行时剥离路径组件呢?
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?
您也许可以使用模板元编程来做到这一点,但没有内置的方法可以做到这一点。
编辑:嗯,更正。 根据我刚刚看到的一页,GCC 使用为文件指定的路径。 如果给出了全名,它将嵌入它; 如果只给出一个相对的,它只会嵌入它。 不过我自己还没有尝试过。
You might be able to do it with template metaprogramming, but there's no built-in way to do it.
EDIT: Hm, correction. According to one page I just saw, GCC uses the path that it's given for the file. If it's given the full name, it'll embed it; if it's only given a relative one, it'll only embed that. I haven't tried it myself though.
这个问题已经有 12 年历史了,早在 2008 年,这个解决方案还不可用,但从
GCC 8 和 CLANG 10 开始,可以使用选项 -fmacro-prefix-map。
根据海湾合作委员会手册:
例如,我的 IDE (Eclipse) 中的 makefile 对于某些文件包含以下 GCC 参数:
-fmacro-prefix-map="../Sources/"=.
因此,我的调试日志始终仅显示文件名,而不显示路径。
注:GCC 8.1 和 Clang 10 分别于 2018 年 5 月和 2020 年 3 月发布。 因此,目前,到 2020 年 9 月,只有我的部分环境支持 -fmacro-prefix-map。
The question is already 12 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:
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.
借鉴 Glomek 的想法,它可以像这样自动化:
源文件 xc
编译行(注意双引号外的单引号):
输出为 '
abcd.c
'。Taking the idea from Glomek, it can be automated like this:
Source file x.c
Compilation line (beware the single quotes outside the double quotes):
The output is '
abcd.c
'.用cmake很容易。
DefineRelativeFilePaths.cmake
位于
CMakeLists.txt
中cmake .. && 使清洁&& make VERBOSE=1
就是这样。 现在您可以制作漂亮的日志消息。
PS 最好在 config.h.in 中声明 ->
config.h
所以你的 linter 不会提供大量错误。
It is easy with cmake.
DefineRelativeFilePaths.cmake
Somewhere in
CMakeLists.txt
cmake .. && make clean && make VERBOSE=1
That's it. Now you can make pretty log messages.
PS It is better to declear in
config.h.in
->config.h
So your linter wan't provide rain of errors.
您可以将 __FILE__ 分配给一个字符串,然后调用 _splitpath() 将其拆分出来。 这可能是一个仅限 Windows/MSVC 的解决方案,老实说我不知道。
我知道您正在寻找编译时解决方案,这是一个运行时解决方案,但我认为由于您使用文件名来进行(大概是运行时)错误日志记录,这可能是一种简单直接的方法来帮助您你需要什么。
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.
您可以获取 __FILE__ 并去掉您不需要的路径部分(以编程方式)。 如果 basedir 满足您的需求,那就没问题了。 否则,从构建系统获取源目录根目录,其余的应该是可行的。
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.
刚刚遇到同样的问题; 找到了不同的分辨率,只是想分享它:
在我所有其他文件中包含的头文件中:
希望这对其他人也有用:)
Just got the same issue; found a different resolution, just thought I'd share it:
In a header file included in all my other files:
Hope this is useful to someone else as well :)