ariadne.space/content/blog/stop-defining-feature-test-...

33 lines
2.1 KiB
Markdown

---
title: "stop defining feature-test macros in your code"
date: "2021-12-21"
---
If there is any change in the C world I would like to see in 2022, it would be the abolition of `#define _GNU_SOURCE`. In many cases, defining this macro in C code can have harmful side effects ranging from subtle breakage to miscompilation, because of how feature-test macros work.
When writing or studying code, you've likely encountered something like this:
```
#define _GNU_SOURCE
#include <string.h>
```
Or worse:
```
#include <stdlib.h>
#include <unistd.h>
#define _XOPEN_SOURCE
#include <string.h>
```
The `#define _XOPEN_SOURCE` and `#define _GNU_SOURCE` in those examples are defining something known as a _feature-test macro_, which is used to selectively expose function declarations in the headers. These macros are necessary because some standards have conflicting definitions of functions and thus are aliased to other symbols, allowing co-existence of the conflicting functions, but only one version of that function may be defined at a time, so the feature-test macros allow the user to select which definitions they want.
The correct way to use these macros is by defining them at compile time with compiler flags, e.g. `-D_XOPEN_SOURCE` or `-std=gnu11`. This ensures that the declared feature-test macros are consistently defined while compiling the project.
As for the reason why `#define _GNU_SOURCE` is a thing? It's because we have documentation which does not correctly explain the role of feature-test macros. Instead, in a given manual page, you might see language like "this function is only enabled if the `_GNU_SOURCE` macro is defined."
To find out the actual way to use those macros, you would have to read [feature\_test\_macros(7)](https://man7.org/linux/man-pages/man7/feature_test_macros.7.html), which is usually not referenced from individual manual pages, and while that manual page shows the incorrect examples above as bad practice, it understates how much of a bad practice it actually is, and it is one of the first code examples you see on that manual page.
In conclusion, never use `#define _GNU_SOURCE`, always use compiler flags for this.