Preface:This article is written for a nifty girl who I cherish.
(0)Preparation
- Clone repository
git clone https://github.com/Kitware/CMake.git
- Direct to the tutorial folder
cd CMake/Help/guide/tutorial
- Open website Cmake tutorial
(1)Step 1
- Description: 这一节主要介绍如何创建一个基本的CMakeLists.txt 文件
- Files organized frame:
.
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Tutorial VERSION 1.0)
#specify the c++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# add the executable
add_executable(Tutorial tutorial.cxx)
#To transfer version information to TutorialConfig.h
configure_file(TutorialConfig.h.in TutorialConfig.h)
#Since the configured file will be written into the binary tree, we must add that directory to the list of paths to search for include files
target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" )
- Highlights:
PROJECT_BINARY_DIR 指的当前cmake的build文件夹
CMakeLists.txt 文件名的大小写不可搞错
(2)Step2
- Description: 创建一个库,为工程添加一个库,这里的库的思想是将工程划分为不同的部分,库为主文件提供调用、接口与抽象。
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cxx)
- CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR}/MathFunctions"
)
- Or optional choice for MathFunctions library, like this:
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
#option will be written to TutorialConfig.h
#option(USE_MYMATH "Use tutorial provided math implementation" OFF)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
cmake with :
cmake ../Step2 -DUSE_MYMATH=OFF
- Highlights:
steps to add a library:
1.add_subdirectory before add_executable
2.target_link_libraries after add_executable, cause linking procedure happens after create executable file
3.target_include_directories in the last
(3)Step3
- Description: 更为便捷的添加library的方法,体现在更少修改源文件的CMakeLists.txt
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cxx)
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
- CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
#option(USE_MYMATH "Use tutorial provided math implementation" on)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
cmake with:
cmake ../Step2 -DUSE_MYMATH=OFF
(4)Step4
- Description: 安装与测试检验
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
-CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include
)
enable_testing()
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
# does the usage message work?
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
)
# define a function to simplify adding tests
function(do_test target arg result)
add_test(NAME Comp${arg} COMMAND ${target} ${arg})
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
endfunction(do_test)
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is [-nan|nan|0]")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
cmake with:
cmake --install .
make
ctest -vv
(5)Step5
- Description: 根据文件包含函数(或变量)与否,执行不同操作
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# install rules
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
include(CheckSymbolExists)
check_symbol_exists(log "Math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP))
unset(HAVE_LOG CACHE)
unset(HAVE_EXP CACHE)
set(CMAKE_REQUIRED_LIBRARIES "m")
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(HAVE_LOG AND HAVE_EXP)
target_link_libraries(MathFunctions PRIVATE m)
endif()
endif()
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(MathFunctions
PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()
(6)Step6
- Description: 生成查询表
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-MathFunctions
|-Table.h
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- MathFunctions/CMakeLists.txt
add_library(MathFunctions
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
# does this system provide the log and exp functions?
include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(NOT (HAVE_LOG AND HAVE_EXP))
unset(HAVE_LOG CACHE)
unset(HAVE_EXP CACHE)
set(CMAKE_REQUIRED_LIBRARIES "m")
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)
if(HAVE_LOG AND HAVE_EXP)
target_link_libraries(MathFunctions PRIVATE m)
endif()
endif()
# add compile definitions
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(MathFunctions
PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()
# install rules
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
add_executable(MakeTable MakeTable.cxx)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
(7)Step7
- Description: 打包安装器,既提供源码又提供二进制代码
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
- CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
)
# add the install targets
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include
)
# enable testing
enable_testing()
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
# does the usage message work?
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
)
# define a function to simplify adding tests
function(do_test target arg result)
add_test(NAME Comp${arg} COMMAND ${target} ${arg})
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
endfunction(do_test)
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is [-nan|nan|0]")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
include(CPack)
(8)Step8
- Description: 测试并将测试提交到dashboard
- Files organized frame:
.
|-MathFunctions
|-MathFunctions.h
|-mysqrt.cxx
|-CMakeLists.txt
|-build
|-TutorialConfig.h
|-CMakeLists.txt
|-tutorial.cxx
|-TutorialConfig.h.in
|-License.txt
|-CTestConfig.cmake
- CMakeLists.txt
替换enable_testing()
为includeinclude(CTest)