C++预定义宏

本文介绍了C++中的预定义宏,包括标准预定义宏和Microsoft Visual C++特有的预定义宏,如__DATE__、__LINE__、__cplusplus等,并举例说明了它们的用途和用法。
部署运行你感兴趣的模型镜像

很长一段时间在win下开发,把一些win下特有的宏和标准c++预定义宏混淆了。记录一下

参考链接:https://msdn.microsoft.com/zh-cn/library/b0084kay.aspx

https://en.cppreference.com/w/cpp/preprocessor/replace

 

Visual c + + 编译器预定义某些预处理器宏,具体取决于语言 (C 或 c + +)、 编译目标,以及选择的编译器选项。

Visual c + + 支持 ANSI/ISO C99 标准和 ISO C + + 14 标准所指定的所需预定义的预处理器宏。 该实现还支持几个更多特定于 Microsoft 的预处理器宏。 仅针对特定的生成环境或编译器选项定义一些宏,宏。 除非另有说明,宏的定义整个翻译单元如同它们指定为 /D 编译器选项参数。 在定义时,宏是由预处理器在编译前扩展为指定的值。 预定义的宏不采用任何参数,并且不能重新定义。

 

标准的预定义的标识符

编译器支持 ISO C99 和 ISO C + + 11 中指定此预定义的标识符。

  • __func__ 为函数本地将封闭函数的未限定和未修饰名称 static``const 数组 char

    C++

    void example(){  
        printf("%s\n", __func__);  
    } // prints "example"  
    
    

 

标准预定义的宏

编译器支持 ISO C99 和 ISO C + + 14 标准所指定的这些预定义的宏。

  • __cplusplus 翻译单元将作为 c + + 编译时定义为整数文字值。 否则,未定义。

  • __DATE__ 当前源文件的编译日期。 日期是一个固定长度的字符串文字的窗体 Mmm dd yyyy。 月份名称 Mmm 等同于中的缩写的月份名称生成的 C 运行库日期 asctime 函数。 日期的第一个字符 dd 是一个空间,如果值是小于 10。 始终定义此宏。

  • __FILE__ 当前源文件的名称。 __FILE__ 扩展到字符的字符串文字。 若要确保显示该文件的完整路径,请使用 /FC (完整路径的源代码文件中诊断程序)。 始终定义此宏。

  • __LINE__ 定义为当前源文件中的整数行号。 值 __LINE__ 宏可通过使用更改 #line 指令。 始终定义此宏。

  • __STDC__ 定义为 1,仅当作为 C 编译,如果 /Za 指定编译器选项。 否则,未定义。

  • __STDC_HOSTED__ 定义为 1,如果实现是 承载实现, ,属于支持整个所需的标准库的支持。 否则,定义为 0。

  • __STDCPP_THREADS__ 定义为 1,当且仅当一个程序可以有多个线程的执行,并且编译为 c + +。 否则,未定义。

  • __TIME__ 预处理过的翻译单元的转换的时间。 时间是字符的字符串文字的窗体 ︰ 分︰ 秒, ,由 C 运行时库返回的时间相同 asctime 函数。 始终定义此宏。

 

Microsoft 专用预定的义宏

