Cosa implica "#define _GNU_SOURCE"?


152

Oggi ho dovuto usare la basename()funzione e il man 3 basename( qui ) mi ha dato uno strano messaggio:

Appunti

Esistono due diverse versioni di basename () : la versione POSIX sopra descritta e la versione GNU , che si ottiene dopo

#define _GNU_SOURCE
#include <string.h>

Mi chiedo cosa #define _GNU_SOURCEsignifichi: sta contaminando il codice che scrivo con una licenza relativa a GNU? O è semplicemente usato per dire al compilatore qualcosa del tipo " Beh, lo so, questo insieme di funzioni non è POSIX, quindi non portatile, ma mi piacerebbe usarlo comunque ".

Se è così, perché non dare alle persone diverse intestazioni, invece di dover definire alcune macro oscure per ottenere un'implementazione della funzione o l'altra?

Qualcosa mi disturba anche: come fa il compilatore a sapere quale implementazione di funzione collegare con l'eseguibile? Usa anche questo #define?

Qualcuno ha qualche suggerimento da darmi?

Risposte:


172

La definizione _GNU_SOURCEnon ha nulla a che fare con la licenza e tutto con la scrittura di codice (non) portatile. Se lo definisci _GNU_SOURCE, otterrai:

  1. accesso a molte funzioni di estensione GNU / Linux non standard
  2. accesso alle funzioni tradizionali che sono state omesse dallo standard POSIX (spesso per una buona ragione, come essere sostituite con alternative migliori o essere legate a particolari implementazioni legacy)
  3. l'accesso alle funzioni di basso livello che non può essere portatile, ma che a volte è necessario per l'attuazione di programmi di utilità di sistema come mount, ifconfig, etc.
  4. comportamento non funzionante per molte funzioni specificate da POSIX, in cui le persone GNU non erano d'accordo con il comitato degli standard su come le funzioni dovrebbero comportarsi e hanno deciso di fare le proprie cose.

Finché sei a conoscenza di queste cose, non dovrebbe essere un problema da definire _GNU_SOURCE, ma dovresti evitare di definirlo e invece definirlo _POSIX_C_SOURCE=200809Lo _XOPEN_SOURCE=700quando possibile per garantire che i tuoi programmi siano portabili.

In particolare, le cose _GNU_SOURCEche non dovresti mai usare sono # 2 e # 4 sopra.


71
Naturalmente, tutti sanno che il vero motivo per definire _GNU_SOURCEè quello di ottenere strfrye memfrob.
user4815162342

5
Questo collegamento alla documentazione della libreria GNU C fornisce alcuni dettagli aggiuntivi (ad esempio, #define _GNU_SOURCEsi consiglia di essere "la prima cosa nel file, preceduta solo da commenti").
Alexander Pozdneev,

Non pertinente ma utilizzato per estendere il limite di dimensioni del file da 2 GB su destinazioni a 32 bit.
mckenzm

1
@mckenzm: penso che tu stia pensando _FILE_OFFSET_BITS, no _GNU_SOURCE.
R .. GitHub smette di aiutare ICE l'

Voglio essere un programmatore a pagamento per il porting di strfry memfrob e servizi simili ad altre piattaforme e catene di strumenti.
Massimo

6

Consentitemi di rispondere ad altri due punti:

Qualcosa mi disturba anche: come fa il compilatore a sapere quale implementazione di funzione collegare con l'eseguibile? Usa anche questo #define?

Un approccio comune è quello di #defineidentificare condizionalmente basenamenomi diversi, a seconda che _GNU_SOURCEsia definito. Per esempio:

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

Ora la biblioteca deve semplicemente fornire entrambi i comportamenti con questi nomi.

Se è così, perché non dare alle persone diverse intestazioni, invece di dover definire alcune variabili di ambiente oscure per ottenere un'implementazione della funzione o l'altra?

Spesso la stessa intestazione aveva contenuti leggermente diversi nelle diverse versioni di Unix, quindi non esiste un contenuto giusto per, diciamo, <string.h>- ci sono molti standard ( xkcd ). C'è un intero set di macro per scegliere la tua preferita, in modo che se il tuo programma prevede uno standard, la libreria sarà conforme a quella.


6

Per i dettagli esatti su cosa sono tutti abilitati da _GNU_SOURCE , la documentazione può aiutare.

Dalla documentazione GNU:

Macro: _GNU_SOURCE

Se si definisce questa macro, tutto è incluso: ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS e GNU. Nei casi in cui POSIX.1 è in conflitto con BSD, le definizioni POSIX hanno la precedenza.

Dalla pagina man di Linux sulle macro di test delle funzionalità :

_GNU_SOURCE

La definizione di questa macro (con qualsiasi valore) definisce in modo implicito _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE con le versioni 200809L (200112L nelle versioni glib prima di 2.1b; glib prima di 2.1b; glib prima dell'1.230; 199b 199699 _XOPEN_SOURCE con il valore 700 (600 nelle versioni glibc precedenti alla 2.10; 500 nelle versioni glibc precedenti alla 2.2). Inoltre, sono esposte anche varie estensioni specifiche per GNU.

Da glibc 2.19, la definizione di _GNU_SOURCE ha anche l'effetto di definire implicitamente _DEFAULT_SOURCE. Nelle versioni glibc precedenti alla 2.20, la definizione di _GNU_SOURCE ha avuto anche l'effetto di definire implicitamente _BSD_SOURCE e _SVID_SOURCE.

Nota : _GNU_SOURCEdeve essere definito prima di includere i file di intestazione in modo che le rispettive intestazioni abilitino le funzionalità. Per esempio:

#define _GNU_SOURCE

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

_GNU_SOURCEpuò anche essere abilitato per compilation usando -Dflag:

$ gcc -D_GNU_SOURCE file.c

( -Dnon è specifico _GNU_SOURCEma qualsiasi macro deve essere definita in questo modo).


4

Da alcune mailing list tramite google:

Guarda glibc's include / features.h:

_GNU_SOURCE Tutto quanto sopra, oltre alle estensioni GNU.

Ciò significa che consente tutto ciò:

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE, _LARGEFILE64_SOURCE, _FILE_OFFSET_BITS_SO, _BS

Quindi consente un sacco di flag di compilazione per gcc


21
Non influisce sul comportamento del compilatore, ma solo quali prototipi e cose sono visibili dalle intestazioni.
Spudd86,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.