How do compilers know where to find #include <stdio.h>? - c++

I am wondering how compilers on Mac OS X, Windows and Linux know where to find the C header files.
Specifically I am wondering how it knows where to find the #include with the <> brackets.
#include "/Users/Brock/Desktop/Myfile.h" // absolute reference
#include <stdio.h> // system relative reference?
I assume there is a text file on the system that it consults. How does it know where to look for the headers? Is it possible to modify this file, if so where does this file reside on the operating system?

When the compiler is built, it knows about a few standard locations to look for header file. Some of them are independent of where the compiler is installed (such as /usr/include, /usr/local/include, etc.) and some of the are based on where the compiler is installed (which for gcc, is controlled by the --prefix option when running configure).
Locations like /usr/include are well known and 'knowledge' of that location is built into gcc. Locations like /usr/local/include is not considered completely standard and can be set when gcc is built with the --with-local-prefix option of configure.
That said, you can add new directories for where to search for include files using the compiler -I command line option. When trying to include a file, it will look in the directories specified with the -I flag before the directories I talked about in the first paragraph.

The OS does not know where look for these files — the compiler does (or more accurately, the preprocessor). It has a set of search paths where it knows to look for headers, much like your command shell has a set of places where it will look for programs to execute when you type in a name. The GCC documentation explains how that compiler does it and how these search paths can be changed.

The location of the file is system dependent. Indeed, the file might be precompiled, or it may not even exist—the compiler may have it as a 'built-in'. On my macbook, I see that there's such a file in /usr/include/c++/4.2.1/iostream, but you shouldn't rely on it, and it's definitely a bad idea to edit it.

If you were using g++, you could do something like this to find out what include paths were searched:
touch empty.cpp
g++ -v empty.cpp
I don't know if there's an equivalent for Xcode. Maybe that will work since Xcode is based on GCC?

In Visual Studio, it's either in the project settings if you use the IDE, or in the %INCLUDE% environment variable if you use the command line.

You should avoid #include-ing files using absolute paths. The compiler searches for the include files in various directories and includes files, starting from each directory. For example;
#include <boost/tokenizer.hpp>
Works because the boost root directory contains a folder called 'boost' and that folder is either in your default include path or you did something like.
g++ -I$BOOST_ROOT {blah, blah}
It is C and C++ standard that the UNIX separator '/' will work the same way for all systems, regardless of what the host system actually uses to denote directories. As others of mentioned, occasionally #include doesn't actually include a real file at all.

Related

How to namespace C++ header files?

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>

Setting C++ include path via program code line

