Що означає "#define _GNU_SOURCE"?


152

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

Примітки

Існують дві різні версії базового імені () - версія POSIX, описана вище, і версія GNU , яку отримує після

#define _GNU_SOURCE
#include <string.h>

Я цікаво , що це #define _GNU_SOURCEозначає: чи є він заражаючи код я пишу з GNU-пов'язаної ліцензії? Або просто використовується для того, щоб сказати компілятору щось на кшталт " Ну, я знаю, цей набір функцій не є POSIX, таким чином, не є портативним, але я б хотів його використовувати в будь-якому випадку ".

Якщо так, то чому б не дати людям різні заголовки, замість того, щоб визначити якийсь незрозумілий макрос, щоб отримати одну чи іншу функцію?

Щось також клопоче мене: як компілятор знає, яку реалізацію функції пов’язати з виконуваним файлом? Це він також використовує #define?

У когось є якісь покажчики, щоб дати мені?

Відповіді:


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.


71
Звичайно, всі знають, що справжня причина визначається _GNU_SOURCE- для того, щоб отримати strfryі memfrob.
user4815162342

5
Це посилання на документацію Бібліотеки GNU C містить деякі додаткові деталі (наприклад, #define _GNU_SOURCEрекомендується бути "найпершою справою у файлі, перед якою лише коментарі").
Олександр Позднеєв

Не настільки актуально, але використовується для розширення обмеження розміру файлу 2 ГБ на 32-бітні цілі.
mckenzm

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 ). Існує цілий набір макросів для вибору улюбленого, так що якщо ваша програма очікує одного стандарту, бібліотека буде відповідати цьому.


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 зі сторінки Linux :

_GNU_SOURCE

Визначення цього макросу (з будь-яким значенням) неявно визначає _ATFILE_SOURCE, _LARGEFILE64_SOURCE, _ISOC99_SOURCE, _XOPEN_SOURCE_EXTENDED, _POSIX_SOURCE, _POSIX_C_SOURCE зі значенням 200809L (200112L в версіях glibc 2; 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але будь-який макрос визначається таким чином).


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_BITSSE_BITS

Таким чином, це дає змогу збирати безліч прапорів для gcc


21
Це не впливає на поведінку компілятора, лише те, які прототипи та речі видно із заголовків.
Spudd86
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.