什么是cmake
由官网的介绍,cmake是一套开源的跨平台的工具库,这套库用来控制软件开发中的构建(build), 测试(test),封装(package)的。cmake同时简单的与平台和编译器无关的配置文件来控制编译过程,生成所在平台的Makefile或workspaces,并且你可以设置这些文件中的编译环境。
cmake提供了什么
-
generator
cmake通过提供多种与所在平台可用的构建工具对应的generators,来生成构建工具的input文件(eg. Makefile)。 比如在Mac平台上的generator有:
The following generators are available on this platform (* marks default): * Unix Makefiles = Generates standard UNIX makefiles. Ninja = Generates build.ninja files. Xcode = Generate Xcode project files. CodeBlocks - Ninja = Generates CodeBlocks project files. CodeBlocks - Unix Makefiles = Generates CodeBlocks project files. CodeLite - Ninja = Generates CodeLite project files. CodeLite - Unix Makefiles = Generates CodeLite project files. Sublime Text 2 - Ninja = Generates Sublime Text 2 project files. Sublime Text 2 - Unix Makefiles = Generates Sublime Text 2 project files. Kate - Ninja = Generates Kate project files. Kate - Unix Makefiles = Generates Kate project files. Eclipse CDT4 - Ninja = Generates Eclipse CDT 4.0 project files. Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.
generator 生成构建工具使用一个叫CMakeLists.txt的脚本文件,这个文件中定义了cmake所要执行的命令。
-
CMakeLists.txt
编写CMakeLists.txt要使用cmake提供的
- 命令(command)
- 流程控制命令(if, else等)
- 包/库查找命令 (find_package,find_library等)
- 添加目标命令(add_executable, add_library, add_subdirectory 等)
- include命令 (include_directories等)
- link命令(link_libraries, link_directoriestarget_link_libraries等)
- 设置/获取变量(set get_property等)
- 模块(module)
- FindXXX模块: 查找XXX包/库,并设置相关的变量,e.g. XXX_FOUND, XXX_VERSION
- CheckXXX模块: e.g. CheckFunctionExists, CheckIncludeFiles, CPack, CTest
- 等等
-
属性(property) 提供了一些接口可以配置目标的编译选项或其他选项 e.g.LINK_OPTIONS, COMPILE_FLAGS
- 变量(variables) 由cmake提供的变量,这些变量对写CMakeLists.txt很有意义 e.g. ANDROID APPLE BORLAND IOS LIBRARY_OUTPUT_PATH MINGW MSVC
- 命令(command)
例子
tutorial.cxx
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "mysqrt.h"
#endif
int main(int argc, char *argv[])
{
if(argc < 2)
{
fprintf(stdout, "%s Version %d.%d\n",
argv[0],
Tutorial_VERSION_MAJOR,
Tutorial_VERSION_MINOR);
fprintf(stdout, "Usage: %s number\n", argv[0]);
return 1;
}
double inputvalue = atof(argv[1]);
#if defined(HAVE_LOG) && defined(HAVE_EXP)
double outputvalue = exp(log(inputvalue)*0.5);
#else
#ifdef USE_MYMATH
double outputvalue = InvSqrt(inputvalue);
#else
double outputvalue = sqrt(inputvalue);
#endif
#endif
fprintf(stdout, "The square root of %g is %g\n",
inputvalue,outputvalue);
return 0;
}
MathFunctions/mysqrt.cpp
float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating VALUE
i = 0x5f375a86- (i>>1); // gives initial guess y0
x = *(float*)&i; // convert bits BACK to float
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
return 1/x;
}
MathFunctions/mysqrt.h
float InvSqrt(float x);
MathFunctions/CMakeLists.txt
# add static library MathFunctions with source code mysqrt.cxx
add_library(MathFunctions SHARED mysqrt.cxx)
set_target_properties(MathFunctions PROPERTIES VERSION 1.2)
install(TARGETS MathFunctions DESTINATION bin)
install(FILES mysqrt.h DESTINATION include)
TutorialConfig.h.in
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP
CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(Tutorial)
# 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)
# 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 the TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
# should we use our own math functions
option(USE_MYMATH "USE tutorial provided math implementation" ON)
if(USE_MYMATH)
# add the mysqrt.h
include_directories("${PROJECT_SOURCE_DIR}/MathFunctions")
# the source code mysqrt.cxx
add_subdirectory(MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif(USE_MYMATH)
# add the add_executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial ${EXTRA_LIBS})
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include)
enable_testing()
#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_test(25 "25 is 5")
do_test(0.01 "0.01 is 0.1")
# 构建一个 CPack 安装包
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)
# Build and Install
mkdir -p build && cd build
cmake -DCMAKE_INSTALL_PREFIX=$HOME/usr/local ..
make && make test && make install
# Pack
cpack -C CPackConfig.cmake # cpack -C CPackSourceConfig.cmake