10

There are essentially two camps of library designers concerning the design of the final header file inclusion:

  • Provide a single header file that includes every other header file that makes up the public API. For example, GTK+ dictates that only gtk.h shall be included. This does not mean that everything is explicitly written into that common header file.
  • Have the user include the header file whose functionality he is most interested in. The most prominent example would be the standard library where he has to include stdio.h for I/O, string.h for string manipulation etc., instead of a common std.h

Is there a preferred way? libabc gives no advice on that matter, whereas an answer to a similar question suggests to keep them separated but does not specifies why.

6
  • Probably better suited for programmers SE. Anyway depends on how focused/diverse your functions are, I would say.
    – Karthik T
    Commented Jan 31, 2013 at 8:03
  • If you keep them separated, it will improve compile time since there will be less code appended to the source file which includes the headers (less preprocessor processing). The only thing to keep in mind is to stick with one of the above policies.
    – Rerito
    Commented Jan 31, 2013 at 8:06
  • I was probably a bit unclear. Each translation unit still provides a public header file. The question is: can the user include them directly or does he have to include the functionality through a common header file as practiced by most GNOME libraries.
    – matthias
    Commented Jan 31, 2013 at 8:09
  • 2
    Why not provide the common file, but still make the individual files available and documented? Then the users of the library can include the convenient single file until they actually need the flexibility and compile-time performance of the individual files. Commented Jan 31, 2013 at 8:36
  • @ThomasPadron-McCarthy: But then there must be a pretty good reason that GTK+ actively prevents including single headers via macro checks.
    – matthias
    Commented Jan 31, 2013 at 8:47

2 Answers 2

12

Design in general is always "the art to balance contradicting goals".

Here, you have these goals:

  1. The framework should be simple to use. If your API is 15 header files, then users will always struggle which ones to include and which ones to omit.
  2. All common functionality should be in a single header file. So file I/O shouldn't be in string.h but you also don't want 3 string.h header files.
  3. Dependencies are bad, so you want to reduce them to the smallest amount possible
  4. Reading huge (amounts of) header files is slow
  5. Each feature in your header file will raise the risk that you need to include another header file to make it compile.

gtk.h makes sense since you want to build a user interface for your application (point #2). You could argue that people should include each widget individually but then, your framework will become slightly harder to use (point #1).

If you look at old X11/Motif code, you will see dozens of #include statements at the top of each C source file. It compiles a little bit faster but it takes hours of manual work to maintain these lists.

OTOH, if you put too many features in your header files, you will have too many dependencies in there and one of them might kill you (for example, when this dependency requires another framework with a certain version -> dependency hell).

I hope you understand by now that there is no solution; the problem is too complex and needs to be addressed again every time a new framework is started.

EDIT

But then there must be a pretty good reason that GTK+ actively prevents including single headers via macro checks. – matthias

For GTK, the #include statements are part of the public API. With these macros, they are free to rearrange the header files, their content, names and include order, in any way they like at any time without breaking a single existing project.

5

Having all headers in one single is great and better, it's easier for others to include one single header than including different headers.

One issue of this sort of design, in big headers such as windows.h, gtk.h still small comparing to window.h, the building process can get slow. In windows.h we get around this issue by defining WIN32_LEAN_AND_MEAN to exclude some uncommon headers such as windows sockets and cryptography API to speed up building process, read more here Using the Windows Headers.

Also by the time when your library grow, there are many headers and it can be hard to work with it, you will have to make a lot of macros, lots, and endup with complex header to not break backward compatibility.

Even though, I personally prefer single header design.

Not the answer you're looking for? Browse other questions tagged or ask your own question.