Modern C++ for
Computer Vision and
Image Processing
Lecture 1: Build and Tools
Ignacio Vizzo and Cyrill Stachniss
SW dev ecosystem
                   1
The compilation
    process
What is a compiler?
 A compiler is basically... a program.
 But not any program.
 Is in charge on transforming your horrible
 source code into binary code.
 Binary code, 0100010001, is the language
 that a computer can understand.
                                              2
What is a compiler?
                      3
Compilation made easy
The easiest compile command possible:
  clang++ main.cpp
  This will build a program called a.out that
  it’s ready to run.
Will be always this easy?
 Of course, not.
                                                4
The Compiler: Behind the scenes
The compiler performs 4 distinct actions
to build your code:
1. Pre-process
2. Compile
3. Assembly
4. Link
                                           5
The Compiler: Behind the scenes
                              6
Compiling step-by-step
1. Preprocess:
  clang++ -E main.cpp > main.i
                                 7
Compiling step-by-step
2. Compilation:
  clang++ -S main.i
                         8
Compiling step-by-step
3. Assembly:
  clang++ -c main.s
                         9
Compiling step-by-step
4. Linking:
  clang++ main.o -o main
                           10
  Compiling recap
1. clang++ -E main.cpp
2. clang++ -S main.i
3. clang++ -c main.s
4. clang++ main.o
                         11
  Compiling recap
1. clang++ main.cpp
                      12
Compilation flags
     There is a lot of flags that can be passed
     while compiling the code
     We have seen some already:
     -std=c++17, -o, etc.
Other useful options:
  Enable all warnings, treat them as errors:
  -Wall, -Wextra, -Werror
  Optimization options:
          -O0 — no optimizations [default]
          -O3 or -Ofast — full optimizations
     Keep debugging symbols: -g
 0
     Play with them with Compiler Explorer: https://godbolt.org/
                                                                   13
Libraries
What is a Library
 Collection of symbols.
 Collection of function implementations.
                                           14
Libraries
 Library: multiple object files that are
 logically connected
 Types of libraries:
   Static: faster, take a lot of space, become part
   of the end binary, named: lib*.a
   Dynamic: slower, can be copied, referenced by a
   program, named lib*.so
 Create a static library with
 ar rcs libname.a module.o module.o …
 Static libraries are just archives just like
 zip/tar/…
                                                  15
Declaration and definition
 Function declaration can be separated from
 the implementation details
 Function declaration sets up an interface
1 void FuncName (int param);
 Function definition holds the
 implementation of the function that can
 even be hidden from the user
1 void FuncName (int param) {
2   // Implementation details .
3   cout << "This function is called FuncName ! ";
4   cout << "Did you expect anything useful from it?";
5 }
                                                         16
Header / Source Separation
     Move all declarations to header files (*.hpp)
     Implementation goes to *.cpp or *.cc
 1   // some_file .hpp
 2   Type SomeFunc (... args ...);
 3
 4   // some_file .cpp
 5   # include " some_file .hpp"
 6   Type SomeFunc (... args ...) {}   // implementation
 7
 8   // program .cpp
 9   # include " some_file .hpp"
10   int main () {
11      SomeFunc (/* args */);
12      return 0;
13   }
                                                           17
    Just build it as before?
    clang++ -std=c++17 program.cpp -o main
    Error:
1   /tmp/ tools_main -0 eacf5.o: In function `main ':
2   tools_main .cpp: undefined reference to `SomeFunc ()'
3   clang : error: linker command failed with exit code 1
4   (use -v to see invocation )
                                                            18
What is linking?
                   19
What is linking?
 The library is a binary object that contains
 the compiled implementation of some
 methods
 Linking maps a function declaration to its
 compiled implementation
 To use a library we need:
 1. A header file library_api.h
 2. The compiled library object libmylibrary.a
                                                 20
  How to build libraries?
1 folder /
2     --- tools.hpp
3     --- tools.cpp
4     --- main.cpp
 Short: we separate the code into modules
 Declaration: tools.hpp
1 # pragma once // Ensure file is included only once
2 void MakeItSunny ();
3 void MakeItRain ();
                                                       21
    How to build libraries?
    Definition: tools.cpp