Microsoft Visual c + + 支持这些其他预定义的宏。

  • __ATOM__ 定义为 1 时 /favor:ATOM 设置编译器选项和编译器目标是 x86 或 x64。 否则,未定义。

  • __AVX__ 定义为 1 时 /arch:AVX 或 /arch: avx2 可以 设置编译器选项和编译器目标是 x86 或 x64。 否则,未定义。

  • __AVX2__ 定义为 1 时 /arch: avx2 可以 设置编译器选项和编译器目标是 x86 或 x64。 否则,未定义。

  • _CHAR_UNSIGNED 默认值定义为 1 如果 char 类型是无符号。 此值设置时 /J (默认 char 类型是无符号) 设置编译器选项。 否则,未定义。

  • __CLR_VER 定义为整数文字表示在已编译的应用程序时使用的公共语言运行时版本。 在窗体中编码的值 Mmmbbbbb, ,其中 M 是运行时,主要版本 mm 是运行时的次要版本和 bbbbb 为内部版本号。 __CLR_VER 如果定义 /clr 设置编译器选项。 否则,未定义。

    C++

    // clr_ver.cpp  
    // compile with: /clr  
    using namespace System;  
    int main() {  
       Console::WriteLine(__CLR_VER);  
    }  
    
    
  • _CONTROL_FLOW_GUARD 定义为 1 时 /guard:cf (启用控制流防护) 设置编译器选项。 否则,未定义。

  • __COUNTER__ Expands 为整数文字,从 0 开始的和每次在源文件中使用,就会递增 1,或者包含的源文件标头。 __COUNTER__ 会记住其状态时使用预编译的头。 始终定义此宏。

    此示例使用 __COUNTER__ 要分配给同一类型的三个不同的对象的唯一标识符。 exampleClass 构造函数采用一个整数作为参数。 在 main, ,应用程序声明了三个对象类型的 exampleClass, ,并使用 __COUNTER__ 用作唯一标识符参数︰

    C++

    // macro__COUNTER__.cpp  
    // Demonstration of __COUNTER__, assigns unique identifiers to  
    // different objects of the same type.  
    // Compile by using: cl /EHsc /W4 macro__COUNTER__.cpp  
    #include <stdio.h>  
    
    class exampleClass {  
        int m_nID;  
    public:  
        // initialize object with a read-only unique ID  
        exampleClass(int nID) : m_nID(nID) {}  
        int GetID(void) { return m_nID; }  
    };  
    
    int main()  
    {  
        // __COUNTER__ is initially defined as 0  
        exampleClass e1(__COUNTER__);  
    
        // On the second reference, __COUNTER__ is now defined as 1  
        exampleClass e2(__COUNTER__);  
    
        // __COUNTER__ is now defined as 2  
        exampleClass e3(__COUNTER__);  
    
        printf("e1 ID: %i\n", e1.GetID());  
        printf("e2 ID: %i\n", e2.GetID());  
        printf("e3 ID: %i\n", e3.GetID());  
    
        // Output  
        // ------------------------------  
        // e1 ID: 0  
        // e2 ID: 1  
        // e3 ID: 2  
    
        return 0;  
    }  
    
    
  • __cplusplus_cli 定义为整数文字值 200406 在作为 c + + 编译时和 /clr, ,/clr: pure, ,或 /clr: safe 设置编译器选项。 否则,未定义。 在定义时, __cplusplus_cli 有效范围是整个翻译单元。

    C++

    // cplusplus_cli.cpp  
    // compile by using /clr  
    #include "stdio.h"  
    int main() {  
       #ifdef __cplusplus_cli  
          printf("%d\n", __cplusplus_cli);  
       #else  
          printf("not defined\n");  
       #endif  
    }  
    
    
  • __cplusplus_winrt 定义为整数文字值 201009 在作为 c + + 编译时和 /ZW (Windows 运行时编译) 设置编译器选项。 否则,未定义。

  • _CPPRTTI 定义为 1 如果 /GR (启用运行时类型信息) 设置编译器选项。 否则,未定义。

  • _CPPUNWIND 定义为 1,如果一个或多个 /GX (启用异常处理), ,/clr (公共语言运行时编译), ,或 /EH (异常处理模型) 设置编译器选项。 否则,未定义。

  • _DEBUG 定义为 1 时 /LDd, ,/MDd, ,或 /MTd 设置编译器选项。 否则,未定义。

  • _DLL 定义为 1 时 /MD 或 /MDd 设置 (多线程 DLL) 编译器选项。 否则,未定义。

  • __FUNCDNAME__ 定义为一个字符串,它包含 修饰名 将封闭函数。 仅在函数内定义宏。 __FUNCDNAME__ 如果您使用不扩展宏 /EP 或 /P 编译器选项。

    此示例使用 __FUNCDNAME__, ,__FUNCSIG__, ,和 __FUNCTION__ 宏来显示函数信息。

     

    C++

    // Demonstrates functionality of __FUNCTION__, __FUNCDNAME__, and __FUNCSIG__ macros
    void exampleFunction()
    {
    	printf("Function name: %s\n", __FUNCTION__);
    	printf("Decorated function name: %s\n", __FUNCDNAME__);
    	printf("Function signature: %s\n", __FUNCSIG__);
    	
    	// Sample Output
    	// -------------------------------------------------
    	// Function name: exampleFunction
    	// Decorated function name: ?exampleFunction@@YAXXZ
    	// Function signature: void __cdecl exampleFunction(void)
    }
    

     

  • __FUNCSIG__ 定义为一个字符串,它包含封闭函数的签名。 仅在函数内定义宏。 __FUNCSIG__ 如果您使用不扩展宏 /EP 或 /P 编译器选项。 当针对 64 位目标编译,调用约定是 __cdecl 默认情况下。 有关用法的示例,请参阅 __FUNCDNAME__ 宏。

  • __FUNCTION__ 定义为包含封闭函数的未修饰的名称的字符串文字。 仅在函数内定义宏。 __FUNCTION__ 如果您使用不扩展宏 /EP 或 /P 编译器选项。 有关用法的示例,请参阅 __FUNCDNAME__ 宏。

  • _INTEGRAL_MAX_BITS 为整数文字值 64 的定义、 非向量整型的最大大小 (以位为单位)。 始终定义此宏。

    C++

    // integral_max_bits.cpp  
    #include <stdio.h>  
    int main() {  
       printf("%d\n", _INTEGRAL_MAX_BITS);  
    }  
    
    
  • __INTELLISENSE__ 定义为 1 期间 IntelliSense 编译器将传递在 Visual Studio IDE 中。 否则,未定义。 可以使用此宏来保护的代码 IntelliSense 编译器不了解,或使用它来生成和智能感知编译器之间切换。 有关详细信息,请参阅 的智能感知缓慢疑难解答提示

  • _ISO_VOLATILE 为 1 如果定义 /volatile: iso 设置编译器选项。 否则,未定义。

  • _KERNEL_MODE 为 1 如果定义 /kernel (创建内核模式二进制) 设置编译器选项。 否则,未定义。

  • _M_AMD64 定义为整数文字值 100 的编译该面向 x64 处理器。 否则,未定义。

  • _M_ARM 为整数文字值 7 面向 ARM 处理器的编译进行定义。 否则,未定义。

  • _M_ARM_ARMV7VE 定义为 1 时 /arch: armv7ve 面向 ARM 处理器的编译进行设置编译器选项。 否则,未定义。

  • _M_ARM_FP 定义为整数文字值,该值指示该 /arch 编译器选项已设置,如果编译目标,则 ARM 处理器。 否则,未定义。

    • 如果不是 30-39 的范围中 /arch ARM 选项已指定,对于 ARM 中指示的默认体系结构已设置 (VFPv3)。

    • 在范围内 40-49 if /arch: vfpv4 设置。

    • 请参阅 /arch (ARM) 有关详细信息。

  • _M_ARM64 定义为 1 的面向 64 位 ARM 处理器的编译。 否则,未定义。

  • _M_CEE 定义为 001 如果任何 /clr (公共语言运行时编译) 设置编译器选项。 否则,未定义。

  • _M_CEE_PURE 定义为 001 if /clr: pure 设置编译器选项。 否则,未定义。

  • _M_CEE_SAFE 定义为 001 if /clr: safe 设置编译器选项。 否则,未定义。

  • _M_FP_EXCEPT 定义为 1 如果 /fp︰ 除 或 /fp: strict 设置编译器选项。 否则,未定义。

  • _M_FP_FAST 定义为 1 如果 /fp:fast 设置编译器选项。 否则,未定义。

  • _M_FP_PRECISE 定义为 1 如果 /fp︰ 精确 设置编译器选项。 否则,未定义。

  • _M_FP_STRICT 定义为 1 如果 /fp: strict 设置编译器选项。 否则,未定义。

  • _M_IX86 定义为整数文字值 600 的编译该面向 x86 处理器。 没有为 x64 或 ARM 编译目标定义此宏。

  • _M_IX86_FP 定义为整数文字值,该值指示 /arch 编译器选项的设置,则默认值。 此宏始终定义的编译目标时 x86 处理器。 否则,未定义。 在定义时,其值为︰

    • /arch:IA32 编译器选项已设置。

    • 1 如果 /arch:SSE 编译器选项已设置。

    • 2 如果 /arch:SSE2, ,/arch:AVX 或 /arch: avx2 可以 编译器选项已设置。 如果此值为默认值 /arch 未指定编译器选项。 当 /arch:AVX 指定,则该宏 __AVX__ 也进行了定义。 当 /arch: avx2 可以 指定,则同时 __AVX__ 和 __AVX2__ 还定义了。

    • 请参阅 /arch (x86) 有关详细信息。

  • _M_X64 定义为整数文字值 100 的编译该面向 x64 处理器。 否则,未定义。

  • _MANAGED 指 1 /clr 设置编译器选项。 否则,未定义。

  • _MSC_BUILD 定义为整数文字,其中包含编译器的版本号的修订号元素。 修订版本号是版本号的句点分隔的第四个元素。 例如,如果 Visual c + + 编译器的版本号为 15.00.20706.01, _MSC_BUILD 宏计算结果为 1。 始终定义此宏。

  • _MSC_EXTENSIONS 定义为 1 如果 /Ze (启用语言扩展) 设置编译器选项,这是默认设置。 否则,未定义。

  • _MSC_FULL_VER 定义为整数文本进行编码主要,次版本号和内部数字元素的数目的编译器的版本号。 主版本号是句点分隔的版本号的第一个元素、 次版本号是第二个元素和内部版本号是第三个元素。 例如,如果 Visual c + + 编译器的版本号为 15.00.20706.01, _MSC_FULL_VER 宏计算结果为 150020706。 输入 cl /? 通过在命令行查看编译器的版本号。 始终定义此宏。

  • _MSC_VER 作为整形文本进行编码编译器的版本号的主要和次要数字元素定义。 主版本号是句点分隔的版本号的第一个元素和次版本号是第二个元素。 例如,如果 Visual c + + 编译器的版本号为 17.00.51106.1, _MSC_VER 宏计算结果为 1700年。 输入 cl /? 通过在命令行查看编译器的版本号。 始终定义此宏。

  • _MSVC_LANG 定义为一个整数,指定由编译器针对 c + + 语言标准。 如果宏时编译为 c + +,为整数型值 201402 /std:c + + 14 编译器选项是否设置,默认情况下,它是设置为更高时,未指定时,值 /std:c + + 中最新 设置编译器选项。 否则,该宏是不确定的。 _MSVC_LANG 宏和 /std (指定语言标准版本) 编译器选项是在 Visual Studio 2015 更新 3 开始。

  • __MSVC_RUNTIME_CHECKS 定义为 1,如果其中的 /RTC 设置编译器选项。 否则,未定义。

  • _MT 定义为 1 时 /MD 或 /MDd (多线程 DLL) 或 /MT 或 /MTd 指定 (多线程)。 否则,未定义。

  • _NATIVE_WCHAR_T_DEFINED 定义为 1 时 /zc: wchar_t 设置编译器选项。 否则,未定义。

  • _OPENMP 定义为整数文字 200203 表示由 Visual c + + 中实现的 OpenMP 规范的日期,如果 /openmp (启用 OpenMP 2.0 支持) 设置编译器选项。 否则,未定义。

    C++

    // _OPENMP_dir.cpp  
    // compile with: /openmp   
    #include <stdio.h>   
    int main() {  
       printf("%d\n", _OPENMP);  
    }  
    
    
  • _PREFAST_ 定义为 1 时 / 分析 设置编译器选项。 否则,未定义。

  • __TIMESTAMP__ 作为一个字符串,它包含的日期和时间的当前源文件返回的 C 运行库的缩写,常量长度窗体的上次修改定义 asctime 正常工作,例如, Fri 19 Aug 13:32:58 2016。 始终定义此宏。

  • _VC_NODEFAULTLIB 定义为 1 时 /Zl (省略默认库名) 设置编译器选项。 否则,未定义。

  • _WCHAR_T_DEFINED 定义为 1 时默认 /zc: wchar_t 设置编译器选项。 _WCHAR_T_DEFINED 宏定义,但如果不具有任何值 /Zc:wchar_t-设置编译器选项,并 wchar_t 项目中包含的系统标头文件中定义。 否则,未定义。

  • _WIN32 定义为 1 时编译目标是 32 位 ARM x86,在 64 位 ARM 或 x64。 否则,未定义。

  • _WIN64 编译目标为 64 位 ARM 或 x64 时定义为 1。 否则,未定义。

  • _WINRT_DLL 定义为 1 时编译为 c + + 和 /ZW (Windows 运行时编译) 和 /LD 或 /LDd 设置编译器选项。 否则,未定义。

