Que signifie «#define _GNU_SOURCE»?

152

Aujourd'hui, j'ai dû utiliser la basename()fonction, et man 3 basename( ici ) m'a donné un message étrange:

Remarques

Il existe deux versions différentes de basename () - la version POSIX décrite ci-dessus et la version GNU , que l'on obtient après

#define _GNU_SOURCE
#include <string.h>

Je me demande ce que cela #define _GNU_SOURCEsignifie: est-ce que cela entache le code que j'écris avec une licence liée à GNU? Ou est-ce simplement utilisé pour dire au compilateur quelque chose comme " Eh bien, je sais, cet ensemble de fonctions n'est pas POSIX, donc pas portable, mais j'aimerais quand même l'utiliser ".

Si tel est le cas, pourquoi ne pas donner aux gens des en-têtes différents, au lieu d'avoir à définir une macro obscure pour obtenir une implémentation de fonction ou une autre?

Quelque chose me dérange aussi: comment le compilateur sait-il quelle implémentation de fonction lier avec l'exécutable? L'utilise-t-il #defineégalement?

Quelqu'un a des conseils à me donner?

Gui13
la source

Réponses:

172

La définition _GNU_SOURCEn'a rien à voir avec la licence et tout à voir avec l'écriture de code (non) portable. Si vous définissez _GNU_SOURCE, vous obtiendrez:

  1. accès à de nombreuses fonctions d'extension GNU / Linux non standard
  2. accès aux fonctions traditionnelles qui ont été omises du standard POSIX (souvent pour une bonne raison, comme être remplacées par de meilleures alternatives ou être liées à des implémentations héritées particulières)
  3. l' accès aux fonctions de bas niveau qui ne peut pas être portable, mais parfois vous avez besoin pour la mise en œuvre des utilitaires système comme mount, ifconfig, etc.
  4. comportement cassé pour beaucoup de fonctions spécifiées par POSIX, où les gens de GNU étaient en désaccord avec le comité des normes sur la façon dont les fonctions devraient se comporter et ont décidé de faire leur propre travail.

Tant que vous êtes conscient de ces choses, cela ne devrait pas être un problème à définir _GNU_SOURCE, mais vous devriez éviter de le définir et plutôt définir _POSIX_C_SOURCE=200809Lou, _XOPEN_SOURCE=700si possible, vous assurer que vos programmes sont portables.

En particulier, les éléments _GNU_SOURCEque vous ne devriez jamais utiliser sont les n ° 2 et 4 ci-dessus.

R .. GitHub STOP AIDING ICE
la source
71
Bien sûr, tout le monde sait que la vraie raison de définir _GNU_SOURCEest d'obtenir strfryet memfrob.
user4815162342
5
Ce lien vers la documentation de la bibliothèque GNU C fournit quelques détails supplémentaires (par exemple, il #define _GNU_SOURCEest recommandé d'être "la toute première chose dans le fichier, précédée uniquement de commentaires").
Alexander Pozdneev
Pas aussi pertinent mais utilisé pour étendre la limite de taille de fichier de 2 Go sur les cibles 32 bits.
mckenzm
1
@mckenzm: Je pense que vous pensez _FILE_OFFSET_BITS, non _GNU_SOURCE.
R .. GitHub STOP HELPING ICE
Je veux être un programmeur rémunéré pour le portage de strfry memfrob et d'équipements similaires sur d'autres plates-formes et chaînes d'outils.
Massimo
6

Permettez-moi de répondre à deux autres points:

Quelque chose me dérange aussi: comment le compilateur sait-il quelle implémentation de fonction lier avec l'exécutable? Utilise-t-il également cette #define?

Une approche courante consiste à #defineidentifier conditionnellement basenamedes noms différents, selon qu'ils _GNU_SOURCEsont définis ou non. Par exemple:

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

Désormais, la bibliothèque doit simplement fournir les deux comportements sous ces noms.

Si tel est le cas, pourquoi ne pas donner aux gens des en-têtes différents, au lieu d'avoir à définir une variable d'environnement obscure pour obtenir une implémentation de fonction ou une autre?

Souvent, le même en-tête avait un contenu légèrement différent dans différentes versions d'Unix, il n'y a donc pas de contenu unique pour, disons, <string.h>- il existe de nombreuses normes ( xkcd ). Il y a tout un ensemble de macros pour choisir votre préférée, de sorte que si votre programme attend un standard, la bibliothèque se conformera à cela.

Blaisorblade
la source
6

Pour plus de détails sur ce qui est activé par _GNU_SOURCE, la documentation peut vous aider.

À partir de la documentation GNU:

Macro: _GNU_SOURCE

Si vous définissez cette macro, tout est inclus: extensions ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS et GNU. Dans les cas où POSIX.1 est en conflit avec BSD, les définitions POSIX prévalent.

Depuis la page de manuel Linux sur les macros de test de fonctionnalités :

_GNU_SOURCE

La définition de cette macro (avec n'importe quelle valeur) définit implicitement _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE avec la valeur 200809L (200112L dans les versions glibc‐ 2.10 avant glibc avant 2.10 et 19950 dans les versions glibc avant 2.10 et 19950) _XOPEN_SOURCE avec la valeur 700 (600 dans les versions glibc antérieures à 2.10; 500 dans les versions glibc antérieures à 2.2). De plus, diverses extensions spécifiques à GNU sont également exposées.

Depuis la glibc 2.19, définir _GNU_SOURCE a également pour effet de définir implicitement _DEFAULT_SOURCE. Dans les versions glibc antérieures à 2.20, la définition de _GNU_SOURCE avait également pour effet de définir implicitement _BSD_SOURCE et _SVID_SOURCE.

Remarque : _GNU_SOURCEdoit être défini avant d' inclure les fichiers d'en-tête afin que les en-têtes respectifs activent les fonctionnalités. Par exemple:

#define _GNU_SOURCE

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

_GNU_SOURCEpeut également être activé par compilation en utilisant l' -Dindicateur:

$ gcc -D_GNU_SOURCE file.c

( -Dn'est pas spécifique à _GNU_SOURCEmais toute macro doit être définie de cette façon).

PP
la source
4

À partir d'une liste de diffusion via google:

Regardez les include / features.h de la glibc:

_GNU_SOURCE Tout ce qui précède, plus les extensions GNU.

Ce qui signifie qu'il permet tout cela:

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE, _LARGEFILE64_SOURCE, _FILE_OFFSET_BVITS_SOURCE = N, _SOURDBS_SOURCE

Donc, il permet un grand nombre d'indicateurs de compilation pour gcc

Chris
la source
21
Cela n'affecte pas le comportement du compilateur, seuls les prototypes et les choses sont visibles depuis les en-têtes.
Spudd86