Фон
В прошлом году я использовал библиотеку 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 / ... типы данных расположены в памяти (размеры данных / выравнивания)
- howработают вложенные вызовы функций (где и как хранится информация о том, как вернуться к вызывающей функции, где в регистры ЦП и / или в память передаются аргументы функций)
- как запуск / инициализация программы работает (какой формат данных имеет "исполняемый файл", как оттуда загружается код / данные, как работают библиотеки DLL ...)
Ответы на эти вопросыявляются:
- для конкретного языка (следовательно, у вас есть C ABI, C ++ ABI, Fortran ABI, Pascal ABI, ... даже спецификация Java-байт-кода, хотя и нацеленная«виртуальный» процессор вместо реального оборудования (ABI),
- для конкретной операционной системы (MS Windows и Linux на одном оборудовании используют другой ABI),
- для оборудования / процессора (ABI ARM и x86 отличаются).
- эволюционирование в течение (длительного) времени (существующие ABI часто обновлялись / обновлялись, чтобы можно было использовать новые функции ЦП, как, например, указание того, как регистры SSE x86 должны использоваться приложениями, былоконечно, это возможно только тогда, когда процессоры имеют этих регистров, поэтому необходимо прояснить существующие ABI).
Таким образом, ABI является всеобъемлющим компонентом и одним из его компонентов(«специфичные для оборудования / процессора») - это psABI.
My Issue
Проблема, с которой я сталкиваюсь,
- Мне не нравится универсальноотключение предупреждений без понимания последствий.
- Рекомендация «используйте
-Wno-psabi
, чтобы убрать заметки», кажется довольно распространенным советом для этих типов диагностических заметок, которые «внезапно появляются» после обновления компилятора. [2] [3] [4] Даже один из разработчиков GCC предлагает сделать это. [5] - Ни
-Wpsabi
, ни -Wno-psabi
не задокументированы [6] в GCC маnual. [7]
В результате я не совсем уверен, что именно -Wno-psabi
повлияет и не повлияет.Связанная опция -Wabi
задокументирована : [8]
-Wabi (C, Objective-C, C++ and Objective-C++ only)
Предупредить, когда G ++ генерирует код, которыйвероятно, не совместим с независимым от производителя C ++ ABI ...
Он также предупреждает об изменениях, связанных с psABI.Известные изменения psABI на этом этапе включают:
- Для SysV / x86-64 объединения с длинными двойными членами передаются в память, как указано в psABI.Например:
union U {
long double ld;
int i;
};
union U
всегда передается в память.
Мое пониманиевсе это
-Wabi
будет генерировать предупреждения при изменении psABI. - GCC 7 исправил ошибку ABI [9] , введенную в GCC5, которая влияет на цели ARM.
- В примечаниях к выпуску указано "это изменение ABI". [10]
- По некоторым причинам в примечаниях к выпуску говорится, что соответствующие диагностические примечания генерируются при использовании недокументированного
-Wpsabi
, а не документированного -Wabi
.
- Это изменение ABI не упоминается в руководстве.
- Соединяя «это изменение ABI» и «используйте
-Wpsabi
», мне кажется, это конкретно изменение psABI, а не другой вид изменения ABI. (На самом деле это изменение реализации psABI в GCC, а не в самой psABI)
Я знаю, что документация не всегда актуальна, особенно для чего-то, что является известным недокументированным вариантом. Но меня беспокоит то, что «use -Wno-psabi
», по-видимому, является стандартным ответом на несколько разных видов этих загадочных диагностических заметок. Но, в моем базовом понимании ABI, разве ABI не меняет дело? Разве я не должен беспокоиться об изменении ABI, вместо того, чтобы просто пропустить сообщение? Между недокументированным материалом и некоторыми мелочами ABI против psABI я не совсем уверен ...
Например, если я добавлю -Wno-psabi
в свой make-файл, чтобы эти заметки исчезли, что если в будущем произойдет еще одно изменение ABI, которое повлияет на мой проект ? Эффективно ли я заставил замолчать будущие предупреждения или заметки, которые могут быть важны?
Кроме того, даже несмотря на то, что нам говорят: «если вы перекомпилируете весь код, вам не о чем беспокоиться» [5] что такое «весь код»? Это мой исходный код? GLibC? Любая другая общесистемная общая библиотека, которую я мог бы использовать?
Ссылки
- https://github.com/nlohmann/json
- https://github.com/nlohmann/json/issues/658
- https://stackoverflow.com/a/48149400
- https://stackoverflow.com/a/13915796/10270632
- https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
- https://gcc.gnu.org/gcc-7/changes.html
- https://stackoverflow.com/a/8063350