How to namespace C++ header files? - c++

I use a code with different libraries, which use names like defines.h. This does not only cause conflicts for identical filenames, but also creates confusion. From which library is the defines.h include?
Including as #include <library/defines.h> would be a clean solution, but then the include path would need to be the parent directory of the library, which is rather unclean again.
Is there some way to alias the include path, so that -I/path/to/library makes the headers available under library/headername.h?

Is there some way to alias the include path, so that -I/path/to/library makes the headers available under library/headername.h?
There seems to be no need to in this case. You can simply use -I/path/to which makes /path/to/library/headername.h available under library/headername.h.
That said, while there is no such compilation option (that I know of), you can create such "aliases" to file paths in most file systems. These aliases are called symbolic links. In this case, you could make a link /path/to/library/mylibrary that points to . which would make /path/to/library/headername.h available under mylibrary/headername.h assuming you've used -I/path/to/library.

At least on unixy systems, when you compile and install a library, headers are installed for example to
/usr/lib/libraryname/*.h
Or maybe something like
/opt/libraryname-1.2/include/libraryname/*.h
And then if necesssry (not installing to compiler's default include search path), right dir is added with compiler option, for gcc for example option
-I/opt/libraryname-1.2/include
Then just always do this in source code, trusting build system to have included the right search paths:
#include <libraryname/includefile.h>

Related

Prefer location relative or include path path relative includes within your own library in C++

Whenever I start developing a new shared library in C++ I come across the same question:
Should I use includes relative to the position of the current file or includes relative to the (potential) include paths (-I) to refer to other header files within my project, i.e. the same library?
I checked with some of the library headers installed on my system.
boost appears to use includes relative to the include path and <>brackets to include other boost headers, i.e. #include <boost/move/move.hpp>
poppler on the other hand appears to use some weird relative paths with "", sometimes relative to the current location and sometimes relative to its base (I didn't even know that this works), .e.g. in fofi/FoFiEncodings.hthere is an #include "goo/gtypes.h" where fofi and goo are directories on the same level
many others simply include files with "" and their location relative paths, mainly files in the same directory
Does it depend on the directory structure (i.e. its complexity) of the shared library itself, i.e. location relative paths work well with simple layouts but have drawbacks with more cross references like in boost? Are there any technical reasons or pitfalls why one might work but the other doesn't (portability, compiler dependent behavior, ...)?
Boost uses brackets instead of quotes. This means that it isn't an absolute path, but that the search starts relative to the list of linclude directories that was provided to the compiler. So it's a variant of the relative path.
A really absolute path is a bad idea because if another developper installs the source code at another location, he/she'll not be able to compile unless he/she changes all the header references in the sources.
Edit:
If you develop a library that is general enough and designed to be shared across several (possibly unrelated) projects, the bracket option should be the preferred one. This lets you the freedom to install the library wherever you want, and also to switch libraries (different versions for different projects) very easily.
If you develop a more specific library in the context of a larger solution, mainly to isolate reusable code, the quoted relative path is an option. If later you want to reuse that library in another context, you would have to install its sources in the new solutions directory so that the relative paths still work. So the use case is a little different (narrow sharing and occasional reuse in the context of very specific projects).
In your source file, do whatever you want/prefer.
For public headers, relative path is the preferred way, as user might place your headers in a specific place and use not exactly the same include directive.
I mean, suppose that your hierarchy is:
lib/headers/sub1/h1.h
lib/headers/sub2/h2.h
lib/headers/lib.h
lib/src/..
with directive to set include path to lib,
user should do #include <headers/lib.h>, but then your lib.h should look like:
#include "headers/sub1/h1.h"
#include "headers/sub2/h2.h"
and sub1/h1.h to
#include "headers/sub2/h2.h"
With directive to set include path to lib/headers,
user should do #include <lib.h>, but then your lib.h should look like:
#include "sub1/h1.h"
#include "sub2/h2.h"
and sub1/h1.h to
#include "sub2/h2.h"
So depending of directive set by user, your code won't compile for user.
With relative path, for both above directives, your files would be identical
lib.h:
#include "sub1/h1.h"
#include "sub2/h2.h"
and sub1/h1.h to
#include "../sub2/h2.h"

MACRO depending on its folder location

In the following files:
app/main.cpp
app/config.hpp
app/show.hpp
app/file.hpp
lib/append.hpp
lib/clear.hpp
lib/reopen.hpp
lib/crypt.hpp
I have a problem. Imagine a few of my files use lib/crypt.hpp. For example in app/file.hpp I should write:
#include "../lib/crypt.hpp"
If I take this file to lib folder it does not work anymore. So I need a something like:
#include "LIB/crypt.hpp"
So, this LIB/ has meaning of (empty) in lib directory while it has meaning of "../lib/" in app directory.
Then I will have no worry about moving file.hpp from app to lib. I just need to fix the callers of it. But not what it calls.
Similar to concept of web programming frameworks. Is it possible in C/C++?
According to what you wrote you're searching for a way to move your sources around without worrying for hard-coded paths to your headers.
You didn't specify the compiler you're using so I'm not focusing on a specific one, anyway most C++ compilers have an option to specify one or more header search paths (on gcc you would just use something like -Ilib_parent_dir).
Once you've included your lib's parent path to the search list, you can move your sources around (as long as you don't move lib's headers) and have them include the right headers with something like #include <lib/crypt.hpp> (and keep include paths priority in mind)
This should be a cleaner and simpler way to achieve what you asked rather than using a macro.

C++ include with full path

I find #include "../app/thing.h" very ugly and I would like to be able to import from the main root of my project, like this:
#include <project/app/submodule/thing.h>
(I know <> is generally used for external but I find it very cleaner)
How can I do that, from anywhere in my project?
You simply need to ensure that your build process sets an option to specify the starting point of the search.
For example, if your header is in:
/work/username/src/project/app/submodule/thing.h
then you need to include (assuming a POSIX-compliant compiler; AFAICR, even MSVC uses /I as the analogue of -I):
-I/work/username/src
as one of the compiler options. You can use that path from anywhere in your project since it is absolute. You just need a defined way for your build system to know what the setting should be, so that when it is moved to /home/someone/src/, you have only one setting to change.
See this answer for a more complete explanation about how the differences between the two formats work. Honestly, though, I think you might want to consider restructuring your folder hierarchy if you need to jump up a folder then jump into another folder to get something. Generally speaking, it's pretty common practice to keep all files local to your program local to each other in the folder structure (i.e. in the same folder), and all files that aren't local, but may be needed (such as header files for libraries used) in a sub-folder within the main program folder, or to include them at compile time.
It is important to note that in the answer I linked above, it explains that "<>" includes are IMPLEMENTATION DEPENDENT, so we'd really need to know what compiler you're using to tell you if you could or couldn't do that.
You can simply use the include directories option of your current compiler (-I usually) to achieve this.
Also note using the "" double quotes will just add to fallback for the compiler standard headers. Files included using the <>, are only guaranteed to search files from the compiler standard headers.

Using project directory in include filename

I am developing C++ headers only library, lets call it PROJ. When a library header is including another, it uses:
#include <proj/foo.h>
And compiler (gcc and clang) have -I path-to-proj-parent. Users of the library should also have parent of PROJ in their include search path.
My rationally for using this scheme is that after installing this library into proj subdirectory of default-seachable parent (/usr/include/proj or /usr/local/include/proj), library user do not need to specify -I option.
Is there cons to this scheme? Is using <foo.h> without proj/ prefix is more conventional and recommended way?
Question is not about if installing in subdir or not (there will be proj subdir), but rather how to refer to include-files.
If you look at boost, you will note that they use a similar scheme:
#include <boost/shared_ptr.hpp>
It has the advantage of preventing clashes with another similarly named file from another dependency.
However, in the case of boost, they take it one step further. If you include <x/y/z.hpp>, then you are likely to be dealing with an entity named ::x::y::z (be it function or class). That is, the way the directories in the project are laid out mimic the namespace organization. It's quite neat really to orient oneself.
Normally, most projects are stashed in subdirectories (and subnamespaces), but the most used ones are pulled into the boost namespace for convenience, and thus they have headers living directly in the boost folder. There are also some convenience headers (whose job is just to gather a smattering of other headers to pull them in all at once).
You may finally note, if you open a header file, than the include guards they use follow the exact same hierarchy:
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
once again because it helps avoiding clashes since it's named after the very file it's in and there can be only one at that place in the whole Boost project (on case sensitive filesystems).
It is ok to have proj in the path if you create the proj directory when you install. In fact its a good way to prevent name collisions with other include files.
The name should not be something generic like "proj' though. It should be specific to the project.

Making library name part of include path in make?

Say I'm working on a library, foo. Within my libraries source files, I'd like to include headers the same way a user of my library would:
#include <foo/bar.hpp>
// code defining bar methods here
In boost for example, includes of other headers within boost are done that way, e.g. <boost/shared_ptr.hpp>, rather than the relative quoted "../shared_ptr.hpp" style. I looked at how some other libraries accomplish this and it appears they add a redundant directory to their file layout in order to do it, e.g. the boost code lives in "boost_1_4_1/boost" rather than just "boost_1_4_1/".
Switching to that scheme is annoying if you already have source control using an existing layout. What's the best way with GNU make to layer it on? My only thought is to add a target that all build targets depend on that makes a hidden folder with a symlink inside to my source tree, and add that hidden folder to the include path. Perhaps there's a less obfuscated way?
Couldn't you use -I gcc key of INC option for your Makefile?
gcc:
gcc -c -I/home/joseph/dev/foo/headers
Makefile:
INC=-I/home/joseph/dev/foo/headers
In this case you would have only one place to make this change, Makefile.