CMake
CMake is an open-source, cross-platform family of tools designed to build, test and package software.
Why CMake?
Theoretically, any C++ program can be compiled with g++. However, when the program gets bigger and bigger, a project may have many folders and source files.
In these cases, using
CMake
will make your life a lot easier that compiling all fines together by running a long tedious command every time.
Resources
- https://cliutils.gitlab.io/modern-cmake/
- This tutorial series
- Visual SLAM book, page 21
All CMake does is create a Makefile
. ahh, so after you write your CMakeLists.txt
, you would call
cmake .
This creates a Makefile
. You then run
make
Which creates the executable!
The
cmake
-make
processThe
cmake
process handles the relationship between the project files, while themake
process actually callsg++
to compile the program.
Compiling without Intermediate Files
The only thing that is dissatisfied with this process is that the intermediate files generated by CMake are still in our code files. When we want to release the code, we don’t want to publish these intermediate files together.
Therefore, the more common practice of compiling CMake projects is as follows:
Using static libraries (.a
) and shared libraries (.so
)
Usually, you have files (ex: main.cpp
) calling functions from other files, which we call libraries.
We divide into 2 types of libraries
- static libraries (“
.a
” extension) - shared libraries (”
.so
” extension)
What is the difference between the 2 kinds of libraries?
The difference is that a static library will generate a copy each time it is called, and the shared library has only one copy, which saves space.
When do I need
add_library
?Whenever you are including other
.h
files, and these interface files have implementation files (.cpp
format), you need to add those so they are linked properly. For Eigen,add_library
is not needed because it doesn’t have.cpp
files, only.h
files.
it searches for the makefile and executes it. A makefile can look like the following:
Commands you should become super familiar with:
- cmake_minimum_required
- project
- include_directories
- add_library
- add_executable
- target_link_libraries
Using OpenCV with CMake
2023-09-17: Lessons on Cmake from this new personal project: https://chat.openai.com/share/1d3b9a2f-1667-4943-8809-50cab080a00b
In CMake, when you specify that a target (like an executable or a library) needs to link against another library, the relationship is often transitive.
Linkage is transitive in CMake
Yes, CMake handles transitive dependencies out-of-the-box. When you use
target_link_libraries
, dependencies are automatically propagated to dependent targets. Source
- Library dependencies are transitive by default with this signature
For example:
In main.cpp
You can get away with this:
- You didn’t link main to openCV, but this still builds, because because linking is transitive.
camera
is linked to openCV
What if you didn’t want this behavior? There are the PRIVATE
, PUBLIC
, and INTERFACE
keywords.
Use of
PRIVATE
vs.PUBLIC
vs.INTERFACE
PRIVATE
: Used when the library is only needed for the target’s implementation.PUBLIC
: Used when both the target and consumers of the target require the library.INTERFACE
: Used when only the consumers of the target need the library.Learn more here
You can add PRIVATE
, but main.cpp
still builds…
This is because inside main.cpp
, you are including camera.hpp
, which has already included the OPENCV header files. However, if you remove the include "camera.hpp"
, you’ll see that this won’t compile anymore
- umm there’s some iffy behavior where this compiles
But not this?
Important
Simply including a header file does not require linking against the library.
When it comes to using the code, it will break unless you link with it in one way or the other.
Modern Cmake
Shown to me by Kajanan. See Modern CMake