-
Notifications
You must be signed in to change notification settings - Fork 139
CMake
This page is maintained by Konstantin Soshin
CMake is a cross-platform free and open-source software for managing the build process of software. It is used in conjunction with native build environments such as make, Apple's Xcode, and Microsoft Visual Studio. It has minimal dependencies, requiring only a C++ compiler on its own build system
-
CMake can handle in-place and out-of-place builds, enabling several builds from the same source tree, and cross-compilation. The ability to build a directory tree outside the source tree is a key feature, ensuring that if a build directory is removed, the source files remain unaffected.
-
CMake can locate executables, files, and libraries. These locations are stored in a cache, which can then be tailored before generating the target build files.
-
CMake can generate project files for several prominent IDEs, such as Microsoft Visual Studio, Xcode, and Eclipse CDT. It can also produce build scripts for MSBuild or NMake on Windows; Unix Make on Unix-like platforms such as Linux, macOS, and Cygwin; and Ninja on both Windows and Unix-like platforms.
For example you have src.cpp
source file. First, you need to create a file for cmake, which is usually called CMakeLists.txt
, and write this here:
add_executable(myproject src.cpp)
add_executable
adds an executable target to be built from the source files listed in the command invocation. That's enough to build simple projects.
Type cmake CMakeLists.txt
(you can also pass directory path to CMakeLists.txt by cmake argument cmake ./.
or cmake ./path/to/my/cmake/
- watch below). CMake will generate all necessary files and create Makefile in the current directory:
default_user@default-user:~/myproject$ cmake CMakeLists.txt
-- The C compiler identification is GNU 7.2.0
-- The CXX compiler identification is GNU 7.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/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/bin/c++
-- Check for working CXX compiler: /usr/bin/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/myproject
Then just type make
and everything is done!
default_user@default-user:~/myproject$ make
[ 50%] Building CXX object CMakeFiles/myproject.dir/src.cpp.o
[100%] Linking CXX executable myproject
[100%] Built target myproject
Briefly: cmake CMakeLists.txt
, then make
As it stated above, the main feature is that CMake can handle out-of-place builds. So it is quite convenient to have all build files and binaries away from current work directory in their own directory. We can make new build directory and launch CMake from there:
default_user@default-user:~/myproject$ mkdir build && cd build
default_user@default-user:~/myproject/build$ cmake ../.
Now binary myproject
and all build files(CMakeCache.txt
, cmake_install.cmake
, etc) are in /build
and aren't mixed with other source files.
Briefly: mkdir ./build && cd ./build
, then cmake <path_to_CMakeLists>.txt
, then make
cmake_minimum_required(VERSION 2.6)
If the version of cmake is less than 2.6, it will not work. To write this command always is a good style
project(Myproject)
Indicates that this cmake file is the root of some project. Stores the name in the PROJECT_NAME
variable. Additionally this sets variables PROJECT_SOURCE_DIR
, <PROJECT-NAME>_SOURCE_DIR
, PROJECT_BINARY_DIR
, <PROJECT-NAME>_BINARY_DIR
(watch next paragraph about variables).
In CMake you can create text variables. Command
set(MYVAR The variable's value)
will write value The variable's value
to variable MYVAR
. To use the value somewhere, you need to write ${MYVAR}
. To add a certain text to a variable, you can do this:
set(MYVAR "${MYVAR} is 42")
Variables are actively used by various libraries - to set flags, build / link parameters (watch paragraph below about libraries).
Quite beautiful variant of CMakeLists.txt with separate list of sources in vatiable:
cmake_minimum_required(VERSION 2.6)
set(SOURCES test.cpp lib1.cpp lib2.cpp)
add_executable(test ${SOURCES})
Moreover, there are a lot of built-in variables, that provide information, change behavior, describe the system and control the build. There are some of them:
-
PROJECT_NAME
- project name -
CMAKE_CXX_FLAGS
- compiler flags -
CMAKE_LD_FLAGS
- linker flags -
CMAKE_BINARY_DIR
- this is the full path to the top level of the current CMake build tree. For an in-source build, this would be the same asCMAKE_SOURCE_DIR
. -
CMAKE_SOURCE_DIR
- the path to the top level of the source tree -
CMAKE_RUNTIME_OUTPUT_DIRECTORY
- where to put all the executable target files when built. -
CMAKE_LIBRARY_OUTPUT_DIRECTORY
- Where to put all theLIBRARY
target files when built -
CMAKE_ARCHIVE_OUTPUT_DIRECTORY
- Where to put all the ARCHIVE target files when built.
Watch MOAR variables.
If you want your header-files (*.h) to be searched in special directories, you can list it in include_directories
:
include_directories("headers/myheaders" "/usr/include" "blahblah")
Let's learn how to search and connect libraries with cmake using Boost as an example
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
Firstly, we want this library be linked staticly. Second flag allows Boost use multithreading.
Suppose we need the components of boost called chrono
(a library for working with time) and filesystem
(a library for working with the file system):
find_package(Boost COMPONENTS chrono filesystem REQUIRED)
REQUIRED
indicates that the library is necessary for the project. Then we will have automatically defined such variables: Boost_INCLUDE_DIRS
- path to headers connected with necessary components, Boost_LIBRARIES
- path to binary library. Then we include directories with headers:
include_directories(${Boost_INCLUDE_DIRS})
and use special comand target_link_libraries
to link libary:
target_link_libraries(Myproject ${Boost_LIBRARIES})
Notice: not all libraries can be linked in that way. Only those which have Find%libraryname%.cmake
could be found using find_package
. For example, libelf doesn't have. But in that case plan is the same: find path to headers and path to binary library and then include_directories
and target_link_libraries
. How to find these paths watch: find_path
, find_library
.
CMake Tutorial (RUS)
MIPT-V / MIPT-MIPS — Cycle-accurate pre-silicon simulation.