翻译自文章https://www.johnlamp.net/cmake-tutorial.html

CMake是什么?

CMake是开源跨平台的构建工具,由Kitware开发。CMake提供一个简单的构建C/C++项目的方式。实际上CMake不算一个完全的构建工具,它实际上是生成你系统构建工具的配置文件(比如Make)。

CMake允许更灵活的开发环境。CMake包括寻找库的工具,包括CTest,一个测试驱动程序。当配置好怎么运行测试的配置后。CTest会运行所以测试,然后提供测试结果总结。

CMake包含CPack工具,用于打包你的项目,将会到目标设备上安装。

CMake安装

macOS:brew install cmake

Ubuntu: sudo apt-get install cmake

RedHat/CentOS: sudo yum install cmake.x86_64

Windows: 在这个地址下载https://cmake.org/download/

上手练习

在教程中将写一个ToDoList程序,使用命令行来生成Makefile

在VSCode中创建CmakeLists.txt,用于描述你的项目,以及输出什么。

CMakeLists.txt

1
2
project("To Do Lists")
add_executable(toDo main.cc Todo.cc)

project(name): project命令用于命名项目,可以添加项目支持的语言选项,CMake默认为C和CXX,因此如果没有安装C/C++编译环境,就需要指定语言。文档:链接

add_executable(target sources…): 这个命令告诉CMake你希望生成的可执行文件,它将作为target。剩下的是源文件,需要注意的是header files没有列出来,CMake将自动处理依赖关系。文档:链接

剩下的源程序

main.cc

1
2
3
4
5
6
7
8
9
10
11
#include "ToDo.h"

int main(
int argc,
char** argv
)
{
ToDo list;

return 0;
}

ToDo.h

1
2
3
4
5
6
7
8
9
10
11
#ifndef TODO_H
#define TODO_H

class ToDo
{
public:
ToDo();
~ToDo();
};

#endif // TODO_H

ToDo.cc

1
2
3
4
5
6
7
8
9
#include "ToDo.h"

ToDo::ToDo()
{
}

ToDo::~ToDo()
{
}

CMake文档建议在源代码之外构建,也就是构建的结果不混在源码文件中,因此首先创建一个build文件夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 > mkdir build
> cd build
> cmake -G "Unix Makefiles" ..
-- The C compiler identification is GNU 4.2.1
-- The CXX compiler identification is GNU 4.2.1
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build
> ls
CMakeCache.txt Makefile
CMakeFiles cmake_install.cmake
> make
Scanning dependencies of target toDo
[ 50%] Building CXX object CMakeFiles/toDo.dir/main.cc.o
[100%] Building CXX object CMakeFiles/toDo.dir/ToDo.cc.o
Linking CXX executable toDo
[100%] Built target toDo

mkdir build: 创建文件夹用于存放程序。需要把它放在源码外,这样很容易的清理构建结果。

cmake -G "Unix Makefiles" .. :使用CMake构建Unix 的Makefiles,-G用于指定什么类型的项目文件会被生成,这依赖于你的系统,使用cmake —help会列出能够构建的类型。..表示源代码的路径,这个路径需要包括你的顶级CMakeLists.txt文件

make: 使用Makefiles生成目标可执行文件

