O que significa "#define _GNU_SOURCE"?

152

Hoje eu tive que usar a basename()função, e o man 3 basename( aqui ) me deu uma mensagem estranha:

Notas

Existem duas versões diferentes de basename () - a versão POSIX descrita acima e a versão GNU , que é obtida depois

#define _GNU_SOURCE
#include <string.h>

Estou imaginando o que isso #define _GNU_SOURCEsignifica: está corrompendo o código que escrevo com uma licença relacionada ao GNU? Ou é simplesmente usado para dizer ao compilador algo como " Bem, eu sei, esse conjunto de funções não é POSIX, portanto não é portátil, mas eu gostaria de usá-lo de qualquer maneira ".

Se sim, por que não dar às pessoas cabeçalhos diferentes, em vez de precisar definir alguma macro obscura para obter uma implementação de função ou outra?

Algo também me incomoda: como o compilador sabe qual implementação de função vincular ao executável? Também usa isso #define?

Alguém tem algumas dicas para me dar?

Gui13
fonte

Respostas:

172

A definição _GNU_SOURCEnão tem nada a ver com licença e tudo a ver com a gravação de código (não) portátil. Se você definir _GNU_SOURCE, receberá:

  1. acesso a várias funções de extensão não padronizadas do GNU / Linux
  2. acesso a funções tradicionais que foram omitidas do padrão POSIX (geralmente por um bom motivo, como serem substituídas por melhores alternativas ou vinculadas a implementações herdadas específicas)
  3. acesso a funções de baixo nível que não pode ser portátil, mas que por vezes é necessário para a implementação de utilitários do sistema como mount, ifconfig, etc.
  4. comportamento quebrado para muitas funções especificadas no POSIX, onde o pessoal do GNU discordou do comitê de padrões sobre como as funções deveriam se comportar e decidiu fazer suas próprias coisas.

Desde que você esteja ciente dessas coisas, não deve ser um problema para definir _GNU_SOURCE, mas evite defini-lo e, em vez disso, defina _POSIX_C_SOURCE=200809Lou _XOPEN_SOURCE=700quando possível para garantir que seus programas sejam portáteis.

Em particular, as coisas _GNU_SOURCEque você nunca deve usar são os nºs 2 e 4 acima.

R .. GitHub PARE DE AJUDAR O GELO
fonte
71
Claro, todo mundo sabe que o verdadeiro motivo para definir _GNU_SOURCEé obter strfrye memfrob.
precisa saber é o seguinte
5
Este link para a documentação da GNU C Library fornece alguns detalhes adicionais (por exemplo, #define _GNU_SOURCErecomenda-se que seja "a primeira coisa no arquivo, precedida apenas por comentários").
Alexander Pozdneev
Não é tão relevante, mas usado para estender o limite de tamanho de arquivo de 2 GB em destinos de 32 bits.
Mckenzm 8/03/19
1
@mckenzm: Eu acho que você está pensando _FILE_OFFSET_BITS, não _GNU_SOURCE.
R .. GitHub Pare de ajudar o gelo
Quero ser um programador pago para portar strfry memfrob e comodidades semelhantes a outras plataformas e cadeias de ferramentas.
Massimo
6

Deixe-me responder mais dois pontos:

Algo também me incomoda: como o compilador sabe qual implementação de função vincular ao executável? Ele usa esse #define também?

Uma abordagem comum é #defineidentificar condicionalmente basenamenomes diferentes, dependendo se _GNU_SOURCEestá definido. Por exemplo:

#ifdef _GNU_SOURCE
# define basename __basename_gnu
#else
# define basename __basename_nongnu
#endif

Agora a biblioteca simplesmente precisa fornecer os dois comportamentos sob esses nomes.

Se sim, por que não dar às pessoas cabeçalhos diferentes, em vez de ter que definir alguma variável de ambiente obscura para obter uma implementação de função ou outra?

Freqüentemente, o mesmo cabeçalho tinha um conteúdo ligeiramente diferente em diferentes versões do Unix, então não existe um conteúdo certo para, digamos, <string.h>- existem muitos padrões ( xkcd ). Há todo um conjunto de macros para escolher a sua favorita, de modo que, se o seu programa espera um padrão, a biblioteca estará em conformidade com isso.

Blaisorblade
fonte
6

Para detalhes exatos sobre o que é ativado por _GNU_SOURCE, a documentação pode ajudar.

Na documentação do GNU:

Macro: _GNU_SOURCE

Se você definir essa macro, tudo será incluído: extensões ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS e GNU. Nos casos em que o POSIX.1 entra em conflito com o BSD, as definições do POSIX têm precedência.

Na página de manual do Linux nas macros de teste de recursos :

_GNU_SOURCE

A definição dessa macro (com qualquer valor) define implicitamente _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE com o valor 200809L (200112L nas versões da glibc anteriores à versão 2.10; 199509). _XOPEN_SOURCE com o valor 700 (600 nas versões glibc anteriores a 2.10; 500 nas versões glibc anteriores a 2.2). Além disso, várias extensões específicas do GNU também são expostas.

Desde o glibc 2.19, a definição de _GNU_SOURCE também tem o efeito de definir implicitamente _DEFAULT_SOURCE. Nas versões glibc anteriores à 2.20, a definição de _GNU_SOURCE também tinha o efeito de definir implicitamente _BSD_SOURCE e _SVID_SOURCE.

Nota : _GNU_SOURCEprecisa ser definido antes da inclusão dos arquivos de cabeçalho para que os respectivos cabeçalhos ativem os recursos. Por exemplo:

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
...

_GNU_SOURCEtambém pode ser ativado por compilação usando o -Dsinalizador:

$ gcc -D_GNU_SOURCE file.c

( -Dnão é específico, _GNU_SOURCEmas qualquer macro deve ser definida dessa maneira).

PP
fonte
4

De alguma lista de discussão via google:

Veja o include / features.h da glibc:

_GNU_SOURCE Todos os itens acima, além de extensões GNU.

O que significa que permite tudo isso:

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE, _LARGEFILE64_SOURCE, _FILE_OFFSET_BITS = N, _BSD

Por isso, permite um monte de sinalizadores de compilação para o gcc

Chris
fonte
21
Não afeta o comportamento do compilador, apenas quais protótipos e coisas são visíveis nos cabeçalhos.
Spudd86