Skip to content

Cpp Build

Pavel I. Kryukov edited this page Sep 23, 2017 · 1 revision

Introduction

Source codes of programs are usually separated to several files. It improves readability of code, increases speed of rebuild, because you have to rebuild only few files; also it is more convinient for version control systems like SVN or Git.

The drawback is increased complexity of the build process. This wiki page will describe the most "popular" problems and common ways of solution.


Types of C++ source and binary files

C++ source codes are divided in 2 big groups: headers an translated files. Translated files can be compiled to objective files, that can be linked together to binary file. Table below show common file extensions

Type File extensions
Header .h, .hpp
Translated files .c, .cxx, .cpp, .cc
Objective files Windows: .obj
Linux: .o
Executables Windows: .exe
Linux: .out, no extension
Static libraries Windows: .lib
Linux: .a
Dynamic libraries Windows: .dll
Linux: .so

Headers

Headers are not compiled. They are needed just to declare classes, methods and functions that can be common for another headers and translated files. Header's content can be added to them with #include preprocessor directive.

#include directive

There are two options to include source files:

   #include <filename>
   #include "filename"

First directive will find a file to include in directories that are specified by compiler options, so this method is commonly used for libraries headers, like STL or Boost, but your are able to provide more pathes to compiler using -I option:

   gcc file.c -I/home/my/includes/

Second directive will find a file in current directory. This method should be used to include headers from your projects. So, usually including code looks like:

   #include <cstdio>
   #include <cstring> // C headers firstly

   #include <vector>
   #include <iostream> // C++ headers than

   #include <boost/filesystem.hpp>
   #include <libelf.h> // External libraries than

   #include "perfsim.h"
   #include "top/def.h" // Local after all

Include protectors

Imagine that your project have two header files, a.h and b.h. After expansion of preprocessor directives, you may face that a.h must include b.h, and b.h must include a.h. To avoid infinite recursion, special trick of include protectors is widely used.

Note: Usually this problem is not detected even by modern compilers and it is hard to understand by compiler logs.

Source code in headers should look like:

  /*
   * Copyright info, brief desciption etc.
   */

  #ifndef _UNIQUE_HEADER_NAME_
  #define _UNIQUE_HEADER_NAME_

  /* 
   * Code itself
   */

  #endif // _UNIQUE_HEADER_NAME_
Warning: Macrovariable _UNIQUE_HEADER_NAME_ must be unique for each .h file. It's strongly recommended to name it like file name, e.g. simulator.h should have _SIMULATOR_H_ protector.

This macro will gurantee that each header's content will be included only once.


Translated files

Translated files are compiled independently. If you have correct header files, you are able to compile main.cpp file to main.o, wait 2 hours and than compile function.cpp to function.o.

GCC builds objective file by command:

   g++ file.cc -c -o file.o

but usually more good arguments are passed, like this:

   g++ file.cc -c -O2 -Wall -Werror -std=c++03 -o file.o

Objective files and linking

Objective files contain binary code that can be run directly on target machine. One objective file correspondes to one translated file.

But, .o is not a complete program, some code that is called from objective file is contained in other objective file or in library, file contains only a link to this code. The process of combining of objective files is called linkage and performed by linker.

Common linker for GNU\Linux environment is ld, but command gcc can be used instead:

    gcc funcsim.o memory.o decoder.o -o funcsim.out

Executable files

Executable files can be launched by OS, e.g. by user command. Therefore, one of source objectives should define entry point — int main(int, char**) method, otherwise linker won't be able to complete linkage.


Static libraries

Static library is a merged objective file that can be linked during compilation of executables or other libraries. To produce it, following flow should be completed:

   gcc -c archsim.cpp -o archsim.o
   gcc -c decoder.cpp -o decoder.o
   gcc decoder.o archsim.o -o libarch.o
   ar rcs libarch.a libarch.o

After you may link this library to your program with -l<libname> flag:

   gcc simulator.cpp –larch -o arch_simulator
Note that all libraries that are used by GCC should have libname.a name!

You can provide to GCC a path where it should find static library with -L option:

   gcc simulator.cpp –larch -o arch_simulator -L/usr/bin/libs

Dynamic libraries

Note: Dynamic libraries are not used in our project, we will skip them.
Clone this wiki locally