How Does G++ Find Headers I Don't Have? - c++

I'm new to C++ and trying to understand how it is finding headers. Originally I was just trying to find out what classes are available for me to include in my source code. I believe that different compilers will use different include directories, and hence class availability will vary. My plan was to find the "include" directory that the compiler was using and assume I can include anything there. So I am just getting more confused as I go.
First, I am writing C++ code in Code::Blocks, on Windows 7. The IDE is set to use GNU GCC for compilation, which I learned means it uses the G++ compiler for C++ code. I found my compiler here: C:\MinGW\bin\mingw32-g++.exe, Code::Blocks settings point to that.
So I assumed that G++ must be using C:\MinGW\include recursively to find all its headers. To test my theory, I searched for "iostream.h". To my surprise, I do not even have "iostream.h" on my C drive. Despite that, my code compiles and works when I include that.
So my questions:
How is G++ finding the iostream header when my hard drive does not even have it?
Will all the standard C++ headers (as listed here: http://msdn.microsoft.com/en-us/library/ct1as7hw.aspx) be available to all C++ compilers? with the same exact name so I don't have to change my source code?

Regarding the second question, the standard does not require the headers to be available as files. It requires the #include directive to be present in the program and the compiler to behave as if the declarations that the standard required were present in the program. But the compiler is free to inject the declarations in any way it deems fit.
That being said, g++ in particular does have files backing up each one of the headers. Without knowing your particular configuration I cannot tell you where the headers will be but you can stop the compilation process after the preprocessor and examine the output:
$ cat test.cpp
#include <iostream>
int main() {
std::cout << "Hi\n";
}
$ g++ -E test.cpp | head -10
# 1 "test.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.cpp"
# 1 "/usr/include/c++/4.2.1/iostream" 1 3
# 42 "/usr/include/c++/4.2.1/iostream" 3
# 43 "/usr/include/c++/4.2.1/iostream" 3
The paths above are on a MacOSX Lion, and it shows that in this particular configuration iostream is included from /usr/include/c++/4.2.1/iostream. In windows head might not be available, but you can redirect the output to a file and read it from there.

Using quotation marks will search the current directory before moving to the ones it would search with angle brackets. There are other directories than the files listed in \include. That's where you'll find the ones without any extension. You may have a c++ folder in there with those files inside, but even searching for them from within the CodeBlocks directory using the Windows 7 search shows you where they're located.
Yes, they should all be accessible with the same name, using angle bracket includes to reach them. Of course there is always a small chance that some might be missing. If this is the case, that implementation would seem pretty unreliable from first sight. All major compilers today should definitely adhere to this.
To use your own headers with your classes in them, they should be in the same directory as the main cpp file, and you should use quotation includes.

1) The reason you can't find iostream.h is there's no such header, it's spelled iostream in standard C++. If you try #include <iostream.h> it will fail, so it isn't finding headers you don't have :)
If you run g++ -v test.cpp it will show all the paths it uses to look for headers when compiling test.cpp
2) Yes, they wouldn't be standard headers if they were missing or had different names depending on your compiler!

Answer 1: I've used Code::Blocks for very little time, but for what I remember in Dev-C++ and MSVC++, the headers are in the IDE's directory. (For example, my MSVC++ include directory is in C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include, and it HAS the iostream file.)
Answer 2: The most common header files are in the most common IDE's / compilers' set.
Tip: Did you not mean "iostream" instead of "iostream.h"?

Related

Why do projects use the -I include switch given the dangers?