用于确定 ATL 或 MFC 库版本的预处理器宏不是由编译器预定义的。 因此它们未定义的预处理器指令中包含必需的标头之前,这些宏的定义在库的标头。

  • _ATL_VER &lt; atldef.h &gt; 中定义为整数文本进行编码的 ATL 版本编号。

  • _MFC_VER &lt; afxver_.h &gt; 中定义为整数文本进行编码的 MFC 版本编号。

 

另请参阅

宏 (C/c + +)
预处理器运算符
预处理器指令

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>我们想要输出C++编译器的预定义。在qmake中,可以通过QMAKE_CXXFLAGS加上特定的编译器选项来实现。 对于GCC和Clang编译器,可以使用`-dM`选项来输出预定义。具体做法是,在qmake项目文件中添加一个自定义目标(custom target),通过执行编译器的命令来导出。 步骤: 1. 在.pro文件中,我们可以使用`system()`函数执行编译器命令,并将输出重定向到文件。 2. 或者,我们可以添加一个自定义目标,使得在构建时执行该命令。 方法一:在配置时输出(qmake运行阶段) 在.pro文件中添加: ``` TEMPLATE = app TARGET = predefines_test # 输出预定义到文件 # 使用GCC/Clang的-dM -E选项 # 注意:这里我们使用QMAKE_CXX来获取当前配置的C++编译器 dump_predefines.commands = $$QMAKE_CXX -dM -E - < /dev/null > predefines.txt 2>&1 dump_predefines.target = predefines.txt QMAKE_EXTRA_TARGETS += dump_predefines PRE_TARGETDEPS += predefines.txt ``` 但是,上述方法在Windows下可能不适用(因为/dev/null在Windows下不存在)。因此,我们可以考虑使用一个空文件,或者使用条件判断分别处理。 方法二:使用条件判断,跨平台处理 我们可以为不同平台编写不同的命令。对于Windows,我们可以使用`nul`(空设备),但是注意,命令可能不同。 另外,我们也可以使用qmake的`system()`函数在配置时直接执行并输出,但这样会在每次运行qmake时执行。 这里我们选择在构建时执行,并输出到文件。 改进的跨平台方案: 对于Unix-like系统(包括Linux和macOS): 命令:`$$QMAKE_CXX -dM -E - < /dev/null > predefines.txt 2>&1` 对于Windows(假设是MinGW或兼容GCC的编译器): 命令:`$$QMAKE_CXX -dM -E - < nul > predefines.txt 2>&1` 但是,在Windows的cmd中,重定向输入使用`<nul`,注意没有空格。 然而,qmake在解析命令时可能会将空格处理成参数分隔,所以我们可以这样写: 在.pro文件中: ``` win32 { dump_predefines.commands = $$QMAKE_CXX -dM -E - < nul > predefines.txt 2>&1 } else { dump_predefines.commands = $$QMAKE_CXX -dM -E - < /dev/null > predefines.txt 2>&1 } dump_predefines.target = predefines.txt QMAKE_EXTRA_TARGETS += dump_predefines PRE_TARGETDEPS += predefines.txt ``` 这样,在构建项目之前,会先生成predefines.txt文件,其中包含所有预定义。 注意:如果编译器不是GCC或Clang(比如MSVC),上述方法可能不适用。对于MSVC,我们可以使用`/EP`和`/dM`选项?但实际上MSVC没有完全等价的选项。我们可以使用`/Bx`选项调用cl.exe来输出,但比较复杂。 因此,这个方法主要适用于GCC和Clang编译器。 另外,我们也可以在.pro文件中通过配置,让qmake在运行时就输出预定义(而不是在构建时)。使用`system()`函数: ``` # 在配置时输出 unix|win32 { # 注意:这里我们使用相同的命令,但使用qmake的system函数立即执行 # 但是要注意,在Windows下,我们使用相同的命令可能不行,因为shell环境? # 我们可以分别写 unix { system($$QMAKE_CXX -dM -E - < /dev/null > predefines.txt 2>&1) } win32 { system($$QMAKE_CXX -dM -E - < nul > predefines.txt 2>&1) } } ``` 这样,在运行qmake时就会生成predefines.txt。 根据需求选择:如果希望在每次构建前更新,则使用自定义目标(方法一改进版);如果只在运行qmake时生成一次,则使用system函数。 另外,我们也可以考虑使用CONFIG选项来控制是否输出,比如: ``` dump_predefines { ... 同上 } ``` 然后在qmake命令行中加入`CONFIG+=dump_predefines`来触发。 综上所述,我们可以根据实际需求选择一种方式。 但请注意,用户的问题是如何使用qmake输出C++编译器的预定义。我们给出了两种主要方式。 如果用户使用的是MSVC编译器,我们可以考虑以下方法: 使用`cl /Bx cl /d /EP nul`(但是输出可能包含很多其他内容)或者使用`cl /?`来查看可用选项。实际上,MSVC的标准做法是使用`/P`预处理到文件,然后查看文件,但这样只能看到展开后的结果,而不是定义列表。 在MSVC中,我们可以使用`/d1reportAllClassLayout`选项来输出一些的信息,但并不是全部。所以对于MSVC,没有直接等价的选项。一个替代方案是使用`/EP`预处理一个空文件,然后从输出中提取定义(但输出中会包含很多系统头文件中的)。 因此,如果用户使用的是MSVC,可能需要更复杂的方法或者使用第三方工具。 鉴于问题主要是针对qmake,且qmake通常配合MinGW(在Windows下)或GCC/Clang(在Unix下)使用,我们主要提供GCC和Clang的方法。 最后,在qmake项目文件中实现: 选择在构建时生成的方法(跨平台GCC/Clang): ``` # 在.pro文件中 # 添加一个选项,例如DUMP_PREDEFINES,可以通过qmake "CONFIG+=dump_predefines"来启用 dump_predefines { win32 { dump_predefines.commands = $$QMAKE_CXX -dM -E - < nul > predefines.txt 2>&1 } else { dump_predefines.commands = $$QMAKE_CXX -dM -E - < /dev/null > predefines.txt 2>&1 } dump_predefines.target = predefines.txt QMAKE_EXTRA_TARGETS += dump_predefines PRE_TARGETDEPS += predefines.txt } ``` 这样,当我们在qmake命令中加入`CONFIG+=dump_predefines`时,就会在构建时生成预定义文件。 如果不希望每次构建都生成,可以将其放在一个自定义目标中,然后通过make来单独调用,但上述方法已经可以满足需求。 示例:运行 ``` qmake CONFIG+=dump_predefines make ``` 然后查看生成的predefines.txt文件。 注意:如果编译器路径中有空格,需要使用引号括起来。但是qmake的system()函数和自定义目标中的命令处理可能不支持带空格的路径。我们可以使用`$$shell_quote`函数(但qmake中并没有这个函数)。因此,我们可以使用`$$QMAKE_CXX`变量,它通常已经被正确设置了(即使有空格)。 另外,在Windows下,nul设备的位置不能有空格,所以没有问题。 如果编译器路径有空格,在命令中直接使用`$$QMAKE_CXX`可能会被拆分成多个单词。解决方法是使用`$ $ ( QMAKE_CXX )`这样的形式?不行。我们可以这样: ``` win32 { # 使用双引号括起来 dump_predefines.commands = \"$$QMAKE_CXX\" -dM -E - < nul > predefines.txt 2>&1 } ``` 但是,在命令中,如果路径有空格,确实需要用双引号括起来。因此,改进为: ``` dump_predefines { win32 { dump_predefines.commands = \"$$replace(QMAKE_CXX, /, \\)\" -dM -E - < nul > predefines.txt 2>&1 } else { dump_predefines.commands = \"$$QMAKE_CXX\" -dM -E - < /dev/null > predefines.txt 2>&1 } ... 其他相同 } ``` 这样应该可以处理路径中的空格。 注意:在Unix下,使用双引号括起来也是可以的。 所以,最终版本: ``` dump_predefines { win32 { # 将正斜杠替换为反斜杠,因为在Windows命令中更常见 compiler = $$replace(QMAKE_CXX, /, \\) dump_predefines.commands = \"$$compiler\" -dM -E - < nul > predefines.txt 2>&1 } else { dump_predefines.commands = \"$$QMAKE_CXX\" -dM -E - < /dev/null > predefines.txt 2>&1 } dump_predefines.target = predefines.txt QMAKE_EXTRA_TARGETS += dump_predefines PRE_TARGETDEPS += predefines.txt } ``` 这样,当启用dump_predefines配置时,就会生成预定义文件。 此外,我们也可以考虑使用`$$QMAKE_CXXFLAGS`,但这里不需要,因为`-dM`和`-E`是编译器选项,与平台无关(GCC和Clang都支持)。 现在,我们可以将这个方案提供给用户。 注意:用户可能没有在项目中使用GCC或Clang,所以需要说明适用条件。 相关问题: 1. 如何在使用MSVC编译器的Qt项目中输出预定义? 2. 如何让qmake自定义目标只在首次构建时运行? 3. 如何将预定义输出集成到Qt Creator的构建步骤中? </think>### 如何使用 qmake 输出 C++ 编译器的预定义 在 Qt 开发中,可通过 qmake 结合编译器选项输出 C++ 预定义。以下是详细步骤和方法: --- #### 方法一:使用 `-dM` 编译器选项(GCC/Clang) 在 `.pro` 文件中添加编译器指令,将预定义输出到文件: ```qmake # 在 .pro 文件中添加 dump_predefines.commands = $$QMAKE_CXX -dM -E - < /dev/null > predefines.txt 2>&1 dump_predefines.target = predefines.txt QMAKE_EXTRA_TARGETS += dump_predefines PRE_TARGETDEPS += predefines.txt ``` **说明**: 1. `-dM`:输出所有预定义 2. `-E`:仅执行预处理阶段 3. 生成文件:`predefines.txt` 4. **适用编译器**:GCC/G++、Clang(MinGW/MSYS2 环境) > **示例输出**: > ``` > #define __cplusplus 201402L > #define __GNUC__ 11 > #define __linux__ 1 > ``` --- #### 方法二:使用 `CONFIG += precompile_header`(MSVC/Qt 专有) 对于 MSVC 编译器,结合 Qt 的预编译头机制: ```qmake # 在 .pro 文件中添加 CONFIG += precompile_header PRECOMPILED_HEADER = precompiled.h ``` 创建 `precompiled.h` 文件: ```cpp // 添加需要检查的 #ifdef _MSC_VER #pragma message("_MSC_VER: " _STRINGIZE(_MSC_VER)) #endif ``` 构建时会在输出窗口显示定义值。 --- #### 方法三:通过 `DEFINES` 传递到 C++ 代码 在 `.pro` 中声明: ```qmake # 输出 C++ 标准版本 DEFINES += CPP_STD=cplusplus_$$replace(__cplusplus, ",", "_") # 输出编译器版本 linux-g++ { DEFINES += COMPILER_VERSION="__GNUC__.__GNUC_MINOR__" } win32-msvc { DEFINES += COMPILER_VERSION=_MSC_VER } ``` 在 C++ 代码中访问: ```cpp std::cout << "C++ Standard: " << CPP_STD << std::endl; std::cout << "Compiler Ver: " << COMPILER_VERSION << std::endl; ``` --- #### 跨平台兼容方案 ```qmake # 自动检测编译器类型 win32-msvc { # MSVC 专用命令 dump_msvc.commands = cl /B1 "C:\Program Files (x86)\Microsoft Visual Studio\...\cl.exe" /d /EP > msvc_defines.txt } else { # GCC/Clang 命令 dump_gcc.commands = $$QMAKE_CXX -dM -E - < /dev/null > gcc_defines.txt } ``` --- ### 关键说明 1. **核心原理**: 利用编译器的预处理指令(如 GCC 的 `-dM` 或 MSVC 的 `/d`)提取定义[^2][^1]。 2. **路径处理**: 使用 `$$QMAKE_CXX` 获取当前编译器路径,确保跨平台兼容性: ```qmake message("Current compiler: $$QMAKE_CXX") ``` 3. **输出定位**: 生成文件默认在构建目录(`OUT_PWD`),可通过 `$$OUT_PWD/defines.txt` 指定路径。 --- ### 相关问题 1. 如何在不同编译器(GCC/MSVC/Clang)下统一获取预定义? 2. Qt 项目中有哪些重要的 Qt 专用预定义(如 `QT_VERSION`)? 3. 如何通过 CMake 实现相同的预定义输出功能?[^3] 4. 预定义在跨平台开发中的典型应用场景有哪些? [^1][^2][^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值