web-dev-qa-db-ja.com

「#define _GNU_SOURCE」とはどういう意味ですか?

今日はbasename()関数を使用する必要があり、man 3 basenamehere )は奇妙なメッセージをくれました:

basename()-上記のPOSIXバージョンとGNUバージョン、後に取得

#define _GNU_SOURCE
#include <string.h>

私はこの#define _GNU_SOURCEが何を意味するのか疑問に思っています。それはtainting私がGNU関連のライセンスで書いたコードですか?または、単にコンパイラに「まあ、この関数のセットはPOSIXではないので移植性がありませんが、とにかく使用したい」のようなものを伝えるために使用されます。

もしそうなら、なんらかの関数の実装を取得するためにいくつかのあいまいなマクロを定義する代わりに、人々に異なるヘッダーを与えないのはなぜですか?

また、何かバグがあります。コンパイラーは、どの関数実装を実行可能ファイルとリンクするかをどのように知るのですか?この#defineも使用しますか?

誰か私に教えてくれるポインターがありますか?

139
Gui13

_GNU_SOURCEを定義することは、ライセンスとは無関係であり、(非)移植性のあるコードを書くことに関係します。 _GNU_SOURCEを定義すると、以下が得られます:

  1. 多くの非標準のGNU/Linux拡張機能へのアクセス
  2. pOSIX標準から省略された従来の機能へのアクセス(多くの場合、より優れた代替物に置き換えられる、特定のレガシー実装に結び付けられるなどの正当な理由のため)
  3. 移植可能ではないが、mountifconfigなどのシステムユーティリティを実装するために必要な低レベル関数へのアクセス.
  4. GNUの人々が関数の振る舞いについて標準化委員会に同意せず、独自のことを行うことを決定した、多くのPOSIX指定関数の壊れた動作。

これらのことを知っている限り、_GNU_SOURCEを定義することは問題ではありませんが、定義を避け、代わりに_POSIX_C_SOURCE=200809Lまたは_XOPEN_SOURCE=700を定義して、プログラムは移植可能です。

特に、_GNU_SOURCEからneverを使用する必要があるものは、上記の#2と#4です。

156
R..

さらに2つのポイントに答えてみましょう。

また、何かバグがあります。コンパイラーは、どの関数実装を実行可能ファイルとリンクするかをどのように知るのですか?この#defineも使用しますか?

一般的なアプローチは、#defineが定義されているかどうかに応じて、異なる名前に_GNU_SOURCE識別子basenameを条件付きで付けることです。例えば:

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

これで、ライブラリはこれらの名前で両方の動作を提供するだけで済みます。

もしそうなら、なんらかの関数実装を取得するためにいくつかのあいまいな環境変数を定義する代わりに、人々に異なるヘッダーを与えないのはなぜですか?

多くの場合、同じヘッダーは異なるUnixバージョンでわずかに異なるコンテンツを持っていたので、たとえば<string.h>には単一の正しいコンテンツはありません—多くの標準があります( xkcd )。お気に入りのマクロを選択するための一連のマクロがあるため、プログラムが1つの標準を想定している場合、ライブラリはそれに準拠します。

6
Blaisorblade

_GNU_SOURCEによってすべて有効になるものの詳細については、ドキュメントが役立ちます。

GNUドキュメントから:

マクロ:_GNU_SOURCE

このマクロを定義すると、ISO C89、ISO C99、POSIX.1、POSIX.2、BSD、SVID、X/Open、LFS、およびGNU拡張のすべてが含まれます。 POSIX.1がBSDと競合する場合、POSIX定義が優先されます。

機能テストマクロ のLinux manページから:

_GNU_SOURCE

(任意の値で)このマクロを定義すると、_ATFILE_SOURCE、_LARGEFILE64_SOURCE、_ISOC99_SOURCE、_XOPEN_SOURCE_EXTENDED、_POSIX_SOURCE、_POSIX_C_SOURCEの値が200809L(2.10より前のglibcバージョンで200112L; glibcバージョン2.5より前の199309L; 199309Lで199309Lの前に)値が700の_XOPEN_SOURCE(2.10より前のglibcバージョンでは600、2.2より前のglibcバージョンでは500)。さらに、さまざまなGNU固有の拡張機能も公開されています。

Glibc 2.19以降、_GNU_SOURCEを定義すると、_DEFAULT_SOURCEを暗黙的に定義する効果もあります。 2.20以前のglibcバージョンでは、_GNU_SOURCEを定義すると、_BSD_SOURCEおよび_SVID_SOURCEを暗黙的に定義する効果もありました。

_GNU_SOURCEを定義する必要がありますbeforeヘッダーを含む各ヘッダーで機能を有効にするためのファイル。例えば:

#define _GNU_SOURCE

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

_GNU_SOURCEは、-Dフラグを使用してコンパイルごとに有効にすることもできます。

$ gcc -D_GNU_SOURCE file.c

-D_GNU_SOURCEに固有ではありませんが、このようにマクロを定義します)。

5
P.P.

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_BITS = N、_BSD_SOURCE、_SVID_SOURCE

そのため、gccの多くのコンパイルフラグが有効になります。

4
Chris