|
|
Welcome to the CMake Wiki Examples\! These short snippets which show you
|
|
|
how to perform many common CMake procedures. Please see
|
|
|
[1](http://www.cmake.org/cmake/help/cmake-2-8-docs.html) for the verbose
|
|
|
documentation.
|
|
|
|
|
|
Please add examples as you find common procedures which are not
|
|
|
explained here\!
|
|
|
|
|
|
## Basics
|
|
|
|
|
|
### Set a CMake variable
|
|
|
|
|
|
``` cmake
|
|
|
SET(VARIABLE VALUE)
|
|
|
```
|
|
|
|
|
|
### View a CMake variable
|
|
|
|
|
|
``` cmake
|
|
|
MESSAGE("CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
|
|
|
```
|
|
|
|
|
|
### View a system variable
|
|
|
|
|
|
``` cmake
|
|
|
MESSAGE("$ENV{PATH}")
|
|
|
```
|
|
|
|
|
|
### Check operating system
|
|
|
|
|
|
``` cmake
|
|
|
IF(WIN32)
|
|
|
...do something...
|
|
|
ELSE(WIN32)
|
|
|
...do something else...
|
|
|
ENDIF(WIN32)
|
|
|
```
|
|
|
|
|
|
### Check operating system
|
|
|
|
|
|
``` cmake
|
|
|
IF(CMAKE_SYSTEM_NAME STREQUAL Linux)
|
|
|
```
|
|
|
|
|
|
### Check if environment variable is set
|
|
|
|
|
|
Test if an environment variable is defined, bail out if it is not
|
|
|
|
|
|
Normally, operating system environment variables are referenced with
|
|
|
syntax like `$ENV{FOO_HOME}`, and CMake variables are referenced as
|
|
|
`${FOO_VAR}`, but [to make the **DEFINED** command work with environment
|
|
|
variables you drop the
|
|
|
**$**](http://cmake.3232098.n2.nabble.com/if-DEFINED-ENV-VAR-doesn-t-work-as-expected-td6881537.html).
|
|
|
|
|
|
``` cmake
|
|
|
IF(DEFINED ENV{FOO_HOME})
|
|
|
message("...using Foo found in $ENV{FOO_HOME}")
|
|
|
ELSE()
|
|
|
message("FOO_HOME is not defined. You must tell CMake where to find Foo")
|
|
|
# exit early
|
|
|
return()
|
|
|
ENDIF()
|
|
|
```
|
|
|
|
|
|
The [mailing list has some alternative proposals for how to accomplish
|
|
|
this](http://cmake.3232098.n2.nabble.com/Test-if-ENV-VAR-is-set-tt7581651.html#none)
|
|
|
|
|
|
## Lists
|
|
|
|
|
|
### Check if a list contains a value
|
|
|
|
|
|
``` cmake
|
|
|
list(FIND VTK_MODULES_ENABLED "vtkFiltersParallel" HasMyModule)
|
|
|
|
|
|
IF(HasMyModule EQUAL -1)
|
|
|
message(FATAL_ERROR "You must build VTK with more modules.")
|
|
|
ENDIF()
|
|
|
```
|
|
|
|
|
|
## Outputs
|
|
|
|
|
|
### Message
|
|
|
|
|
|
``` cmake
|
|
|
MESSAGE("Hello world")
|
|
|
```
|
|
|
|
|
|
### Output a Variable
|
|
|
|
|
|
``` cmake
|
|
|
message("VTK Using Boost? ${VTK_USE_BOOST}")
|
|
|
```
|
|
|
|
|
|
### Error
|
|
|
|
|
|
``` cmake
|
|
|
MESSAGE(FATAL_ERROR "An error occured.")
|
|
|
```
|
|
|
|
|
|
## Conditional Statement (if)
|
|
|
|
|
|
There are two allowable syntaxes:
|
|
|
|
|
|
``` cmake
|
|
|
if(something)
|
|
|
do something
|
|
|
else(something) # the argument must match the if(...)
|
|
|
do something else
|
|
|
endif(something) # the argument must match the if(...)
|
|
|
```
|
|
|
|
|
|
The following is also allowed. It is easier to read (because "else(the
|
|
|
same thing)" doesn't really make sense if you read it like c++, for
|
|
|
example), but it is also easier to confuse yourself with nested ifs.
|
|
|
|
|
|
``` cmake
|
|
|
if(something)
|
|
|
do something
|
|
|
else()
|
|
|
do something else
|
|
|
endif()
|
|
|
```
|
|
|
|
|
|
Example:
|
|
|
|
|
|
``` cmake
|
|
|
if (!VTK_USE_BOOST)
|
|
|
MESSAGE(SEND_ERROR "VTK must be built with VTK_USE_BOOST=ON.")
|
|
|
endif ()
|
|
|
```
|
|
|
|
|
|
## Logical Operators
|
|
|
|
|
|
These operators work exactly as you would expect.
|
|
|
|
|
|
### AND
|
|
|
|
|
|
if(A AND B)
|
|
|
|
|
|
### OR
|
|
|
|
|
|
if(A OR B)
|
|
|
|
|
|
### NOT
|
|
|
|
|
|
if(NOT A)
|
|
|
|
|
|
### Compound
|
|
|
|
|
|
if(NOT(A AND B))
|
|
|
|
|
|
## Finding Packages
|
|
|
|
|
|
Most of the time large packages will have their
|
|
|
Find\[PackageName\].cmake file included in the cmake distribution. If
|
|
|
that is the case, all you must do it:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(Eigen3)
|
|
|
```
|
|
|
|
|
|
### Specifying where to look for .cmake files
|
|
|
|
|
|
If you place your FindXYZ.cmake and UseXYZ.cmake files in the same
|
|
|
directory as your main CMakeLists.txt file, you can tell CMake to try to
|
|
|
use them first before looking at system paths by doing:
|
|
|
|
|
|
``` cmake
|
|
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/" ${CMAKE_MODULE_PATH})
|
|
|
```
|
|
|
|
|
|
### Checking if a package was found
|
|
|
|
|
|
Most of the time the \[PackageName\]_FOUND variable is defined. You can
|
|
|
use it like this:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(Eigen3)
|
|
|
if(EIGEN3_FOUND)
|
|
|
... do something ...
|
|
|
endif(EIGEN3_FOUND)
|
|
|
```
|
|
|
|
|
|
### Suppress warnings
|
|
|
|
|
|
Sometimes you may want to optionally include a package. You can suppress
|
|
|
the warning about the package not being found
|
|
|
with:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(Eigen3 QUIET)
|
|
|
```
|
|
|
|
|
|
## Fix Mininum Version Error/Warning
|
|
|
|
|
|
``` cmake
|
|
|
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
|
|
|
```
|
|
|
|
|
|
## Look in the directory that the CMakeLists.txt file is for header and implementation files
|
|
|
|
|
|
``` cmake
|
|
|
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
|
|
|
```
|
|
|
|
|
|
or
|
|
|
|
|
|
``` cmake
|
|
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
```
|
|
|
|
|
|
## Set Link Directories
|
|
|
|
|
|
If a library you are using does not have a \[LibraryName\].cmake, you
|
|
|
can do
|
|
|
|
|
|
``` cmake
|
|
|
find_library(OPENSSL_LIB ssl $ENV{OPENSSL_LIB_PATH})
|
|
|
```
|
|
|
|
|
|
This will check the environment for a variable named OPENSSL_LIB_PATH.
|
|
|
If it exists, you can then use
|
|
|
|
|
|
``` cmake
|
|
|
target_link_libraries(mytarget ${OPENSSL_LIB})
|
|
|
```
|
|
|
|
|
|
If it does not, it can be set through the CMake GUI.
|
|
|
|
|
|
## Set Include Directories
|
|
|
|
|
|
This command adds a path to the include directories, you do NOT have to
|
|
|
do the 'export' style \`\`keep everything that is here and add this
|
|
|
one'' syntax.
|
|
|
|
|
|
``` cmake
|
|
|
INCLUDE_DIRECTORIES(/some/directory)
|
|
|
```
|
|
|
|
|
|
## View the directories that are set
|
|
|
|
|
|
``` cmake
|
|
|
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
|
|
|
message("inc_dirs = ${inc_dirs}")
|
|
|
```
|
|
|
|
|
|
## Automate configure and generate
|
|
|
|
|
|
Note 'cmake' instead of 'ccmake' (ccmake is curses cmake (curses is the
|
|
|
terminal
|
|
|
gui))
|
|
|
|
|
|
``` cmake
|
|
|
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr/mylocation ../
|
|
|
```
|
|
|
|
|
|
## Compiler options
|
|
|
|
|
|
### Set a cmake flag
|
|
|
|
|
|
``` cmake
|
|
|
ccmake ../../src/boost -DCMAKE_IS_EXPERIMENTAL=YES_I_KNOW
|
|
|
```
|
|
|
|
|
|
### Set a cpp flag/preprocessor definition
|
|
|
|
|
|
``` cmake
|
|
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__WXGTK__")
|
|
|
```
|
|
|
|
|
|
### Force g++
|
|
|
|
|
|
Ocassionally you will come across files with the extension .c that
|
|
|
actually contain c++ code. CMake treats the file based on its extension.
|
|
|
If you want to override this behavior (in this case, compile .c files
|
|
|
with your c++ compiler), do the following:
|
|
|
|
|
|
``` cmake
|
|
|
set(MySources main.c anotherFile.c)
|
|
|
add_executable(SpinRecognize ${MySource})
|
|
|
set_source_files_properties(${MySources} PROPERTIES LANGUAGE CXX)
|
|
|
```
|
|
|
|
|
|
### Per-target
|
|
|
|
|
|
``` cmake
|
|
|
set_target_properties(myexe_target
|
|
|
PROPERTIES COMPILE_FLAGS "-Wall")
|
|
|
```
|
|
|
|
|
|
## Set the default build type
|
|
|
|
|
|
``` cmake
|
|
|
SET(CMAKE_BUILD_TYPE Debug CACHE STRING "default to debug" FORCE)
|
|
|
```
|
|
|
|
|
|
## Custom variable
|
|
|
|
|
|
Here is a list of supported variable types:
|
|
|
<http://www.cmake.org/cmake/help/cmake2.6docs.html#command:set>
|
|
|
|
|
|
### String
|
|
|
|
|
|
``` cmake
|
|
|
SET(BUILD_PARAVIEW_PLUGIN ON CACHE STRING "Build Paraview plugin?" FORCE)
|
|
|
```
|
|
|
|
|
|
### Bool
|
|
|
|
|
|
``` cmake
|
|
|
SET(DAI_WITH_BP ON CACHE BOOL "Belief Propagation" FORCE)
|
|
|
```
|
|
|
|
|
|
#### Comparison
|
|
|
|
|
|
``` cmake
|
|
|
if(DAI_WITH_BP EQUALS ON)
|
|
|
#do something
|
|
|
endif(DAI_WITH_BP EQUALS ON)
|
|
|
```
|
|
|
|
|
|
This is equivalent to
|
|
|
|
|
|
``` cmake
|
|
|
if(DAI_WITH_BP)
|
|
|
#do something
|
|
|
endif(DAI_WITH_BP)
|
|
|
```
|
|
|
|
|
|
## Linking to specific libraries
|
|
|
|
|
|
### ITK
|
|
|
|
|
|
Add the path to your environment:
|
|
|
|
|
|
``` text
|
|
|
export ITK_DIR=/home/doriad/bin/ITK
|
|
|
```
|
|
|
|
|
|
Then in the CMakeLists.txt use:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(ITK REQUIRED)
|
|
|
INCLUDE(${ITK_USE_FILE})
|
|
|
|
|
|
ADD_EXECUTABLE(CastImageFilter CastImageFilter.cxx)
|
|
|
TARGET_LINK_LIBRARIES(CastImageFilter
|
|
|
vtkHybrid
|
|
|
ITKIO ITKBasicFilters ITKCommon
|
|
|
)
|
|
|
```
|
|
|
|
|
|
### VXL
|
|
|
|
|
|
Add the path to your environment:
|
|
|
|
|
|
``` text
|
|
|
export VXLBIN="/home/doriad/bin/vxl"
|
|
|
```
|
|
|
|
|
|
Then in the CMakeLists.txt use:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(VXL REQUIRED)
|
|
|
INCLUDE(${VXL_CMAKE_DIR}/UseVXL.cmake)
|
|
|
```
|
|
|
|
|
|
### VTK
|
|
|
|
|
|
Add the path to your environment:
|
|
|
|
|
|
``` text
|
|
|
export VTK_DIR="/home/doriad/bin/VTK"
|
|
|
```
|
|
|
|
|
|
Then in the CMakeLists.txt use:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(VTK REQUIRED)
|
|
|
INCLUDE(${VTK_USE_FILE})
|
|
|
```
|
|
|
|
|
|
### Boost
|
|
|
|
|
|
Lets assume we built boost with ./bjam --prefix=/home/doriad/bin install
|
|
|
|
|
|
Then for CMake to find Boost, all you need is to add to your .bashrc:
|
|
|
|
|
|
``` text
|
|
|
export BOOST_ROOT="/home/doriad/bin"
|
|
|
```
|
|
|
|
|
|
Then in the CMakeLists.txt use:
|
|
|
|
|
|
``` cmake
|
|
|
SET(Boost_USE_MULTITHREAD ON) #set a flag
|
|
|
FIND_PACKAGE(Boost)
|
|
|
INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${Boost_INCLUDE_DIRS})
|
|
|
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${Boost_LIBRARY_DIRS})
|
|
|
```
|
|
|
|
|
|
### OpenCV
|
|
|
|
|
|
Add to the environment:
|
|
|
|
|
|
``` text
|
|
|
export OpenCV_DIR=/home/doriad/bin/OpenCV
|
|
|
```
|
|
|
|
|
|
Then in the CMakeLists.txt use:
|
|
|
|
|
|
``` cmake
|
|
|
FIND_PACKAGE(OpenCV REQUIRED )
|
|
|
INCLUDE_DIRECTORIES( ${OPENCV_INCLUDE_DIR} )
|
|
|
|
|
|
ADD_EXECUTABLE(Scalar Scalar.cxx)
|
|
|
TARGET_LINK_LIBRARIES(Scalar ${OpenCV_LIBS})
|
|
|
```
|
|
|
|
|
|
### Get Help Using a Library
|
|
|
|
|
|
``` cmake
|
|
|
cmake --help-module FindBoost
|
|
|
```
|
|
|
|
|
|
### Add new libraries to CMake
|
|
|
|
|
|
``` cmake
|
|
|
/usr/share/cmake/Modules/FindOpenGL.cmake|
|
|
|
```
|
|
|
|
|
|
## Dependency Graph
|
|
|
|
|
|
``` cmake
|
|
|
ccmake ../src/Program/ --graphviz=test.graph
|
|
|
dotty test.graph
|
|
|
```
|
|
|
|
|
|
## CTest
|
|
|
|
|
|
### Run a specific test by number
|
|
|
|
|
|
e.g. Test 622
|
|
|
|
|
|
``` cmake
|
|
|
ctest -I 622,622
|
|
|
```
|
|
|
|
|
|
### Run a range of tests
|
|
|
|
|
|
e.g. Test 622 to 625
|
|
|
|
|
|
``` cmake
|
|
|
ctest -I 622,625
|
|
|
```
|
|
|
|
|
|
### Run a test by name
|
|
|
|
|
|
``` cmake
|
|
|
ctest -R "itkTransformPoint*"|
|
|
|
```
|
|
|
|
|
|
### Show verbose output of a test
|
|
|
|
|
|
``` cmake
|
|
|
ctest -V -R "itkTransformPoint*"|
|
|
|
```
|
|
|
|
|
|
### Create a Test
|
|
|
|
|
|
``` cmake
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
|
|
|
|
project(simple)
|
|
|
ENABLE_TESTING()
|
|
|
|
|
|
add_executable(simple simple.cpp)
|
|
|
add_test(SimpleTest simple)
|
|
|
```
|
|
|
|
|
|
## Link to a library
|
|
|
|
|
|
``` cmake
|
|
|
ADD_EXECUTABLE(ColoredLines ColoredLines.cpp)
|
|
|
TARGET_LINK_LIBRARIES(ColoredLines vtkHybrid)
|
|
|
```
|
|
|
|
|
|
## Create a library
|
|
|
|
|
|
``` cmake
|
|
|
add_library(MatlabLibrary ./MatlabDll/LidarK.cpp)
|
|
|
```
|
|
|
|
|
|
## Installing executables
|
|
|
|
|
|
Once your project is built, you can use the 'install' make target to
|
|
|
copy the executables to the directory specified by
|
|
|
CMAKE_INSTALL_PREFIX.
|
|
|
|
|
|
``` cmake
|
|
|
add_executable(test test.cxx)
|
|
|
install(TARGETS test RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
|
|
```
|
|
|
|
|
|
If you get an error like:
|
|
|
|
|
|
error while loading shared libraries: I get
|
|
|
libwx_gtk2u_core-2.9.so.1: cannot open shared object file: No such file or directory
|
|
|
|
|
|
you should add:
|
|
|
|
|
|
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|
|
|
|
|
to your CMakeLists.txt file.
|
|
|
|
|
|
## Utilities
|
|
|
|
|
|
### Add non-compiled files to a project
|
|
|
|
|
|
This allows files that are not compiled to be added to a project (Qt
|
|
|
Creator, for example) while keeping them logically separated from files
|
|
|
that are compiled (in the normal add_executable command):
|
|
|
|
|
|
``` cmake
|
|
|
add_custom_target(MyProjectSources SOURCES
|
|
|
MyProject.h
|
|
|
)
|
|
|
```
|
|
|
|
|
|
## Recursively add subdirectories to INCLUDE_DIRECTORIES
|
|
|
|
|
|
``` cmake
|
|
|
MACRO(HEADER_DIRECTORIES return_list)
|
|
|
FILE(GLOB_RECURSE new_list *.h)
|
|
|
SET(dir_list "")
|
|
|
FOREACH(file_path ${new_list})
|
|
|
GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
|
|
|
SET(dir_list ${dir_list} ${dir_path})
|
|
|
ENDFOREACH()
|
|
|
LIST(REMOVE_DUPLICATES dir_list)
|
|
|
SET(${return_list} ${dir_list})
|
|
|
ENDMACRO()
|
|
|
```
|
|
|
|
|
|
----
|
|
|
This page was initially populated by conversion from its [original location](https://public.kitware.com/Wiki/CMake/Examples) in another wiki. |