From: Daan De Meyer Date: Sat, 19 Apr 2025 08:11:12 +0000 (+0200) Subject: docs: Add paragraph about circular includes to CODING_STYLE.md X-Git-Tag: v258-rc1~774^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7e42c2705c71ff50d156e58583149d0a70ca398;p=thirdparty%2Fsystemd.git docs: Add paragraph about circular includes to CODING_STYLE.md --- diff --git a/docs/CODING_STYLE.md b/docs/CODING_STYLE.md index b8b420c1423..2b8cf694208 100644 --- a/docs/CODING_STYLE.md +++ b/docs/CODING_STYLE.md @@ -234,6 +234,74 @@ SPDX-License-Identifier: LGPL-2.1-or-later const char *input); ``` +- Please do not introduce new circular dependencies between header files. + Effectively this means that if a.h includes b.h, then b.h cannot include a.h, + directly or transitively via another header. Circular header dependencies can + make for extremely confusing errors when modifying the headers, which can be + easily avoided by getting rid of the circular dependency. To get rid of a + circular header dependency, there are a few possible techniques: + - Introduce a new common header with the declarations that need to be shared + by both headers and include only this header in the other headers. + - Move declarations around between the two headers so one header doesn't need + to include the other header anymore. + - Use forward declarations if possible to remove the need for one header to + include the other. To make this possible, you can move the body of static + inline functions that require the full definition of a struct into the + implementation file so that only a forward declaration of the struct is + required and not the full definition. + + Bad: + + ```c + // manager.h + + typedef struct Manager Manager; + + #include "unit.h" + + struct Manager { + Unit *unit; + }; + + // unit.h + + typedef struct Unit Unit; + + #include "manager.h" + + struct Unit { + Manager *manager; + }; + ``` + + Good: + + ```c + // manager.h + + typedef struct Unit Unit; + + typedef struct Manager { + Unit *unit; + } Manager; + + // manager.c + + #include "unit.h" + + // unit.h + + typedef struct Manager Manager; + + typedef struct Unit { + Manager *manager; + } Unit; + + // unit.c + + #include "manager.h" + ``` + - The order in which header files are included doesn't matter too much. systemd-internal headers must not rely on an include order, so it is safe to include them in any order possible. However, to not clutter global