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

pod7payv  于 2022-12-20  发布在  其他
关注(0)|答案(2)|浏览(202)

bounty已结束。回答此问题可获得+250声望奖励。奖励宽限期将在23小时后结束。user541686希望引起更多人关注此问题。

我最近发现,当在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;
}

高度:

#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>\documents\dev\solution\project\foo.h
Press enter to exit

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

ohfgkhjo

ohfgkhjo1#

我将发布我自己的解决方案,这是不完美的,但最接近的变通方案,我知道。
当调用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
egdjgwm8

egdjgwm82#

若要配置Microsoft Visual C++(MSVC)使用FILE预定义宏显示头文件得相对路径,可以定义/FC编译器选项.此选项告诉编译器在FILE宏得输出中显示源文件得完整路径与头文件得相对路径.
要在项目中定义/FC选项,可以按照下列步骤操作:
在Visual Studio中打开项目。在解决方案资源管理器中右键单击项目并选择“属性”,转到项目属性页。在左侧菜单中,导航到“配置属性”〉“C/C++”〉“预处理器”。在“预处理器定义”字段中,将/FC添加到定义列表中。保存项目属性并重新生成项目。定义/FC选项并重新生成项目后,FILE宏的输出应该显示头文件的相对路径和源文件的完整路径。
请注意,/FC选项的效果与FILE宏的默认行为相反,后者显示源文件的相对路径和头文件的绝对路径。如果要保持默认行为,可以省略/FC选项。
希望这有帮助!

相关问题