1   # include " tools .hpp"
2   # include <iostream >
3   void MakeItRain () {
4      // important weather manipulation code
5      std :: cout << "Here! Now it rains ! Happy ?\n";
6   }
7   void MakeItSunny () { std :: cerr << "Not available \n"; }
    Calling: main.cpp
1 # include " tools .hpp"
2 int main () {
3    MakeItRain ();
4    MakeItSunny ();
5    return 0;
6 }
                                                                 22
Use modules and libraries!
Compile modules:
c++ -std=c++17 -c tools.cpp -o tools.o
Organize modules into libraries:
ar rcs libtools.a tools.o <other_modules>
Link libraries when building code:
c++ -std=c++17 main.cpp -L . -ltools -o main
Run the code:
./main
                                               23
Build Systems
Building by hand is hard
 4 commands to build a simple hello world
 example with 2 symbols.
 How does it scales on big projects?
 Impossible to mantain.
 Build systems to the rescue!
                                            24
What are build systems
 Tools.
 Many of them.
 Automate the build process of projects.
 They began as shell scripts
 Then turn into MakeFiles.
 And now into MetaBuild Sytems like CMake.
   Accept it, CMake is not a build system.
   It’s a build system generator
   You need to use an actual build system like Make
   or Ninja.
                                                      25
  What I wish I could write
 Replace the build commands:
 1. c++ -std=c++17 -c tools.cpp -o tools.o
 2. ar rcs libtools.a tools.o <other_modules>
 3. c++ -std=c++17 main.cpp -L . -ltools
 For a script in the form of:
1 add_library (tools tools.cpp)
2 add_executable (main main.cpp)
3 target_link_libraries (main tools)
                                                26
Use CMake to simplify the build
 One of the most popular build tools
 Does not build the code, generates files to
 feed into a build system
 Cross-platform
 Very powerful, still build receipt is readable
                                              27
Build a CMake project
 Build process from the user’s perspective
 1.   cd <project_folder>
 2.   mkdir build
 3.   cd build
 4.   cmake ..
 5.   make
 The build process is completely defined in
 CMakeLists.txt
 And childrens src/CMakeLists.txt, etc.
                                              28
     First CMakeLists.txt
 1   cmake_minimum_required ( VERSION 3.1) # Mandatory .
 2   project ( first_project )             # Mandatory .
 3   set( CMAKE_CXX_STANDARD 17)           # Use c ++17.
 4
 5   # tell cmake where to look for *.hpp , *.h files
 6   include_directories ( include /)
 7
 8   # create library " libtools "
 9   add_library (tools src/tools.cpp) # creates libtools .a
10
11   # add executable main
12   add_executable (main src/ tools_main .cpp) # main.o
13
14   # tell the linker to bind these objects together
15   target_link_libraries (main tools) # ./ main
                                                               29
CMake is easy to use
 All build files are in one place
 The build script is readable
 Automatically detects changes
 After doing changes:
 1. cd <project_folder>/build
 2. make
                                    30
     Typical project structure
 1   |--   project_name /
 2   |     |-- CMakeLists .txt
 3   |     |-- build/     # All generated build files
 4   |     |-- results / # Executable artifacts
 5   |     |   |-- bin/
 6   |     |        |-- tools_demo
 7   |     |   |-- lib/
 8   |     |        |-- libtools .a
 9   |     |-- include / # API of the project
10   |     |   |-- project_name
11   |     |        |-- library_api .hpp
12   |     |-- src/
13   |     |   |-- CMakeLists .txt
14   |     |   |-- project_name
15   |     |        |-- CMakeLists .txt
16   |     |        |-- tools.hpp
17   |     |        |-- tools.cpp
18   |     |        |-- tools_demo .cpp
19   |     |-- tests/ # Tests for your code
20   |     |   |-- test_tools .cpp
21   |     |   |-- CMakeLists .txt
22   |     |-- README .md # How to use your code
                                                        31
    Compilation options in CMake
1   set( CMAKE_CXX_STANDARD 17)
2
3   # Set build type if not set.
4   if(NOT CMAKE_BUILD_TYPE )
5     set( CMAKE_BUILD_TYPE Debug)
6   endif ()
7   # Set additional flags .
8   set( CMAKE_CXX_FLAGS "-Wall -Wextra ")
9   set( CMAKE_CXX_FLAGS_DEBUG "-g -O0")
       -Wall -Wextra: show all warnings
       -g: keep debug information in binary
       -O<num>: optimization level in {0, 1, 2, 3}
          0: no optimization
          3: full optimization
                                                     32
