通过宏判断VS编译版本以及系统平台

本文详细介绍了MSVC系列编译器版本与_MSC_VER的对应关系,包括Visual Studio 2005到2013的版本标识,并提供了在不同平台上的自动检测方法。

1编译器

_MSC_VER 定义编译器的版本。下面是一些编译器版本的_MSC_VER值(参见扩展阅读中的参考文献2的链接)
MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)
MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)
MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio 2003)
MSVC++ 7.0  _MSC_VER == 1300
MSVC++ 6.0  _MSC_VER == 1200
MSVC++ 5.0  _MSC_VER == 1100
其中MS VC++ 10.0就是Visual C++ 2010,MS VC++ 9.0就是Visual C++ 2008,MS VC++ 8.0就是Visual C++ 2005。版本名称上的的对应关系参见扩展阅读中的参考文献1的链接.

//******************************************************************************
// Automated platform detection
//******************************************************************************

// _WIN32 is used by
// Visual C++
#ifdef _WIN32
#define __NT__
#endif

// Define __MAC__ platform indicator
#ifdef macintosh
#define __MAC__
#endif

// Define __OSX__ platform indicator
#ifdef __APPLE__
#define __OSX__
#endif

// Define __WIN16__ platform indicator 
#ifdef _Windows_
#ifndef __NT__
#define __WIN16__
#endif
#endif

// Define Windows CE platform indicator
#ifdef WIN32_PLATFORM_HPCPRO
#define __WINCE__
#endif

#if (_WIN32_WCE == 300) // for Pocket PC
#define __POCKETPC__
#define __WINCE__
//#if (_WIN32_WCE == 211) // for Palm-size PC 2.11 (Wyvern)
//#if (_WIN32_WCE == 201) // for Palm-size PC 2.01 (Gryphon)  
//#ifdef WIN32_PLATFORM_HPC2000 // for H/PC 2000 (Galileo)
#endif


转自:

