Что означает «#define _GNU_SOURCE»?

152

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

Ноты

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

#define _GNU_SOURCE
#include <string.h>

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

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

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

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

Gui13
источник

Ответы:

172

Определение не _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 выше.

R .. GitHub ОСТАНОВИТЬ, ПОМОГАЯ ЛЕД
источник
71
Конечно, все знают, что реальная причина, чтобы определить _GNU_SOURCEэто для того, чтобы получить strfryи memfrob.
user4815162342
5
Эта ссылка на документацию библиотеки GNU C содержит некоторые дополнительные детали (например, #define _GNU_SOURCEрекомендуется быть «самой первой вещью в файле, перед которой должны быть только комментарии»).
Александр Позднеев
Не так актуально, но используется для расширения предела размера файла 2 ГБ для 32-битных целей.
Маккензм
1
@Mckenzm: я думаю, что вы думаете _FILE_OFFSET_BITS, а не _GNU_SOURCE.
R .. GitHub ОСТАНОВИТЬСЯ, ПОМОГАЯ ЛЬДУ
Я хочу быть платным программистом для портирования strfry memfrob и аналогичных функций для других платформ и цепочек инструментов.
Массимо
6

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

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

Распространенным подходом является условно #defineидентифицировать basenameразные имена в зависимости от того _GNU_SOURCE, определен ли . Например:

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

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

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

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

Blaisorblade
источник
6

Точная информация о том, что все включено _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 версии 2000 2001 года; _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 но любой макрос должен быть определен таким образом).

PP
источник
4

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

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

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

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

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

Так что это позволяет много компилировать флаги для gcc

Крис
источник
21
Это не влияет на поведение компилятора, только то, что прототипы и вещи видны из заголовков.
Spudd86