Skip to content

Instantly share code, notes, and snippets.

@Qix-
Last active December 10, 2021 14:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Qix-/408f893f724016a8608b054f27894934 to your computer and use it in GitHub Desktop.
Save Qix-/408f893f724016a8608b054f27894934 to your computer and use it in GitHub Desktop.
Order of includes

C/C++ Order of Includes

The order in which I group my header includes is as follows. Each section is separated by exactly one blank line, even if the section only has one include.

  1. "" Internal headers
  2. "" Internal generated headers (e.g. from version.h.in; okay to use from include path)
  3. "" Internal third-party headers (vendored into project)
  4. "" Private API headers (always relative paths)
  5. "" Public API headers
  6. <> Build-system level third party headers (e.g. from CMake's add_subdirectory(); always from include path)
  7. <> System-wide third party (but not platform) headers (e.g. from sudo apt install ...)
  8. <> Platform headers (e.g. unistd.h, sys/net.h, etc.)
  9. <> Standard library headers

Any conditionally included headers come as early as technically possible (barring inclusion-order constraints), but not earlier than their respective section (corollary: conditional includes in section X should be preceded by all unconditional includes also in section X).


Here are a few real-world examples (with added comments showing which section they belong to):

/* from Minimap, src/context.c */

//-> 1. internal
#include "./context.h"
#include "./init.h"
#include "./string.h"
#include "./error.h"

//-> 3. internal third-party
#include "./third_party/cwalk.h"

//-> 4. public API
#include "../include/minimap.h"

//-> 6. system-wide third-party
#include <git2.h>

//-> 7. platform
#include <unistd.h>

//-> 8. standard
#include <assert.h>
#include <string.h>
#include <limits.h>
/* from Minimap, src/init.c */

//-> 1. internal
#include "./init.h"
#include "./error.h"

//-> 2. internal generated (seen here using internal include path)
#include "minimap--generated-version-info.h" /* see CMakeLists.txt */

//-> 4. public API
#include "../include/minimap.h"

//-> 6. system-wide third-party
#include <git2.h>

//-> 8. standard
#include <assert.h>
// from Tide Online; note that the <tide/*> includes
// are from intra-project modules linked together
// as though they were individual modules *all done
// via CMake targets* so this was the rationale behind
// including them with <> as opposed to "" (they functioned
// more like third-party modules than internal modules).

//-> 1. internal
#include "./render/thread.hh"
#include "./game/thread.hh"
#include "./physics/thread.hh"
#include "./fatal-error.hh"

//-> 5. build-system third-party (see above comment)
#include <tide/log.hh>
#include <tide/util.hh>
#include <tide/engine.hh>
#include <tide/assert.hh>

//-> 8. standard
#include <csignal>
#include <stdexcept>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <string>
/*
  From the ORO operating system stage 0 loader's
  x86 CPU VGA driver.
  
  Note that the FRAMAC include was
  required first due to technical reasons,
  which of course outweighs any subjective
  ordering conventions.
*/

#ifdef __FRAMAC__
#	include <string.h>
#endif

//-> 1. internal
#include "./vga.h"
#include "../boot.h"

//-> 4. private API
#include "../../stage1/string.h"
#include "../../stage1/types.h"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment