Was bedeutet "#define _GNU_SOURCE"?

152

Heute musste ich die basename()Funktion benutzen und das man 3 basename( hier ) gab mir eine seltsame Nachricht:

Anmerkungen

Es gibt zwei verschiedene Versionen von basename () - die oben beschriebene POSIX- Version und die GNU-Version , nach der man sucht

#define _GNU_SOURCE
#include <string.h>

Ich frage mich, was das #define _GNU_SOURCEbedeutet: Beschmutzt es den Code, den ich mit einer GNU-bezogenen Lizenz schreibe? Oder wird es einfach verwendet, um dem Compiler so etwas wie " Nun, ich weiß, dieser Funktionssatz ist nicht POSIX, also nicht portabel, aber ich würde ihn trotzdem gerne verwenden" zu sagen .

Wenn ja, warum nicht den Leuten unterschiedliche Header geben, anstatt ein obskures Makro definieren zu müssen, um die eine oder andere Funktionsimplementierung zu erhalten?

Etwas stört mich auch: Woher weiß der Compiler, welche Funktionsimplementierung mit der ausführbaren Datei verknüpft werden soll? Verwendet es #definedas auch?

Hat jemand ein paar Hinweise, die er mir geben kann?

Gui13
quelle

Antworten:

172

Das Definieren _GNU_SOURCEhat nichts mit Lizenz zu tun und alles mit dem Schreiben von (nicht) portablem Code. Wenn Sie definieren _GNU_SOURCE, erhalten Sie:

  1. Zugriff auf viele nicht standardmäßige GNU / Linux-Erweiterungsfunktionen
  2. Zugriff auf traditionelle Funktionen, die im POSIX-Standard nicht enthalten waren (häufig aus gutem Grund, z. B. durch bessere Alternativen ersetzt oder an bestimmte ältere Implementierungen gebunden)
  3. Zugriff auf Low-Level - Funktionen , die nicht tragbar sein kann, sondern dass man manchmal für die Implementierung der Systemprogramme wie benötigen mount, ifconfigetc.
  4. gebrochenes Verhalten für viele POSIX-spezifizierte Funktionen, bei denen die GNU-Leute mit dem Standardkomitee nicht einverstanden waren, wie sich die Funktionen verhalten sollten, und beschlossen, ihr eigenes Ding zu machen.

Solange Sie sich dieser Dinge bewusst sind, sollte es kein Problem sein, sie zu definieren _GNU_SOURCE, aber Sie sollten es vermeiden, sie zu definieren , und stattdessen definieren _POSIX_C_SOURCE=200809Loder _XOPEN_SOURCE=700wenn möglich sicherstellen, dass Ihre Programme portabel sind.

Insbesondere sind die Dinge _GNU_SOURCE, die Sie niemals verwenden sollten , # 2 und # 4 oben.

R .. GitHub HÖREN SIE AUF, EIS ZU HELFEN
quelle
71
Natürlich weiß jeder, dass der wahre Grund für die Definition darin _GNU_SOURCEbesteht, zu bekommen strfryund memfrob.
user4815162342
5
Dieser Link zur Dokumentation der GNU C-Bibliothek enthält einige zusätzliche Details (z. B. #define _GNU_SOURCEwird empfohlen, "das allererste Element in der Datei zu sein, dem nur Kommentare vorangestellt sind").
Alexander Pozdneev
Nicht so relevant, wird jedoch verwendet, um die Dateigrößenbeschränkung von 2 GB auf 32-Bit-Ziele zu erweitern.
McKenzm
1
@ McKenzm: Ich denke du denkst _FILE_OFFSET_BITSnicht daran _GNU_SOURCE.
R .. GitHub STOP HELPING ICE
Ich möchte ein bezahlter Programmierer für die Portierung von strfry memfrob und ähnlichen Annehmlichkeiten zu anderen Plattformen und Toolketten sein .
Massimo
6

Lassen Sie mich zwei weitere Punkte beantworten:

Etwas stört mich auch: Woher weiß der Compiler, welche Funktionsimplementierung mit der ausführbaren Datei verknüpft werden soll? Verwendet es auch dieses #define?

Ein üblicher Ansatz besteht darin , verschiedene Namen bedingt zu #defineidentifizieren basename, je nachdem, ob sie _GNU_SOURCEdefiniert sind. Zum Beispiel:

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

Jetzt muss die Bibliothek einfach beide Verhaltensweisen unter diesen Namen bereitstellen.

Wenn ja, warum geben Sie den Benutzern nicht unterschiedliche Header, anstatt eine obskure Umgebungsvariable definieren zu müssen, um die eine oder andere Funktionsimplementierung zu erhalten?

Oft hatte derselbe Header in verschiedenen Unix-Versionen leicht unterschiedliche Inhalte, daher gibt es keinen einzigen richtigen Inhalt für beispielsweise <string.h>- es gibt viele Standards ( xkcd ). Es gibt eine ganze Reihe von Makros, mit denen Sie Ihr Lieblingsmakro auswählen können. Wenn Ihr Programm einen Standard erwartet, entspricht die Bibliothek diesem Standard.

Blaisorblade
quelle
6

Für genaue Details zu den Funktionen von _GNU_SOURCEkann die Dokumentation hilfreich sein.

Aus der GNU-Dokumentation:

Makro: _GNU_SOURCE

Wenn Sie dieses Makro definieren, ist alles enthalten: ISO C89-, ISO C99-, POSIX.1-, POSIX.2-, BSD-, SVID-, X / Open-, LFS- und GNU-Erweiterungen. In den Fällen, in denen POSIX.1 mit BSD in Konflikt steht, haben die POSIX-Definitionen Vorrang.

In der Linux-Manpage zu Funktionstestmakros :

_GNU_SOURCE

Das Definieren dieses Makros (mit einem beliebigen Wert) definiert implizit _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE mit dem Wert 200809L (200112L in glibc-Versionen vor Gl _XOPEN_SOURCE mit dem Wert 700 (600 in Glibc-Versionen vor 2.10; 500 in Glibc-Versionen vor 2.2). Darüber hinaus sind verschiedene GNU-spezifische Erweiterungen verfügbar.

Seit glibc 2.19 hat das Definieren von _GNU_SOURCE auch den Effekt, dass _DEFAULT_SOURCE implizit definiert wird. In glibc-Versionen vor 2.20 hatte das Definieren von _GNU_SOURCE auch den Effekt, dass _BSD_SOURCE und _SVID_SOURCE implizit definiert wurden.

Hinweis : _GNU_SOURCEMuss vor dem Einfügen von Header-Dateien definiert werden, damit die jeweiligen Header die Funktionen aktivieren. Beispielsweise:

#define _GNU_SOURCE

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

_GNU_SOURCEkann auch pro Kompilierung mit -Dflag aktiviert werden :

$ gcc -D_GNU_SOURCE file.c

( -Dist nicht spezifisch, _GNU_SOURCEaber jedes Makro kann auf diese Weise definiert werden).

PP
quelle
4

Aus einer Mailingliste über Google:

Schauen Sie sich glibcs ​​include / features.h an:

_GNU_SOURCE Alle oben genannten sowie GNU-Erweiterungen.

Das heißt, es ermöglicht all dies:

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

Es ermöglicht also eine ganze Reihe von Kompilierungsflags für gcc

Chris
quelle
21
Es hat keinen Einfluss auf das Verhalten des Compilers, sondern nur darauf, welche Prototypen und Dinge in den Headern sichtbar sind.
Spudd86