去年,我使用 nlohmann json 库 [1],在 x86 _ 64上使用 GCC 5.x arm-linux-gnueabi-*
进行交叉编译,没有任何警告。当我将 GCC 更新到一个新版本时,GCC 会生成一页页含糊不清的诊断说明。例如,下面是其中一个注释
In file included from /usr/arm-linux-gnueabi/include/c++/7/vector:69:0,
from include/json.hpp:58,
from src/write_hsi.cpp:23:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long int, long long unsigned int, double, std::allocator, nlohmann::adl_serializer>}; _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:394:7: note: parameter passing for argument of type ‘std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > >::iterator {aka __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >}’ changed in GCC 7.1
vector<_Tp, _Alloc>::
^~~~~~~~~~~~~~~~~~~
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer> nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::parser::parse_internal(bool) [with ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:105:21: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >’ changed in GCC 7.1
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
很容易找到解决方案,即将 -Wno-psabi
添加到编译器选项中。实际上,这就是库.[2]中实现的补丁
我了解应用程序二进制接口(ABI)和处理器特定 ABI (psABI)的基础知识。作为参考,这个答案 [11]给出了 ABI 的一个快速概述:
ABI (应用二进制接口)是一种标准,它定义了高级语言中的低级概念与特定硬件/操作系统平台的机器代码能力之间的映射。其中包括:
- 如何在内存中布局 C/C + +/Fortran/... 数据类型(数据大小/对齐)
- 嵌套的 函数调用是如何工作的(关于如何返回到函数调用者的信息存储在何处以及如何存储,在 CPU 寄存器和/或内存函数参数传递到何处)
- 程序启动/初始化是如何工作的(一个“可执行文件”具有什么样的数据格式,代码/数据是如何从那里加载的,DLL 是如何工作的... ...)
这些问题的答案是:
- 特定于语言的 (因此你有一个 C ABI,C + + ABI,Fortran ABI,Pascal ABI,... 甚至 Java 字节码规范,虽然目标是一个“虚拟”处理器而不是实际的硬件,是一个 ABI) ,
- 特定于操作系统的 (MS Windows 和 Linux 在同一硬件上使用不同的 ABI) ,
- 特定于硬件/CPU 的 (ARM 和 x86ABI 是不同的)。
- 随着时间的推移而发展(现有的 ABI 经常被更新/加速,以便新的 CPU 特性可以被利用,比如说,指定应用程序如何使用 x86 SSE 寄存器当然只有在 CPU 曾经这些规则时才可能,因此现有的 ABI 需要被澄清)。
因此,ABI 是总体组件,其中一个组件(“硬件/CPU 特定的”细节)是 psABI。
我的问题是
-Wno-psabi
使注释消失”似乎是相当常见的建议。甚至一个 GCC 开发人员也建议这样做-Wpsabi
和 -Wno-psabi
都没有记录在 [6]中因此,我真的不知道究竟什么 -Wno-psabi
会和不会影响。记录了一个相关的选项 -Wabi
是: [8]
-Wabi (C, Objective-C, C++ and Objective-C++ only)
当 G + + 生成的代码可能与与供应商无关的 C + + ABI 不兼容时发出警告..。
此时已知的 psABI 变化包括:
- 对于 SysV/x86-64,具有长双成员的联合按照 psABI 中指定的方式在内存中传递:
union U {
long double ld;
int i;
};
union U
总是在内存中传递。
我对这一切的理解是
-Wabi
将生成警告。-Wpsabi
时生成的,而不是记录的 -Wabi
。-Wpsabi
”放在一起,在我看来,这是 特别是一个 psABI 变化,而不是一个不同类型的 ABI 变化。(实际上,这是 GCC 实现 psABI 的一个变化,而不是 psABI 本身)我知道文档并不总是最新的,特别是对于那些已知的非文档化选项。但我担心的是,“使用 -Wno-psabi
”似乎是对几种不同类型的这些神秘的诊断说明的标准响应。但是,根据我对 ABI 的基本理解,ABI 的变化不是很大吗?我是否应该关心 ABI 的变化,而不是仅仅让消息消失?在没有文件的东西和一些更好的细节 ABI 与 psABI,我真的不确定..。
例如,如果我将 -Wno-psabi
添加到我的 makefile 中,使这些注释消失,那么如果在未来有另一个 ABI 更改,是的影响到我的项目,该怎么办?我是否有效地压制了未来可能很重要的警告或注意事项?
此外,即使我们被告知“如果你重新编译所有的代码,没有什么可担心的”,[5]到底是什么“所有的代码”?那是我的源代码吗?Glibc?我可能使用的任何其他系统范围的共享库?