Por que existem várias cópias de arquivos de cabeçalho em / usr / include?

4

Eu tenho navegado na minha pasta / usr / include tentando se familiarizar com o layout e notei que há várias cópias de arquivos de cabeçalho (pelo menos pelo nome, eu não os diferenciei realmente para ver se eram cópias exatas) encontradas em vários subdiretórios de / usr / include. Esse é especialmente o caso dos arquivos de cabeçalho padrão C e C ++, bem como dos arquivos de cabeçalho padrão POSIX / LSB.

Alguns exemplos incluem (observe ./ refere-se a / usr / include):

./asm-generic/unistd.h
./linux/unistd.h
./unistd.h
./x86_64-linux-gnu/sys/unistd.h
./x86_64-linux-gnu/bits/unistd.h
./x86_64-linux-gnu/asm/unistd.h

./stdlib.h
./x86_64-linux-gnu/bits/stdlib.h
./c++/7/stdlib.h
./c++/7/tr1/stdlib.h

./c++/7/cmath
./c++/7/ext/cmath
./c++/7/tr1/cmath

./asm-generic/termios.h
./linux/termios.h
./x86_64-linux-gnu/sys/termios.h
./x86_64-linux-gnu/bits/termios.h
./x86_64-linux-gnu/asm/termios.h
./termios.h

./linux/time.h
./time.h
./x86_64-linux-gnu/sys/time.h
./x86_64-linux-gnu/bits/time.h

Por que isso? E por que alguns cabeçalhos padrão C aparecem em locais C ++?

Eu só tenho um compilador instalado (GCC 7).

    
por Adam Sperry 19.11.2018 / 06:26

1 resposta

3

Não, eles não são cópias exatas.

Se você se interessar em investigar, verá que os arquivos no nível superior /usr/include normalmente terão muitos #ifdef s ou outros condicionais, e eles só definirão as partes independentes da arquitetura e #include outras coisas de diretórios específicos da arquitetura mais profundos na hierarquia. Como algumas partes específicas da arquitetura podem, por sua vez, depender de algumas partes independentes da arquitetura, pode haver várias camadas de inclusão umas sobre as outras.

Da mesma forma, os arquivos em /usr/include/c++ terão as declarações adicionais que só farão sentido para C ++ e #include s para os arquivos de inclusão correspondentes de C, conforme apropriado.

O nome do jogo é desduplicação para manutenção : o objetivo é que quando um desenvolvedor glibc precisa adicionar algo novo que afeta apenas a ABI entre o aplicativo e a glibc e não possui partes específicas da arquitetura , a adição idealmente precisa acontecer em apenas um local na árvore de arquivos de inclusão, e terá efeito para todas as arquiteturas de hardware que usam o glibc. Ou, digamos, quando uma nova chamada de sistema é adicionada ao kernel do Linux, haverá um lugar para adicioná-la sem interferir nas definições de chamada do sistema * BSD ou GNU Hurd, por exemplo. Ou se você estiver portando o glibc para outra arquitetura de hardware / kernel, você encontrará lugares nos quais você pode inserir as definições ABI de kernel necessárias sem perturbar as coisas independentes de arquitetura mais do que o absolutamente necessário.

Sim, é bem complicado.

Eu não tenho nenhuma referência fácil para você, já que todo o layout /usr/include é uma soma dos requisitos de padrões ISO C e POSIX e as escolhas feitas pelos projetos GCC e glibc.

Sugiro que anote o seu trio de arquitectura ( x86_64-linux-gnu no seu caso; obtenível com gcc -dumpmachine em qualquer arquitectura suportada pelo GCC) e depois estude o padrão do compilador #include <...> caminhos de pesquisa de arquivos.

Você pode ver os caminhos de pesquisa com:

  • cpp -v /dev/null -o /dev/null para C simples
  • cpp -x c++ -v /dev/null -o /dev/null para C ++

Eu não tenho um sistema com o GCC 7 disponível, mas para o GCC 6, a lista de caminhos de inclusão é semelhante a C:

...
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
...

... e assim para o C ++:

...
#include <...> search starts here:
 /usr/include/c++/6
 /usr/include/x86_64-linux-gnu/c++/6
 /usr/include/c++/6/backward
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
...

Se o diretório /usr/local/include/<architecture triplet> existisse, ele seria adicionado nas listas, logo antes de /usr/local/include .

Assim, parece que, para os seus próprios projetos, se você precisa ter versões específicas de uma arquitetura de um arquivo de inclusão, pode colocá-las em /usr/[local/]include/<architecture triplet>/ e os independentes de arquitetura regulares incluem arquivos em /usr/[local/]include/ . Eu não tocaria em nenhum diretório de inclusão cujo nome do caminho incluísse o número da versão principal do compilador sem um bom motivo.

Se você planeja modificar o glibc e não encontrar o que precisa na documentação do glibc do desenvolvedor, é melhor pedir conselhos sobre a lista de e-mail glibc development; glibc é extremamente complicado porque é utilizável também em arquiteturas que usam um compilador diferente do GCC e, portanto, pode não ter a convenção triplet de arquitetura como padrão.

    
por 19.11.2018 / 09:21