There are already many options listed of how to add a path to a C++ compiler so that the #include <...> command works on these paths. However, assume that I have a single file (not an entire project) and I want to add an include path just for this file alone. I'd like to do this via a line of code within the cpp-file (say, as very first line). How is this possible? Why? Because I need to include some header file from another directory which in turn depends also on other header files within that same directory (and I get error messages that these other files could not be found due to the fact that this path was not added to the include-list).
For example:
Let's assume I want to include file_a.h in directory
.../include/extra,
I can do that via
#include <extra/file_a.h>
However, if, e.g., I do not have the extra-directory directly as a sub-directory of include, or the file_a wants to include some other file from somewhere else (maybe even /extra, but it's not a sub directory of include e.g.), then I run into trouble, because then the tracking of directories/dependencies gets hard.
I thought it would be a bad habit to change those directories via compiler, so I thought better solution would be to integrate it into the program, so no matter which compiler I use, it would work anyway without even having to think about afterwards, once specified, which directories I have to add.
Per my understanding you did:
#include <absolute/path/to/header/header.h
or
#include <relative/path/to/header/header.h
But into the header.h some other include are included.
#include <header_1.h>
#include <header_2.h>
[...]
#include <header_n.h>
Those other headers haven't relative/absolute path, so compiler doesn't know how to find them.
To solve this you can use (using gcc) the -I compiler option:
-I dir
Add the directory dir to the list of directories to be searched for header files during preprocessing. [...]
Emphasis mine
So you can use
#include <header.h>
In your file and compile it using
gcc ... -I/path/to/headers ...
When you have to specify one or more include paths in the compile command, you can do it as follows:
g++ -I/path1/to/headers -I/path2/to/headers YourProgram.cpp
Include paths tell the compiler where it finds the files it actually shall include into other files. This is (usually) controlled via compiler options as LPs explained in this answer.
C++ standard does not provide any facilities to do this from within a C++ source file and I am not aware either of any compiler extension of any vendor that would allow doing so, so bad luck...
Now depending on the IDE you are using (hopefully you are using one...), though, you most likely can add include paths for files individually there (would be a strange IDE if it didn't allow...), e. g. with eclipse + GCC, right click the file, select "Properties" -> C/C++ Build -> Tool Settings -> GCC C++ Compiler -> Includes.
Alternatively you could use a make file instead (actually, eclipse in standard settings generates one for you automatically...), which again allows you to set compiler options for each file individually - either written directly by yourself or generated by some other tools facilitating this such as cmake.

There is a way to differ between types of headers?

I'm working on a project that system headers can appear in "" and also in <>
for example: "io.h" and <io.h>
I need to determine if the included header is a customer one or not.
someone knows if there is a way to do it?
Aside from "asking the compiler", there is no trivial way to determine if "io.h" or <io.h> is taken from a local directory or somewhere in the standard headers. For example, a program will compile perfectly happily with #include "iostream".
The main difference is that the compiler will look FIRST in the local directory for the file "io.h" when using "io.h", where if you use <io.h> it will look in the include directories specified as "system include directories". However, there is nothing saying that system include directories does not include "current directory" in one way or another.
You can use g++ -M myfile.cpp to list what include files are used in the file "myfile.cpp". Unfortunately, as far as I can tell, there is no such option for Visual Studio.
Edit: The MS compiler does indeed support a similar feature using the /showinclude option.
Take a look to the documentation of your compiler, for example the MS C++ compiler will check system includes after local with quotes (so #include "io.h" will get the system include if there are no io.h local header files), but it won't look locally for angled brackets:
http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
I guess that you will have to manually check for project files if there are names collisions for include files.

Is it possible to force compiler to use the name of "working" directory to construct all full names from includes?

Let us assume that in first.h we have #include "aaa/second.h" and in the aaa/second.h we have #include "bbb/third.h". I think that in the "default settings" the compiler will complain if "third.h" is not located in "aaa/bbb".
Is it possible to change this behavior in such a way that the directory, in which the first.cpp is located is used to construct the full names in all includes?
For example, if "first.h" is located in '/home/bucky/' then #include "bbb/third.h" (from "aaa/second.h") should be interpreted as /home/bucky/bbb/third.h and not as /home/bucky/aaa/bbb/third.h.
EDITS
I cannot change the whole source code. In the code quotation marks are used instead of angle brackets.
I compile using g++ -std=c++0x name.cpp -o name in the command line. I do it in two different terminals. It looks like in the first terminal the working directory is used to construct the full names and in the second terminal it is not the case. I am almost sure that it happens because of the environment variables but I do not know which ones. So, my question is, to larger extent, what environment variables can force the compiler to construct full names using the working directory.
EDIT 2
In my test.cpp file I include "first.h". This inclusion does not cause any problem (complier sees "first.h"). The "first.h" file includes "ppp/second.h". It also causes no problems. But "ppp/second.h" includes "ppp/third.h" and this is the place where the problem appears. I think that the reason of the problem is that "second.h" tries to find "third.h" in the "ppp" subdirectory of the directory where second.h is located. In other words, second.h tries to find the third.h in the "ppp/ppp" subdirectory (because second.h is located in the ppp subdirectory).
In another terminal, the same compilation command, in the same directory does not cause any problem. The reason, is obviously in the values of the environment varibales.
Yes. The exact mechanics depend on the compiler but the short and the long of it is that you need to configure your compiler to include the project path in the search path. For GCC and clang that’s done via the -I command line flag (-I path/of/first.cpp). This configuration would usually be done in the project settings (if you’re working with an IDE), a Makefile or similar.
Since you’re talking about environment variables: the flags that are passed to the g++ and c++ compiler are controlled by the CXXFLAGS and CFLAGS variables.
You should set up include paths for your project globally. In your example, you would pass some option like -I /home/bucky to your compiler (if it is GCC or Clang). MSVC has analogous options.
(All #includes are searched relative to the include paths. The difference between <...> and "..." is that the latter also searches the current directory.)

Override default header search path

I'm currently trying to get a program to compile on a system that I don't have control over.
The problem that I'm having is the include directories look like this:
/usr/include:
gmpxx.h gmp.h
/usr/local/include:
gmp.h
In my cpp file, I use
#include <gmpxx.h>
and this finds the correct file in /usr/include, however when gmpxx.h includes gmp.h, it pulls it from /usr/local/include, which breaks the build.
Right now, I see 3 very ugly solutions to the problem
In my cpp file, add #include </usr/include/gmp.h>
Having an absolute include path is pretty ugly and non-portable, and I think that this sort of thing should belong in the Makefile instead of the source.
add the -nostdinc flag to my makefile, and specify the include paths by hand
create local symlinks to the libraries that I really want, and then do local includes (#include "gmp.h")
Is there a better solution that I'm missing?
The search paths for includes are taken in the following order:
The -I command-line option.
The CPLUS_INCLUDE_PATH environment variable.
The standard defaults.
So, you can use either of the first two (whichever seems better/more convenient for your purposes).
Remove gmp.h from /usr/local/include, or find out why you have a software distribution that wants to have gmp.h in /usr/local/include and remove the distribution. I think the problem is caused by you having for some reason two conflicting header file sets for GMP. If you have a standard installation of GMP development files on your system (/usr/include/...) there shouldn't be a reason to have another set of headers in /usr/local/include/.
There's no clean way to fix it otherwise, because you should include gmpxx.h using angle brackets
#include <gmpxx.h>
as you do. Now gmpxx.h includes gmp.h using angle brackets also, and on your system /usr/local/include takes precedence over /usr/include, which kind of makes sense.
So I'd recommend you to figure out why there are two gmp.h's and remove the spurious one. There is something fishy in your header file setup.
You can't easily resuffle /usr/include and /usr/local/include because they are considered system include directories and if you try to use -I on them, GCC will ignore the option.