Como posso saber com certeza que biblioteca C da terra do usuário meu sistema usa? Os possíveis motivos para precisar essas informações incluem:
Estou pensando em fazer o download de um pacote de origem gigantesco que, com certeza, fará verificações adequadas e lista uma versão mínima da biblioteca, mas prefiro me poupar de um possível aborrecimento, verificando primeiro se ele funcionará.
Estou preocupado com a compatibilidade da ABI com alguns binários de terceiros que quero tentar instalar fora do sistema de gerenciamento de pacotes do sistema.
Eu tenho um pacote de origem cuja documentação menciona a necessidade de uma versão mínima da biblioteca do meu sistema, mas o processo de compilação não executa nenhuma verificação.
Estou criando um compilador cruzado direcionado a um sistema específico e não quero arriscar problemas de compatibilidade futuros .
fonte
ldd
. Não tenho certeza se issootool --version
pode dar a mesma informação.Respostas:
Os sistemas GNU / Linux geralmente usam glibc (família Fedora / Redhat, Arch) ou seu primo próximo, eglibc (família Debian / Ubuntu); Como o eglibc agora está sendo mesclado de novo no glibc ( consulte EGLIBC 2.19 Branch Criado em "Notícias" ), em um futuro próximo todos eles serão glibc novamente.
A maneira mais fácil de verificar a versão exata é perguntar
ldd
, que acompanha a biblioteca C.No Fedora 20:
Isso é glibc 2.18.
No Raspbian (porta Debian 7 para ARMv6 Broadcom SoC):
Isso é o eglibc 2.13.
Se, por qualquer motivo, você tiver misturado e correspondido algumas partes ou não tiver certeza
ldd
, poderá consultar a biblioteca C diretamente.Nenhum deles é executável, mas eles fornecem uma pista sobre onde encontrar um.
No entanto, não é necessariamente tão fácil, porque a biblioteca C não precisa residir em algum lugar
whereis
para encontrá-lo.Infelizmente, a página do manual não fornece um número de versão.
ldd
ainda é útil, pois qualquer executável dinamicamente vinculado no sistema (por exemplo, quase tudo incluído/usr/bin
) será vinculado à biblioteca C.libc.so.6
está na terceira linha.fonte
/lib/`uname -m`*
caminho. Assim maneira portátil seria:find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version
. Obrigado pela boa explicação.Na verdade, um sistema não está limitado a uma biblioteca C. A maioria, no entanto, usa principalmente apenas um, que também será o usado pelo compilador padrão. E como você está baixando o código-fonte para compilar, é com isso que você se preocupa.
Comece com um programa trivial:
compile-o usando o compilador que você usará para o código-fonte e use
ldd
para descobrir onde está a biblioteca C:Agora você tem o caminho para a biblioteca C. Você pode procurar isso no seu gerenciador de pacotes para encontrar o pacote (por exemplo,
dpkg -S /lib/x86_64-linux-gnu/libc.so.6
ourpm -q -f /lib/x86_64-linux-gnu/libc.so.6
).Pelo menos no caso do eglibc / glibc, você pode executá-lo:
Por fim, você pode ver se consegue obter dicas
objdump -p /lib/x86_64-linux-gnu/libc.so.6
, procurando na seção de definições de versão :Observe como o símbolo GLIBC_2.18 tem o número da versão mais recente entre os símbolos listados e a versão da biblioteca é realmente 2.18. É o eglibc, no entanto (ele visa ser compatível com binários com o glibc 2.18, por isso usa as mesmas versões de símbolos).
Você também pode tentar usar
strings
para descobrir algo sobre isso. Você deseja especificar um comprimento mínimo mais longo (-n
) ou usar grep para procurar algo:ambos trabalham para este eglibc.
NOTA: O utilitário de pacotes Debian
dpkg-shlibdeps
usaobjdump
sob o capô, juntamente com informações de símbolos armazenados nos pacotes de bibliotecas da Debian para determinar as versões mínimas de dependências exigidas pelos pacotes binários da Debian no momento da construção. Basicamente, ele examina os símbolos exportados pelo pacote binário do Debian e, em seguida, encontra as versões mínimas das bibliotecas que contêm esses símbolos.fonte
A resposta óbvia, embora não seja a mais abrangente, é verificar o seu gerenciador de pacotes, por exemplo
(Infelizmente, o glibc não possui um
.pc
arquivo pkconfig , tambémpkgconfig --modversion glibc
não é um corredor.) Veja também a excelentegetconf
sugestão do @ Gnouc .O caso mais simples, com gcc + glibc, e o que mais uso primeiro é apenas executar
libc.so
, conforme descrito em algumas das outras respostas aqui. Não há necessidade de passar nenhum argumento, ele exibe sua versão por padrão. Isso funciona desde o glibc-2.1 (glibc-2.0 seg-faults, embora na época você pudesse verificar oglibcbug
script (agora aposentado) para confirmar a versão). Este método também funciona com versões recentes (> 0.9.15) do musl-libc (que foi 1.0 hoje, 20 de março). Ele não funciona com o uClibc, é segmentado por falhas.Uma maneira simples de saber exatamente o que você
gcc
fará é compilar:(com glibc,
<stdio.h>
inclui o<features.h>
que define as macros GLIBC relevantes, você precisa<gnu/libc-version.h>
das declarações de função.)Isso captura casos mais complexos (vários libc e / ou vários compiladores), supondo que você esteja usando o compilador (e sinalizadores) certo, é claro. (Suspeito que não faça distinção entre eglibc e glibc propriamente dito.)
Se você tiver certeza de que está usando o glibc (ou eglibc),(desculpe, isso não está correto).ld
também confirmará a versãoSe
__GNU_LIBRARY__
não estiver definido, você receberá erros, é hora do plano B.gcc -dumpmachine
pode ajudar, por exemplo, para uclibc, ele tem um-uclibc
sufixo, como podegcc -dumpspecs | grep dynamic-linker
. Isso também pode implicar a ABI.gcc -print-file-name=libc.so
lhe dirá qual arquivo o compilador usará para "-lc
", este é quase certamente um script vinculador dentro da instalação do gcc, que você pode ler como texto simples. Isso mostrará o caminho exato paralibc.so
. Isso também funcionará se você estiver passando bandeiras como-m32
ou-m64
.No caso de você estiver usando uClibc (como o usado por OpenWRT e mais), define
__UCLIBC_MAJOR__
,__UCLIBC_MINOR__
e__UCLIBC_SUBLEVEL__
, assim como__UCLIBC__
em<features.h>
, por isso é facilmente detectada usando uma pequena variação no exposto C trecho de código. No interesse da compatibilidade, o uClibc também pode definir as macros GNU / GLIBC, conforme usado acima, atualmente fingindo ser glibc-2.2. Ele atualmente não implementar asgnu_get_libc_X()
funções, mas não implementargetconf
o que também pode induzir em erro (Eu suspeito que ele retorna uma resposta vazia paragetconf GNU_LIBC_VERSION
, meu construir env está de mau humor hoje, por isso não posso confirmar.)No caso improvável de usar dietlibc , a execução
diet -v
exibirá a versão.(FWIW, durante vários anos com software usando o autoconf, tive mais problemas com requisitos
gcc
eg++
requisitos não verificados do que com os recursos glibc verificados.)fonte
O GNU libc (o que a maioria das distribuições Linux usa de uma forma ou de outra) se esforça bastante para manter uma compatibilidade estrita com versões anteriores. Portanto, você deve ter problemas apenas se tentar executar um binário muito novo em uma versão antiga (ou em uma distribuição "corporativa", eles normalmente congelam versões, particularmente as básicas como a biblioteca C, corrigindo backport enquanto mantêm uma compatibilidade binária rigorosa) . Eu acredito que você é muito mais suscetível a ter problemas com outras bibliotecas (o C ++ teve algumas alterações de API / ABI na memória recente, outras bibliotecas simplesmente não se importam com a compatibilidade com versões anteriores).
Infelizmente, a única maneira de descobrir com certeza é tentar.
fonte
(Isso é essencialmente o mesmo que a resposta dos cachinhos dourados, mas com mais algumas explicações sobre o que está acontecendo sob o capô.)
A biblioteca compartilhada principal para GNU libc,
libc.so.6
(no Linux; Hurd tem um SONAME diferente), possui a propriedade incomum (para bibliotecas compartilhadas) que você pode invocá-la como executável. Se o fizer, ele imprime o tipo de coisa que os utilitários GNU geralmente imprimem quando executados--version
, como este:Mas é claro que o diretório em que
libc.so.6
vive não está$PATH
, então você precisa saber onde procurar. Pode ser em/lib
,/lib64
,/usr/lib
, ou algo ainda mais malucos (como neste caso). Convenientemente,ldd
irá dizer-lhe:Para que isso funcione, é claro, você precisa conhecer o nome completo do caminho de um executável binário vinculado dinamicamente. O
sh
executável é garantido para estar em/bin
(porque muitos#!
scripts de esperar que ele seja), e não pode ser ele próprio um#!
script. Ele pode ser ligado estaticamente, mas eu não encontrei um sistema que fez isso em muitos anos.Não sei o que você faz se estiver usando uClibc ou musl ou algo mais exótico.
fonte
$ ldd $(which sh) | grep libc
. : DOutra maneira de obtê-lo:
fonte