c++ - comando - gcc compile 32



O que exatamente a opção-Wpsabi do GCC faz? Quais são as implicações de suprimi-lo? (1)

fundo

No ano passado eu estava usando a biblioteca json nlohmann [1] e estava compilando em x86_64 usando o GCC 5.x arm-linux-gnueabi-* sem avisos. Quando atualizei o GCC para uma versão mais recente, o GCC gerava páginas de anotações de diagnóstico enigmáticas. Por exemplo, aqui está uma das notas

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)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Foi fácil encontrar uma solução, adicionando -Wno-psabi às opções do compilador. Na verdade, essa foi a correção implementada na biblioteca. [2]

Eu entendo o básico de Interfaces Binárias de Aplicativos (ABIs) e ABIs específicas de processadores (psABIs). Para referência, esta resposta [11] fornece uma visão geral rápida das ABIs:

Um ABI ( Application Binary Interface ) é um padrão que define um mapeamento entre conceitos de baixo nível em linguagens de alto nível e as habilidades de um código de máquina específico de uma plataforma de hardware / sistema operacional. Isso inclui coisas como:

  • como tipos de dados C / C ++ / Fortran / ... são dispostos na memória (tamanhos de dados / alinhamentos)
  • como a função aninhada chama o trabalho (onde e como as informações sobre como retornar ao chamador de uma função são armazenadas, onde nos registros da CPU e / ou na memória os argumentos da função são passados)
  • como funciona a inicialização / inicialização do programa (que formato de dados tem um "executável", como o código / dados é carregado a partir daí, como as DLLs funcionam ...)

As respostas para estas são:

  • específico do idioma (portanto, você tem uma ABI C ABI, ABI C ++, ABI Fortran, ABI Pascal, ... até mesmo a especificação de bytecode Java, embora tenha como alvo um processador "virtual" em vez de hardware real, é uma ABI),
  • específico do sistema operacional (MS Windows e Linux no mesmo hardware usam uma ABI diferente),
  • hardware / específico da CPU (as ABIs ARM e x86 são diferentes).
  • evoluindo ao longo (longo) tempo (as ABIs existentes foram atualizadas / revendidas para que novos recursos de CPU pudessem ser utilizados, como, digamos, especificar como os registradores x86 SSE devem ser usados ​​pelos aplicativos, é claro, só é possível uma vez CPUs tinham esses regs, portanto, as ABIs existentes precisavam ser esclarecidas).

Portanto, a ABI é o componente abrangente e um de seus componentes (os detalhes "específicos de hardware / CPU") é o psABI.

Meu problema

O problema que estou tendo é

  1. Eu não gosto de desabilitar universalmente os avisos sem entender as implicações.
  2. O conselho "use -Wno-psabi para fazer as notas desaparecerem" parece ser um conselho bastante comum para esses tipos de notas de diagnóstico que "aparecem de repente" após uma atualização do compilador. [2] [3] [4] Até mesmo um dos desenvolvedores do GCC sugere fazer isso. [5]
  3. Nem o -Wpsabi nem o -Wno-psabi estão documentados [6] no manual do GCC. [7]

Como resultado, não tenho certeza do que exatamente -Wno-psabi irá e não afetará. Uma opção relacionada -Wabi está documentada: [8]

-Wabi (C, Objective-C, C++ and Objective-C++ only)

Avisa quando G + + gera código que provavelmente não é compatível com o C ++ ABI neutro de fornecedor ...

Ele também avisa sobre alterações relacionadas ao psABI. As alterações conhecidas do psABI neste ponto incluem:

  • Para SysV / x86-64, uniões com longos membros duplos são passados ​​na memória conforme especificado em psABI. Por exemplo:

union U { long double ld; int i; };

union U é sempre passada na memória.

Meu entendimento disso tudo é

  1. -Wabi gerará avisos quando houver uma alteração psABI.
  2. O GCC 7 corrigiu um bug ABI [9] introduzido no GCC 5 que afeta os objetivos do ARM.
    • Nas notas de lançamento, afirma-se "esta é uma alteração da ABI". [10]
    • Por alguma razão, as notas de lançamento afirmam que as notas de diagnóstico relacionadas são geradas ao usar o não documentado -Wpsabi , não o documentado -Wabi .
    • Esta alteração da ABI não é mencionada no manual.
  3. Juntando "isto é uma mudança ABI" e "use -Wpsabi ", parece-me que isto é especificamente uma alteração psABI, não um tipo diferente de alteração ABI. (Na realidade, é uma mudança na implementação do psabi, não do próprio psabi)

Eu sei que a documentação não está sempre atualizada, especialmente para algo que é uma opção não documentada conhecida. Mas a minha preocupação é que "use -Wno-psabi " parece ser a resposta padrão para vários tipos diferentes dessas notas de diagnóstico crípticas. Mas, no meu entendimento básico das ABIs, a ABI não é um grande negócio? Eu não deveria estar preocupado com uma mudança na ABI, em vez de apenas fazer a mensagem desaparecer? Entre as coisas não documentadas e alguns dos detalhes mais sutis da ABI vs psABI, não tenho certeza ...

Por exemplo, se eu adicionar -Wno-psabi ao meu makefile para fazer essas anotações desaparecerem, e se houver outra alteração na ABI no futuro que afete o meu projeto? Eu efetivamente silenciei futuros avisos ou anotações que podem ser importantes?

Além disso, mesmo que nos digam "se você recompilar todo o código, não há nada com que se preocupar" [5], o que exatamente é "todo o código"? Esse é o meu código fonte? glibc? Qualquer outra biblioteca compartilhada de todo o sistema que eu possa estar usando?

Referências

  1. https://github.com/nlohmann/json
  2. https://github.com/nlohmann/json/issues/658
  3. https://stackoverflow.com/a/48149400
  4. https://stackoverflow.com/a/13915796/10270632
  5. https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
  6. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
  7. https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
  8. https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
  9. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
  10. https://gcc.gnu.org/gcc-7/changes.html
  11. https://stackoverflow.com/a/8063350

https://ffff65535.com


Você só precisa se preocupar com as ABIs quando estiver cruzando os limites da biblioteca. Dentro de suas próprias aplicações / bibliotecas, a ABI realmente não importa, pois presumivelmente todos os seus arquivos-objeto são compilados com a mesma versão do compilador e comutadores.

Se você tiver uma biblioteca compilada com o ABI1 e um aplicativo compilado com o ABI2, o aplicativo irá travar quando tentar chamar funções da biblioteca, já que não passará os argumentos corretamente. Para consertar a falha, você precisaria recompilar a biblioteca (e quaisquer outras bibliotecas das quais ela depende) com o ABI2.

No seu caso específico, contanto que você compile o nlohmann com a mesma versão do compilador que o seu aplicativo (ou esteja apenas usando o nlohmann como cabeçalho), então você não precisa se preocupar com a alteração da ABI.

Suprimir globalmente o aviso parece ser uma opção perigosa, pois impedirá que você veja quaisquer problemas futuros da ABI. Uma opção melhor seria usar # #pragma para desativar o aviso apenas para as funções em questão, por exemplo:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wno-psabi"
void foo()
{
}
#pragma GCC diagnostic pop




abi