On Fedora install CMake using dnf
$ sudo dnf install cmake
on Debian based distros you can isntall it using
$ sudo apt install cmake
CMake is an open-source, cross-platform family of tools designed to build, test and package software.
We have CMake
installed now. Let’s build a C++
Hello World
program using
CMake
.
#include <iostream>
using namespace std;
int main(int argc, const char **argv){
if(argc < 2)
cout<<"Hello World\n";
else
cout<<"Hello "<< argv[1]<< "\n";
return 0;
}
Typically in order to build this program the command looks something like
$ g++ -o hello hello.cpp
Now let’s see how to compile this program using CMake
The CMakeLists.txt
looks like.
cmake_minimum_required(VERSION 3.13)
project(hello)
set(CMAKE_CXX_STANDARD 11)
add_executable(hello hello.cpp)
Let’s see what we have got in CMakeLists.txt
.
cmake_minimum_required(VERSION 3.13)
: we are checking the minimum required version ofCMake
to build this project. IfCMake Version 3.13
or greater not found on the system, the build won’t go ahed.project(hello)
: we are declearing the project name here.set(CMAKE_CXX_STANDARD 11)
: This will essentially tell the compiler that this project needs to be built usingC++ 11
. So in the case ofgcc
it will set the-std=c++11
compiler flag.add_executable(hello hello.cpp)
: Here the first argumenthello
is the name of executable (ie filename in-o <filename>
part of theg++
command mentioned above),hello.cpp
is the source file required to buildhello
exe. In this case we are buildinghello
using only one.cpp
file, although we can provide a whole list of input files toadd_executable
function.
With that said let’s buld this program.
[04:04 PM][girish@battle-ship]:cmake-hello-world $ ls CMakeLists.txt hello.cpp [04:04 PM][girish@battle-ship]:cmake-hello-world $ mkdir build [04:04 PM][girish@battle-ship]:cmake-hello-world $ cd build [04:04 PM][girish@battle-ship]:build $ cmake .. -- The C compiler identification is GNU 10.2.1 -- The CXX compiler identification is GNU 10.2.1 -- Check for working C compiler: /usr/lib64/ccache/cc -- Check for working C compiler: /usr/lib64/ccache/cc - works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/lib64/ccache/c++ -- Check for working CXX compiler: /usr/lib64/ccache/c++ - works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/girish/git/cmake-hello-world/build [04:04 PM][girish@battle-ship]:build $ make Scanning dependencies of target hello [ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o [100%] Linking CXX executable hello [100%] Built target hello [04:04 PM][girish@battle-ship]:build $ ls CMakeCache.txt CMakeFiles cmake_install.cmake hello Makefile [04:04 PM][girish@battle-ship]:build $ ./hello Hello World [04:04 PM][girish@battle-ship]:build $
At this point we have CMake
installed on the system. Let’s now install
OpenCV
.
To build OpenCV applications using C++
we need to install binary and
development packages for OpenCV
and OpenCV Contrib
.
On Fedora
$ sudo dnf install opencv opencv-contrib opencv-devel
So now that we have installed both OpenCV
and CMake
let’s start building
OpenCV
application. As always let’s build a Hello World
program for video
using OpenCV
. The C++
code for that looks something like following.
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char **argv){
// Create a VideoCapture object and open the input file
// If the input is the web camera, pass 0 instead of the video file name
VideoCapture cap(argv[1]);
// Check if camera opened successfully
if(!cap.isOpened()){
cout << "Error opening video stream or file" << endl;
return -1;
}
while(1){
Mat frame;
// Capture frame-by-frame
cap >> frame;
// If the frame is empty, break immediately
if (frame.empty())
break;
// Display the resulting frame
imshow( "Frame", frame );
// Press ESC on keyboard to exit
char c=(char)waitKey(25);
if(c==27)
break;
}
// When everything done, release the video capture object
cap.release();
// Closes all the frames
destroyAllWindows();
return 0;
}
The command to compile this hello world code would be
$ g++ -w hello_opencv.cpp -o hello-opencv $(pkg-config --cflags --libs opencv)
In the command above, $(pkg-config --cflags --libs opencv)
returns the include
path and the libraries for opencv
.
Now let’s create a CMakeLists.txt
file to build this exe using CMake
.
cmake_minimum_required(VERSION 2.6)
# set the project name and version
project (temp)
#set (CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS}) # not needed for opencv>=4.0
add_executable(hello-opencv hello_opencv.cpp)
target_link_libraries(hello-opencv ${OpenCV_LIBS})
In this file CMakeLists.txt
function find_package
is responsible for
finding the OpenCV
pakcage form the environment/package-config
and setting
all of the required variable for using OpenCV
as a dependency. Out of those
veriables we are using OpenCV_INCLUDE_DIRS
and OpenCV_LIBS
which holds
the include path for OpenCV
and libraries provided by OpenCV
.
To build the this program.
# go to the project directory
$ cd <proj-directory>
# create a new directory
$ mkdir build
$ cd build
# run cmake and pass the location of CMakeLists.txt as an argument to it.
$ cmake ..
After running cmake ..
you will have Makefile
and a lot of other stuff
created in the build
folder. Now go ahead and run
$ make
and you will have the binary executable for the OpenCV Hello World
program
under build
directory with the name hello_opencv
. You can run it
$ hello_opencv <path to a video file>
NOTE: There is a specific reason that you need to create a separate folder to generate build files. You can read more about that here.
This post covers the very basics of CMake
(and may not be complete).
But it can be a good point to start from. For further reading following
links can be useful