CMake/Examples: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
(Add explicit preformat markup)
(Replace content with link to new CMake community wiki)
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
Welcome to the CMake Wiki Examples! These short snippets which show you how to perform many common CMake procedures. Please see [http://www.cmake.org/cmake/help/cmake-2-8-docs.html] for the verbose documentation.
{{CMake/Template/Moved}}


Please add examples as you find common procedures which are not explained here!
This page has moved [https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Examples here].
 
==Basics==
 
===Set a CMake variable===
<source lang="cmake">
SET(VARIABLE VALUE)
</source>
 
===View a CMake variable===
<source lang="cmake">
MESSAGE("CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
</source>
 
===View a system variable===
<source lang="cmake">
MESSAGE("$ENV{PATH}")
</source>
 
===Check operating system===
<source lang="cmake">
IF(WIN32)
  ...do something...
ELSE(WIN32)
  ...do something else...
ENDIF(WIN32)
</source>
 
===Check operating system===
<source lang="cmake">
IF(CMAKE_SYSTEM_NAME STREQUAL Linux)
</source>
 
===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 <code>$ENV{FOO_HOME}</code>, and CMake variables are referenced as <code>${FOO_VAR}</code>, but [http://cmake.3232098.n2.nabble.com/if-DEFINED-ENV-VAR-doesn-t-work-as-expected-td6881537.html to make the '''DEFINED''' command work with environment variables you drop the '''$'''].
 
<source lang="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()
</source>
 
The [http://cmake.3232098.n2.nabble.com/Test-if-ENV-VAR-is-set-tt7581651.html#none mailing list has some alternative proposals for how to accomplish this]
 
==Lists==
 
===Check if a list contains a value===
<source lang="cmake">
list(FIND VTK_MODULES_ENABLED "vtkFiltersParallel" HasMyModule)
 
IF(HasMyModule EQUAL -1)
  message(FATAL_ERROR "You must build VTK with more modules.")
ENDIF()
</source>
 
==Outputs==
===Message===
<source lang="cmake">
MESSAGE("Hello world")
</source>
===Output a Variable===
<source lang="cmake">
message("VTK Using Boost? ${VTK_USE_BOOST}")
</source>
 
===Error===
<source lang="cmake">
MESSAGE(FATAL_ERROR "An error occured.")
</source>
 
==Conditional Statement (if)==
There are two allowable syntaxes:
 
<source lang="cmake">
if(something)
do something
else(something) # the argument must match the if(...)
do something else
endif(something) # the argument must match the if(...)
</source>
 
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.
<source lang="cmake">
if(something)
do something
else()
do something else
endif()
</source>
 
Example:
<source lang="cmake">
if (!VTK_USE_BOOST)
  MESSAGE(SEND_ERROR "VTK must be built with VTK_USE_BOOST=ON.")
endif ()
</source>
 
==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:
<source lang="cmake">
FIND_PACKAGE(Eigen3)
</source>
 
===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:
<source lang="cmake">
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/" ${CMAKE_MODULE_PATH})
</source>
 
===Checking if a package was found===
Most of the time the [PackageName]_FOUND variable is defined. You can use it like this:
<source lang="cmake">
FIND_PACKAGE(Eigen3)
if(EIGEN3_FOUND)
... do something ...
endif(EIGEN3_FOUND)
</source>
 
===Suppress warnings===
Sometimes you may want to optionally include a package. You can suppress the warning about the package not being found with:
<source lang="cmake">
FIND_PACKAGE(Eigen3 QUIET)
</source>
 
==Fix Mininum Version Error/Warning==
<source lang="cmake">
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
</source>
 
 
==Look in the directory that the CMakeLists.txt file is for header and implementation files==
<source lang="cmake">
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
</source>
 
or
 
<source lang="cmake">
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
</source>
 
==Set Link Directories==
If a library you are using does not have a [LibraryName].cmake, you can do
<source lang="cmake">
find_library(OPENSSL_LIB ssl $ENV{OPENSSL_LIB_PATH})
</source>
This will check the environment for a variable named OPENSSL_LIB_PATH. If it exists, you can then use
<source lang="cmake">
target_link_libraries(mytarget ${OPENSSL_LIB})
</source>
 
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.
<source lang="cmake">
INCLUDE_DIRECTORIES(/some/directory)
</source>
 
==View the directories that are set==
<source lang="cmake">
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
</source>
 
==Automate configure and generate==
Note 'cmake' instead of 'ccmake' (ccmake is curses cmake (curses is the terminal gui))
<source lang="cmake">
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr/mylocation ../
</source>
 
==Compiler options==
===Set a cmake flag===
<source lang="cmake">
ccmake ../../src/boost -DCMAKE_IS_EXPERIMENTAL=YES_I_KNOW
</source>
 
===Set a cpp flag/preprocessor definition===
<source lang="cmake">
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__WXGTK__")
</source>
 
===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:
 
<source lang="cmake">
set(MySources main.c anotherFile.c)
add_executable(SpinRecognize ${MySource})
set_source_files_properties(${MySources} PROPERTIES LANGUAGE CXX)
</source>
 
===Per-target===
<source lang="cmake">
set_target_properties(myexe_target
                                PROPERTIES COMPILE_FLAGS "-Wall")
</source>
 
==Set the default build type==
<source lang="cmake">
SET(CMAKE_BUILD_TYPE Debug CACHE STRING "default to debug" FORCE)
</source>
 
==Custom variable==
 
Here is a list of supported variable types: http://www.cmake.org/cmake/help/cmake2.6docs.html#command:set
 
===String===
<source lang="cmake">
SET(BUILD_PARAVIEW_PLUGIN ON CACHE STRING "Build Paraview plugin?" FORCE)
</source>
===Bool===
<source lang="cmake">
SET(DAI_WITH_BP ON CACHE BOOL "Belief Propagation" FORCE)
</source>
 
====Comparison====
<source lang="cmake">
if(DAI_WITH_BP EQUALS ON)
#do something
endif(DAI_WITH_BP EQUALS ON)
</source>
 
This is equivalent to
 
<source lang="cmake">
if(DAI_WITH_BP)
#do something
endif(DAI_WITH_BP)
</source>
 
==Linking to specific libraries==
===ITK===
Add the path to your environment:
<source lang="text">
export ITK_DIR=/home/doriad/bin/ITK
</source>
 
Then in the CMakeLists.txt use:
<source lang="cmake">
FIND_PACKAGE(ITK REQUIRED)
INCLUDE(${ITK_USE_FILE})
 
ADD_EXECUTABLE(CastImageFilter CastImageFilter.cxx)
TARGET_LINK_LIBRARIES(CastImageFilter
vtkHybrid
ITKIO ITKBasicFilters ITKCommon
)
</source>
 
===VXL===
Add the path to your environment:
<source lang="text">
export VXLBIN="/home/doriad/bin/vxl"
</source>
 
Then in the CMakeLists.txt use:
<source lang="cmake">
FIND_PACKAGE(VXL REQUIRED)
INCLUDE(${VXL_CMAKE_DIR}/UseVXL.cmake)
</source>
 
===VTK===
Add the path to your environment:
<source lang="text">
export VTK_DIR="/home/doriad/bin/VTK"
</source>
 
Then in the CMakeLists.txt use:
<source lang="cmake">
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
</source>
 
===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:
<source lang="text">
export BOOST_ROOT="/home/doriad/bin"
</source>
 
Then in the CMakeLists.txt use:
<source lang="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})
</source>
 
===OpenCV===
 
Add to the environment:
<source lang="text">
export OpenCV_DIR=/home/doriad/bin/OpenCV
</source>
 
Then in the CMakeLists.txt use:
<source lang="cmake">
FIND_PACKAGE(OpenCV REQUIRED )
INCLUDE_DIRECTORIES( ${OPENCV_INCLUDE_DIR} )
 
ADD_EXECUTABLE(Scalar Scalar.cxx)
TARGET_LINK_LIBRARIES(Scalar ${OpenCV_LIBS})
</source>
 
===Get Help Using a Library===
<source lang="cmake">
cmake --help-module FindBoost
</source>
 
===Add new libraries to CMake===
<source lang="cmake">
/usr/share/cmake/Modules/FindOpenGL.cmake|
</source>
 
==Dependency Graph==
<source lang="cmake">
ccmake ../src/Program/ --graphviz=test.graph
dotty test.graph
</source>
 
==CTest==
===Run a specific test by number===
e.g. Test 622
<source lang="cmake">
ctest -I 622,622
</source>
 
===Run a range of tests===
e.g. Test 622 to 625
<source lang="cmake">
ctest -I 622,625
</source>
 
===Run a test by name===
<source lang="cmake">
ctest -R "itkTransformPoint*"|
</source>
 
===Show verbose output of a test===
<source lang="cmake">
ctest -V -R "itkTransformPoint*"|
</source>
 
===Create a Test===
<source lang="cmake">
cmake_minimum_required(VERSION 2.6)
 
project(simple)
ENABLE_TESTING()
 
add_executable(simple simple.cpp)
add_test(SimpleTest simple)
</source>
 
==Link to a library==
<source lang="cmake">
ADD_EXECUTABLE(ColoredLines ColoredLines.cpp)
TARGET_LINK_LIBRARIES(ColoredLines vtkHybrid)
</source>
 
 
==Create a library==
<source lang="cmake">
add_library(MatlabLibrary ./MatlabDll/LidarK.cpp)
</source>
 
==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.
 
<source lang="cmake">
add_executable(test test.cxx)
install(TARGETS test RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
</source>
 
If you get an error like:
<pre>
error while loading shared libraries: I get
libwx_gtk2u_core-2.9.so.1: cannot open shared object file: No such file or directory
</pre>
 
you should add:
<pre>
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
</pre>
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):
<source lang="cmake">
add_custom_target(MyProjectSources SOURCES
MyProject.h
)
</source>
 
==Recursively add subdirectories to INCLUDE_DIRECTORIES==
<source lang="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()
</source>
 
{{CMake/Template/Footer}}

Latest revision as of 15:40, 30 April 2018


The CMake community Wiki has moved to the Kitware GitLab Instance.

This page has moved here.