Что означает "#define _GNU_SOURCE"? - PullRequest
138 голосов
/ 07 апреля 2011

Сегодня мне пришлось использовать функцию basename(), а man 3 basename ( здесь ) дал мне странное сообщение:

Примечания

Существуют две разные версии basename () - версия POSIX , описанная выше, и GNU версия , которую получают после

#define _GNU_SOURCE
#include <string.h>

Мне интересно, что означает #define _GNU_SOURCE: действительно ли это портит код, который я пишу с помощью GNUлицензия?Или это просто используется, чтобы сообщить компилятору что-то вроде " Ну, я знаю, этот набор функций не POSIX, поэтому не переносим, ​​но я все равно хотел бы использовать его ".

Если так, почему бы не дать людям разные заголовки вместо того, чтобы определять какой-то непонятный макрос, чтобы получить одну реализацию функции или другую?

Что-то меня также беспокоит: как компилятор узнает, какую реализацию функции связать с исполняемым файлом?Он также использует это #define?

У кого-нибудь есть какие-нибудь указатели, чтобы дать мне?

Ответы [ 4 ]

156 голосов
/ 07 апреля 2011

Определение _GNU_SOURCE не имеет ничего общего с лицензией и не связано с написанием (не) переносимого кода.Если вы определите _GNU_SOURCE, вы получите:

  1. доступ ко многим нестандартным функциям расширения GNU / Linux
  2. доступ к традиционным функциям, которые были исключены из стандарта POSIX (часто длявеская причина, например, замена на более подходящие альтернативы или привязка к конкретным устаревшим реализациям)
  3. доступ к низкоуровневым функциям, которые не могут быть переносимыми, но которые иногда требуются для реализации системных утилит, таких как mount,ifconfig и т. Д.
  4. неправильное поведение для многих функций, определенных POSIX, когда люди из GNU не согласились с комитетом по стандартам о том, как эти функции должны вести себя, и решили сделать свое дело.

Пока вы знаете об этих вещах, не должно быть проблемой определить _GNU_SOURCE, но вы должны избегать его определения и вместо этого определять _POSIX_C_SOURCE=200809L или _XOPEN_SOURCE=700, когда это возможно, чтобы гарантировать, что ваши программы

В частности, вещи из _GNU_SOURCE, которые вы должны никогда использовать,№ 2 и № 4 выше.

6 голосов
/ 12 июня 2016

Позвольте мне ответить еще на два вопроса:

Что-то меня также беспокоит: как компилятор узнает, какую реализацию функции связать с исполняемым файлом? Использует ли он также этот #define?

Общий подход заключается в условном #define идентификаторе basename для разных имен в зависимости от того, определен ли _GNU_SOURCE. Например:

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

Теперь библиотеке просто необходимо предоставить оба поведения под этими именами.

Если так, то почему бы не дать людям разные заголовки вместо того, чтобы определять какую-то непонятную переменную окружения, чтобы получить одну реализацию функции или другую?

Зачастую один и тот же заголовок имеет несколько разное содержимое в разных версиях Unix, поэтому нет единого правильного содержимого, скажем, для <string.h> - существует много стандартов ( xkcd ). Существует целый набор макросов для выбора вашего любимого, так что если ваша программа ожидает один стандарт, библиотека будет соответствовать этому.

5 голосов
/ 16 октября 2017

Точная информация о том, что все включено _GNU_SOURCE, может помочь в документации.

Из документации GNU:

Макрос: _GNU_SOURCE

Если вы определите этот макрос, все будет включено: расширения ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X / Open, LFS и GNU. В случаях, когда POSIX.1 конфликтует с BSD, определения POSIX имеют приоритет.

Со страницы руководства Linux по макросам тестирования функций :

_GNU_SOURCE

Определение этого макроса (с любым значением) неявно определяет _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE с значение 200809L (200112L в версиях glibc до 2.10; 199506L в версиях glibc до 2.5; 199309L в вербальной версии до версии 2.1) и _XOPEN_SOURCE со значением 700 (600 в версиях glibc до 2.10; 500 в версиях glibc перед 2.2). Кроме того, различные специфичные для GNU расширения также подвергаются.

Начиная с glibc 2.19, определение _GNU_SOURCE также имеет эффект неявно определяя _DEFAULT_SOURCE. В версиях glibc до 2.20 определение _GNU_SOURCE также имело эффект неявно определяя _BSD_SOURCE и _SVID_SOURCE.

Примечание : _GNU_SOURCE необходимо определить перед , включая заголовочные файлы, чтобы соответствующие заголовки включали функции. Например:

#define _GNU_SOURCE

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

_GNU_SOURCE также можно включить для каждой компиляции, используя флаг -D:

$ gcc -D_GNU_SOURCE file.c

(-D не относится к _GNU_SOURCE, но любой макрос может быть определен таким образом).

4 голосов
/ 07 апреля 2011

Из какого-либо списка рассылки через Google:

Посмотрите на glibc include / features.h:

_GNU_SOURCE Все вышеперечисленное, а также расширения GNU.

это означает, что позволяет все это:

1009 *
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

Таким образом, он включает множество флагов компиляции для gcc

...