因为CMake执行的输出十分干净,但这样会让debug更困难。使用make VERBOSE=1来获取所有的输出信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 > cd build
> make VERBOSE=1
/usr/local/Cellar/cmake/2.8.8/bin/cmake -H"/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1" -B"/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build" --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_progress_start "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles" "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles/progress.marks"
make -f CMakeFiles/Makefile2 all
make -f CMakeFiles/toDo.dir/build.make CMakeFiles/toDo.dir/depend
cd "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build" && /usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_depends "Unix Makefiles" "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1" "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1" "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build" "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build" "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles/toDo.dir/DependInfo.cmake" --color=
Dependee "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles/toDo.dir/DependInfo.cmake" is newer than depender "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles/toDo.dir/depend.internal".
Dependee "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles/toDo.dir/depend.internal".
Scanning dependencies of target toDo
make -f CMakeFiles/toDo.dir/build.make CMakeFiles/toDo.dir/build
/usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_progress_report "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles" 1
[ 50%] Building CXX object CMakeFiles/toDo.dir/main.cc.o
/usr/bin/c++ -o CMakeFiles/toDo.dir/main.cc.o -c "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/main.cc"
/usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_progress_report "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles" 2
[100%] Building CXX object CMakeFiles/toDo.dir/ToDo.cc.o
/usr/bin/c++ -o CMakeFiles/toDo.dir/ToDo.cc.o -c "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/ToDo.cc"
Linking CXX executable toDo
/usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_link_script CMakeFiles/toDo.dir/link.txt --verbose=1
/usr/bin/c++ -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/toDo.dir/main.cc.o CMakeFiles/toDo.dir/ToDo.cc.o -o toDo
/usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_progress_report "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles" 1 2
[100%] Built target toDo
/usr/local/Cellar/cmake/2.8.8/bin/cmake -E cmake_progress_start "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step1/build/CMakeFiles" 0

简单的改进

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)

project("To Do List")

enable_testing()


add_executable(toDo main.cc
ToDo.cc)

add_test(toDoTest toDo)

cmake_minimum_required(VERSION version [FATAL_ERROR]):这个命令指定运行CMakeLists.txt至少需要的CMake版本。

set(CMAKE_LEGACY_CYGWIN_WIN32 0): 避免使用Cygwin的警告。

enable_testing() : 启用CMake项目的测试功能,只能在顶层CMakeLists.txt中使用。开启后能够使用add_test()命令

add_test(testname executable arg1 …):使用CTest运行测试,executable可以是测试程序、脚本等,接下来给代码添加测试

main.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;

#include "ToDo.h"

#define EXPECT_EQUAL(test, expect) equalityTest( test, expect, \
#test, #expect, \
__FILE__, __LINE__)

template < typename T1, typename T2 >
int equalityTest(const T1 testValue,
const T2 expectedValue,
const char* testName,
const char* expectedName,
const char* fileName,
const int lineNumber);


int main(
int argc,
char** argv
)
{
int result = 0;

ToDo list;

list.addTask("write code");
list.addTask("compile");
list.addTask("test");

result |= EXPECT_EQUAL(list.size(), 3);
result |= EXPECT_EQUAL(list.getTask(0), "write code");
result |= EXPECT_EQUAL(list.getTask(1), "compile");
result |= EXPECT_EQUAL(list.getTask(2), "test");

if (result == 0)
{
cout << "Test passed" << endl;
}

return result;
}


template < typename T1, typename T2 >
int equalityTest(
const T1 testValue,
const T2 expectedValue,
const char* testName,
const char* expectedName,
const char* fileName,
const int lineNumber
)
{
if (testValue != expectedValue)
{
cerr << fileName << ":" << lineNumber << ": "
<< "Expected " << testName << " "
<< "to equal " << expectedName << " (" << expectedValue << ") "
<< "but it was (" << testValue << ")" << endl;

return 1;
}
else
{
return 0;
}
}

ToDo.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef TODO_H
#define TODO_H

#include <string>
#include <vector>


class ToDo
{
public:
ToDo();
~ToDo();

size_t size() const;

void addTask(const std::string& task);
std::string getTask(size_t index) const;

private:
std::vector< std::string > this_tasks;
};

#endif // TODO_H

ToDo.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "ToDo.h"


ToDo::ToDo()
{
}

ToDo::~ToDo()
{
}


size_t ToDo::size() const
{
return this_tasks.size();
}


void ToDo::addTask(
const std::string& task
)
{
this_tasks.push_back(task);
}

std::string ToDo::getTask(
size_t index
) const
{
if (index < this_tasks.size())
{
return this_tasks[index];
}
else
{
return "";
}
}

