¿Qué implica "#define _GNU_SOURCE"?

152

Hoy tuve que usar la basename()función, y el man 3 basename( aquí ) me dio un mensaje extraño:

Notas

Hay dos versiones diferentes de basename () : la versión POSIX descrita anteriormente y la versión GNU , que se obtiene después

#define _GNU_SOURCE
#include <string.h>

Me pregunto qué #define _GNU_SOURCEsignifica esto : ¿está contaminando el código que escribo con una licencia relacionada con GNU? ¿O simplemente se usa para decirle al compilador algo como " Bueno, lo sé, este conjunto de funciones no es POSIX, por lo tanto no es portátil, pero me gustaría usarlo de todos modos ".

Si es así, ¿por qué no dar a las personas diferentes encabezados, en lugar de tener que definir alguna macro oscura para obtener una implementación de una función u otra?

Algo también me molesta: ¿cómo sabe el compilador qué implementación de función vincular con el ejecutable? ¿Utiliza esto #definetambién?

¿Alguien tiene algunos consejos para darme?

Gui13
fuente

Respuestas:

172

La definición _GNU_SOURCEno tiene nada que ver con la licencia y todo que ver con la escritura de código (no) portátil. Si define _GNU_SOURCE, obtendrá:

  1. acceso a muchas funciones de extensión GNU / Linux no estándar
  2. acceso a funciones tradicionales que se omitieron del estándar POSIX (a menudo por una buena razón, como ser reemplazado por mejores alternativas o estar vinculado a implementaciones heredadas particulares)
  3. el acceso a las funciones de bajo nivel que no puede ser portátil, pero que a veces es necesario para la implementación de los servicios públicos al sistema como mount, ifconfig, etc.
  4. comportamiento roto para muchas funciones especificadas por POSIX, donde la gente de GNU no estuvo de acuerdo con el comité de estándares sobre cómo deberían comportarse las funciones y decidieron hacer lo suyo.

Siempre y cuando esté al tanto de estas cosas, no debería ser un problema definirlo _GNU_SOURCE, pero debe evitar definirlo y, en su lugar, definirlo _POSIX_C_SOURCE=200809Lo, _XOPEN_SOURCE=700cuando sea posible, asegurarse de que sus programas sean portátiles.

En particular, las cosas de las _GNU_SOURCEque nunca debes usar son # 2 y # 4 arriba.

R .. GitHub DEJA DE AYUDAR AL HIELO
fuente
71
Por supuesto, todos saben que la verdadera razón para definir _GNU_SOURCEes para obtener strfryy memfrob.
user4815162342
55
Este enlace a la documentación de la Biblioteca GNU C proporciona algunos detalles adicionales (por ejemplo, #define _GNU_SOURCEse recomienda que sea "lo primero en el archivo, precedido solo por comentarios").
Alexander Pozdneev
No es tan relevante, pero se usa para extender el límite de tamaño de archivo de 2GB en objetivos de 32 bits.
mckenzm
1
@mckenzm: Creo que estás pensando _FILE_OFFSET_BITS, no _GNU_SOURCE.
R .. GitHub DEJA DE AYUDAR AL HIELO
Quiero ser un programador pagado para la transferencia de memfrob strfry y servicios similares a otras plataformas y cadenas de herramientas.
Massimo
6

Permítanme responder dos puntos más:

Algo también me molesta: ¿cómo sabe el compilador qué implementación de función vincular con el ejecutable? ¿Utiliza este #define también?

Un enfoque común es #defineidentificar condicionalmente basenamea diferentes nombres, dependiendo de si _GNU_SOURCEestá definido. Por ejemplo:

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

Ahora la biblioteca simplemente necesita proporcionar ambos comportamientos bajo esos nombres.

Si es así, ¿por qué no dar a las personas diferentes encabezados, en lugar de tener que definir alguna variable de entorno oscura para obtener la implementación de una función u otra?

A menudo, el mismo encabezado tenía contenidos ligeramente diferentes en diferentes versiones de Unix, por lo que no hay un contenido correcto único para, digamos, <string.h>hay muchos estándares ( xkcd ). Hay un conjunto completo de macros para elegir su favorito, de modo que si su programa espera un estándar, la biblioteca se ajustará a eso.

Blaisorblade
fuente
6

Para obtener detalles exactos sobre lo que todos están habilitados _GNU_SOURCE, la documentación puede ayudar.

De la documentación de GNU:

Macro: _GNU_SOURCE

Si define esta macro, todo está incluido: ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS y extensiones GNU. En los casos en que POSIX.1 entra en conflicto con BSD, las definiciones POSIX tienen prioridad.

Desde la página de manual de Linux en macros de prueba de características :

_GNU_SOURCE

La definición de esta macro (con cualquier valor) define implícitamente _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE con el valor 200809L (200112L en versiones glibc antes de 2.10; glibc antes de 2.10; 201 y anterior a 2.10; l de esta versión anterior a 2.10; _XOPEN_SOURCE con el valor 700 (600 en versiones de glibc anteriores a 2.10; 500 en versiones de glibc anteriores a 2.2). Además, varias extensiones específicas de GNU también están expuestas.

Desde glibc 2.19, definir _GNU_SOURCE también tiene el efecto de definir implícitamente _DEFAULT_SOURCE. En las versiones de glibc anteriores a 2.20, definir _GNU_SOURCE también tuvo el efecto de definir implícitamente _BSD_SOURCE y _SVID_SOURCE.

Nota : _GNU_SOURCEdebe definirse antes de incluir archivos de encabezado para que los encabezados respectivos habiliten las funciones. Por ejemplo:

#define _GNU_SOURCE

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

_GNU_SOURCEtambién se puede habilitar por compilación usando -Dflag:

$ gcc -D_GNU_SOURCE file.c

( -Dno es específico _GNU_SOURCEpero cualquier macro se define de esta manera).

PÁGINAS
fuente
4

De alguna lista de correo a través de google:

Mira glibc's include / features.h:

_GNU_SOURCE Todo lo anterior, más extensiones GNU.

Lo que significa que permite todo esto:

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

Por lo tanto, permite una gran cantidad de indicadores de compilación para gcc

Chris
fuente
21
No afecta el comportamiento del compilador, solo qué prototipos y cosas son visibles desde los encabezados.
Spudd86