-D_DEFAULT_SOURCE 是做什么的?

What does -D_DEFAULT_SOURCE do?

之前我收到来自 gcc -std=c99 的警告,即 usleep() 被隐式声明。然后我偶然发现了 this Whosebug post,这让我使用了 -D_BSD_SOURCE。但是,现在 gcc 告诉我 -D_BSD_SOURCE 已被弃用,我应该改用 -D_DEFAULT_SOURCE

#warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"

为什么 -D_BSD_SOURCE 被弃用了?为什么使用 -D_DEFAULT_SOURCE 代替?它有什么作用?

我做了 some googling,但结果却充斥着用它来闭嘴的人 gcc。我无法找出 为什么 -D_BSD_SOURCE 已被弃用,就是这样。

glibc manual 描述了每个功能测试宏 (FTM),包括 _DEFAULT_SOURCE:

If you define this macro, most features are included apart from X/Open, LFS and GNU extensions: the effect is to enable features from the 2008 edition of POSIX, as well as certain BSD and SVID features without a separate feature test macro to control them. Defining this macro, on its own and without using compiler options such as -ansi or -std=c99, has the same effect as not defining any feature test macros; defining it together with other feature test macros, or when options such as -ansi are used, enables those features even when the other options would otherwise cause them to be disabled.

This LWN.net article 关于 FTM 为我们提供了一个基本原理(以及其他可能有趣的信息):

The original intent seems to have been that, within each of the glibc header files that employs FTMs, only one of the __USE_* internal macros should govern the exposure of any particular definition. Additionally, the macros should not be used in nested #ifdef directives. An inspection of the glibc header files quickly shows that the reality is far from the intent, a situation that led Roland McGrath to suggest that it was time for a major cleanup to bring things back to the intended situation. Roland thought that task could be simplified by eliminating the _BSD_SOURCE and _SVID_SOURCE FTMs, which, although they had a purpose historically, have ceased to be useful these days. Anymore, he said, the only macros that are needed for modern source code are those that relate to formal standards plus _GNU_SOURCE.

Joseph Myers duly obliged with a series of patches to implement the first steps in this work. The conservative approach encouraged by Roland meant that the deprecation of the _BSD_SOURCE and _SVID_SOURCE FTMs is taking place across two glibc versions. Version 2.19 of glibc added a new FTM, _DEFAULT_SOURCE. Defining this macro causes the default definitions to be exposed even when the explicit definition of other macros would cause that not to happen. The effect of defining this macro is equivalent to the effect of explicitly defining three macros in earlier glibc versions:

cc -D_BSD_SOURCE -D_SVID_SOURCE -D_POSIX_C_SOURCE=200809C

因此,如果您需要定义 _BSD_SOURCE_SVID_SOURCE,也只需定义 _DEFAULT_SOURCE。 glibc 版本 <= 2.18 不关心它并且版本 >= 2.19 如果定义了两个或所有三个则不要警告。

我需要超越 linux 和 glibc 的可移植性,我不喜欢 #ifdef。所以:

/* asprintf() does not appear on linux without this */
#define _GNU_SOURCE

/* gettimeofday() does not appear on linux without this. */
#define _BSD_SOURCE

/* modern glibc will complain about the above if it doesn't see this. */
#define _DEFAULT_SOURCE