什么是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