历史
CMake是为了解决美国国家医学图书馆出资的Visible Human Project专案下的Insight Segmentation and Registration Toolkit (ITK) 软件的跨平台建构的需求而创造出来的,其设计受到了Ken Martin开发的pcmaker所影响。pcmaker当初则是为了支援Visualization Toolkit这个开放源代码的三维图形和视觉系统才出现的,今日VTK也采用了CMake。在设计CMake之时,Kitware公司的Bill Hoffman采用了pcmaker的一些重要想法,加上更多他自己的点子,想把GNU建构系统的一些功能整合进来。CMake最初的实作是在2000年中作的,在2001年初有了急速的进展,许多改良是来自其他把CMake整合到自己的系统中的开发者,比方说,采用CMake作为建构环境的VXL社群就贡献了很多重要的功能,Brad King为了支援CABLE和GCC-XML这套自动包装工具也加了几项功能,奇异公司的研发部门则用在内部的测试系统DART,还有一些功能是为了让VTK可以过渡到CMake和支援(“美国Los Alamos国家实验室”&“洛斯阿拉莫斯国家实验室”)的Advanced Computing Lab的平行视觉系统ParaView而加的。
官网的教程
传送门
本章节将会按照官方网站里面提到的步骤来学习cmake的基本用法。
编译一个exe
CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cxx)
tutorial.cxx
// tutorial.cxx
#include <stdio.h>
int main (int argc, char *argv[])
{
//...
printf("hello");
return 0;
}
使用版本号定义
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
# add the executable
add_executable(Tutorial tutorial.cxx)
TutorialConfig.h.in文件中编写这个内容
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
最后将会生成代码TutorialConfig.h
在源码里面我们能很方便的使用
#include "TutorialConfig.h"
fprintf(stdout,"%s Version %d.%d\n",
argv[0],
Tutorial_VERSION_MAJOR,
Tutorial_VERSION_MINOR);
使用自己的lib库
# should we use our own math functions?
option (USE_MYMATH
"Use tutorial provided math implementation" ON)
add_library(MathFunctions mysqrt.cxx)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)
# add the MathFunctions library?
#
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial ${EXTRA_LIBS})
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
#endif
#cmakedefine USE_MYMATH
安装与测试
将安装的文件拷贝到指定的目录中。
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)
# add the install targets
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include)
先引入这个模块
include(CTest)
通过编写的宏来检查当前的测试是否能通过。
#define a macro to simplify adding tests, then use it
macro (do_test arg result)
add_test (TutorialComp${arg} Tutorial ${arg})
set_tests_properties (TutorialComp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
# do a bunch of result based tests
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")
平台检查
添加检查
# does this system provide the log and exp functions?
include (CheckFunctionExists)
check_function_exists (log HAVE_LOG)
check_function_exists (exp HAVE_EXP)
通过这个来检查当前平台是否存在log,exp函数,如果有将直接在代码里面使用系统的支持函数。
console
// does the platform provide exp and log functions?
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP
代码
// if we have both log and exp then use them
#if defined (HAVE_LOG) && defined (HAVE_EXP)
result = exp(log(x)*0.5);
#else // otherwise use an iterative approach
. . .
自定义选项
用于制作条件打开某个功能。
# 设置一个OctSvr的开关,默认设置为OFF
option (OctSvr "OctSvr" OFF)
if (OctSvr)
# 做一些开关内的事情。
endif (OctSvr)
# 在命令行中手动的打开或这关闭
cmake -DOctSvr=[ON|OFF(default)]
开启c++ 17
// windows
add_compile_options("/std:c++17")
// linux
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 ")
目录文件批量添加
file(GLOB pbc_SRC "3rd/pbc/src/*.h" "3rd/pbc/src/*.c" )
设置cmake工程依赖关系
add_subdirectory(common)
add_subdirectory(chuanqi_robot)
add_dependencies(chuanqi_robot common)
执行程序
添加一个生成文件和生成器
这个实例是编写了一个table生成的execute文件,生成一个开方的文件出来。然后通过cmake集成到编译过程中。
MakeTable.cxx文件中实现了一个可以生成table的一个程序
// A simple program that builds a sqrt table
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (int argc, char *argv[])
{
int i;
double result;
// make sure we have enough arguments
if (argc < 2)
{
return 1;
}
// open the output file
FILE *fout = fopen(argv[1],"w");
if (!fout)
{
return 1;
}
// create a source file with a table of square roots
fprintf(fout,"double sqrtTable[] = {\n");
for (i = 0; i < 10; ++i)
{
result = sqrt(static_cast<double>(i));
fprintf(fout,"%g,\n",result);
}
// close the table with a zero
fprintf(fout,"0};\n");
fclose(fout);
return 0;
}
这里的cmakefile.txt文件中说明要如何生成这个MakeTable,之后添加了一个add_custom_command的命令,用于将一个table.h生成出来。
通过include_directories将本地目录加入到include搜索目录,并且在编译MathFunctions这个library库的时候,添加上Table.h的依赖。
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
# add the command to generate the source code
add_custom_command (
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
# add the binary tree directory to the search path for
# include files
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
# add the main library
add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h )
现在完整的cmake
# CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
include(CTest)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# does this system provide the log and exp functions?
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (log HAVE_LOG)
check_function_exists (exp HAVE_EXP)
# 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 (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories ("${PROJECT_BINARY_DIR}")
# add the MathFunctions library?
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial ${EXTRA_LIBS})
# add the install targets
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include)
# does the application run
add_test (TutorialRuns Tutorial 25)
# does the usage message work?
add_test (TutorialUsage Tutorial)
set_tests_properties (TutorialUsage
PROPERTIES
PASS_REGULAR_EXPRESSION "Usage:.*number"
)
#define a macro to simplify adding tests
macro (do_test arg result)
add_test (TutorialComp${arg} Tutorial ${arg})
set_tests_properties (TutorialComp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
endmacro (do_test)
# do a bunch of result based tests
do_test (4 "4 is 2")
do_test (9 "9 is 3")
do_test (5 "5 is 2.236")
do_test (7 "7 is 2.645")
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")
do_test (0.0001 "0.0001 is 0.01")
btw: 今天发现在mac机器上dll文件换了个后缀,叫做*.dylib文件。_