<think>首先,用户在询问如何在UEFI中使用PCD值作为编译判断。意思是,他们想使用PCD(Platform Configuration Database)的值在编译时作为判断条件。 从引用中: - 引用[1]描述了PCD作为平台配置数据库,类似于但可动态修改。 - 引用[2]提到编译阶段确定的值,有些PCD是静态的,在整个运行阶段不可改,类似或const全局变量。它说"编译阶段确定的值",并且"FeatureFlag"可能是一个类型。 - 引用[3]讨论了PCD在UEFI中的使用,包括在库中传递全局变量。 - 引用[4]解释PCD作为可配置的数据,类似于,但有些可以动态修改。提到"PCD常用类型"。 用户的具体问题是:"我想查找在UEFI中使用PCD值作为编译判断的方法"。所以,我需要解释如何在使用PCD值在编译时作为来进行条件判断。 关键点是"编译判断",意思是使用在编译时基于PCD值进行条件编译。 在UEFI中,PCD有几种类型: - FeatureFlag PCD:布尔类型,用于启用或禁用特性。 - FixedAtBuild PCD:在编译时固定值,运行时不改变。 - Dynamic PCD:在运行时可以修改。 用户提到"编译判断",所以他们可能关心如何在编译时使用PCD值作为来进行条件编译。 在UEFI开发中,常见的做法是使用FeatureFlag PCD或FixedAtBuild PCD,因为这些在编译时是已知的。 从引用[2]:"编译阶段确定的值,整个UEFI运行阶段不可改的静态值,二进制下也不可以改,可以认为是一个,const全局变量。" 这指向FixedAtBuild PCD。 引用[4]:"类似于C语言中的,降低了代码维护的工作量",并提到"PCD常用类型"。 所以,我应该解释如何使用FeatureFlag或FixedAtBuild PCD在编译时进行判断。 步骤可能包括: 1. 在DEC文件中定义PCD:在那里声明PCD的类型和默认值。 2. 在INF文件中使用PCD:INF文件指定模块使用的PCD。 3. 在代码中访问PCD:在C代码中,使用像FeaturePcdGet()或FixedPcdGet()这样的来获取值。 4. 作为条件编译:在源文件中使用预处理器指令如#ifdef或#if基于PCD值来条件编译代码。 例如,对于一个FeatureFlag PCD: - 定义FeatureFlag PCD在DEC文件中。 - 在INF文件中包含它。 - 在代码中,使用FeaturePcdGet(PcdFeatureName)来获取布尔值,但这可能在运行时。对于编译时条件编译,需要使用方式。 在UEFI中,为了条件编译,通常会使用预处理器。PCD的访问如FeaturePcdGet()定义为,所以在编译时会被替换。 例如,FeaturePcdGet()可能会扩展为一个常量表达式,允许在#if指令中使用。 在UEFI规范中,FeatureFlag PCD是为了在编译时进行条件编译而设计的。 类似地,FixedAtBuild PCD在编译时是常量。 所以,方法: - 定义PCD:在平台的DEC文件中添加类似: [PcdsFeatureFlag] gEfiMyFeaturePkgTokenSpaceGuid.PcdMyFeatureEnable|FALSE|BOOLEAN|0x12345678 - 在模块的INF文件中,在[FeaturePcd]部分添加它: [FeaturePcd] gEfiMyFeaturePkgTokenSpaceGuid.PcdMyFeatureEnable - 在C代码中,使用: #if FeaturePcdGet(PcdMyFeatureEnable) // 启用特性的代码 #else // 禁用特性的代码 #endif FeaturePcdGet()是一个,在编译时被替换为1或0,所以它可以在#if中使用。 对于FixedAtBuild PCD,类似地,使用FixedPcdGetBool()或直接比较。 但FeaturePcdGet()是专门为布尔标志设计的。 用户的具体查询是"作为编译判断",所以重点是编译时的条件编译。 现在,关于生成相关问题:系统指令说"生成相关问题",所以我需要在回答结束时添加相关问题。 回答结构:使用中文,清晰结构。 参考引用:在回答中自然地添加引用标识,如[^1]。 用户提供的引用是[1]到[4],所以我应该引用它们。 最后,确保LaTeX语法正确:用户提到数学表达式,但这里可能不涉及数学,所以可能不需要。但如果有变量等,使用$...$。 在UEFI上下文中,可能没有太多数学。 组织回答: 1. 解释什么是PCD和它的类型。 2. 描述如何使用FeatureFlag PCD进行编译时条件编译。 3. 提供示例代码或步骤。 4. 添加相关问题。 </think>### UEFI中使用PCD值作为编译判断的方法 在UEFI(Unified Extensible Firmware Interface)开发中,PCD(Platform Configuration Database)提供了一种机制来存储和访问平台配置信息。用户查询的核心是如何使用PCD值在编译时作为进行条件判断(即编译判断),这类似于C语言中的预处理器(如`#if`),以实现代码的条件编译。这种机制特别适合于启用或禁用特定功能、优化代码路径或根据平台配置定制固件行为。 以下内容基于UEFI规范和相关引用,我将逐步解释实现方法。重点在于使用**FeatureFlag PCD**或**FixedAtBuild PCD**类型,因为这些类型在编译时确定值,运行时不改变,适合作为编译使用[^2][^4]。动态PCD(如PatchableInModule)在运行时可修改,不适合编译时判断,因此不在此讨论。 #### 1. **理解PCD类型及其适用性** - **FeatureFlag PCD**:布尔类型(`BOOLEAN`),专为条件编译设计。值在编译时固定(如`TRUE`或`FALSE`),在UEFI运行阶段不可修改,相当于一个全局常量或[^2][^4]。它允许在代码中使用预处理器指令(如`#if`)进行条件判断。 - **FixedAtBuild PCD**:在编译时确定的常量值(如整数、字符串),运行时不改变。可用于编译时判断,但相比FeatureFlag更通用(不限于布尔值)[^2][^4]。 - **为什么选择这些类型?** FeatureFlag PCD是编译判断的首选,因为它直接集成到预处理器中,简化条件编译[^2][^4]。引用[4]强调PCD类似于,但提供更好的可维护性和配置灵活性。 #### 2. **实现步骤:使用FeatureFlag PCD作为编译** 以下是详细步骤,以FeatureFlag PCD为例说明如何在UEFI模块中使用PCD值进行编译时条件判断。整个过程涉及DEC文件(平台配置定义)、INF文件(模块定义)和C源代码。 ##### 步骤1: 在DEC文件中定义PCD 在平台的DEC文件(如`YourPlatformPkg.dec`)中,声明一个FeatureFlag PCD。这定义了PCD的全局标识、默认值和类型。 ```c [PcdsFeatureFlag] # 定义一个布尔型FeatureFlag PCD,用于启用/禁用特定功能 gEfiYourTokenSpaceGuid.PcdYourFeatureEnable|FALSE|BOOLEAN|0x00000001 ``` - **解释**: - `gEfiYourTokenSpaceGuid`:一个唯一的GUID(Globally Unique Identifier),用于命名空间,需在DEC文件中定义(如`[Guids]`部分)。 - `PcdYourFeatureEnable`:PCD名称,表示“你的特性是否启用”。 - `FALSE`:默认值(编译时可覆盖)。 - `BOOLEAN`:类型,确保是布尔值。 - `0x00000001`:PCD的Token值(唯一标识符)。 引用[2]指出,此类PCD在编译时确定值,类似,易于在不同模块中配置[^2]。 ##### 步骤2: 在INF文件中引用PCD 在模块的INF文件(如`YourModule.inf`)中,指定该PCD为`FeaturePcd`,以便编译器在编译时处理。 ```c [Defines] INF_VERSION = 0x00010005 BASE_NAME = YourModule [FeaturePcd] # 关键部分:声明FeatureFlag PCD用于条件编译 gEfiYourTokenSpaceGuid.PcdYourFeatureEnable ``` - **解释**:`[FeaturePcd]`部分告诉UEFI构建工具(如edk2的build命令),该PCD将用于预处理器扩展。编译时,工具会生成定义(如`FeaturePcdGet(PcdYourFeatureEnable)`),替换为`1`(TRUE)或`0`(FALSE)。 ##### 步骤3: 在C代码中使用PCD进行编译判断 在源文件(如`YourModule.c`)中,使用预处理器指令`#if`或`#ifdef`基于PCD值进行条件编译。`FeaturePcdGet()`是一个,在编译时被展开为常量值。 ```c #include <Library/PcdLib.h> // 必须包含PCD库头文件 VOID YourFunction() { // 编译时条件判断:如果PcdYourFeatureEnable为TRUE,则编译特定代码块 #if FeaturePcdGet(PcdYourFeatureEnable) // 启用特性的代码(仅在PCD值为TRUE时编译) DEBUG((DEBUG_INFO, "Feature is enabled\n")); YourEnabledCode(); #else // 禁用特性的代码(仅在PCD值为FALSE时编译) DEBUG((DEBUG_INFO, "Feature is disabled\n")); YourDisabledCode(); #endif // 其他代码(无论PCD值如何,都会被编译) } ``` - **关键点**: - `FeaturePcdGet(PcdYourFeatureEnable)`:编译时,直接扩展为`1`或`0`,允许在`#if`指令中使用(这是UEFI PCD库的标准实现)。 - 优势:代码块在编译时被包含或排除,减少运行时开销,并避免未使用代码进入二进制文件。 - 引用[4]强调,这种方式降低了硬编码带来的维护工作量,类似但更灵活[^4]。 ##### 完整示例场景 假设你需要控制一个调试功能的编译: - 在DEC文件定义:`gEfiCommonPkgTokenSpaceGuid.PcdDebugEnable|TRUE|BOOLEAN|0x10000000` - 在INF文件声明:`[FeaturePcd] gEfiCommonPkgTokenSpaceGuid.PcdDebugEnable` - 在C代码中使用: ```c #include <Library/PcdLib.h> #if FeaturePcdGet(PcdDebugEnable) #define DEBUG_PRINT(msg) DEBUG((DEBUG_INFO, msg)) #else #define DEBUG_PRINT(msg) // 空定义,编译时移除调试打印 #endif ``` #### 3. **注意事项和最佳实践** - **编译时覆盖PCD值**:在构建时,可以通过命令行或DSC文件(平台描述文件)覆盖PCD默认值。例如,在DSC文件中: ```c [PcdsFeatureFlag] gEfiYourTokenSpaceGuid.PcdYourFeatureEnable|TRUE # 覆盖为TRUE ``` 这允许针对不同构建配置(如DEBUG/RELEASE)定制行为。 - **错误处理**:确保PCD访问(如`FeaturePcdGet()`)只用于编译时判断;不要将其用于运行时逻辑,否则可能引入错误。 - **适用阶段**:FeatureFlag PCD在UEFI大部分阶段可用,但在早期阶段(如SEC或PEI初期)可能不可访问,引用[3]指出PCD模块加载后才可用[^3]。 - **与动态PCD的区别**:动态PCD(如`DynamicEx`类型)可在运行时修改,但不能用于`#if`指令(因为值在编译时不确定)。如果需要在运行时判断,使用`PcdGetBool()`函数,而非编译。 - **性能影响**:编译判断无运行时开销,适合性能敏感代码[^1][^4]。 通过这种方法,你可以高效地利用PCD作为编译,实现UEFI固件的模块化和可配置性。如果在实际项目中遇到问题,建议查阅UEFI规范或edk2文档。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值