├── .gitignore ├── Demo1 ├── CMakeLists.txt └── main.cc ├── Demo2 ├── CMakeLists.txt ├── MathFunctions.cc ├── MathFunctions.h └── main.cc ├── Demo3 ├── CMakeLists.txt ├── main.cc └── math │ ├── CMakeLists.txt │ ├── MathFunctions.cc │ └── MathFunctions.h ├── Demo4 ├── CMakeLists.txt ├── config.h.in ├── main.cc └── math │ ├── CMakeLists.txt │ ├── MathFunctions.cc │ └── MathFunctions.h ├── Demo5 ├── CMakeLists.txt ├── config.h.in ├── main.cc └── math │ ├── CMakeLists.txt │ ├── MathFunctions.cc │ └── MathFunctions.h ├── Demo6 ├── CMakeLists.txt ├── config.h.in ├── main.cc └── math │ ├── CMakeLists.txt │ ├── MathFunctions.cc │ └── MathFunctions.h ├── Demo7 ├── CMakeLists.txt ├── config.h.in ├── main.cc └── math │ ├── CMakeLists.txt │ ├── MathFunctions.cc │ └── MathFunctions.h ├── Demo8 ├── CMakeLists.txt ├── License.txt ├── config.h.in ├── main.cc └── math │ ├── CMakeLists.txt │ ├── MathFunctions.cc │ └── MathFunctions.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /Demo1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | project (Demo1) 4 | add_executable(Demo main.cc) 5 | -------------------------------------------------------------------------------- /Demo1/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * power - Calculate the power of number. 6 | * @param base: Base value. 7 | * @param exponent: Exponent value. 8 | * 9 | * @return base raised to the power exponent. 10 | */ 11 | double power(double base, int exponent) 12 | { 13 | int result = base; 14 | int i; 15 | 16 | if (exponent == 0) { 17 | return 1; 18 | } 19 | 20 | for(i = 1; i < exponent; ++i){ 21 | result = result * base; 22 | } 23 | 24 | return result; 25 | } 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | if (argc < 3){ 30 | printf("Usage: %s base exponent \n", argv[0]); 31 | return 1; 32 | } 33 | double base = atof(argv[1]); 34 | int exponent = atoi(argv[2]); 35 | double result = power(base, exponent); 36 | printf("%g ^ %d is %g\n", base, exponent, result); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Demo2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required (VERSION 2.8) 3 | 4 | # 项目信息 5 | project (Demo2) 6 | 7 | # 查找目录下的所有源文件 8 | # 并将名称保存到 DIR_SRCS 变量 9 | aux_source_directory(. DIR_SRCS) 10 | 11 | # 指定生成目标 12 | add_executable(Demo ${DIR_SRCS}) 13 | -------------------------------------------------------------------------------- /Demo2/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Demo2/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Demo2/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "MathFunctions.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | if (argc < 3){ 8 | printf("Usage: %s base exponent \n", argv[0]); 9 | return 1; 10 | } 11 | double base = atof(argv[1]); 12 | int exponent = atoi(argv[2]); 13 | double result = power(base, exponent); 14 | printf("%g ^ %d is %g\n", base, exponent, result); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Demo3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required (VERSION 2.8) 3 | 4 | # 项目信息 5 | project (Demo3) 6 | 7 | # 查找目录下的所有源文件 8 | # 并将名称保存到 DIR_SRCS 变量 9 | aux_source_directory(. DIR_SRCS) 10 | 11 | # 添加 math 子目录 12 | add_subdirectory(math) 13 | 14 | # 指定生成目标 15 | add_executable(Demo ${DIR_SRCS}) 16 | 17 | # 添加链接库 18 | target_link_libraries(Demo MathFunctions) -------------------------------------------------------------------------------- /Demo3/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "math/MathFunctions.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | if (argc < 3){ 8 | printf("Usage: %s base exponent \n", argv[0]); 9 | return 1; 10 | } 11 | double base = atof(argv[1]); 12 | int exponent = atoi(argv[2]); 13 | double result = power(base, exponent); 14 | printf("%g ^ %d is %g\n", base, exponent, result); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Demo3/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 查找当前目录下的所有源文件 2 | # 并将名称保存到 DIR_LIB_SRCS 变量 3 | aux_source_directory(. DIR_LIB_SRCS) 4 | 5 | # 指定生成 MathFunctions 链接库 6 | add_library (MathFunctions ${DIR_LIB_SRCS}) 7 | -------------------------------------------------------------------------------- /Demo3/math/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Demo3/math/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Demo4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required (VERSION 2.8) 3 | 4 | # 项目信息 5 | project (Demo4) 6 | 7 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 8 | 9 | # 是否使用自己的 MathFunctions 库 10 | option (USE_MYMATH 11 | "Use provided math implementation" ON) 12 | 13 | # 加入一个配置头文件,用于处理 CMake 对源码的设置 14 | configure_file ( 15 | "${PROJECT_SOURCE_DIR}/config.h.in" 16 | "${PROJECT_BINARY_DIR}/config.h" 17 | ) 18 | 19 | # 是否加入 MathFunctions 库 20 | if(USE_MYMATH) 21 | # 将math添加到include路径中 22 | # 这样cmake在编译过程中就能直接找到math中的头文件 23 | # 编写main的时候就不需要include相对路径了 24 | include_directories("${PROJECT_SOURCE_DIR}/math") 25 | add_subdirectory(math) 26 | # 将 EXTRA_LIBS 的值与字符串 "MathFunctions" 连接,重新赋值给 EXTRA_LIBS 27 | set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 28 | else() 29 | # 不链接math库会报错,因为linux中默认没有math库 30 | LINK_LIBRARIES(m) 31 | endif(USE_MYMATH) 32 | 33 | # 查找当前目录下的所有源文件 34 | # 并将名称保存到 DIR_SRCS 变量 35 | aux_source_directory(. DIR_SRCS) 36 | 37 | # 指定生成目标 38 | add_executable (Demo ${DIR_SRCS}) 39 | target_link_libraries (Demo ${EXTRA_LIBS}) 40 | -------------------------------------------------------------------------------- /Demo4/config.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine USE_MYMATH 2 | -------------------------------------------------------------------------------- /Demo4/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef USE_MYMATH 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | if (argc < 3){ 15 | printf("Usage: %s base exponent \n", argv[0]); 16 | return 1; 17 | } 18 | 19 | double base = atof(argv[1]); 20 | int exponent = atoi(argv[2]); 21 | 22 | #ifdef USE_MYMATH 23 | printf("Now we use our own Math library. \n"); 24 | double result = power(base, exponent); 25 | #else 26 | printf("Now we use the standard library. \n"); 27 | double result = pow(base, exponent); 28 | #endif 29 | 30 | printf("%g ^ %d is %g\n", base, exponent, result); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /Demo4/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 查找当前目录下的所有源文件 2 | # 并将名称保存到 DIR_LIB_SRCS 变量 3 | aux_source_directory(. DIR_LIB_SRCS) 4 | 5 | # 指定生成 MathFunctions 链接库 6 | add_library (MathFunctions ${DIR_LIB_SRCS}) -------------------------------------------------------------------------------- /Demo4/math/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Demo4/math/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Demo5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required (VERSION 2.8) 3 | 4 | # 项目信息 5 | project (Demo5) 6 | 7 | set (CMAKE_INCLUDE_CURRENT_DIR ON) 8 | 9 | # 加入一个配置头文件,用于处理 CMake 对源码的设置 10 | configure_file ( 11 | "${PROJECT_SOURCE_DIR}/config.h.in" 12 | "${PROJECT_BINARY_DIR}/config.h" 13 | ) 14 | 15 | # 是否使用自己的 MathFunctions 库 16 | option (USE_MYMATH 17 | "Use provided math implementation" ON) 18 | 19 | # 是否加入 MathFunctions 库 20 | if (USE_MYMATH) 21 | include_directories ("${PROJECT_SOURCE_DIR}/math") 22 | add_subdirectory (math) 23 | set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 24 | endif (USE_MYMATH) 25 | 26 | # 查找当前目录下的所有源文件 27 | # 并将名称保存到 DIR_SRCS 变量 28 | aux_source_directory(. DIR_SRCS) 29 | 30 | # 指定生成目标 31 | add_executable(Demo ${DIR_SRCS}) 32 | target_link_libraries (Demo ${EXTRA_LIBS}) 33 | 34 | # 指定安装路径 35 | install (TARGETS Demo DESTINATION bin) 36 | install (FILES "${PROJECT_BINARY_DIR}/config.h" 37 | DESTINATION include) 38 | 39 | # 启用测试 40 | enable_testing() 41 | 42 | # 测试程序是否成功运行 43 | add_test (test_run Demo 5 2) 44 | 45 | # 测试帮助信息是否可以正常提示 46 | add_test (test_usage Demo) 47 | set_tests_properties (test_usage 48 | PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent") 49 | 50 | # 测试 5 的平方 51 | # add_test (test_5_2 Demo 5 2) 52 | 53 | # set_tests_properties (test_5_2 54 | # PROPERTIES PASS_REGULAR_EXPRESSION "is 25") 55 | 56 | # 测试 10 的 5 次方 57 | # add_test (test_10_5 Demo 10 5) 58 | 59 | # set_tests_properties (test_10_5 60 | # PROPERTIES PASS_REGULAR_EXPRESSION "is 100000") 61 | 62 | # 测试 2 的 10 次方 63 | # add_test (test_2_10 Demo 2 10) 64 | 65 | # set_tests_properties (test_2_10 66 | # PROPERTIES PASS_REGULAR_EXPRESSION "is 1024") 67 | 68 | # 定义一个宏,用来简化测试工作 69 | macro (do_test arg1 arg2 result) 70 | add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2}) 71 | set_tests_properties (test_${arg1}_${arg2} 72 | PROPERTIES PASS_REGULAR_EXPRESSION ${result}) 73 | endmacro (do_test) 74 | 75 | # 利用 do_test 宏,测试一系列数据 76 | do_test (5 2 "is 25") 77 | do_test (10 5 "is 100000") 78 | do_test (2 10 "is 1024") 79 | -------------------------------------------------------------------------------- /Demo5/config.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine USE_MYMATH 2 | -------------------------------------------------------------------------------- /Demo5/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef USE_MYMATH 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | if (argc < 3){ 15 | printf("Usage: %s base exponent \n", argv[0]); 16 | return 1; 17 | } 18 | double base = atof(argv[1]); 19 | int exponent = atoi(argv[2]); 20 | 21 | #ifdef USE_MYMATH 22 | printf("Now we use our own Math library. \n"); 23 | double result = power(base, exponent); 24 | #else 25 | printf("Now we use the standard library. \n"); 26 | double result = pow(base, exponent); 27 | #endif 28 | printf("%g ^ %d is %g\n", base, exponent, result); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Demo5/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 查找当前目录下的所有源文件 2 | # 并将名称保存到 DIR_LIB_SRCS 变量 3 | aux_source_directory(. DIR_LIB_SRCS) 4 | 5 | # 指定生成 MathFunctions 链接库 6 | add_library (MathFunctions ${DIR_LIB_SRCS}) 7 | 8 | # 指定 MathFunctions 库的安装路径 9 | install (TARGETS MathFunctions DESTINATION lib) 10 | install (FILES MathFunctions.h DESTINATION include) 11 | -------------------------------------------------------------------------------- /Demo5/math/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Demo5/math/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Demo6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake 最低版本号要求 2 | cmake_minimum_required (VERSION 2.8) 3 | 4 | # 项目信息 5 | project (Demo6) 6 | 7 | set (CMAKE_INCLUDE_CURRENT_DIR ON) 8 | 9 | # 检查系统是否支持 pow 函数 10 | include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) 11 | check_function_exists (pow HAVE_POW) 12 | 13 | # 加入一个配置头文件,用于处理 CMake 对源码的设置 14 | configure_file ( 15 | "${PROJECT_SOURCE_DIR}/config.h.in" 16 | "${PROJECT_BINARY_DIR}/config.h" 17 | ) 18 | 19 | # 是否加入 MathFunctions 库 20 | if (NOT HAVE_POW) 21 | include_directories ("${PROJECT_SOURCE_DIR}/math") 22 | add_subdirectory (math) 23 | set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 24 | endif (NOT HAVE_POW) 25 | 26 | # 查找当前目录下的所有源文件 27 | # 并将名称保存到 DIR_SRCS 变量 28 | aux_source_directory(. DIR_SRCS) 29 | 30 | # 指定生成目标 31 | add_executable(Demo ${DIR_SRCS}) 32 | target_link_libraries (Demo ${EXTRA_LIBS}) 33 | 34 | # 指定安装路径 35 | install (TARGETS Demo DESTINATION bin) 36 | install (FILES "${PROJECT_BINARY_DIR}/config.h" 37 | DESTINATION include) 38 | 39 | # 启用测试 40 | enable_testing() 41 | 42 | # 测试程序是否成功运行 43 | add_test (test_run Demo 5 2) 44 | 45 | # 测试帮助信息是否可以正常提示 46 | add_test (test_usage Demo) 47 | set_tests_properties (test_usage 48 | PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent") 49 | 50 | # 定义一个宏,用来简化测试工作 51 | macro (do_test arg1 arg2 result) 52 | add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2}) 53 | set_tests_properties (test_${arg1}_${arg2} 54 | PROPERTIES PASS_REGULAR_EXPRESSION ${result}) 55 | endmacro (do_test) 56 | 57 | # 利用 do_test 宏,测试一系列数据 58 | do_test (5 2 "is 25") 59 | do_test (10 5 "is 100000") 60 | do_test (2 10 "is 1024") 61 | -------------------------------------------------------------------------------- /Demo6/config.h.in: -------------------------------------------------------------------------------- 1 | // does the platform provide pow function? 2 | #cmakedefine HAVE_POW 3 | -------------------------------------------------------------------------------- /Demo6/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HAVE_POW 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | if (argc < 3){ 14 | printf("Usage: %s base exponent \n", argv[0]); 15 | return 1; 16 | } 17 | double base = atof(argv[1]); 18 | int exponent = atoi(argv[2]); 19 | 20 | #ifdef HAVE_POW 21 | printf("Now we use the standard library. \n"); 22 | double result = pow(base, exponent); 23 | #else 24 | printf("Now we use our own Math library. \n"); 25 | double result = power(base, exponent); 26 | #endif 27 | 28 | printf("%g ^ %d is %g\n", base, exponent, result); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Demo6/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 查找当前目录下的所有源文件 2 | # 并将名称保存到 DIR_LIB_SRCS 变量 3 | aux_source_directory(. DIR_LIB_SRCS) 4 | 5 | # 指定生成 MathFunctions 链接库 6 | add_library (MathFunctions ${DIR_LIB_SRCS}) 7 | 8 | # 指定 MathFunctions 库的安装路径 9 | install (TARGETS MathFunctions DESTINATION lib) 10 | install (FILES MathFunctions.h DESTINATION include) 11 | -------------------------------------------------------------------------------- /Demo6/math/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Demo6/math/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Demo7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | # 项目信息 4 | project (Demo7) 5 | set (Demo_VERSION_MAJOR 1) 6 | set (Demo_VERSION_MINOR 0) 7 | 8 | set (CMAKE_INCLUDE_CURRENT_DIR ON) 9 | 10 | # 检查系统是否支持 pow 函数 11 | include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) 12 | check_function_exists (pow HAVE_POW) 13 | 14 | # 加入一个配置头文件,用于处理 CMake 对源码的设置 15 | configure_file ( 16 | "${PROJECT_SOURCE_DIR}/config.h.in" 17 | "${PROJECT_BINARY_DIR}/config.h" 18 | ) 19 | 20 | # 是否加入 MathFunctions 库 21 | if (NOT HAVE_POW) 22 | include_directories ("${PROJECT_SOURCE_DIR}/math") 23 | add_subdirectory (math) 24 | set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 25 | endif (NOT HAVE_POW) 26 | 27 | # 查找当前目录下的所有源文件 28 | # 并将名称保存到 DIR_SRCS 变量 29 | aux_source_directory(. DIR_SRCS) 30 | 31 | # 指定生成目标 32 | add_executable(Demo ${DIR_SRCS}) 33 | target_link_libraries (Demo ${EXTRA_LIBS}) 34 | 35 | # 指定安装路径 36 | install (TARGETS Demo DESTINATION bin) 37 | install (FILES "${PROJECT_BINARY_DIR}/config.h" 38 | DESTINATION include) 39 | 40 | # 启用测试 41 | enable_testing() 42 | 43 | # 测试程序是否成功运行 44 | add_test (test_run Demo 5 2) 45 | 46 | # 测试帮助信息是否可以正常提示 47 | add_test (test_usage Demo) 48 | set_tests_properties (test_usage 49 | PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent") 50 | 51 | # 定义一个宏,用来简化测试工作 52 | macro (do_test arg1 arg2 result) 53 | add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2}) 54 | set_tests_properties (test_${arg1}_${arg2} 55 | PROPERTIES PASS_REGULAR_EXPRESSION ${result}) 56 | endmacro (do_test) 57 | 58 | # 利用 do_test 宏,测试一系列数据 59 | do_test (5 2 "is 25") 60 | do_test (10 5 "is 100000") 61 | do_test (2 10 "is 1024") 62 | -------------------------------------------------------------------------------- /Demo7/config.h.in: -------------------------------------------------------------------------------- 1 | // the configured options and settings for Tutorial 2 | #define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@ 3 | #define Demo_VERSION_MINOR @Demo_VERSION_MINOR@ 4 | 5 | // does the platform provide pow function? 6 | #cmakedefine HAVE_POW 7 | -------------------------------------------------------------------------------- /Demo7/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HAVE_POW 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | if (argc < 3){ 14 | // print version info 15 | printf("%s Version %d.%d\n", 16 | argv[0], 17 | Demo_VERSION_MAJOR, 18 | Demo_VERSION_MINOR); 19 | printf("Usage: %s base exponent \n", argv[0]); 20 | return 1; 21 | } 22 | double base = atof(argv[1]); 23 | int exponent = atoi(argv[2]); 24 | 25 | #ifdef HAVE_POW 26 | printf("Now we use the standard library. \n"); 27 | double result = pow(base, exponent); 28 | #else 29 | printf("Now we use our own Math library. \n"); 30 | double result = power(base, exponent); 31 | #endif 32 | 33 | printf("%g ^ %d is %g\n", base, exponent, result); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Demo7/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 查找当前目录下的所有源文件 2 | # 并将名称保存到 DIR_LIB_SRCS 变量 3 | aux_source_directory(. DIR_LIB_SRCS) 4 | 5 | # 指定生成 MathFunctions 链接库 6 | add_library (MathFunctions ${DIR_LIB_SRCS}) 7 | 8 | # 指定 MathFunctions 库的安装路径 9 | install (TARGETS MathFunctions DESTINATION lib) 10 | install (FILES MathFunctions.h DESTINATION include) 11 | -------------------------------------------------------------------------------- /Demo7/math/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Demo7/math/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Demo8/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | # 项目信息 4 | project (Demo8) 5 | set (Demo_VERSION_MAJOR 1) 6 | set (Demo_VERSION_MINOR 0) 7 | 8 | set (CMAKE_INCLUDE_CURRENT_DIR ON) 9 | 10 | # 检查系统是否支持 pow 函数 11 | include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) 12 | check_function_exists (pow HAVE_POW) 13 | 14 | # 加入一个配置头文件,用于处理 CMake 对源码的设置 15 | configure_file ( 16 | "${PROJECT_SOURCE_DIR}/config.h.in" 17 | "${PROJECT_BINARY_DIR}/config.h" 18 | ) 19 | 20 | # 是否加入 MathFunctions 库 21 | if (NOT HAVE_POW) 22 | include_directories ("${PROJECT_SOURCE_DIR}/math") 23 | add_subdirectory (math) 24 | set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 25 | endif (NOT HAVE_POW) 26 | 27 | # 查找当前目录下的所有源文件 28 | # 并将名称保存到 DIR_SRCS 变量 29 | aux_source_directory(. DIR_SRCS) 30 | 31 | # 指定生成目标 32 | add_executable(Demo ${DIR_SRCS}) 33 | target_link_libraries (Demo ${EXTRA_LIBS}) 34 | 35 | # 指定安装路径 36 | install (TARGETS Demo DESTINATION bin) 37 | install (FILES "${PROJECT_BINARY_DIR}/config.h" 38 | DESTINATION include) 39 | 40 | # 启用测试 41 | enable_testing() 42 | 43 | # 测试程序是否成功运行 44 | add_test (test_run Demo 5 2) 45 | 46 | # 测试帮助信息是否可以正常提示 47 | add_test (test_usage Demo) 48 | set_tests_properties (test_usage 49 | PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent") 50 | 51 | # 定义一个宏,用来简化测试工作 52 | macro (do_test arg1 arg2 result) 53 | add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2}) 54 | set_tests_properties (test_${arg1}_${arg2} 55 | PROPERTIES PASS_REGULAR_EXPRESSION ${result}) 56 | endmacro (do_test) 57 | 58 | # 利用 do_test 宏,测试一系列数据 59 | do_test (5 2 "is 25") 60 | do_test (10 5 "is 100000") 61 | do_test (2 10 "is 1024") 62 | 63 | # 构建一个 CPack 安装包 64 | include (InstallRequiredSystemLibraries) 65 | set (CPACK_RESOURCE_FILE_LICENSE 66 | "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") 67 | set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}") 68 | set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}") 69 | include (CPack) 70 | -------------------------------------------------------------------------------- /Demo8/License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Joseph Pan(http://hahack.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Demo8/config.h.in: -------------------------------------------------------------------------------- 1 | // the configured options and settings for Tutorial 2 | #define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@ 3 | #define Demo_VERSION_MINOR @Demo_VERSION_MINOR@ 4 | 5 | // does the platform provide pow function? 6 | #cmakedefine HAVE_POW 7 | -------------------------------------------------------------------------------- /Demo8/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HAVE_POW 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | if (argc < 3){ 14 | // print version info 15 | printf("%s Version %d.%d\n", 16 | argv[0], 17 | Demo_VERSION_MAJOR, 18 | Demo_VERSION_MINOR); 19 | printf("Usage: %s base exponent \n", argv[0]); 20 | return 1; 21 | } 22 | double base = atof(argv[1]); 23 | int exponent = atoi(argv[2]); 24 | 25 | #ifdef HAVE_POW 26 | printf("Now we use the standard library. \n"); 27 | double result = pow(base, exponent); 28 | #else 29 | printf("Now we use our own Math library. \n"); 30 | double result = power(base, exponent); 31 | #endif 32 | 33 | printf("%g ^ %d is %g\n", base, exponent, result); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Demo8/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 查找当前目录下的所有源文件 2 | # 并将名称保存到 DIR_LIB_SRCS 变量 3 | aux_source_directory(. DIR_LIB_SRCS) 4 | 5 | # 指定生成 MathFunctions 链接库 6 | add_library (MathFunctions ${DIR_LIB_SRCS}) 7 | 8 | # 指定 MathFunctions 库的安装路径 9 | install (TARGETS MathFunctions DESTINATION lib) 10 | install (FILES MathFunctions.h DESTINATION include) 11 | -------------------------------------------------------------------------------- /Demo8/math/MathFunctions.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * power - Calculate the power of number. 3 | * @param base: Base value. 4 | * @param exponent: Exponent value. 5 | * 6 | * @return base raised to the power exponent. 7 | */ 8 | double power(double base, int exponent) 9 | { 10 | int result = base; 11 | int i; 12 | 13 | if (exponent == 0) { 14 | return 1; 15 | } 16 | 17 | for(i = 1; i < exponent; ++i){ 18 | result = result * base; 19 | } 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Demo8/math/MathFunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef POWER_H 2 | #define POWER_H 3 | 4 | extern double power(double base, int exponent); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CMake 入门实战 2 | ===== 3 | 4 | > 本仓库是 [CMake 入门实战](https://hahack.com/codes/cmake) 的源代码。 5 | > 6 | > 为了方便 github pages 无法正常阅读的朋友,下面也附带上正文。 7 | > 8 | > 但为了您更好的阅读体验,不妨前往原博客阅读: 。 9 | 10 | ## 什么是 CMake ## 11 | 12 | > All problems in computer science can be solved by another level of indirection. 13 | 14 | 你或许听过好几种 Make 工具,例如 [GNU Make](/wiki/tools-makefile.html) ,QT 的 [qmake](http://qt-project.org/doc/qt-4.8/qmake-manual.html) ,微软的 [MS nmake](http://msdn.microsoft.com/en-us/library/ms930369.aspx),BSD Make([pmake](http://www.freebsd.org/doc/en/books/pmake/)),[Makepp](http://makepp.sourceforge.net/),等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile ,这将是一件让人抓狂的工作。 15 | 16 | CMake 就是针对上面问题所设计的工具:它首先允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。显然,CMake 是一个比上述几种 make 更高级的编译配置工具。一些使用 CMake 作为项目架构系统的知名开源项目有 [VTK](http://www.vtk.org/)、[ITK](http://www.itk.org/)、[KDE](http://kde.org/)、[OpenCV](http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/core/doc/intro.html)、[OSG](http://www.openscenegraph.org/) 等 ^[[这个页面](http://www.cmake.org/Wiki/CMake_Projects)详细罗列了使用 CMake 的知名项目]。 17 | 18 | 在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下: 19 | 20 | 1. 编写 CMake 配置文件 CMakeLists.txt 。 21 | 2. 执行命令 `cmake PATH` 或者 `ccmake PATH` 生成 Makefile(`ccmake` 和 `cmake` 的区别在于前者提供了一个交互式的界面)。其中, `PATH` 是 CMakeLists.txt 所在的目录。 22 | 3. 使用 `make` 命令进行编译。 23 | 24 | 本文将从实例入手,一步步讲解 CMake 的常见用法,文中所有的实例代码可以在[这里](https://github.com/wzpan/cmake-demo)找到。如果你读完仍觉得意犹未尽,可以继续学习我在文章末尾提供的其他资源。 25 | 26 | ## 入门案例:单个源文件 ## 27 | 28 | > 本节对应的源代码所在目录:[Demo1](https://github.com/wzpan/cmake-demo/tree/master/Demo1)。 29 | 30 | 对于简单的项目,只需要写几行代码就可以了。例如,假设现在我们的项目中只有一个源文件 main.cc ,该程序的用途是计算一个数的指数幂。 31 | 32 | ``` c 33 | #include 34 | #include 35 | 36 | /** 37 | * power - Calculate the power of number. 38 | * @param base: Base value. 39 | * @param exponent: Exponent value. 40 | * 41 | * @return base raised to the power exponent. 42 | */ 43 | double power(double base, int exponent) 44 | { 45 | int result = base; 46 | int i; 47 | 48 | if (exponent == 0) { 49 | return 1; 50 | } 51 | 52 | for(i = 1; i < exponent; ++i){ 53 | result = result * base; 54 | } 55 | 56 | return result; 57 | } 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | if (argc < 3){ 62 | printf("Usage: %s base exponent \n", argv[0]); 63 | return 1; 64 | } 65 | double base = atof(argv[1]); 66 | int exponent = atoi(argv[2]); 67 | double result = power(base, exponent); 68 | printf("%g ^ %d is %g\n", base, exponent, result); 69 | return 0; 70 | } 71 | ``` 72 | 73 | #### 编写 CMakeLists.txt #### 74 | 75 | 首先编写 CMakeLists.txt 文件,并保存在与 main.cc 源文件同个目录下: 76 | 77 | ``` plain 78 | # CMake 最低版本号要求 79 | cmake_minimum_required (VERSION 2.8) 80 | 81 | # 项目信息 82 | project (Demo1) 83 | 84 | # 指定生成目标 85 | add_executable(Demo main.cc) 86 | ``` 87 | 88 | CMakeLists.txt 的语法比较简单,由命令、注释和空格组成,其中命令是不区分大小写的。符号 `#` 后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。 89 | 90 | 对于上面的 CMakeLists.txt 文件,依次出现了几个命令: 91 | 92 | 1. `cmake_minimum_required`:指定运行此配置文件所需的 CMake 的最低版本; 93 | 2. `project`:参数值是 `Demo1`,该命令表示项目的名称是 `Demo1` 。 94 | 3. `add_executable`: 将名为 main.cc 的源文件编译成一个名称为 Demo 的可执行文件。 95 | 96 | #### 编译项目 #### 97 | 98 | 之后,在当前目录执行 `cmake .` ,得到 Makefile 后再使用 `make` 命令编译得到 Demo1 可执行文件。 99 | 100 | ``` sh 101 | [ehome@xman Demo1]$ cmake . 102 | -- The C compiler identification is GNU 4.8.2 103 | -- The CXX compiler identification is GNU 4.8.2 104 | -- Check for working C compiler: /usr/sbin/cc 105 | -- Check for working C compiler: /usr/sbin/cc -- works 106 | -- Detecting C compiler ABI info 107 | -- Detecting C compiler ABI info - done 108 | -- Check for working CXX compiler: /usr/sbin/c++ 109 | -- Check for working CXX compiler: /usr/sbin/c++ -- works 110 | -- Detecting CXX compiler ABI info 111 | -- Detecting CXX compiler ABI info - done 112 | -- Configuring done 113 | -- Generating done 114 | -- Build files have been written to: /home/ehome/Documents/programming/C/power/Demo1 115 | [ehome@xman Demo1]$ make 116 | Scanning dependencies of target Demo 117 | [100%] Building C object CMakeFiles/Demo.dir/main.cc.o 118 | Linking C executable Demo 119 | [100%] Built target Demo 120 | [ehome@xman Demo1]$ ./Demo 5 4 121 | 5 ^ 4 is 625 122 | [ehome@xman Demo1]$ ./Demo 7 3 123 | 7 ^ 3 is 343 124 | [ehome@xman Demo1]$ ./Demo 2 10 125 | 2 ^ 10 is 1024 126 | ``` 127 | 128 | ## 多个源文件 ## 129 | 130 | ### 同一目录,多个源文件 ### 131 | 132 | > 本小节对应的源代码所在目录:[Demo2](https://github.com/wzpan/cmake-demo/tree/master/Demo2)。 133 | 134 | 上面的例子只有单个源文件。现在假如把 `power` 函数单独写进一个名为 `MathFunctions.c` 的源文件里,使得这个工程变成如下的形式: 135 | 136 | ``` plain 137 | ./Demo2 138 | | 139 | +--- main.cc 140 | | 141 | +--- MathFunctions.cc 142 | | 143 | +--- MathFunctions.h 144 | ``` 145 | 146 | 这个时候,CMakeLists.txt 可以改成如下的形式: 147 | 148 | ``` plain 149 | # CMake 最低版本号要求 150 | cmake_minimum_required (VERSION 2.8) 151 | 152 | # 项目信息 153 | project (Demo2) 154 | 155 | # 指定生成目标 156 | add_executable(Demo main.cc MathFunctions.cc) 157 | ``` 158 | 159 | 唯一的改动只是在 `add_executable` 命令中增加了一个 `MathFunctions.cc` 源文件。这样写当然没什么问题,但是如果源文件很多,把所有源文件的名字都加进去将是一件烦人的工作。更省事的方法是使用 `aux_source_directory` 命令,该命令会查找指定目录下的所有源文件,然后将结果存进指定变量名。其语法如下: 160 | 161 | ``` 162 | aux_source_directory( ) 163 | ``` 164 | 165 | 因此,可以修改 CMakeLists.txt 如下: 166 | 167 | ``` plain 168 | # CMake 最低版本号要求 169 | cmake_minimum_required (VERSION 2.8) 170 | 171 | # 项目信息 172 | project (Demo2) 173 | 174 | # 查找当前目录下的所有源文件 175 | # 并将名称保存到 DIR_SRCS 变量 176 | aux_source_directory(. DIR_SRCS) 177 | 178 | # 指定生成目标 179 | add_executable(Demo ${DIR_SRCS}) 180 | ``` 181 | 182 | 这样,CMake 会将当前目录所有源文件的文件名赋值给变量 `DIR_SRCS` ,再指示变量 `DIR_SRCS` 中的源文件需要编译成一个名称为 Demo 的可执行文件。 183 | 184 | ### 多个目录,多个源文件 ### 185 | 186 | > 本小节对应的源代码所在目录:[Demo3](https://github.com/wzpan/cmake-demo/tree/master/Demo3)。 187 | 188 | 现在进一步将 MathFunctions.h 和 MathFunctions.cc 文件移动到 math 目录下。 189 | 190 | ``` plain 191 | ./Demo3 192 | | 193 | +--- main.cc 194 | | 195 | +--- math/ 196 | | 197 | +--- MathFunctions.cc 198 | | 199 | +--- MathFunctions.h 200 | ``` 201 | 202 | 对于这种情况,需要分别在项目根目录 Demo3 和 math 目录里各编写一个 CMakeLists.txt 文件。为了方便,我们可以先将 math 目录里的文件编译成静态库再由 main 函数调用。 203 | 204 | > 如果想学习不使用静态库的处理,可以看看 [@zhc2019github](https://github.com/zhc2019github) 贡献的[一个示例](https://github.com/wzpan/cmake-demo/pull/10)。 205 | 206 | 根目录中的 CMakeLists.txt : 207 | 208 | ``` plain 209 | # CMake 最低版本号要求 210 | cmake_minimum_required (VERSION 2.8) 211 | 212 | # 项目信息 213 | project (Demo3) 214 | 215 | # 查找当前目录下的所有源文件 216 | # 并将名称保存到 DIR_SRCS 变量 217 | aux_source_directory(. DIR_SRCS) 218 | 219 | # 添加 math 子目录 220 | add_subdirectory(math) 221 | 222 | # 指定生成目标 223 | add_executable(Demo main.cc) 224 | 225 | # 添加链接库 226 | target_link_libraries(Demo MathFunctions) 227 | ``` 228 | 229 | 该文件添加了下面的内容: 第 3 行,使用命令 `add_subdirectory` 指明本项目包含一个子目录 math,这样 math 目录下的 CMakeLists.txt 文件和源代码也会被处理 。第 18 行,使用命令 `target_link_libraries` 指明可执行文件 main 需要连接一个名为 MathFunctions 的链接库 。 230 | 231 | 子目录中的 CMakeLists.txt: 232 | 233 | ``` plain 234 | # 查找当前目录下的所有源文件 235 | # 并将名称保存到 DIR_LIB_SRCS 变量 236 | aux_source_directory(. DIR_LIB_SRCS) 237 | 238 | # 生成链接库 239 | add_library (MathFunctions ${DIR_LIB_SRCS}) 240 | ``` 241 | 242 | 在该文件中使用命令 `add_library` 将 src 目录中的源文件编译为静态链接库。 243 | 244 | ## 自定义编译选项 ## 245 | 246 | > 本节对应的源代码所在目录:[Demo4](https://github.com/wzpan/cmake-demo/tree/master/Demo4)。 247 | 248 | CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。 249 | 250 | 例如,可以将 MathFunctions 库设为一个可选的库,如果该选项为 `ON` ,就使用该库定义的数学函数来进行运算。否则就调用标准库中的数学函数库。 251 | 252 | #### 修改 CMakeLists 文件 #### 253 | 254 | 我们要做的第一步是在顶层的 CMakeLists.txt 文件中添加该选项: 255 | 256 | ``` plain 257 | # CMake 最低版本号要求 258 | cmake_minimum_required (VERSION 2.8) 259 | 260 | # 项目信息 261 | project (Demo4) 262 | 263 | # 加入一个配置头文件,用于处理 CMake 对源码的设置 264 | configure_file ( 265 | "${PROJECT_SOURCE_DIR}/config.h.in" 266 | "${PROJECT_BINARY_DIR}/config.h" 267 | ) 268 | 269 | # 是否使用自己的 MathFunctions 库 270 | option (USE_MYMATH 271 | "Use provided math implementation" ON) 272 | 273 | # 是否加入 MathFunctions 库 274 | if (USE_MYMATH) 275 | include_directories ("${PROJECT_SOURCE_DIR}/math") 276 | add_subdirectory (math) 277 | set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 278 | endif (USE_MYMATH) 279 | 280 | # 查找当前目录下的所有源文件 281 | # 并将名称保存到 DIR_SRCS 变量 282 | aux_source_directory(. DIR_SRCS) 283 | 284 | # 指定生成目标 285 | add_executable(Demo ${DIR_SRCS}) 286 | target_link_libraries (Demo ${EXTRA_LIBS}) 287 | ``` 288 | 289 | 其中: 290 | 291 | 1. 第7行的 `configure_file` 命令用于加入一个配置头文件 config.h ,这个文件由 CMake 从 config.h.in 生成,通过这样的机制,将可以通过预定义一些参数和变量来控制代码的生成。 292 | 2. 第13行的 `option` 命令添加了一个 `USE_MYMATH` 选项,并且默认值为 `ON` 。 293 | 3. 第17行根据 `USE_MYMATH` 变量的值来决定是否使用我们自己编写的 MathFunctions 库。 294 | 295 | #### 修改 main.cc 文件 #### 296 | 297 | 之后修改 main.cc 文件,让其根据 `USE_MYMATH` 的预定义值来决定是否调用标准库还是 MathFunctions 库: 298 | 299 | ``` plain 300 | #include 301 | #include 302 | #include "config.h" 303 | 304 | #ifdef USE_MYMATH 305 | #include "math/MathFunctions.h" 306 | #else 307 | #include 308 | #endif 309 | 310 | 311 | int main(int argc, char *argv[]) 312 | { 313 | if (argc < 3){ 314 | printf("Usage: %s base exponent \n", argv[0]); 315 | return 1; 316 | } 317 | double base = atof(argv[1]); 318 | int exponent = atoi(argv[2]); 319 | 320 | #ifdef USE_MYMATH 321 | printf("Now we use our own Math library. \n"); 322 | double result = power(base, exponent); 323 | #else 324 | printf("Now we use the standard library. \n"); 325 | double result = pow(base, exponent); 326 | #endif 327 | printf("%g ^ %d is %g\n", base, exponent, result); 328 | return 0; 329 | } 330 | ``` 331 | 332 | #### 编写 config.h.in 文件 #### 333 | 334 | 上面的程序值得注意的是第2行,这里引用了一个 config.h 文件,这个文件预定义了 `USE_MYMATH` 的值。但我们并不直接编写这个文件,为了方便从 CMakeLists.txt 中导入配置,我们编写一个 config.h.in 文件,内容如下: 335 | 336 | ``` plain 337 | #cmakedefine USE_MYMATH 338 | ``` 339 | 340 | 这样 CMake 会自动根据 CMakeLists 配置文件中的设置自动生成 config.h 文件。 341 | 342 | #### 编译项目 #### 343 | 344 | 现在编译一下这个项目,为了便于交互式的选择该变量的值,可以使用 `ccmake` 命令(也可以使用 `cmake -i` 命令,该命令会提供一个会话式的交互式配置界面): 345 | 346 | ![CMake的交互式配置界面](https://hahack-1253537070.file.myqcloud.com/images/blog/images/cmake/ccmake.png) 347 | 348 | 从中可以找到刚刚定义的 `USE_MYMATH` 选项,按键盘的方向键可以在不同的选项窗口间跳转,按下 `enter` 键可以修改该选项。修改完成后可以按下 `c` 选项完成配置,之后再按 `g` 键确认生成 Makefile 。ccmake 的其他操作可以参考窗口下方给出的指令提示。 349 | 350 | 我们可以试试分别将 `USE_MYMATH` 设为 `ON` 和 `OFF` 得到的结果: 351 | 352 | ##### USE_MYMATH 为 ON ##### 353 | 354 | 运行结果: 355 | 356 | ``` plain 357 | [ehome@xman Demo4]$ ./Demo 358 | Now we use our own MathFunctions library. 359 | 7 ^ 3 = 343.000000 360 | 10 ^ 5 = 100000.000000 361 | 2 ^ 10 = 1024.000000 362 | ``` 363 | 364 | 此时 config.h 的内容为: 365 | 366 | ``` plain 367 | #define USE_MYMATH 368 | ``` 369 | 370 | ##### USE_MYMATH 为 OFF ##### 371 | 372 | 运行结果: 373 | 374 | ``` plain 375 | [ehome@xman Demo4]$ ./Demo 376 | Now we use the standard library. 377 | 7 ^ 3 = 343.000000 378 | 10 ^ 5 = 100000.000000 379 | 2 ^ 10 = 1024.000000 380 | ``` 381 | 382 | 此时 config.h 的内容为: 383 | 384 | ``` plain 385 | /* #undef USE_MYMATH */ 386 | ``` 387 | 388 | ## 安装和测试 ## 389 | 390 | > 本节对应的源代码所在目录:[Demo5](https://github.com/wzpan/cmake-demo/tree/master/Demo5)。 391 | 392 | CMake 也可以指定安装规则,以及添加测试。这两个功能分别可以通过在产生 Makefile 后使用 `make install` 和 `make test` 来执行。在以前的 GNU Makefile 里,你可能需要为此编写 `install` 和 `test` 两个伪目标和相应的规则,但在 CMake 里,这样的工作同样只需要简单的调用几条命令。 393 | 394 | ### 定制安装规则 ### 395 | 396 | 首先先在 math/CMakeLists.txt 文件里添加下面两行: 397 | 398 | ``` plain 399 | # 指定 MathFunctions 库的安装路径 400 | install (TARGETS MathFunctions DESTINATION bin) 401 | install (FILES MathFunctions.h DESTINATION include) 402 | ``` 403 | 404 | 指明 MathFunctions 库的安装路径。之后同样修改根目录的 CMakeLists 文件,在末尾添加下面几行: 405 | 406 | ``` plain 407 | # 指定安装路径 408 | install (TARGETS Demo DESTINATION bin) 409 | install (FILES "${PROJECT_BINARY_DIR}/config.h" 410 | DESTINATION include) 411 | ``` 412 | 413 | 通过上面的定制,生成的 Demo 文件和 MathFunctions 函数库 libMathFunctions.o 文件将会被复制到 `/usr/local/bin` 中,而 MathFunctions.h 和生成的 config.h 文件则会被复制到 `/usr/local/include` 中。我们可以验证一下(顺带一提的是,这里的 `/usr/local/` 是默认安装到的根目录,可以通过修改 `CMAKE_INSTALL_PREFIX` 变量的值来指定这些文件应该拷贝到哪个根目录): 414 | 415 | ``` sh 416 | [ehome@xman Demo5]$ sudo make install 417 | [ 50%] Built target MathFunctions 418 | [100%] Built target Demo 419 | Install the project... 420 | -- Install configuration: "" 421 | -- Installing: /usr/local/bin/Demo 422 | -- Installing: /usr/local/include/config.h 423 | -- Installing: /usr/local/bin/libMathFunctions.a 424 | -- Up-to-date: /usr/local/include/MathFunctions.h 425 | [ehome@xman Demo5]$ ls /usr/local/bin 426 | Demo libMathFunctions.a 427 | [ehome@xman Demo5]$ ls /usr/local/include 428 | config.h MathFunctions.h 429 | ``` 430 | 431 | ### 为工程添加测试 ### 432 | 433 | 添加测试同样很简单。CMake 提供了一个称为 CTest 的测试工具。我们要做的只是在项目根目录的 CMakeLists 文件中调用一系列的 `add_test` 命令。 434 | 435 | ``` plain 436 | # 启用测试 437 | enable_testing() 438 | 439 | # 测试程序是否成功运行 440 | add_test (test_run Demo 5 2) 441 | 442 | # 测试帮助信息是否可以正常提示 443 | add_test (test_usage Demo) 444 | set_tests_properties (test_usage 445 | PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent") 446 | 447 | # 测试 5 的平方 448 | add_test (test_5_2 Demo 5 2) 449 | 450 | set_tests_properties (test_5_2 451 | PROPERTIES PASS_REGULAR_EXPRESSION "is 25") 452 | 453 | # 测试 10 的 5 次方 454 | add_test (test_10_5 Demo 10 5) 455 | 456 | set_tests_properties (test_10_5 457 | PROPERTIES PASS_REGULAR_EXPRESSION "is 100000") 458 | 459 | # 测试 2 的 10 次方 460 | add_test (test_2_10 Demo 2 10) 461 | 462 | set_tests_properties (test_2_10 463 | PROPERTIES PASS_REGULAR_EXPRESSION "is 1024") 464 | ``` 465 | 466 | 上面的代码包含了四个测试。第一个测试 `test_run` 用来测试程序是否成功运行并返回 0 值。剩下的三个测试分别用来测试 5 的 平方、10 的 5 次方、2 的 10 次方是否都能得到正确的结果。其中 `PASS_REGULAR_EXPRESSION` 用来测试输出是否包含后面跟着的字符串。 467 | 468 | 让我们看看测试的结果: 469 | 470 | ``` sh 471 | [ehome@xman Demo5]$ make test 472 | Running tests... 473 | Test project /home/ehome/Documents/programming/C/power/Demo5 474 | Start 1: test_run 475 | 1/4 Test #1: test_run ......................... Passed 0.00 sec 476 | Start 2: test_5_2 477 | 2/4 Test #2: test_5_2 ......................... Passed 0.00 sec 478 | Start 3: test_10_5 479 | 3/4 Test #3: test_10_5 ........................ Passed 0.00 sec 480 | Start 4: test_2_10 481 | 4/4 Test #4: test_2_10 ........................ Passed 0.00 sec 482 | 483 | 100% tests passed, 0 tests failed out of 4 484 | 485 | Total Test time (real) = 0.01 sec 486 | ``` 487 | 488 | 如果要测试更多的输入数据,像上面那样一个个写测试用例未免太繁琐。这时可以通过编写宏来实现: 489 | 490 | ``` cmake 491 | # 定义一个宏,用来简化测试工作 492 | macro (do_test arg1 arg2 result) 493 | add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2}) 494 | set_tests_properties (test_${arg1}_${arg2} 495 | PROPERTIES PASS_REGULAR_EXPRESSION ${result}) 496 | endmacro (do_test) 497 | 498 | # 使用该宏进行一系列的数据测试 499 | do_test (5 2 "is 25") 500 | do_test (10 5 "is 100000") 501 | do_test (2 10 "is 1024") 502 | ``` 503 | 504 | 关于 CTest 的更详细的用法可以通过 `man 1 ctest` 参考 CTest 的文档。 505 | 506 | ## 支持 gdb ## 507 | 508 | 让 CMake 支持 gdb 的设置也很容易,只需要指定 `Debug` 模式下开启 `-g` 选项: 509 | 510 | ``` CMake 511 | set(CMAKE_BUILD_TYPE "Debug") 512 | set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") 513 | set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 514 | ``` 515 | 516 | 之后可以直接对生成的程序使用 gdb 来调试。 517 | 518 | ## 添加环境检查 ## 519 | 520 | > 本节对应的源代码所在目录:[Demo6](https://github.com/wzpan/cmake-demo/tree/master/Demo6)。 521 | 522 | 有时候可能要对系统环境做点检查,例如要使用一个平台相关的特性的时候。在这个例子中,我们检查系统是否自带 pow 函数。如果带有 pow 函数,就使用它;否则使用我们定义的 power 函数。 523 | 524 | #### 添加 CheckFunctionExists 宏 #### 525 | 526 | 首先在顶层 CMakeLists 文件中添加 CheckFunctionExists.cmake 宏,并调用 `check_function_exists` 命令测试链接器是否能够在链接阶段找到 `pow` 函数。 527 | 528 | ``` plain 529 | # 检查系统是否支持 pow 函数 530 | include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) 531 | check_function_exists (pow HAVE_POW) 532 | ``` 533 | 534 | 将上面这段代码放在 `configure_file` 命令前。 535 | 536 | #### 预定义相关宏变量 #### 537 | 538 | 接下来修改 config.h.in 文件,预定义相关的宏变量。 539 | 540 | ``` c 541 | // does the platform provide pow function? 542 | #cmakedefine HAVE_POW 543 | ``` 544 | 545 | #### 在代码中使用宏和函数 #### 546 | 547 | 最后一步是修改 main.cc ,在代码中使用宏和函数: 548 | 549 | ``` plain 550 | #ifdef HAVE_POW 551 | printf("Now we use the standard library. \n"); 552 | double result = pow(base, exponent); 553 | #else 554 | printf("Now we use our own Math library. \n"); 555 | double result = power(base, exponent); 556 | #endif 557 | ``` 558 | 559 | ## 添加版本号 ## 560 | 561 | > 本节对应的源代码所在目录:[Demo7](https://github.com/wzpan/cmake-demo/tree/master/Demo7)。 562 | 563 | 给项目添加和维护版本号是一个好习惯,这样有利于用户了解每个版本的维护情况,并及时了解当前所用的版本是否过时,或是否可能出现不兼容的情况。 564 | 565 | 首先修改顶层 CMakeLists 文件,在 `project` 命令之后加入如下两行: 566 | 567 | ``` plain 568 | set (Demo_VERSION_MAJOR 1) 569 | set (Demo_VERSION_MINOR 0) 570 | ``` 571 | 572 | 分别指定当前的项目的主版本号和副版本号。 573 | 574 | 之后,为了在代码中获取版本信息,我们可以修改 config.h.in 文件,添加两个预定义变量: 575 | 576 | ``` plain 577 | // the configured options and settings for Tutorial 578 | #define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@ 579 | #define Demo_VERSION_MINOR @Demo_VERSION_MINOR@ 580 | ``` 581 | 582 | 这样就可以直接在代码中打印版本信息了: 583 | 584 | ``` c 585 | #include 586 | #include 587 | #include 588 | #include "config.h" 589 | #include "math/MathFunctions.h" 590 | 591 | int main(int argc, char *argv[]) 592 | { 593 | if (argc < 3){ 594 | // print version info 595 | printf("%s Version %d.%d\n", 596 | argv[0], 597 | Demo_VERSION_MAJOR, 598 | Demo_VERSION_MINOR); 599 | printf("Usage: %s base exponent \n", argv[0]); 600 | return 1; 601 | } 602 | double base = atof(argv[1]); 603 | int exponent = atoi(argv[2]); 604 | 605 | #if defined (HAVE_POW) 606 | printf("Now we use the standard library. \n"); 607 | double result = pow(base, exponent); 608 | #else 609 | printf("Now we use our own Math library. \n"); 610 | double result = power(base, exponent); 611 | #endif 612 | 613 | printf("%g ^ %d is %g\n", base, exponent, result); 614 | return 0; 615 | } 616 | ``` 617 | 618 | ## 生成安装包 ## 619 | 620 | > 本节对应的源代码所在目录:[Demo8](https://github.com/wzpan/cmake-demo/tree/master/Demo8)。 621 | 622 | 本节将学习如何配置生成各种平台上的安装包,包括二进制安装包和源码安装包。为了完成这个任务,我们需要用到 CPack ,它同样也是由 CMake 提供的一个工具,专门用于打包。 623 | 624 | 首先在顶层的 CMakeLists.txt 文件尾部添加下面几行: 625 | 626 | ``` plain 627 | # 构建一个 CPack 安装包 628 | include (InstallRequiredSystemLibraries) 629 | set (CPACK_RESOURCE_FILE_LICENSE 630 | "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") 631 | set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}") 632 | set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}") 633 | include (CPack) 634 | ``` 635 | 636 | 上面的代码做了以下几个工作: 637 | 638 | 1. 导入 InstallRequiredSystemLibraries 模块,以便之后导入 CPack 模块; 639 | 2. 设置一些 CPack 相关变量,包括版权信息和版本信息,其中版本信息用了上一节定义的版本号; 640 | 3. 导入 CPack 模块。 641 | 642 | 接下来的工作是像往常一样构建工程,并执行 `cpack` 命令。 643 | 644 | * 生成二进制安装包: 645 | 646 | ``` sh 647 | cpack -C CPackConfig.cmake 648 | ``` 649 | 650 | * 生成源码安装包 651 | 652 | ``` sh 653 | cpack -C CPackSourceConfig.cmake 654 | ``` 655 | 656 | 我们可以试一下。在生成项目后,执行 `cpack -C CPackConfig.cmake` 命令: 657 | 658 | ``` sh 659 | [ehome@xman Demo8]$ cpack -C CPackSourceConfig.cmake 660 | CPack: Create package using STGZ 661 | CPack: Install projects 662 | CPack: - Run preinstall target for: Demo8 663 | CPack: - Install project: Demo8 664 | CPack: Create package 665 | CPack: - package: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux.sh generated. 666 | CPack: Create package using TGZ 667 | CPack: Install projects 668 | CPack: - Run preinstall target for: Demo8 669 | CPack: - Install project: Demo8 670 | CPack: Create package 671 | CPack: - package: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux.tar.gz generated. 672 | CPack: Create package using TZ 673 | CPack: Install projects 674 | CPack: - Run preinstall target for: Demo8 675 | CPack: - Install project: Demo8 676 | CPack: Create package 677 | CPack: - package: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux.tar.Z generated. 678 | ``` 679 | 680 | 此时会在该目录下创建 3 个不同格式的二进制包文件: 681 | 682 | ``` sh 683 | [ehome@xman Demo8]$ ls Demo8-* 684 | Demo8-1.0.1-Linux.sh Demo8-1.0.1-Linux.tar.gz Demo8-1.0.1-Linux.tar.Z 685 | ``` 686 | 687 | 这 3 个二进制包文件所包含的内容是完全相同的。我们可以执行其中一个。此时会出现一个由 CPack 自动生成的交互式安装界面: 688 | 689 | ``` sh 690 | [ehome@xman Demo8]$ sh Demo8-1.0.1-Linux.sh 691 | Demo8 Installer Version: 1.0.1, Copyright (c) Humanity 692 | This is a self-extracting archive. 693 | The archive will be extracted to: /home/ehome/Documents/programming/C/power/Demo8 694 | 695 | If you want to stop extracting, please press . 696 | The MIT License (MIT) 697 | 698 | Copyright (c) 2013 Joseph Pan(http://hahack.com) 699 | 700 | Permission is hereby granted, free of charge, to any person obtaining a copy of 701 | this software and associated documentation files (the "Software"), to deal in 702 | the Software without restriction, including without limitation the rights to 703 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 704 | the Software, and to permit persons to whom the Software is furnished to do so, 705 | subject to the following conditions: 706 | 707 | The above copyright notice and this permission notice shall be included in all 708 | copies or substantial portions of the Software. 709 | 710 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 711 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 712 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 713 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 714 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 715 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 716 | 717 | 718 | Do you accept the license? [yN]: 719 | y 720 | By default the Demo8 will be installed in: 721 | "/home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux" 722 | Do you want to include the subdirectory Demo8-1.0.1-Linux? 723 | Saying no will install in: "/home/ehome/Documents/programming/C/power/Demo8" [Yn]: 724 | y 725 | 726 | Using target directory: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux 727 | Extracting, please wait... 728 | 729 | Unpacking finished successfully 730 | ``` 731 | 732 | 完成后提示安装到了 Demo8-1.0.1-Linux 子目录中,我们可以进去执行该程序: 733 | 734 | ``` sh 735 | [ehome@xman Demo8]$ ./Demo8-1.0.1-Linux/bin/Demo 5 2 736 | Now we use our own Math library. 737 | 5 ^ 2 is 25 738 | ``` 739 | 740 | 关于 CPack 的更详细的用法可以通过 `man 1 cpack` 参考 CPack 的文档。 741 | 742 | ## 将其他平台的项目迁移到 CMake ## 743 | 744 | CMake 可以很轻松地构建出在适合各个平台执行的工程环境。而如果当前的工程环境不是 CMake ,而是基于某个特定的平台,是否可以迁移到 CMake 呢?答案是可能的。下面针对几个常用的平台,列出了它们对应的迁移方案。 745 | 746 | #### autotools #### 747 | 748 | * [am2cmake](https://projects.kde.org/projects/kde/kdesdk/kde-dev-scripts/repository/revisions/master/changes/cmake-utils/scripts/am2cmake) 可以将 autotools 系的项目转换到 CMake,这个工具的一个成功案例是 KDE 。 749 | * [Alternative Automake2CMake](http://emanuelgreisen.dk/stuff/kdevelop_am2cmake.php.tgz) 可以转换使用 automake 的 KDevelop 工程项目。 750 | * [Converting autoconf tests](http://www.cmake.org/Wiki/GccXmlAutoConfHints) 751 | 752 | #### qmake #### 753 | 754 | * [qmake converter](http://www.cmake.org/Wiki/CMake:ConvertFromQmake) 可以转换使用 QT 的 qmake 的工程。 755 | 756 | #### Visual Studio #### 757 | 758 | * [vcproj2cmake.rb](http://vcproj2cmake.sf.net/) 可以根据 Visual Studio 的工程文件(后缀名是 `.vcproj` 或 `.vcxproj`)生成 CMakeLists.txt 文件。 759 | * [vcproj2cmake.ps1](http://nberserk.blogspot.com/2010/11/converting-vc-projectsvcproj-to.html) vcproj2cmake 的 PowerShell 版本。 760 | * [folders4cmake](http://sourceforge.net/projects/folders4cmake/) 根据 Visual Studio 项目文件生成相应的 "source_group" 信息,这些信息可以很方便的在 CMake 脚本中使用。支持 Visual Studio 9/10 工程文件。 761 | 762 | #### CMakeLists.txt 自动推导 #### 763 | 764 | * [gencmake](http://websvn.kde.org/trunk/KDE/kdesdk/cmake/scripts/) 根据现有文件推导 CMakeLists.txt 文件。 765 | * [CMakeListGenerator](http://www.vanvelzensoftware.com/postnuke/index.php?name=Downloads&req=viewdownload&cid=7) 应用一套文件和目录分析创建出完整的 CMakeLists.txt 文件。仅支持 Win32 平台。 766 | 767 | ## 相关链接 ## 768 | 769 | 1. [官方主页](http://www.cmake.org) 770 | 2. [官方文档](http://www.cmake.org/cmake/help/cmake2.4docs.html) 771 | 3. [官方教程](http://www.cmake.org/cmake/help/cmake_tutorial.html) 772 | 4. [Wiki](http://www.cmake.org/Wiki/CMake#Basic_CMakeLists.txt_from-scratch-generator) 773 | 5. [FAQ](http://www.cmake.org/Wiki/CMake_FAQ) 774 | 6. [bug tracker](http://www.cmake.org/Bug) 775 | 7. 邮件列表: 776 | - [cmake on Gmane](http://dir.gmane.org/gmane.comp.programming.tools.cmake.user) 777 | - [http://www.mail-archive.com/cmake@cmake.org/](http://www.mail-archive.com/cmake@cmake.org/) 778 | - [http://marc.info/?l=cmake](http://www.mail-archive.com/cmake@cmake.org/) 779 | 8. 其他推荐文章 780 | - [在 linux 下使用 CMake 构建应用程序](http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/) 781 | - [cmake的一些小经验](http://www.cppblog.com/skyscribe/archive/2009/12/14/103208.aspx) 782 | - [Packaging Software with CPack](http://www.kitware.com/media/archive/kitware_quarterly0107.pdf) 783 | - [视频教程: 《Getting Started with CMake》](http://www.youtube.com/watch?v=CLvZTyji_Uw) 784 | 785 | ## 类似工具 ## 786 | 787 | * [SCons](http://scons.org/):Eric S. Raymond、Timothee Besset、Zed A. Shaw 等大神力荐的项目架构工具。和 CMake 的最大区别是使用 Python 作为执行脚本。 788 | --------------------------------------------------------------------------------