5

If a C or CPP program needs to be compiled with our own header files with declarations and cpp files with definitions, we need to include the cpp files with definitions in the compilation command (See this answer). However, when we write #include <iostream>, we do not include iostream.cpp in the compilation statement like g++ main.cpp iostream.cpp -o main.

If we write our custom declaration files, for instance hello.hpp with class declaration and hello.cpp with the definitions, we need to compile it using g++ main.cpp hello.cpp -o main after including hello.hpp in the header in the main.cpp file. Why is this?

EDIT: Is it possible that we can imitate the behavior of the standard template library for our custom header and cpp files such that all we have to do is just include the header and the declarations automatically get compiled? If yes, then how? If no, why not?

Community
  • 1
  • 1
Sahil Arora
  • 875
  • 2
  • 8
  • 27
  • 6
    The linker automatically links with a default runtime library that contains all the functions in the standard headers. – Barmar Apr 18 '17 at 20:57
  • 5
    The STL is heavily templated, and so most of the STL's source code is in the header files themselves. For portions of the STL that are pre-compiled and not in the headers themselves, chances are your development environment has a default configuration to pull in the necessary libraries automatically during linking. – Remy Lebeau Apr 18 '17 at 20:57
  • 1
    *"Why ?"* I would say for convenience. – Jarod42 Apr 18 '17 at 21:01
  • In fact you *don't* necessarily need to include the C++ source file corresponding to a given header file in your compilation command, and under some common circumstances you want to be sure to avoid doing so. You can instead compile it separately to an object file, and link the object file into the final program. You can also build a library, put the compiled object inside, and link *that* to your program. – John Bollinger Apr 18 '17 at 21:04
  • 1
    Related (but not quite a duplicate IMO): http://stackoverflow.com/questions/25036467/g-why-dont-you-have-to-link-iostream-binaries-but-for-pthread-you-do – Oliver Charlesworth Apr 18 '17 at 21:04
  • @Barmar: I wouldn't call that a "runtime" library. It's just a library. It's not used at "runtime" any more than the OP's hello.cpp. (If anything, I would call the "runtime component" of C++ things like the dynamic cast implementation and the RTTI stuff.) – Kerrek SB Apr 18 '17 at 21:19
  • @KerrekSB What about things like `iostream` and math libraries? Those are used at runtime. The point is that there's a standard library that's linked automatically, you don't have to specify it explicitly like your own libraries and object files. – Barmar Apr 18 '17 at 21:24
  • @Barmar: Yeah, but by that logic *everything* is "runtime". I think that muddies the distinction with proper "runtimes", i.e. things that happen *without* explicitly appearing in your code: interpreters, garbage collectors, etc. In that sense, C and Rust are languages that don't *have* a runtime component, and C++ only has a very limited one for RTTI, dynamic_cast and exceptions. (Vectors and iostreams and printf are just "regular" libraries that you could have written yourself.) – Kerrek SB Apr 18 '17 at 21:33
  • 2
    @KerrekSB From [wikipedia](https://en.wikipedia.org/wiki/Runtime_library): *The runtime environment implements the execution model, built-in functions, and other fundamental behaviors of a programming language.* Things like `stdio` and `malloc` are part of the C runtime. – Barmar Apr 18 '17 at 21:43
  • When runtime is used as one word, it means something different than the phrase "run time", which is usually the opposite of "compile time". – David Grayson Apr 18 '17 at 21:45
  • @Barmar Can we replicate that behavior for custom header files, and is it a good practice? Also, how can we change / view the default behavior? – Sahil Arora Apr 18 '17 at 21:48
  • 1
    @SahilArora You might have to rebuild GCC to change its defaults. Why do you need to do this? Just use a makefile that specifies your library location. – Barmar Apr 18 '17 at 21:52
  • 1
    Answer is really simple. Because they have already been built. – Logman Apr 18 '17 at 22:10

3 Answers3

6

The standard libraries are being implicitly linked against. So

g++ main.cpp -o main

is really

g++ main.cpp -o main -lstdc++ -lc

where libstdc++ is the c++ standard library, and libc is the c standard library. Other libraries need to be explicitly linked against (such as libm).

This becomes more clear if you separate your compile and linking steps:

g++ -c main.cpp -o main.o
g++ -c other.cpp -o other.o
g++ main.o other.o /usr/lib/libstdc++.a /usr/lib/libc.a -o main

Here we compile our main() function definition and other definitions (other.cpp) into object files, and combine them with the existing compiled function/class/variable definitions in the standard libraries.

See TLDP's pages on Shared Library Creation and Static Library Creation for details on how definition files (.c and .cpp) are turned into libraries.

dlasalle
  • 1,615
  • 3
  • 19
  • 25
  • An edit has been made to the question, will you please have a look at that as well? – Sahil Arora Apr 18 '17 at 21:43
  • 1
    @SahilArora no, the compiler will not magically find a library containing your definitions sitting around somewhere in your computer. You need to tell him the path to your library so it can link it. You could although put everything in headers and Mark every functions as inline, but compilations times will explode the more stuff you put in your headers. – Guillaume Racicot Apr 19 '17 at 00:13
2

First of all, check the difference between including a <filename> and "filename" at this post:

For #include "filename" the preprocessor searches in the same directory as the file containing the directive. This method is normally used to include programmer-defined header files.

For #include < filename> the preprocessor searches in an implementation dependent manner, normally in search directories pre-designated by the compiler/IDE. This method is normally used to include standard library header files

The fact that you are including a file does not mean that you are compiling a file. In fact, by including your are solving the syntax references to the included file, like class declarations (in C++), common variables, structures, enums and funcion calls. This will avoid your code to get unreferenced object errors, breaking the compilation process.

Compiling your code with these references does not mean also that the original referenced code is compiled. Take the example below:

mycode.cpp includes myclass.hpp, as:

#include "myclass.hpp"

If the references are correct, you can compile it using:

g++ mycode.cpp 

You are gonna have a compiled code for mycode.cpp (an object file called mycode.o), but not the compiled code to myclass. The mycode.cpp compiled properly because it has the references to the myclass objects/functions/etc., but this does not mean that the myclass is compiled (you don´t have yet a object file myclass.o).

If you link edit mycode.cpp, there will be several missing references as there is no myclass compiled code.

If you choose:

g++ mycode.cpp myclass.cpp 

It will generate object files for both mycode.o and myclass.o, that later can be linked together.

In case of STL libraries, you just need the reference, as they are already compiled and available though in the so called standard library (a bundle of object .o files already compiled for you). The liker will take care of linking then together either automatically or if you properly tell him to do it.

I suggest you go through the compilation -> object files -> link editing -> executable file process to understand these steps, that happens only to compiled languages.

Mendes
  • 17,489
  • 35
  • 150
  • 263
1

You need to understand that the compiler reads input files, then pre-processes them and the preprocessor replaces all the #include statements so the compiler itself never sees them. As far as the real compiler is concerned, there are no #include statements. The compiler then converts the source language to machine code. There is one object file written by the compiler for every input (c or cpp) file. The machine code in the object files cannot be executed directly; it must be linked with other code.

Originally, programmers would link their programs with other object files that are already compiled into libraries of object files. Multiple object files were linked together statically to make an executable and that might be done for many executables. So in other words each of many object files might exist many times, once for each of many executables. And that means that when something changes, sometimes many programs using the same object files had to be linked again. Later programmers learned that it helps to link to object files dynamically, and that is what a dynamic link library is.

When you compile your program, the compiler includes instructions to the linker to link to other libraries, mainly the "C Runtime" (CRT). The link can be either a static link or a dynamic link. Also, the headers provides information about the CRT. Most of the Standard Libraries (std namespace) are actually in the headers, such as in "iostream" and get compiled with your program. Anything that is not in the header is in a CRT library somewhere.

So the equivalent of what might be a iostream.cpp is either in your own program, such as main.cpp, or has already been compiled and is in a CRT library that is linked with your program.

Sam Hobbs
  • 2,594
  • 3
  • 21
  • 32