接下来像之前那样构建makefiles,然后运行测试make test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 > mkdir build
> cd build
> cmake -G "Unix Makefiles" ..
-- The C compiler identification is GNU 4.2.1
-- The CXX compiler identification is GNU 4.2.1
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/build
> make
Scanning dependencies of target toDo
[ 50%] Building CXX object CMakeFiles/toDo.dir/main.cc.o
[100%] Building CXX object CMakeFiles/toDo.dir/ToDo.cc.o
Linking CXX executable toDo
[100%] Built target toDo
> make test
Running tests...
Test project /Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/build
Start 1: toDoTest
1/1 Test #1: toDoTest ......................... Passed 0.01 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.03 sec
> ls Testing
Temporary
> ls Testing/Temporary
CTestCostData.txt LastTest.log
> cat Testing/Temporary/LastTest.log
Start testing: Jul 16 22:00 EDT
----------------------------------------------------------
1/1 Testing: toDoTest
1/1 Test: toDoTest
Command: "/Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/build/toDo"
Directory: /Volumes/Documents/Programming/C++/CMake Tutorial/flavors/part1_step2/build
"toDoTest" start time: Jul 16 22:00 EDT
Output:
----------------------------------------------------------
Test passed
<end of output>
Test time = 0.01 sec
----------------------------------------------------------
Test Passed.
"toDoTest" end time: Jul 16 22:00 EDT
"toDoTest" time elapsed: 00:00:00
----------------------------------------------------------
End testing: Jul 16 22:00 EDT
> cat Testing/Temporary/CTestCostData.txt
toDoTest 1 0.00976491
---

make test: 因为向CMakelists.txt中添加了enable_testing()方法,这样Makefile里有“test”这个target,这个target会运行CTest来运行所以的测试用例,这里只有一个。

ZMAP的CMakelists.txt阅读

1
2
3
4
5
6
7
8
9
10
11
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
project(ZMAP C)
set(ZMAP_VERSION DEVELOPMENT) # Change DEVELOPMENT to version number for release

option(WITH_REDIS "Build with support for Redis DB" OFF)
option(ENABLE_DEVELOPMENT "Enable development specific compiler and linker flags" OFF)
option(ENABLE_LOG_TRACE "Enable log trace messages" OFF)
option(RESPECT_INSTALL_PREFIX_CONFIG "Respect CMAKE_INSTALL_PREFIX for /etc" OFF)
option(WITH_WERROR "Build with -Werror" OFF)
option(WITH_PFRING "Build with PF_RING ZC for send (10 GigE)" OFF)
option(FORCE_CONF_INSTALL "Overwrites existing configuration files at install" OFF)

set(<variable> <value>... [PARENT_SCOPE]):声明在目前区域的变量

project(<PROJECT-NAME> [LANGUAGES] [<language-name>...]): 项目名zmap,使用C语言

option(<option_variable> "help string describing option" [initial value]): 命令行时的用户选项cmake [{-D <var>=<value>}...],比如cmake -G -DWITH_REDIS=ON -DENABLE_DEVELOPMENT=ON

1
2
3
4
5
6
7
8
9
10
11
12
13
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(USING_CLANG "YES")
else()
set(USING_GCC "YES")
endif()

if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR "${CMAKE_SYSTEM_NAME}" MATCHES "NetBSD" OR "${CMAKE_SYSTEM_NAME}" MATCHES "DragonFly")
set(BSD "YES")
endif()

if("${CMAKE_SYSTEM_NAME}" MATCHES "NetBSD")
set(NetBSD "YES")
endif()

${name}:用于引用变量,更多用在字符串展开。CMAKE_CXX_COMPILER_ID是编译器的厂商信息,CMAKE_SYSTEM_NAME获取操作系统信息

STREQUAL:对比前后两个字符串是否相等

if表达式: 包含许多能够判断的条件关闭,比如变量、<expr1> OR <expr2>TARGET target-nameIS_DIRECTORY path-to-directory等.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
set(GCCWARNINGS
"-Wall -Wformat=2 -Wno-format-nonliteral"
"-pedantic -fno-strict-aliasing"
"-Wextra"
"-Wfloat-equal -Wundef -Wwrite-strings -Wredundant-decls"
"-Wnested-externs -Wbad-function-cast -Winit-self"
"-Wmissing-noreturn"
"-Wstack-protector"
)

