Що означає "#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.