Reading the fine print of the -I switch in GCC, I'm rather shocked to find that using it on the command line overrides system includes. From the preprocessor docs
"You can use -I to override a system header file, substituting your own version, since these directories are searched before the standard system header file directories."
They don't seem to be lying. On two different Ubuntu systems with GCC 7, if I create a file endian.h:
#error "This endian.h shouldn't be included"
...and then in the same directory create a main.cpp (or main.c, same difference):
#include <stdlib.h>
int main() {}
Then compiling with g++ main.cpp -I. -o main (or clang, same difference) gives me:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:194:0,
from /usr/include/stdlib.h:394,
from /usr/include/c++/7/cstdlib:75,
from /usr/include/c++/7/stdlib.h:36,
from main.cpp:1:
./endian.h:1:2: error: #error "This endian.h shouldn't be included"
So stdlib.h includes this types.h file, which on line 194 just says #include <endian.h>. My apparent misconception (and perhaps that of others) was that the angle brackets would have prevented this, but -I is stronger than I'd thought.
Though not strong enough, because you can't even fix it by sticking /usr/include in on the command line first, because:
"If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option is ignored. The directory is still searched but as a system directory at its normal position in the system include chain."
Indeed, the verbose output for g++ -v main.cpp -I/usr/include -I. -o main leaves /usr/include at the bottom of the list:
#include "..." search starts here:
#include <...> search starts here:
.
/usr/include/c++/7
/usr/include/x86_64-linux-gnu/c++/7
/usr/include/c++/7/backward
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
Color me surprised. I guess to make this a question:
What legitimate reason is there for most projects to use -I considering this extremely serious issue? You can override arbitrary headers on systems based on incidental name collisions. Shouldn't pretty much everyone be using -iquote instead?
What legitimate reasons are there for -I over -iquote? -I is standardized (at least by POSIX) while -iquote isn't. (Practically, I'm using -I because tinycc (one of the compilers I want my project to compile with) doesn't support -iquote.)
How do projects manage with -I given the dangers? You'd have the includes wrapped in a directory and use -I to add the directory containing that directory.
filesystem: includes/mylib/endian.h
command line: -Iincludes
C/C++ file: #include "mylib/endian.h" //or <mylib/endian.h>
With that, as long as you don't clash on the mylib name, you don't clash (at least as far header names are concerned).
Looking back at the GCC manuals it looks like -iquote and other options were only added in GCC 4: https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Directory-Options.html#Directory%20Options
So the use of "-I" is probably some combination of: habit, lazyness, backwards compatibility, ignorance of the new options, compatibility with other compilers.
The solution is to "namespace" your header files by putting them in sub directories. For example put your endian header in "include/mylib/endian.h" then add "-Iinclude" to the command line and you can #include "mylib/endian.h" which shouldn't conflict with other libraries or system libraries.
I this your premise that it's -I that's dangerous is false. The language leaves the search for header files with either form of #include sufficiently implementation-defined that it's unsafe to use header files that conflict with the names of the standard header files at all. Simply refrain from doing this.
An obvious case is cross-compilation. GCC suffers a bit from a historical UNIX assumption that you're always compiling for your local system, or at least something that's very close. That's why the compiler's header files are in the system root. The clean interface is missing.
In comparison, Windows assumes no compiler, and Windows compilers do not assume you're targeting the local system. That's why you can have a set of compilers and a set of SDK's installed.
Now in cross-compilation, GCC behaves much more like a compiler for Windows. It no longer assumes that you intend to use the local system headers, but lets you specify exactly which headers you want. And obviously, the same then goes for the libraries you link in.
Now note that when you do this, the set of replacement headers is designed to go on top of the base system. You can leave out headers in the replacement set if their implementation would be identical. E.g. chances are that <complex.h> is the same. There's not that much variation in complex number implementations. However, you can't randomly replace internal implementation bits like <endian.h>.
TL,DR : this option if for people who know what they're doing. "Being unsafe" is not an argument for the target audience.

How to make C/C++ compiler to look for headers in a user specified path