# Fix line breaks
string(REPLACE ";" " " GCCWARNINGS "${GCCWARNINGS}")

if(WITH_WERROR)
set(GCCWARNINGS "${GCCWARNINGS} -Werror")
endif()

if(ENABLE_DEVELOPMENT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g")
else()
# Hardening and optimizations for building with gcc
set(GCCHARDENING "-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all -fwrapv -fPIC --param ssp-buffer-size=1")
if(NOT APPLE AND NOT BSD)
set(LDHARDENING "-z relro -z now")
else()
set(LDHARDENING "")
endif()

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCCHARDENING} -O2")
set(CMAKE_EXE_LINKER_FLAGS "${LDHARDENING} ${CMAKE_EXE_LINKER_FLAGS}")
endif()

if(ENABLE_LOG_TRACE)
add_definitions("-DDEBUG")
endif()


set(CMAKE_C_FLAGS "${GCCWARNINGS} ${CMAKE_C_FLAGS}")

string(FUNC, ARGS):使用字符串相关操作。string(REPLACE ";" " " GCCWARNINGS "${GCCWARNINGS}")表示这里使用REPLACE操作string(REPLACE <match-string> <replace-string> <out-var> <input>…), 参考链接

add_definitions(-DFOO -DBAR..):通过编译器命令行添加预定义

可以看到如果打开ENABLE_DEVELOPMENT,生成调试信息,相对于-g选项,-ggdb能够提供最多的编译信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
include(FindPkgConfig)
pkg_check_modules(JSON json-c)
if(JSON_FOUND)
include_directories(${JSON_INCLUDE_DIRS})
else()
message(FATAL_ERROR "Did not find libjson")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${JSON_CFLAGS}")

if(WITH_REDIS)
set(REDIS_LIBS hiredis)
add_definitions("-DREDIS")
endif()

if(WITH_PFRING)
add_definitions("-DPFRING")
set(PFRING_LIBRARIES pfring rt numa)
endif()

# Standard FLAGS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
if(NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
endif()

# Set up OS-specific include directories
if(APPLE)
if(EXISTS /opt/local/include)
include_directories(/opt/local/include)
endif()
if(EXISTS /opt/local/lib)
link_directories(/opt/local/lib)
endif()
if(EXISTS /usr/local/include)
include_directories(/usr/local/include)
endif()
if(EXISTS /usr/local/lib)
link_directories(/usr/local/lib)
endif()
endif()

if(BSD)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
endif()

if(NetBSD)
include_directories(/usr/pkg/include)
link_directories(/usr/pkg/lib)
endif()

add_subdirectory(lib)
add_subdirectory(src)

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>] [NO_POLICY_SCOPE]): 加载并运行指定文件(模块)里的cmake代码。这里加载模块pkg_check_modules

pkg_check_modules(<PREFIX> [REQUIRED] [QUIET] <MODULE> [<MODULE>]*) :检测所有给定的模块是否存在,pkg_check_modules(JSON json-c)检查json-c模块是否存在,JSON_FOUND表示模块是否存在。参考文档

JSON_LIBRARY_DIRS:由<PREFIX>_LIBRARY_DIRS组成,表示到目标模块的路径

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]):添加相关文件夹来给编译器搜索include文件

link_directories([AFTER|BEFORE] directory1 [directory2 ...]):添加相关库的路径,用于linker来链接

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL]):添加子目录,需要子目录也有cmakelists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Install conf files
if(RESPECT_INSTALL_PREFIX_CONFIG)
set(CONFIG_DESTINATION "etc/zmap")
else()
set(CONFIG_DESTINATION "/etc/zmap")
endif()

FILE(GLOB CONF_FILES "${PROJECT_SOURCE_DIR}/conf/*")

