The C++ build pipeline
DECLARATIONS AND DEFINITIONS IN three EXAMPLES
1.
2.
3.
DEclarations
Definitions
int main()
{
sqr(3);
}
int sqr(int x)
{
return x * x;
}
main.cpp
int sqr(int x)
{
return x * x;
}
int main()
{
sqr(3);
}
main.cpp
main.cpp
int sqr(int);
int main()
{
sqr(3);
}
int sqr(int x)
{
return x * x;
}
HOW TO USE MULTIPLE FILES IN C++?
MULTIPLE FILES
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
int main()
{
sqr(3);
cube(2);
}
main.cpp
1.
2.
HOW TO USE MULTIPLE FILES IN C++?
MULTIPLE FILES
int sqr(int);
int cube(int);
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
int main()
{
sqr(3);
cube(2);
}
main.cpp
1.
2.
HOW TO USE MULTIPLE FILES IN C++?
MULTIPLE FILES
int sqr(int);
int cube(int);
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
2.
#include "math.h"
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
3.
int sqr(int);
int cube(int);
math.h
HOW TO USE MULTIPLE FILES IN C++?
MULTIPLE FILES
Header Files
Source Files
(DEclarations)
(Definitions)
#include "math.h"
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
int sqr(int);
int cube(int);
math.h
HOW TO USE MULTIPLE FILES IN C++?
MULTIPLE FILES
Header Files
Source Files
(DEclarations)
(Definitions)
math.h io.h utility.h error.h net.h log.h
math.cpp io.cpp utility.cpp error.cpp net.cpp log.cpp
main.cpp
THE one definition rule - the reason for headers
O
R
D
#include "math.cpp"
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
THE one definition rule - the reason for headers
O
R
D
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
THE one definition rule - the reason for headers
O
R
D
#include "math.cpp"
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
int sqr(int);
int cube(int);
math.h
THE one definition rule - the reason for headers
O
R
D
#include "math.h"
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
int sqr(int);
int cube(int);
math.h
THE one definition rule - the reason for headers
O
R
D
int sqr(int);
int cube(int);
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int x)
{
return x * x;
}
int cube(int x)
{
return x * x * x;
}
math.cpp
int sqr(int);
int cube(int);
math.h
int sqr(int);
int cube(int);
shapes.h
namespaces
#include "math.h"
#include "shapes.h"
int main()
{
sqr(3);
cube(2);
}
main.cpp
int sqr(int);
int cube(int);
math.h
int sqr(int);
int cube(int);
shapes.h
...
math.cpp
...
shapes.cpp
namespaces
#include "math.h"
#include "shapes.h"
int main()
{
math_sqr(3);
shapes_cube(2);
}
main.cpp
int math_sqr(int);
int math_cube(int);
math.h
int shapes_sqr(int);
int shapes_cube(int);
shapes.h
...
math.cpp
...
shapes.cpp
namespaces
#include "math.h"
#include "shapes.h"
int main()
{
math::sqr(3);
shapes::cube(2);
}
main.cpp
namespace math {
int sqr(int);
int cube(int);
}
math.h
namespace shapes {
int sqr(int);
int cube(int);
}
shapes.h
...
math.cpp
...
shapes.cpp
namespaces
#include "math.h"
#include "shapes.h"
int main()
{
math::sqr(3);
shapes::cube(2);
}
main.cpp
namespace math {
int sqr(int);
int cube(int);
}
math.h
namespace shapes {
int sqr(int);
int cube(int);
}
shapes.h
...
math.cpp
...
shapes.cpp
namespace std {
istream cin;
ostream cout;
...
}
iostream
namespaces
#include "math.h"
#include "shapes.h"
using namespace math;
int main()
{
sqr(3);
shapes::cube(2);
}
main.cpp
namespace math {
int sqr(int);
int cube(int);
}
math.h
namespace shapes {
int sqr(int);
int cube(int);
}
shapes.h
...
math.cpp
...
shapes.cpp
namespace std {
istream cin;
ostream cout;
...
}
iostream
namespaces
#include "math.h"
#include "shapes.h"
int main()
{
using namespace math;
sqr(3);
shapes::cube(2);
}
int func(int x)
{
math::sqr(3);
}
main.cpp
namespace math {
int sqr(int);
int cube(int);
}
math.h
namespace shapes {
int sqr(int);
int cube(int);
}
shapes.h
...
math.cpp
...
shapes.cpp
namespace std {
istream cin;
ostream cout;
...
}
iostream
The C++ build pipeline
What is
?
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Compiler
Linker
Assembler
Preprocessor
The C++ build pipeline
What is
?
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Compiler
Linker
Assembler
Preprocessor
Source Files
Preprocessed Code
Object
Files
Static
Libraries
Executable
File
Dynamic
Libraries
Library
Header
Files
Header Files
HOW IS A C++ program STRUCTURED?
Source Files
Header Files
Internal
Compile-time
Runtime
Resource Files
Textures, Audio
Config Files
...
Static Libraries
Dynamic Libraries
Library Header Files
EXternal
Compile-time
Runtime
Resource Files
Textures, Audio
...
The C++ build pipeline
What is
?
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Compiler
Linker
Assembler
Preprocessor
Preprocessor
#ifndef HEADER_GUARD
#define HEADER_GUARD
#include <type_traits>
#include "myheader.h"
#define PI 3.1415926
#define ERROR_MSG "Exception access violation"
#define ADD(ARG1, ARG2) ((ARG1) + (ARG2))
#define STRINGIFY(ARG1) #ARG1
#define CONCAT(ARG1, ARG2) ARG1 ## ARG2
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#ifdef __APPLE__
#include "apple_specific.h"
#elif __linux__
#include "linux_specific.h"
#elif _WIN32
#include "windows_specific.h"
#else
#error Unsupported platform
#endif
#line 42
#endif // HEADER_GUARD
- Header guards
- Includes
- Constants
- Compile-time computation
- Source code transformation
- Cross-platform compatibility
- Platform detection
- Conditional compilation
- Reporting compilation errors
- Code generation support
Preprocessor
#include <iostream>
#define SQR(x) x * x
int main()
{
std::cout << SQR(2);
}
Preprocessor
#include <iostream>
#define SQR(x) x * x
int main()
{
std::cout << 2 * 2;
}
Preprocessor
#include <iostream>
#define SQR(x) x * x
int main()
{
std::cout << SQR(2 + 3);
}
Preprocessor
#include <iostream>
#define SQR(x) x * x
int main()
{
std::cout << 2 + 3 * 2 + 3;
}
Preprocessor
#include <iostream>
#define SQR(x) x * x
int main()
{
std::cout << 2 + 3 * 2 + 3;
//std::cout << (2 + 3) * (2 + 3);
}
Preprocessor
#include <iostream>
#define SQR(x) ((x) * (x))
int main()
{
std::cout << SQR(2 + 3);
}
Preprocessor
#include <iostream>
#define SQR(x) ((x) * (x))
int main()
{
std::cout << ((2 + 3) * (2 + 3));
}
Preprocessor
#include <iostream>
#define SQR(x) ((x) * (x))
int main()
{
int x = 3;
std::cout << SQR(++x);
}
Preprocessor
#include <iostream>
#define SQR(x) ((x) * (x))
int main()
{
int x = 3;
std::cout << ((++x) * (++x));
}
Preprocessor
#include <iostream>
#define SQR(x) ((x) * (x))
int main()
{
int x = 3;
std::cout << ((++x) * (++x));
//std::cout << 20;
}
Preprocessor
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1
#pragma GCC system_header
#include <bits/c++config.h>
#include <ostream>
#include <istream>
namespace std
{
extern istream cin;
extern ostream cout;
extern ostream cerr;
extern ostream clog;
#ifdef _GLIBCXX_USE_WCHAR_T
extern wistream wcin;
extern wostream wcout;
extern wostream wcerr;
extern wostream wclog;
#endif
static ios_base::Init __ioinit;
} // namespace std
#endif /* _GLIBCXX_IOSTREAM */
Preprocessor
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1
#pragma GCC system_header
#include <bits/c++config.h>
#include <ostream>
#include <istream>
namespace std
{
extern istream cin;
extern ostream cout;
extern ostream cerr;
extern ostream clog;
#ifdef _GLIBCXX_USE_WCHAR_T
extern wistream wcin;
extern wostream wcout;
extern wostream wcerr;
extern wostream wclog;
#endif
static ios_base::Init __ioinit;
} // namespace std
#endif /* _GLIBCXX_IOSTREAM */
int main()
{
std::cout << "Hello World!\n";
}
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1
#pragma GCC system_header
#include <bits/c++config.h>
#include <ostream>
#include <istream>
namespace std
{
extern istream cin;
extern ostream cout;
extern ostream cerr;
extern ostream clog;
#ifdef _GLIBCXX_USE_WCHAR_T
extern wistream wcin;
extern wostream wcout;
extern wostream wcerr;
extern wostream wclog;
#endif
static ios_base::Init __ioinit;
} // namespace std
#endif /* _GLIBCXX_IOSTREAM */
Compiler
Preprocessor
...
int main()
{
std::cout << "Hello World!\n";
}
Compiler
The C++ build pipeline
What is
?
...
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Compiler
Linker
Assembler
Preprocessor
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Compiler
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Compiler
main: # @main
push rax
mov edi, offset _ZSt4cout
mov esi, offset .L.str
mov edx, 13
call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
xor eax, eax
pop rcx
ret
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
push rax
mov edi, offset _ZStL8__ioinit
call _ZNSt8ios_base4InitC1Ev
mov edi, offset _ZNSt8ios_base4InitD1Ev
mov esi, offset _ZStL8__ioinit
mov edx, offset __dso_handle
pop rax
jmp __cxa_atexit # TAILCALL
.L.str:
.asciz "Hello World!\n"
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Compiler
$ ./a.out
Hello World!
$
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Compiler
$ ./a.out
Hello World!
$
=
=
01010111011010101010101010101010101010100100101110100000010101010101000001111101010110101010101010100001011111001010111011010101010101010101010101010100100101110100001010110101010101010100001011111001010111011010101010101010101010101010100100101110100001011010100001011111010100111000011100101110101001000011011001010111110010011101010111101001000101011110101101010101010101101010101010110111110100011110100101110000101100101011100101001110
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Compiler
01010111011010101010101010101010101010100100101110100000010101010101000001111101010110101010101010100001011111001010111011010101010101010101010101010100100101110100001010110101010101010100001011111001010111011010101010101010101010101010100100101110100001011010100001011111010100111000011100101110101001000011011001010111110010011101010111101001000101011110101101010101010101101010101010110111110100011110100101110000101100101011100101001110
$ ./a.out
Hello World!
$
Compiler
01010111011010101010101010101010101010100100101110100000010101010101000001111101010110101010101010100001011111001010111011010101010101010101010101010100100101110100001010110101010101010100001011111001010111011010101010101010101010101010100100101110100001011010100001011111010100111000011100101110101001000011011001010111110010011101010111101001000101011110101101010101010101101010101010110111110100011110100101110000101100101011100101001110
ff 25 da 2f 00 00
68 01 00 00 00
e9 df 00 00 00
ff 25 d2 2f 00 00
...
main: # @main
push rax
mov edi, offset _ZSt4cout
mov esi, offset .L.str
mov edx, 13
call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
xor eax, eax
pop rcx
ret
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
push rax
mov edi, offset _ZStL8__ioinit
call _ZNSt8ios_base4InitC1Ev
mov edi, offset _ZNSt8ios_base4InitD1Ev
mov esi, offset _ZStL8__ioinit
mov edx, offset __dso_handle
pop rax
jmp __cxa_atexit # TAILCALL
.L.str:
.asciz "Hello World!\n"
$ ./a.out
Hello World!
$
Compiler
01010111011010101010101010101010101010100100101110100000010101010101000001111101010110101010101010100001011111001010111011010101010101010101010101010100100101110100001010110101010101010100001011111001010111011010101010101010101010101010100100101110100001011010100001011111010100111000011100101110101001000011011001010111110010011101010111101001000101011110101101010101010101101010101010110111110100011110100101110000101100101011100101001110
ff 25 da 2f 00 00
68 01 00 00 00
e9 df 00 00 00
ff 25 d2 2f 00 00
...
main: # @main
push rax
mov edi, offset _ZSt4cout
mov esi, offset .L.str
mov edx, 13
call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
xor eax, eax
pop rcx
ret
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
push rax
mov edi, offset _ZStL8__ioinit
call _ZNSt8ios_base4InitC1Ev
mov edi, offset _ZNSt8ios_base4InitD1Ev
mov esi, offset _ZStL8__ioinit
mov edx, offset __dso_handle
pop rax
jmp __cxa_atexit # TAILCALL
.L.str:
.asciz "Hello World!\n"
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Assembler
$ ./a.out
Hello World!
$
Compiler
01010111011010101010101010101010101010100100101110100000010101010101000001111101010110101010101010100001011111001010111011010101010101010101010101010100100101110100001010110101010101010100001011111001010111011010101010101010101010101010100100101110100001011010100001011111010100111000011100101110101001000011011001010111110010011101010111101001000101011110101101010101010101101010101010110111110100011110100101110000101100101011100101001110
ff 25 da 2f 00 00
68 01 00 00 00
e9 df 00 00 00
ff 25 d2 2f 00 00
...
main: # @main
push rax
mov edi, offset _ZSt4cout
mov esi, offset .L.str
mov edx, 13
call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
xor eax, eax
pop rcx
ret
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
push rax
mov edi, offset _ZStL8__ioinit
call _ZNSt8ios_base4InitC1Ev
mov edi, offset _ZNSt8ios_base4InitD1Ev
mov esi, offset _ZStL8__ioinit
mov edx, offset __dso_handle
pop rax
jmp __cxa_atexit # TAILCALL
.L.str:
.asciz "Hello World!\n"
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Assembler
Linker
Compiler
01010111011010101010101010101010101010100100101110100000010101010101000001111101010110101010101010100001011111001010111011010101010101010101010101010100100101110100001010110101010101010100001011111001010111011010101010101010101010101010100100101110100001011010100001011111010100111000011100101110101001000011011001010111110010011101010111101001000101011110101101010101010101101010101010110111110100011110100101110000101100101011100101001110
ff 25 da 2f 00 00
68 01 00 00 00
e9 df 00 00 00
ff 25 d2 2f 00 00
...
main: # @main
push rax
mov edi, offset _ZSt4cout
mov esi, offset .L.str
mov edx, 13
call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
xor eax, eax
pop rcx
ret
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
push rax
mov edi, offset _ZStL8__ioinit
call _ZNSt8ios_base4InitC1Ev
mov edi, offset _ZNSt8ios_base4InitD1Ev
mov esi, offset _ZStL8__ioinit
mov edx, offset __dso_handle
pop rax
jmp __cxa_atexit # TAILCALL
.L.str:
.asciz "Hello World!\n"
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Assembler
Linker
The C++ build pipeline
What is
?
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Compiler
Linker
Assembler
Preprocessor
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
Linker
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Linker
The C++ build pipeline
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
$ ./a.out
Hello World!
$
Compiler
Linker
Assembler
Preprocessor
Source Files
Preprocessed Code
Object
Files
Static
Libraries
Executable
File
Dynamic
Libraries
Library
Header
Files
Header Files
The C++ Build Pipeline
By Jan Bielak
The C++ Build Pipeline
A presentation about the C++ build pipeline. It is presented here: https://www.youtube.com/watch?v=Ev8DrjtBtNg .
- 674