Compiling, Linking and Executing

After writing C++ files, we need to compile the source code, and (optionally) link against different libraries to obtain the final executable. Traditionally, this compilation and linking process is merged into a single command line, in which the users provide different compile-time definitions (to configure parts of the dependencies), include directories (to search for library files), and the libraries to link against. However, this gets tedious when projects get bigger.

As we have discussed in Installing the Library, polo relies on CMake to manage its dependencies in a cross-platform compatible way. From the user’s perspective, this also has the added advantage of managing the compilation and linking process much more easily.

To build code that requires polo, we simply create a CMake project. A CMake project is a directory that has a CMakeLists.txt file, which lists the executable files, and their dependencies in the directory. Most modern integrated development environments (IDEs) natively support CMake projects, and help users create the CMakeLists.txt file interactively 1. However, we briefly mention here how to create and use CMake projects, manually, in the most basic form.

Let’s assume that we have a directory, $HOME/examples, which contains the sample code in Listing 1 in a file, anatomy.cpp. In the same directory, we create a CMakeLists.txt file that has the following lines

cmake_minimum_required(VERSION 3.9.0)
project(polo-examples)

find_package(polo CONFIG REQUIRED)

add_executable(anatomy anatomy.cpp)
target_link_libraries(anatomy polo::polo)

Here, we first choose a minimum version of CMake that is required for our project, and name our project polo-examples. Then, we tell CMake to find the configuration files for polo, which is required for our project. If CMake cannot find the configuration files, the build process will stop. Otherwise, CMake will source the configuration files, and create a target library called polo::polo, which knows how to handle its own dependencies. Finally, for each executable we might have in the directory, we create a target executable (add_executable), and we link it against polo::polo (target_link_libraries). In the example, we have only one target executable, which is named anatomy, and it consists of only one source file, anatomy.cpp. Note that we do not need to define any compile-time definitions, include directories, or any of the optional dependencies of polo as they are already handled transitively by CMake behind the scenes.

The next step is to create a new directory (e.g., build) inside $HOME/examples for CMake to put its build artifacts. Eventually, we will end up with the following directory structure

cd $HOME/examples # change directory to $HOME/examples
mkdir build # make a directory named build
tree . # check the directory structure
.
├── anatomy.cpp
├── build
└── CMakeLists.txt

Finally, we change directory to build, ask CMake to build the project for us, and run the executable

cd build
cmake -D CMAKE_BUILD_TYPE=Release \
      -D CMAKE_PREFIX_PATH=$HOME/local ../
cmake --build .
./anatomy # could be ./anatomy.exe on Windows systems

Here, we again use Release mode for CMAKE_BUILD_TYPE, which results in optimized binaries, and point CMAKE_PREFIX_PATH to $HOME/local, where we have installed polo, so that CMake can find and source the configuration files.

Note

If -D CMAKE_INSTALL_PREFIX=$HOME/local is not used in Installing the Library, we can drop -D CMAKE_PREFIX_PATH=$HOME/local when building targets that require polo. This is the case when polo is installed in system directories, or when Docker images are used.

In the end, the executable should give the following output:

Optimum: 0.0300018
Optimizer: [-4.57459,4.61311,4.61311,].

Footnotes

1

See, for instance, CMake Wiki for a comprehensive list of editors.