¿Qué implica "#define_GNU_SOURCE"?
posix (4)
Hoy tuve que usar la función basename()
, y el man 3 basename
( here ) 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é significa este #define _GNU_SOURCE
: ¿está manchando 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 darle a las personas encabezados diferentes, en lugar de tener que definir alguna macro oscura para obtener una implementación de función o la otra?
Algo también me molesta: ¿cómo sabe el compilador qué implementación de función vincular con el ejecutable? ¿Utiliza también este #define
?
Alguien tiene algunos consejos para darme?
Déjame 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 también este #define?
Un enfoque común es definir #define
condicionalmente el basename
identificador para diferentes nombres, dependiendo de si se ha definido _GNU_SOURCE
. 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 encabezados diferentes, en lugar de tener que definir alguna variable de entorno oscura para obtener una implementación de función o la otra?
A menudo, el mismo encabezado tiene contenidos ligeramente diferentes en diferentes versiones de Unix, por lo que no hay un solo contenido correcto para, por ejemplo, <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.
De alguna lista de correo a través de google:
Mira glibc''s include / features.h:
_GNU_SOURCE Todo lo anterior, más extensiones de GNU.
Lo que significa que habilita 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_SOURCE, _SVID_SOURCE
Por lo tanto, permite una gran cantidad de indicadores de compilación para gcc
Definir _GNU_SOURCE
no tiene nada que ver con la licencia y todo lo relacionado con la escritura de código (no) portátil. Si defines _GNU_SOURCE
, obtendrás:
- acceso a muchas funciones de extensión no estándar de GNU / Linux
- acceso a funciones tradicionales que se omitieron en el estándar POSIX (a menudo por una buena razón, como ser reemplazado por mejores alternativas o estar vinculado a implementaciones heredadas particulares)
- acceso a funciones de bajo nivel que no pueden ser portátiles, pero que a veces necesita implementar utilidades del sistema como
mount
,ifconfig
, etc. - comportamiento defectuoso para muchas funciones especificadas por POSIX, donde la gente de GNU no estaba de acuerdo con el comité de estándares sobre cómo deberían comportarse las funciones y decidió hacer lo suyo.
Siempre que sepa estas cosas, no debería ser un problema definir _GNU_SOURCE
, pero debe evitar definirlo y, en su lugar, defina _POSIX_C_SOURCE=200809L
o _POSIX_C_SOURCE=200809L
_XOPEN_SOURCE=700
cuando sea posible para asegurarse de que sus programas sean portátiles.
En particular, las cosas de _GNU_SOURCE
que nunca debe usar son # 2 y # 4 arriba.
Para obtener detalles exactos sobre todos los habilitados por _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 de GNU. En los casos en que POSIX.1 entra en conflicto con BSD, las definiciones POSIX tienen prioridad.
Desde la página man 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 anteriores a 2.10; 199506L en versiones glibc anteriores a 2.5; 199309L en versiones glibc anteriores a 2.1) y _XOPEN_SOURCE con el valor 700 (600 en versiones glibc antes 2.10; 500 en versiones 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 versiones glibc anteriores a 2.20, definir _GNU_SOURCE también tuvo el efecto de definir implícitamente _BSD_SOURCE y _SVID_SOURCE.
Nota : _GNU_SOURCE
debe definirse antes de incluir los archivos de encabezado para que los encabezados respectivos habiliten las características. Por ejemplo:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
...
_GNU_SOURCE
también se puede habilitar por compilación usando el indicador -D
:
$ gcc -D_GNU_SOURCE file.c
( -D
no es específico de _GNU_SOURCE
pero cualquier macro se define de esta manera).