message(STATUS "Default ZMap configuration file location is /etc/zmap")
foreach(EACH_CONF ${CONF_FILES})
get_filename_component(CONF_BASENAME ${EACH_CONF} NAME)
message(STATUS "Checking if ${CONF_BASENAME} exists there...")
if(NOT EXISTS "/etc/zmap/${CONF_BASENAME}")
install(FILES ${EACH_CONF} DESTINATION ${CONFIG_DESTINATION})
elseif(FORCE_CONF_INSTALL)
message(WARNING "FORCE_CONF_INSTALL will overwrite any exsiting configuration files")
install(FILES ${EACH_CONF} DESTINATION ${CONFIG_DESTINATION})
else()
message(WARNING "Existing configuration file detected at /etc/zmap/${CONF_BASENAME}, ${CONF_BASENAME} from sources will NOT be installed. Please check and install manually!")
endif()
endforeach()

File(FUNC, ARGS):File操作命令,FILE(GLOB CONF_FILES "${PROJECT_SOURCE_DIR}/conf/*")中GLOB表示Globbing通配符,也就是将通配符匹配的文件列表存入CONF_FILES这个变量中。

foreach:遍历列表

get_filename_component(CONF_BASENAME ${EACH_CONF} NAME):获取${EACH_CONF}路径中的文件名(NAME)存放到CONF_BASENAME中

install: 将文件存放到指定位置,install(FILES, …)指定了是文件形式,还有PROGRAMS形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Allow Debian Packaging
include(InstallRequiredSystemLibraries)

set(CPACK_SET_DESTDIR "on")
set(CPACK_PACKAGING_INSTALL_PREFIX "/tmp")
set(CPACK_GENERATOR "DEB")

set(${VERSION} CPACK_DEBIAN_PACKAGE_VERSION)
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_SECTION "network")
set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.1.3), libgmp10, libpcap0.8, libjson-c-dev")

set(CPACK_PACKAGE_DESCRIPTION "Internet-scale network scanner")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ZMap is an open source network scanner that enables researchers to easily perform Internet-wide network studies. With a single machine and a well provisioned network uplink, ZMap is capable of performing a complete scan of the IPv4 address space in under five minutes, approaching the theoretical limit of gigabit Ethernet. ZMap can be used to study protocol adoption over time, monitor service availability, and help us better understand large systems distributed across the Internet.")
set(CPACK_PACKAGE_CONTACT "Zakir Durumeric <zakird@gmail.com>")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_ARCHITECTURE}")

set(CPACK_COMPONENTS_ALL Libraries ApplicationData)

include(CPack)

InstallRequiredSystemLibraries:这个模块用于搜索编译器提供的系统运行时库,添加相关规则。

CPack:这个模块用于生成多种形式的二进制和源码安装器

常用信息

常用变量

CMAKE_MAJOR_VERSION,CMAKE 主版本号,比如2.4.6 中的2

CMAKE_MINOR_VERSION,CMAKE 次版本号,比如2.4.6 中的4

CMAKE_PATCH_VERSION,CMAKE 补丁等级,比如2.4.6 中的6

CMAKE_SYSTEM ,系统名称,比如Linux-2.6.22

CMAKE_SYSTEM_NAME ,不包含版本的系统名,比如Linux

CMAKE_SYSTEM_VERSION ,系统版本,比如2.6.22

CMAKE_SYSTEM_PROCESSOR,处理器名称,比如i686.

UNIX ,在所有的类UNIX平台为TRUE,包括OS X 和cygwin

WIN32 ,在所有的win32 平台为TRUE,包括cygwin

常用开关变量:

CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ,用来控制IF ELSE 语句的书写方式,在下一节语法部分会讲到。

BUILD_SHARED_LIBS

这个开关用来控制默认的库编译方式,如果不进行设置,使用ADD_LIBRARY 并没有指定库类型的情况下,默认编译生成的库都是静态库。如果SET(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库。

CMAKE_C_FLAGS 设置C编译选项,也可以通过指令ADD_DEFINITIONS() 添加。

CMAKE_CXX_FLAGS 设置C++ 编译选项,也可以通过指令ADD_DEFINITIONS() 添加。

环境变量

MESSAGE(STATUS “HOME dir: $ENV{HOME}”)