OpenCV By Example
上QQ阅读APP看书,第一时间看更新

Making the script more complex

In this section, we will show you a more complex script that includes subfolders, libraries, and executables, all in only two files and a few lines, as shown in this script.

It's not mandatory to create multiple CMakeLists.txt files because we can specify everything in the main CMakeLists.txt file. It is more common to use different CMakeLists.txt files for each project subfolder, making it more flexible and portable.

This example has a code structure folder that contains one folder for the utils library and the other for the root folder, which contains the main executable:

CMakeLists.txt
main.cpp
utils/
  CMakeLists.txt
  computeTime.cpp
  computeTime.h
  logger.cpp
  logger.h
  plotting.cpp
  plotting.h

Then, we need to define two CMakeLists.txt files: one in the root folder and the other in the utils folder. The CMakeLists.txt root folder file has the following contents:

cmake_minimum_required (VERSION 2.6)
project (Chapter2)

# Opencv Package required
FIND_PACKAGE( OpenCV  3.0.0 REQUIRED )

#Add opencv header files to project
include_directories( ${OpenCV_INCLUDE_DIR} )
link_directories(${OpenCV_LIB_DIR})

add_subdirectory(utils)

# Add optional log with a precompiler definition
option(WITH_LOG "Build with output logs and images in tmp" OFF)
if(WITH_LOG)
  add_definitions(-DLOG)
endif(WITH_LOG)

# generate our new executable
add_executable( ${PROJECT_NAME} main.cpp )
# link the project with his dependencies
target_link_libraries( ${PROJECT_NAME} ${OpenCV_LIBS} Utils)

Almost all the lines are described in the previous sections except for some functions that we will explain in later sections.

The add_subdirectory() tells CMake to analyze the CMakeLists.txt of a desired subfolder.

Before we continue with an explanation of the main CMakeLists.txt file, we will explain the utils CMakeLists.txt file.

In the CMakeLists.txt file in the utils folder, we will write a new library to include it in our main project folder:

# Add new variable for src utils lib
SET(UTILS_LIB_SRC
  computeTime.cpp 
  logger.cpp 
  plotting.cpp
)
# create our new utils lib
add_library(Utils ${UTILS_LIB_SRC} )
# make sure the compiler can find include files for our library
target_include_directories(Utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

This CMake script file defines an UTILS_LIB_SRC variable where we add all the source files included in our library, generate the library with the add_library function, and use the target_include_directories function to allow our main project to detect all header files.

Leaving out the utils subfolder and continuing with the root cmake script, the Option function creates a new variable—in our case, WITH_LOG, with a small description attached. This variable can be changed via the ccmake command line or CMake GUI interface, where the description and a checkbox appears that allow users to enable or disable this option.

This function is very useful and allows the user to decide about compile-time features such as enabling or disabling logs, compiling with Java or Python support as with OpenCV, and so on.

In our case, we use this option to enable a logger in our application. To enable the logger, we use a precompiler definition in our code:

#ifdef LOG
logi("Number of iteration %d", i);
#endif

To tell our compiler that we require the LOG compile time definition, we use the add_definitions(-DLOG) function in our CMakeLists.txt. To allow the user to decide whether they want to enable it or not, we only have to verify whether the WITH_LOG CMake variable is checked or not with a simple condition:

if(WITH_LOG)
  add_definitions(-DLOG)
endif(WITH_LOG)

Now, we are ready to create our CMake script files to be compiled in any operating system our Computer Vision projects. Then, we will continue with the OpenCV basics before we start with a sample project.