I am writing a library in C++. The library has multiple headers and cpp files and needs to be cross platform (Windows Visual Studio and Linux gcc). When built the library and headers are installed in a system directory somewhere, where they can be found by other code on the same machine (e.g. /usr/local on a Linux system).
If one of my headers needs to #include one of my other headers then should I use angle brackets or quotes?
I feel like angle brackets is what should be used once the library is installed so that system directories are checked, but when building the library I need to use quotes so that local directories are checked and I don't pick up an out of date version from the system directories.
I am aware ow what the different versions of #include <filename>
and #include “filename”
mean. I am asking which is appropriate and why, for the situation of writing a library.
When you use angle brackets, the compiler searches for the file in the include path list. When you use double quotes, it first searches the current directory (i.e. the directory where the module being compiled is) and only then it'll search the include path list.
So, by convention, you use the angle brackets for standard includes and the double quotes for everything else. This ensures that in the (not recommended) case in which you have a local header with the same name as a standard header, the right one will be chosen in each case.
Refer following SO answer for more details
Difference between angle bracket < > and double quotes " " while including header files in C++?
If you use "..."
the compiler will search the local directory first and then the system directory.
If you use <...>
the compiler will search the system directory.
A user library will normally reside along with the program. So you can use "..."
You can in any case add additional search paths using the IDE or make file.
I'm currently facing the same decision with a library I'm working on, which is intended to be consumed by projects other than my own. None of the other answers here address the practicality of quoted vs angular form of includes within libraries themselves, but merely explain the technical differences between the two forms.
There seems to be a divide into which include form is best for library sources/headers including headers from the same library. I don't think I'm qualified to give the Ultimate Answer. What I'm going to do here instead is attempt to summarize the pros and cons of each approach as best as I can, and link to some resources I found online.
The C++ Core Guidelines [1] has this to say under SF.12:
Library creators should put their headers in a folder and have clients include those files using the relative path
#include <some_library/common.h>
The advantages of the angular form listed below assume that a library's headers are put into such a "root" folder named after the library (I hate it when libraries don't do that).
Unfortunately, the C++ Core Guidelines do not explicitly state what library creators should do when including their own headers from within their own library source/header files. However, a contributor kindly clarified to me in [4] that in their example:
#include "foo_utils/utils.h"
// A file locally relative to foo.cpp in the same project, use the "" form
the term project also applies to libraries. That contributor also clarified that "locally relative" was left up to the reader so that instances of #include "../../include/somelib/foo.hpp"
could be interpreted as non-locally relative so that #include <somelib/foo.hpp>
may be used instead.
Note that the C++ Core Guidelines, co-authored by Stroustrup, somewhat contradicts the AV Rule 33 of Stroutrup's earlier JSF coding standards [2] when it comes to the preferred #include
form. Perhaps he changed his views regarding this.
#include <somelib/foo.hpp>
approach:-I
or -isystem
compiler flags. Patching via this method is probably only viable for header-only libraries.#include <somelib/float.h>
vs #include "float.h"
, where float.h happens to be a C standard library header.#include <somelib/foo/bar.hpp>
vs #include "../foo/bar.hpp"
. Also consider the case where the source and header files live in different directories of the library project: #include <somelib/foo/bar.hpp>
vs #include "../include/foo/bar.hpp"
when including from a library cpp file.#include "foo.hpp"
approach:-I
or -isystem
flags.-I
or -isystem
flags properly to point to a local version of the library, they can just do #include "../dependencies/somelib/include/somelib/foo.hpp"
(which I find terribly ugly - perhaps irrationally).Based on the above research and on the kind help from the C++ Core Guidelines contributor, I'm now personally aiming to adopt the following convention:
#include "foo.h"
, #include "bar/foo.hpp"
, or #include "../bar/foo.hpp"
, depending on the relative location of the other header file.#include <somelib/foo.hpp>
or #include <somelib/bar/foo.hpp>
.The former makes it clear that I want to include a header file that's bundled with the same library as the file doing the including.
The latter makes it possible for the library source files to be compiled by being directly dropped into an application's build system, without having to maintain the same relative directory structure between the library's source and header files. It also avoids the #include "../include/somelib/foo.hpp"
ugliness in favor of the cleaner #include <somelib/foo.hpp>
.
When my library source files are being compiled using the library's CMake scripts (to generate a static/shared library), the CMake scripts are in control of the -I
and -isystem
flags and can thus ensure that the correct library headers path will be given top search priority.
[1] https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rs-incform
[2] https://www.stroustrup.com/JSF-AV-rules.pdf
[3] https://lists.boost.org/Archives/boost//2008/09/142030.php
[4] https://github.com/isocpp/CppCoreGuidelines/pull/1596#issuecomment-1113901271
if the headers in the your working directory, you should use ""
but,
if the headers in the system path or inside the your include path you should use <>.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With