Useful commands in CMake
 Just a scripting language
 Has features of a scripting language, i.e.
 functions, control structures, variables, etc.
 All variables are string
 Set variables with set(VAR VALUE)
 Get value of a variable with ${VAR}
 Show a message message(STATUS "message")
 Also possible WARNING, FATAL_ERROR
                                              33
Build process
 CMakeLists.txt defines the whole build
 CMake reads CMakeLists.txt sequentially
 Build process:
 1.   cd <project_folder>
 2.   mkdir build
 3.   cd build
 4.   cmake ..
 5.   make -j2 # pass your number of cores here
                                                  34
Everything is broken, what
should I do?
 Sometimes you want a clean build
 It is very easy to do with CMake
 1. cd project/build
 2. make clean [remove generated binaries]
 3. rm -rf * [make sure you are in build folder]
 Short way(If you are in project/):
   rm -rf build/
                                                   35
Use pre-compiled library
 Sometimes you get a compiled library
 You can use it in your build
 For example, given libtools.so it can be
 used in the project as follows:
1 find_library (TOOLS
2               NAMES tools
3               PATHS ${ LIBRARY_OUTPUT_PATH })
4 # Use it for linking :
5 target_link_libraries (< some_binary > ${TOOLS })
                                                      36
CMake find_path and find_library
 We can use an external library
 Need headers and binary library files
 There is an easy way to find them
 Headers:
1 find_path ( SOME_PKG_INCLUDE_DIR include / some_file .hpp
2             <path1 > <path2 > ...)
3 include_directories (${ SOME_PKG_INCLUDE_DIR })
 Libraries:
1 find_library ( SOME_LIB
2                NAMES <some_lib >
3                PATHS <path1 > <path2 > ...)
4 target_link_libraries ( target ${ SOME_LIB })
                                                              37
find_package
 find_package calls multiple find_path and
 find_library functions
 To use find_package(<pkg>) CMake must
 have a file Find<pkg>.cmake in
 CMAKE_MODULE_PATH folders
 Find<pkg>.cmake defines which libraries and
 headers belong to package <pkg>
 Pre-defined for most popular libraries,
 e.g. OpenCV, libpng, etc.
                                               38
     CMakeLists.txt
 1   cmake_minimum_required ( VERSION 3.1)
 2   project ( first_project )
 3
 4   # CMake will search here for Find <pkg >. cmake files
 5   SET( CMAKE_MODULE_PATH
 6        ${ PROJECT_SOURCE_DIR }/ cmake_modules )
 7
 8   # Search for Findsome_pkg . cmake file and load it
 9   find_package ( some_pkg )
10
11   # Add the include folders from some_pkg
12   include_directories (${ some_pkg_INCLUDE_DIRS })
13
14   # Add the executable "main"
15   add_executable (main small_main .cpp)
16   # Tell the linker to bind these binary objects
17   target_link_libraries (main ${ some_pkg_LIBRARIES })
                                                             39
    cmake_modules/Findsome_pkg.cmake
1 # Find the headers that we will need
2 find_path ( some_pkg_INCLUDE_DIRS include / some_lib .hpp <
       FOLDER_WHERE_TO_SEARCH >)
3   message ( STATUS " headers : ${ some_pkg_INCLUDE_DIRS }")
4
5   # Find the corresponding libraries
6   find_library ( some_pkg_LIBRARIES
7                  NAMES some_lib_name
8                  PATHS <FOLDER_WHERE_TO_SEARCH >)
9   message ( STATUS "libs: ${ some_pkg_LIBRARIES }")
                                                                40
Watch for Homeworks
https://youtu.be/hwP7WQkmECE
                               41
Watch for Homeworks
https://youtu.be/OZEGnam2M9s
                               42
Suggested Video
“Free software, free society” by Richard
Stallman
https://youtu.be/Ag1AKIl_2GM
                                           43
References
 CMake Documentation
 cmake.org/cmake/help/v3.10/
 GCC Manual
 gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/
 Clang Manual
 releases.llvm.org/10.0.0/tools/clang/docs/index.html
                                                   44