如何配置MSVC以使用__FILE__显示头文件的相对路径

How do I configure MSVC to show relative path for header files using __FILE__?

本文关键字:显示 FILE 文件 路径 相对 何配置 配置 MSVC      更新时间:2023-10-16

我最近发现,在MSVC(特别是2013)中使用__FILE__预定义宏时,默认情况下,它将打印源文件的相对路径和头文件的绝对路径。

例如,我有一个VS项目,其中包含以下内容:

Solution
Project
Headers
foo.h
Sources
main.cpp

main.cpp和foo.h都在磁盘上的同一目录中。

main.cpp:

#include <iostream>
#include <string>
#include "foo.h"
int main(int, char*[])
{
std::cout << __FILE__ << std::endl;
foo::bar();
std::cout << "Press enter to exit";
std::string str;
std::getline(std::cin, str);
return 0;
}

foo.h:

#ifndef FOO_H
#define FOO_H
#include <iosfwd>
class foo
{
public:
static void bar()
{
std::cout << __FILE__ << std::endl;
}
};
#endif

当我运行应用程序时(在发布模式下,使用默认设置-未定义使用/Zi/FC编译),输出为:

main.cpp
c:users<user>documentsdevsolutionprojectfoo.h
Press enter to exit

我知道我可能会传入一个基本路径,并在运行时将其剥离,但我想知道是否有任何方法可以在编译时更改这种行为?显然,定义/FC会产生相反的结果,并且我在MSVC手册中看不到任何其他内容来控制标题路径的显示。我认为这可能是一种硬编码行为,因此,如果编译器能够从不同的包含路径中提取两个名为foo.h的文件,您仍然可以区分它们,或者因为可能有一个与源的基无关的包含路径,并且显示为相对路径会很混乱。

我将发布我自己的解决方案,这是不完美的,但也是我所知道的最接近的解决方案。

当调用assert时,该代码包含的每个文件都会从__FILE__中去掉PROJECT_DIR前缀,因此二进制文件将不包含该前缀。

一个更好的解决方案可能希望在必要时添加..前缀,同时处理/,并可能保留不同卷上的任何绝对路径,但我在这里不做任何这些操作。

// Add this to your .vcxproj:
// <PreprocessorDefinitions>PROJECT_DIR="$(ProjectDir.Replace('', '').TrimEnd(''))";%(PreprocessorDefinitions)</PreprocessorDefinitions>
#include <cassert>
#include <type_traits>
#ifdef PROJECT_DIR
template<class Char1, class Char2>
constexpr size_t path_imismatch(Char1 const a[], Char2 const b[])
{
size_t r = 0;
size_t i = 0;
for (;;)
{
Char1 ch1 = a[i];
Char2 ch2 = b[i];
bool const finished = ch1 == Char1() || ch2 == Char2() || !(ch1 == ch2);
if (ch2 == Char2()) { ch2 = ''; }
bool const isdirsep = ch1 == '' && ch1 == ch2;
if (isdirsep && ch1 == ch2) { r = i + 1; }
if (finished) { break; }
++i;
}
return r;
}
#define FILENAME(File, Root) ([]() { typedef std::decay_t<decltype(*(File))> _FileNameChar; constexpr _FileNameChar const f[] = File; enum : size_t { O = path_imismatch(f, Root), N = sizeof(f) / sizeof(*f) - O }; constexpr std::array<_FileNameChar, N> const result = []() { std::array<_FileNameChar, N> r = {}; for (size_t i = 0; i < N; ++i) { r[i] = f[O + i]; } return r; }(); return std::integral_constant<std::remove_const_t<decltype(result)>, result>(); }().value.data())
#define _wassert(Source, File, Line) (_wassert)(Source, FILENAME(File, _CRT_WIDE(PROJECT_DIR)), Line)
#endif