“#define _GNU_SOURCE”暗示什么?
今天我不得不使用basename()
函数, man 3 basename
( 这里 )给了我一些奇怪的消息:
笔记
basename()有两个不同的版本 – 上面描述的POSIX版本和GNU版本
#define _GNU_SOURCE
#include <string.h>
我想知道这个#define _GNU_SOURCE
是什么意思:它是否#define _GNU_SOURCE
了我用GNU相关许可证编写的代码? 或者它只是用来告诉编译器这样的东西,“ 我知道,这套函数不是POSIX,因此不能移植,但我仍然想用它 ”。
如果是这样,为什么不给人们不同的标题,而不必定义一些不起眼的macros来获得一个函数的实现或其他?
有些东西也使我感到困惑:编译器如何知道哪个函数实现与可执行文件链接? 它也使用这个#define
吗?
有人有指示给我?
定义_GNU_SOURCE
与许可证和与编写(非)可移植代码有关的一切无关。 如果你定义_GNU_SOURCE
,你会得到:
- 访问大量非标准的GNU / Linux扩展function
- 访问POSIX标准中忽略的传统function(通常是出于很好的原因,比如replace为更好的select,或者与特定的传统实现绑定)
- 访问不能移植的底层函数,但有时需要实现像
mount
,ifconfig
等系统实用程序。 - 在许多POSIX指定的函数中,破坏了行为,GNU人们不同意标准委员会关于函数的行为方式,并决定做自己的事情。
只要你知道这些事情,定义_GNU_SOURCE
应该不是问题,但是你应该避免定义它,而是尽可能定义_POSIX_C_SOURCE=200809L
或_XOPEN_SOURCE=700
,以确保你的程序是可移植的。
尤其是_GNU_SOURCE
中你永远不会使用的东西是上面的#2和#4。
我再回答两点:
有些东西也使我感到困惑:编译器如何知道哪个函数实现与可执行文件链接? 它也使用这个#define吗?
通常的做法是有条件地将#define
标识符basename
名称定义为不同的名称,具体取决于是否定义了_GNU_SOURCE
。 例如:
#ifdef _GNU_SOURCE # define basename __basename_gnu #else # define basename __basename_nongnu #endif
现在图书馆只需要提供这两个名称下的行为。
如果是这样,为什么不给人们不同的标题,而不必定义一些模糊的环境variables来获得一个函数的实现或其他?
通常在不同的Unix版本中,相同的头文件的内容略有不同,所以没有单一的正确的内容,例如<string.h>
– 有很多标准( xkcd )。 有一整套的macrosselect你最喜欢的,所以如果你的程序需要一个标准,图书馆将符合这一点。
从一些邮件列表通过谷歌:
看看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启用了大量的编译标志
有关_GNU_SOURCE
全部启用的具体细节,文档可以提供帮助。
从GNU文档:
macros:_GNU_SOURCE
如果你定义了这个macros,包含所有内容:ISO C89,ISO C99,POSIX.1,POSIX.2,BSD,SVID,X / Open,LFS和GNU扩展。 在POSIX.1与BSD冲突的情况下,POSIX定义优先。
从functiontestingmacros的Linux手册页:
_GNU_SOURCE
定义这个macros(带有任何值)隐式定义了_ATFILE_SOURCE,_LARGEFILE64_SOURCE,_ISOC99_SOURCE,_XOPEN_SOURCE_EXTENDED,_POSIX_SOURCE,_POSIX_C_SOURCE的值为200809L(在2.10之前的glibc版本中的200112L;在2.5之前的glibc版本中的199506L;在2.1之前的glibc版本中的199309L) _XOPEN_SOURCE的值为700(在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
,以便相应的头文件启用这些function。 例如:
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> ...
_GNU_SOURCE
也可以使用-D
标志进行编译:
$ gcc -D_GNU_SOURCE file.c
( -D
并不特定于_GNU_SOURCE
但是可以用这种方式定义任何macros)。