「#define _GNU_SOURCE」は何を意味しますか?


152

今日、私はbasename()関数を使わなければなりませんでした、そしてman 3 basenameここ)は私にいくつかの奇妙なメッセージを与えました:

ノート

basename()には2つの異なるバージョンがあります。上記のPOSIXバージョンと、GNUバージョンです

#define _GNU_SOURCE
#include <string.h>

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

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

何かが私を悩ませます:コンパイラーはどのように実行可能ファイルとリンクする関数の実装を知るのですか?これ#defineも使用しますか?

誰かが私に与えるいくつかの指針がありますか?

回答:


172

定義_GNU_SOURCEはライセンスとは関係がなく、(非)移植可能なコードを書くこととはすべて関係があります。を定義すると_GNU_SOURCE、次のようになります。

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

これらのことを認識している限り、を定義することは問題になりませんが、それを定義する_GNU_SOURCEことは避け、代わりに、_POSIX_C_SOURCE=200809Lまたは_XOPEN_SOURCE=700可能な場合はプログラムを移植可能にするために定義する必要があります。

特に、使用_GNU_SOURCEすべきではないものは上記の#2と#4です。


71
もちろん、定義する本当の理由_GNU_SOURCEは、strfryとを取得するためであることを誰もが知っていますmemfrob
user4815162342 2013年

5
GNU Cライブラリのドキュメントへのこのリンクは、いくつかの追加の詳細を提供します(たとえば、#define _GNU_SOURCE「ファイルの最初の部分であり、コメントのみが続く」ことが推奨されます)。
Alexander Pozdneev 16

それほど関連性はありませんが、32ビットターゲットの2GBのファイルサイズ制限を拡張するために使用されます。
mckenzm

1
@mckenzm:_FILE_OFFSET_BITSではなく、を考えていると思います_GNU_SOURCE
R .. GitHub ICE HELPING ICE停止

strfry memfrobと同様の設備を他のプラットフォームやツールチェーンに移植するための有料プログラマになりたいです。
Massimo

6

さらに2つの点に答えさせてください。

何かが私を悩ませます:コンパイラーはどのように実行可能ファイルとリンクする関数の実装を知るのですか?この#defineも使用していますか?

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

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

ライブラリは、これらの名前で両方の動作を提供する必要があるだけです。

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

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


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(glibcバージョン2.10より前では200112L、バージョン2.5より前のglibcバージョン2.1では199506L、バージョン199309より前のバージョンでは199506L)と暗黙的に定義されます。値が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に定義する必要があります。例えば:

#define _GNU_SOURCE

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

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

$ gcc -D_GNU_SOURCE file.c

(これ-Dは特定のものではありません_GNU_SOURCEが、どのマクロもこの方法で定義できます)。


4

グーグル経由のいくつかのメーリングリストから:

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のコンパイルフラグの多くを有効にします


21
コンパイラーの動作には影響せず、ヘッダーから見えるプロトタイプやものにのみ影響します。
Spudd86 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.