【UEFI实战】StdLib的编译和使用 您所在的位置:网站首页 c语言中stdlibh的含义 【UEFI实战】StdLib的编译和使用

【UEFI实战】StdLib的编译和使用

#【UEFI实战】StdLib的编译和使用| 来源: 网络整理| 查看: 265

StdLib简要说明

UEFI的源代码中有一个Pacakge实现了UEFI下的标准C库,如下所示:

里面有很多C语言的基础函数,比如有stdio.h:

使用StdLib库可以方便对Linux等的代码的快速移植,也方便从其他C语言领域到UEFI开发的转移。

本文接下去介绍如何在UEFI下使用StdLib。

代码以vUDK2017: https://github.com/tianocore/edk2.git Tag vUDK2017.中的为例。

StdLib的编译

StdLib有独立的Package,可以独立编译。

本文使用的编译器是VS2015。

编译的步骤如下:

1. 运行edksetup.bat:

D:\Codes\vUDK2017>edksetup.bat PATH = D:\Codes\vUDK2017\BaseTools\Bin\Win32;C:\Program Files (x86)\Razer Chroma SDK\bin;C:\Program Files\Razer Chroma SDK\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;D:\Program Files\TortoiseGit\bin;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin;;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32\config\systemprofile\AppData\Local\Microsoft\WindowsApps;C:\Python37\Scripts\;C:\Python37\;C:\Users\HOME\AppData\Local\Microsoft\WindowsApps;D:\Program Files\Microsoft VS Code\bin;C:\Python27;C:\Python36;C:\Nasm;D:\Program Files\qemu;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin; WORKSPACE = D:\Codes\vUDK2017 EDK_TOOLS_PATH = D:\Codes\vUDK2017\BaseTools BASE_TOOLS_PATH = D:\Codes\vUDK2017\BaseTools EDK_TOOLS_BIN = D:\Codes\vUDK2017\BaseTools\Bin\Win32 CONF_PATH = D:\Codes\vUDK2017\Conf !!! WARNING !!! No CYGWIN_HOME set, gcc build may not be used !!! D:\Codes\vUDK2017>

2. 执行build命令:

D:\Codes\vUDK2017>build -a X64 -p StdLib\StdLib.dsc -t VS2015x86

但是发现执行命令时报错了:

Processing meta-data ... done! Building ... d:\codes\vudk2017\StdLib\LibC\LibC.inf [X64] "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe" /Fod:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\LibC\LibC\OUTPUT\Main\errno.obj /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /X /Zc:wchar_t /D UEFI_C_SOURCE /Wv:11 /Id:\codes\vudk2017\StdLib\LibC\Main\X64 /Id:\codes\vudk2017\StdLib\LibC\Main /Id:\codes\vudk2017\StdLib\LibC /Id:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\LibC\LibC\DEBUG /Id:\codes\vudk2017\StdLib /Id:\codes\vudk2017\StdLib\Include /Id:\codes\vudk2017\StdLib\Include\X64 /Id:\codes\vudk2017\StdLibPrivateInternalFiles /Id:\codes\vudk2017\StdLibPrivateInternalFiles\Include /Id:\codes\vudk2017\StdLibPrivateInternalFiles\Include\X64 /Id:\codes\vudk2017\MdePkg /Id:\codes\vudk2017\MdePkg\Include /Id:\codes\vudk2017\MdePkg\Include\X64 /Id:\codes\vudk2017\ShellPkg /Id:\codes\vudk2017\ShellPkg\Include d:\codes\vudk2017\StdLib\LibC\Main\errno.c errno.c "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe" /Fod:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\LibC\LibC\OUTPUT\Main\assert.obj /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /X /Zc:wchar_t /D UEFI_C_SOURCE /Wv:11 /Id:\codes\vudk2017\StdLib\LibC\Main\X64 /Id:\codes\vudk2017\StdLib\LibC\Main /Id:\codes\vudk2017\StdLib\LibC /Id:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\LibC\LibC\DEBUG /Id:\codes\vudk2017\StdLib /Id:\codes\vudk2017\StdLib\Include /Id:\codes\vudk2017\StdLib\Include\X64 /Id:\codes\vudk2017\StdLibPrivateInternalFiles /Id:\codes\vudk2017\StdLibPrivateInternalFiles\Include /Id:\codes\vudk2017\StdLibPrivateInternalFiles\Include\X64 /Id:\codes\vudk2017\MdePkg /Id:\codes\vudk2017\MdePkg\Include /Id:\codes\vudk2017\MdePkg\Include\X64 /Id:\codes\vudk2017\ShellPkg /Id:\codes\vudk2017\ShellPkg\Include d:\codes\vudk2017\StdLib\LibC\Main\assert.c assert.c d:\codes\vudk2017\StdLib\Include\sys/EfiCdefs.h(342): error C2220: 警告被视为错误 - 没有生成“object”文件 d:\codes\vudk2017\StdLib\Include\sys/EfiCdefs.h(342): warning C4117: 保留“__STDC_HOSTED__”宏名,忽略“#define” NMAKE : fatal error U1077: “"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe"”: 返回代码“0x2” Stop.

从说明中可以看出,报错的原因是宏重定义了,这是一个warning(编号是4117),由于EDK编译时默认设置了警告视为错误,所以这里就报错了。

