web-dev-qa-db-fra.com

Qu'implique "#define _GNU_SOURCE"?

Aujourd'hui, je devais utiliser la fonction basename(), et le man 3 basename _ ( ici ) m'a donné un message étrange:

Notes

Il existe deux versions différentes de basename () - le [~ # ~] le posix [~ # ~] version décrit ci-dessus, et la version de GNU , que l’on obtient après

#define _GNU_SOURCE
#include <string.h>

Je me demande ce que cela #define _GNU_SOURCE _ signifie: est-ce altération 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 bien l’utiliser quand même".

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

Quelque chose me gêne aussi: comment le compilateur sait-il quelle implémentation de fonction lier à l'exécutable? Est-ce qu'il utilise ce #define ainsi que?

Quelqu'un a des indications à me donner?

139
Gui13

Définir _GNU_SOURCE N'a rien à voir avec une licence et tout à faire avec l'écriture de code (non) portable. Si vous définissez _GNU_SOURCE, Vous obtiendrez:

  1. accès à de nombreuses fonctions d'extension non standard GNU/Linux
  2. accès aux fonctions traditionnelles qui ont été omises du standard POSIX (souvent pour une bonne raison, telle que d'être remplacé par de meilleures alternatives ou d'être lié à des mises en œuvre héritées particulières)
  3. accès à des fonctions de bas niveau qui ne peuvent pas être portables, mais dont vous avez parfois besoin pour implémenter des utilitaires système tels que mount, ifconfig, etc.
  4. comportement interrompu pour de nombreuses fonctions spécifiées par POSIX, où les membres de GNU étaient en désaccord avec le comité de normalisation sur la manière dont les fonctions devraient se comporter et ont décidé de faire leur propre chose.

Tant que vous êtes au courant de ces choses, définir _GNU_SOURCE Ne devrait pas poser de problème, mais évitez de le définir et définissez plutôt _POSIX_C_SOURCE=200809L Ou _XOPEN_SOURCE=700 Lorsque cela est possible. pour vous assurer que vos programmes sont portables.

En particulier, les éléments de _GNU_SOURCE Que vous devriez jamais utiliser sont # 2 et # 4 ci-dessus.

156
R..

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

Quelque chose me gêne aussi: comment le compilateur sait-il quelle implémentation de fonction lier à l'exécutable? Est-ce qu'il utilise aussi cette #define?

Une approche courante consiste à conditionnellement #define identifiant basename vers différents noms, selon que _GNU_SOURCE est défini. Par exemple:

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

Maintenant, la bibliothèque doit simplement fournir les deux comportements sous ces noms.

Si tel est le cas, pourquoi ne pas donner différents en-têtes aux personnes, au lieu de devoir définir une variable d’environnement obscure pour obtenir l’implémentation d’une fonction ou de l’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 correct pour, par exemple, <string.h> - il y a beaucoup de standards ( xkcd ). Il y a tout un ensemble de macros pour choisir votre préférée, de sorte que si votre programme attend une norme, la bibliothèque se conformera à cela.

6
Blaisorblade

Pour des détails exacts sur ce qui sont tous activés par _GNU_SOURCE, la documentation peut aider.

De la GNU documentation:

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 en cas de conflit entre POSIX.1 et BSD, les définitions POSIX ont priorité.

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

_GNU_SOURCE

Définir implicitement cette macro (quelle que soit sa valeur) définit _ATFILE_SOURCE, _LARGEFILE64_SOUR, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE avec la valeur 200809L (200112L), en voie de construction, en vue de la création du système _XOPEN_SOURCE avec la valeur 700 (600 dans les versions de glibc antérieures à 2.10; 500 dans les versions de glibc antérieures à 2.2). En outre, 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 de glibc antérieures à la version 2.20, la définition de _GNU_SOURCE avait également pour effet de définir implicitement _BSD_SOURCE et _SVID_SOURCE.

Remarque : _GNU_SOURCE doit être défini avant , y compris les fichiers d’en-tête afin que les en-têtes respectifs activent les fonctions. Par exemple:

#define _GNU_SOURCE

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

_GNU_SOURCE peut également être activé par compilation en utilisant -D drapeau:

$ gcc -D_GNU_SOURCE file.c

(-D n'est pas spécifique à _GNU_SOURCE mais toute macro doit être définie de cette façon).

5
P.P.

À partir d'une liste de diffusion via google:

Regardez les include/features.h de glibc:

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

Ce qui signifie que cela permet tout cela:

STRICT_ANSI , _ISOC99_SOURCE, _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED, _LARGEFILE_SOURCE,

Donc, cela permet un tas d’indicateurs de compilation pour gcc

4
Chris