¿Qué implica "# definir FUENTE GNU"?


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

Notas

Hay dos versiones diferentes de basename () - la POSIX versión descrita anteriormente, y la versión GNU , que se obtiene después de {[9]]}

#define _GNU_SOURCE
#include <string.h>

Me pregunto qué significa esto #define _GNU_SOURCE: ¿está contaminando el código que escribo con una licencia relacionada con GNU? O es que simplemente se usa para decirle al compilador algo como " Bueno, sé que este conjunto de funciones no es POSIX, por lo tanto no es portable, 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 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 #define también?

Cualquiera tiene algunos ¿consejos para darme?

 120
Author: hmijail, 2011-04-07

4 answers

Definir _GNU_SOURCE no tiene nada que ver con la licencia y todo que ver con escribir código (no)portable. Si defines _GNU_SOURCE, obtendrás:

  1. acceso a muchas funciones de extensión no estándar de GNU/Linux
  2. acceso a funciones tradicionales que fueron omitidas del estándar POSIX (a menudo por una buena razón, como ser reemplazadas por mejores alternativas, o estar vinculadas a implementaciones heredadas particulares)
  3. acceso a funciones de bajo nivel que no pueden ser portable, pero que a veces necesita para implementar utilidades del sistema como mount, ifconfig, etc.
  4. comportamiento roto para muchas funciones especificadas en 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 decidieron hacer lo suyo.

Mientras esté consciente de estas cosas, no debería ser un problema definir _GNU_SOURCE, pero debe evitar definirlo y en su lugar definir _POSIX_C_SOURCE=200809L o _XOPEN_SOURCE=700 cuando sea posible para asegurarse de que su los programas son portátiles.

En particular, las cosas de _GNU_SOURCE que usted debe nunca usar son #2 y #4 arriba.

 140
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-07 15:40:09

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 condicionalmente #define identificador basename a diferentes nombres, dependiendo de si _GNU_SOURCE está definida. 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 la gente ¿diferentes encabezados, en lugar de tener que definir alguna variable de entorno oscura para obtener una implementación de función u otra?

A menudo la misma cabecera tenía 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.

 4
Author: Blaisorblade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-12 17:51:07

Para obtener detalles exactos sobre lo que está habilitado 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 GNU. En los casos en que POSIX.1 conflictos con BSD, las definiciones POSIX tienen prioridad.

De la página man de Linux en macros de prueba de características :

_GNU_SOURCE

Definir 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 glibc versiones anteriores a 2.5; 199309L en glibc ver‐ sions antes de 2.1) y _XOPEN_SOURCE con el valor 700 (600 en versiones glibc antes de 2.10; 500 en versiones glibc antes 2.2). Además, varias extensiones específicas de GNU también son expuesto.

Desde glibc 2.19, la definición de _GNU_SOURCE también tiene el efecto de definiendo implícitamente _DEFAULT_SOURCE. En versiones glibc antes de la versión 2.20, la definición de _GNU_SOURCE también tenía el efecto de definiendo implícitamente _BSD_SOURCE y _SVID_SOURCE.

Nota: _GNU_SOURCE necesita ser definido antes de incluyendo archivos de encabezado para que los encabezados respectivos habiliten las entidades. Por ejemplo:

#define _GNU_SOURCE

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

_GNU_SOURCE también se puede habilitar por compilación usando -D flag:

$ gcc -D_GNU_SOURCE file.c

(-D no es específico de _GNU_SOURCE pero cualquier macro se define de esta manera).

 2
Author: P.P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-16 09:17:06

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

Mira el include/features de glibc.h:

_GNU_SOURCE Todo lo anterior, más las extensiones 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 que permite una gran cantidad de compilación banderas para gcc

 1
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-07 13:58:51