我们可以查看出错代码:

// Keep compiler quiet about casting from smaller to larger types #pragma warning ( disable : 4306 ) #define __STDC__ 1 #define __STDC_VERSION__ 199409L #define __STDC_HOSTED__ 1

所以意思是这里的__STDC_HOSTED__有重定义,所以这里可以做如下的修改:

// Keep compiler quiet about casting from smaller to larger types #pragma warning ( disable : 4306 ) #define __STDC__ 1 #define __STDC_VERSION__ 199409L #ifndef __STDC_HOSTED__ #define __STDC_HOSTED__ 1 #endif

这样的话编译就OK了。

这种方法理论上是OK的,但是有一个疑问,即默认情况下__STDC_HOSTED__的值是1吗?如果不是1的话,显然跟我们需要定义的值不一致。

这边没有找到这个宏到底是在哪个文件,不过可以在网上搜到相关的说明(Predefined macros | Microsoft Docs):

Standard predefined macros

The compiler supports these predefined macros specified by the ISO C99 and ISO C++17 standards.

__cplusplus Defined as an integer literal value when the translation unit is compiled as C++. Otherwise, undefined.

__DATE__ The compilation date of the current source file. The date is a constant length string literal of the form Mmm dd yyyy. The month name Mmm is the same as the abbreviated month name in dates generated by the C Runtime Library asctime function. The first character of date dd is a space if the value is less than 10. This macro is always defined.

__FILE__ The name of the current source file. __FILE__ expands to a character string literal. To ensure that the full path to the file is displayed, use /FC (Full Path of Source Code File in Diagnostics). This macro is always defined.

__LINE__ Defined as the integer line number in the current source file. The value of the __LINE__ macro can be changed by using a #line directive. This macro is always defined.

__STDC__ Defined as 1 only when compiled as C and if the /Za compiler option is specified. Otherwise, undefined.

__STDC_HOSTED__ Defined as 1 if the implementation is a hosted implementation, one that supports the entire required standard library. Otherwise, defined as 0.

__STDCPP_THREADS__ Defined as 1 if and only if a program can have more than one thread of execution, and compiled as C++. Otherwise, undefined.

__TIME__ The time of translation of the preprocessed translation unit. The time is a character string literal of the form hh:mm:ss, the same as the time returned by the C Runtime Library asctime function. This macro is always defined.

可见这个宏的值不是0,就是1,所以上述的代码修改是没有问题的。

我们也可以在VS2015下实际编写一个程序来确定:

#include "stdafx.h" int main() { printf("hello world %d\n", __STDC_HOSTED__); while (1); return 0; }

执行的结果如下:

当然上述的问题还有其它的解决方法:

1. 在代码中使用#pragma来屏蔽这个警告:

// Keep compiler quiet about casting from smaller to larger types #pragma warning ( disable : 4306 ) #pragma warning ( disable : 4117 ) #define __STDC__ 1 #define __STDC_VERSION__ 199409L #define __STDC_HOSTED__ 1

2. 在DSC中添加宏控制来屏蔽这个警告:

[Defines] PLATFORM_NAME = StdLib PLATFORM_GUID = 6135e67b-d813-4e4a-93c3-945d6af41858 PLATFORM_VERSION = 0.01 DSC_SPECIFICATION = 0x00010006 OUTPUT_DIRECTORY = Build/StdLib SUPPORTED_ARCHITECTURES = IA32|X64|ARM|AARCH64 BUILD_TARGETS = DEBUG|RELEASE|NOOPT SKUID_IDENTIFIER = DEFAULT [BuildOptions] MSFT:*_*_*_CC_FLAGS = /wd4117

新加了宏之后,可以看到编译时有体现:

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Vc\bin\x86_amd64\cl.exe" /Fod:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\SocketDxe\SocketDxe\OUTPUT\.\AutoGen.obj /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2s /GL /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /wd4117 /X /Zc:wchar_t /D UEFI_C_SOURCE /Wv:11 /Id:\codes\vudk2017\StdLib\SocketDxe /Id:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\SocketDxe\SocketDxe\DEBUG /Id:\codes\vudk2017\MdePkg /Id:\codes\vudk2017\MdePkg\Include /Id:\codes\vudk2017\MdePkg\Include\X64 /Id:\codes\vudk2017\MdeModulePkg /Id:\codes\vudk2017\MdeModulePkg\Include /Id:\codes\vudk2017\StdLib /Id:\codes\vudk2017\StdLib\Include /Id:\codes\vudk2017\StdLib\Include\X64 d:\codes\vudk2017\Build\StdLib\DEBUG_VS2015x86\X64\StdLib\SocketDxe\SocketDxe\DEBUG\AutoGen.c AutoGen.c

以上的三种方式都能够解决编译的问题。

StdLib的使用

一般StdLib单独编译没有多大的意义,重要的是将它编译到其它的实用模块中。

比如有AppPkg:

在AppPkg.dsc中可以看到对StdLib的包含:

############################################################################## # # Include Boilerplate text required for building with the Standard Libraries. # ############################################################################## !include StdLib/StdLib.inc

对于StdLib的使用似乎也没有什么好多讲的,就是包含头文件之类的。

后续如果使用到再深入。

以上。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有