I'm using a library written by others which is kinda based on C for C++ usage -I think-. All inclusions used inside the headers or source files are in the form <> instead of "" even though they are not standard library files. My compiler doesn't recognize them and returns error "file not found"
An example of the problem is inside the following header:
#ifndef _ga_ga_h_
#define _ga_ga_h_
// Make sure that we get the configuration into each of the galib components
// that will be used.
#include <ga/gaconfig.h>
// These are the headers for all of the genetic algorithm classes.
#include <ga/GASimpleGA.h>
#include <ga/GASStateGA.h>
#include <ga/GAIncGA.h>
#include <ga/GADemeGA.h>
#include <ga/GADCrowdingGA.h>
// Here we include the headers for all of the various genome types.
#include <ga/GA1DBinStrGenome.h>
#include <ga/GA2DBinStrGenome.h>
#include <ga/GA3DBinStrGenome.h>
#include <ga/GABin2DecGenome.h>
I include that header inside my program using #include "ga.h" but it is very hard to change inside every header/source file in the library.
Is there a way to make the compiler use <> as if they were ""?
I tried adding the paths to "Addition include directories"from Project properties (I'm using Visual Studio), Many inclusions' errors disappeared but around 30 persisted. The strange thing is that they are in a file called "c1xx" but i don't have that file!!
thanks,
The definition is somewhat that <> is used for "system" header files, usually found in locations like /usr/include (on Unix-like systems) and "" is used for local header files. When you compile your code, you can indicate the location of additional directories containing header files e.g. using the -I option when using GCC. Check your compiler's documentation for the setting needed
So, e.g. on Linux and GCC, if your "ga" directory is in /usr/local/include/ga, you would use cc -I /usr/local/include.
This indeed looks like a problem of telling the compiler where to look for the included header files. As mentioned in the other answers, when you do a #include <header.h>, header.h must be in one of the include search paths - either the system includes, or the additional paths that you are telling the compiler to look for headers. In Linux/g++ (as mentioned in the other answers here), you do that by passing in the the additional search paths in the -I flag. The compilation command would look something like:
g++ -I/additional/header/search/path -o a.out your_file.cpp
Since you are using visual studio and the MSVC compiler, the equivalent would be the /I flag, and the compilation command would look something like:
CL /I\additional\header\path your_file.cpp
I am assuming you are using Visual Studio - you can also configure that from the project properties. Go to Configuration Properties > C/C++ > General and modify Additional Include Directories. Refer these for more info:
Setting C++ compiler and build properties
Additional include directories
First about the difference between <header> and <file>. The standards (both C and C++) only specifies that
#include <header>
includes an header named header and that
#include "file"
includes a source file named file, if none is found an header named file is included instead.
What are headers and how they differ from source files is left to the implementation. In practice they are files as well. So #include <header> is looking for a file in some places, #include "file" is looking for a file in some other places and if not found at the same places as for #include <file>.
AFAIK all compilers
are able to search for source files in the directory of the file containing the include directive
are able to be given a list of directories to search for headers before their default search path.
ISTR that Visual C++ is also searching for a source file in the directories of files indirectly including it. (I can't confirm currently if my memory is good; that behavior is AFAIK unachievable with other compilers so I never relied on it and -- by luck? -- it never resulted in a different behavior for my programs).
Obviously that behavior is more or less customizable. For instance with g++ is possible to:
disable the search of a source file in the directory of the file containing the include directive (with -I-, note that -I- is deprecated since gcc 4.0 -- 2005 -- when -iquote has been introduced and there is no non-deprecated way to achieve this)
to add a list of directories to search for source files and not for headers (with -iquote and it's an effect of -I- as well)
to give a list of directories to search for headers after the default list of directories (with -idirafter)
to give a list of directories to search for headers which are processed specially (with -isystem; less warnings are given for constructs in those files which help when using the "treat warnings as errors" flags, they aren't considered as dependencies with -MM and -MMD which usually is a nuisance)
Now for your problem. The library has been visibly designed to be used by adding the directory containing the directory ga to the include path. That should be enough as I'm unaware of any compiler modifying its search path for headers depending on how the file including the header has been included.
Note that c1xx is probably the name of the compiler executable, not the name of a file trying to include another (again, I'm not in position to ensure that's the case now, but compare with cc1plus which is the name of the compiler for GCC -- g++ is a driver handling several things and executing cc1plus to handle the compilation of C++ code)
If you do on the command line:
echo | gcc -v -E -x c++ -
You will get an output with the default include directories for C++. Those are the built in system's include search paths.
If you compile with g++ -I/some/dir -o foo foo.cpp, you are adding an additional include search path (/some/dir) to the compilation.
Headers in the above locations can be found by include directives like #include <header>. #include "header" directives can also find headers in those locations, but they are more relevant for the following case.
When you do #include "header", your compiler will first try to find "header" relative to the directory of foo.cpp if it includes it, despite foo.cpp directory being in search paths or not. If it doesn't find it there, it will try to look up in the include search paths. So this one is more relevant for headers that are more tied to a specific .cpp file and you don't want additional include search paths added to the compilation, or if you prefer to use include directives with relative paths.
So if you use #include <header>, header must be in some of the include search paths, system or /some/dir from -I flag. If header is relative to foo.cpp, but not in search paths, compilation will fail.
If you use #include "header" and header is not in any of the include search paths, it can still be found relative to foo.cpp location.

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.)

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

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.

Handling stdafx.h in cross-platform code

I have a Visual Studio C++ based program that uses pre-compiled headers (stdafx.h). Now we are porting the application to Linux using gcc 4.x.
The question is how to handle pre-compiled header in both environments.
I've googled but can not come to a conclusion.
Obviously I want leave stdafx.h in Visual Studio since the code base is pretty big and pre-compiled headers boost compilation time.
But the question is what to do in Linux. This is what I found:
Leave the stdafx.h as is. gcc compiles code considerable faster than VC++ (or it is just my Linux machine is stronger ... :) ), so I maybe happy with this option.
Use approach from here - make stdafx.h look like (set USE_PRECOMPILED_HEADER for VS only):
#ifdef USE_PRECOMPILED_HEADER
... my stuff
#endif
Use the approach from here - compile VC++ with /FI to implicitly include stdafx.h in each cpp file. Therefore in VS your code can be switched easily to be compiled without pre-compiled headers and no code will have to be changed.
I personally dislike dependencies and the mess stdafx.h is pushing a big code base towards. Therefore the option is appealing to me - on Linux you don't have stdafx.h, while still being able to turn on pre-compiled headers on VS by /FI only.
On Linux compile stdafx.h only as a precompiled header (mimic Visual Studio)
Your opinion? Are there other approaches to treat the issue?
You're best off using precompiled headers still for fastest compilation.
You can use precompiled headers in gcc as well. See here.
The compiled precompiled header will have an extension appended as .gch instead of .pch.
So for example if you precompile stdafx.h you will have a precompiled header that will be automatically searched for called stdafx.h.gch anytime you include stdafx.h
Example:
stdafx.h:
#include <string>
#include <stdio.h>
a.cpp:
#include "stdafx.h"
int main(int argc, char**argv)
{
std::string s = "Hi";
return 0;
}
Then compile as:
> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out
Your compilation will work even if you remove stdafx.h after step 1.
I used option 3 last time I needed to do this same thing. My project was pretty small but this worked wonderfully.
I'd either go for option 4 or option 2. I've experimented with precompiled headers on both various VS versions and GCC on Linux (blog posts about this here and here). In my experience, VS is a lot more sensitive to the length of the include paths, number of directories in the include path and the number of include files than G++ is. When I measured build times properly arranged precompiled headers would make a massive difference to the compile time under VS whereas G++ was pretty much unimpressed by this.
Actually, based on the above what I did the last time I worked on a project where this was necessary to rein in the compile time was to precompile the equivalent of stdafx.h under Windows where it made sense and simply used it as a regular file under Linux.
Very simple solution.
Add a dummy file entry for "stdafx.h" in Linux environment.
I would only use option 1 in a big team of developers.
Options 2, 3, and 4 will often halt the productivity of other members of your team, so you can save a few minutes a day in compile time.
Here's why:
Let's assume that half of your developers use VS and half use gcc.
Every now and then some VS developer will forget to include a header in a .cpp file.
He won't notice, because the stdafx.h implicitly includes it. So, he pushes his changes in the version control, and then a few other members of the gcc team will get compiler errors.
So, for every 5 minutes-a-day you gain by using precompiled headers, 5 other people waste by fixing your missing headers.
If you don't share the same code across all of your compilers, you will run into problems like that every day. If you force your VS developers to check for compilation on gcc before pushing changes, then you will throw away all your productivity gains from using precompiled headers.
Option 4 sounds appealing, but what if you want to use another compiler at some point in time ? Option 4 only works if you only use VS and gcc.
Notice that option 1 may make gcc compilation suffer a few seconds. Although it may not be noticeable.
It's simple, really:
Project->Project Settings (Alt + F7)
Project-Settings-Dialog:
C++ -> Category: Precompiled Headers -> Precompiled Headers radio buttons --> disable
Since stdafx.h is by default all the Windows-specific stuff, I've put an empty stdafx.h on my other platform. That way your source code stays identical, while effectively disabling stdafx on Linux without having to remove all the #include "stdafx.h" lines from your code.
If you are using CMake in your project, then there are modules which automate it for you, very convenient, for example see cmake-precompiled-header here. To use it just include the module and call:
include( cmake-precompiled-header/PrecompiledHeader.cmake )
add_precompiled_header( ${target} ${header} FORCEINCLUDE SOURCE_CXX ${source} )
Another module called Cotire creates the header file to be precompiled (no need to manually write StdAfx.h) and speeds up builds in other ways - see here.
I've done both option 2 (#ifdef) and option 4 (PCH for gcc) for cross platform code with no issues.
I find gcc compiles much faster than VS so the precompiled headers are generally not that important, unless you are referencing some huge header file.
I have a situation where #2 in particular didn't work for me (There are numerous VS build configs where a #ifdef around #include "stdafx.h" does not work). Other solutions were suboptimal because the files themselves were cross-project as well as being cross-platform. I did not want to force preprocessor macros to be set or force linux or even windows builds to use (or not use) pch, so...
What I did, given a file named notificationEngine.cpp, for example, was removed the #include stdafx.h line entirely, created a new file in the same directory called pchNotificationEngine.cpp with the following contents:
#include "stdafx.h"
#include "notificationEngine.cpp"
Any given project can just include the correct version of the file. This admittedly is probably not the best option for cpp files that are only used by a single project.