# 写明版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名和版本号
project(Tutorial)
# 生成可执行文件
add_executable(Demo main.c)
语法由命令、注释和空格组成,其中命令是不区分大小写的。符号 # 后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。
cmake .
,得到Makefile。make
命令编译得到源码的可执行文件。比如一个文件夹下有main.c,function.c,和function.h可以这样写
# 写明版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名
project(Tutorial)
# 生成可执行文件
add_executable(Tutorial main.c function.c)
当一个文件夹下的源文件很多时,使用aux_source_directory 命令,将指定目录下的所有源文件名存到指定的变量名。
# <dir> 文件夹路径;<variable>变量名
aux_source_directory(<dir> <variable>)
# 写明版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名
project(Tutorial)
# 查找当前目录下所有源文件名,并将其存储到 DIR_CURR中
aux_source_directory(. DIR_CURR)
# 生成可执行文件
add_executable(Tutorial ${DIR_CURR})
如当前目录下为main.c,当前目录下有目录fun,fun目录有文件function.c,function.h。
这种情况下需要将fun文件夹下的源文件编译成为静态库,再由main.c调用。
# 写明版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名
project(Tutorial)
# 查找当前目录下所有源文件名,并将其存储到 DIR_CURR中
aux_source_directory(. DIR_CURR)
# 添加子目录fun,同时将子目录下的CMakeLists.txt文件执行
add_subdirectory(fun)
# 生成可执行文件
add_executable(Tutorial ${DIR_CURR})
# 添加链接库,指明可执行文件 main 需要连接一个名为 function 的链接库
target_link_libraries(Tutorial function)
子目录fun下的CMakeLists.txt文件内容:
# 查找当前目录下所有源文件名,并将其存储到 DIR_CURR中
aux_source_directory(. DIR_FUN)
# 生成链接库,将 fun 目录中的源文件编译为静态链接库。
add_library(function ${DIR_FUN})
configure_file 指令通过读取输入文件中的内容,将 CMakeLists.txt 文件中的变量转变为 C/C++ 中可识别的宏定义,然后存入另一个文件中。
configure_file(<input> <output>
[NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
FILE_PERMISSIONS <permissions>...]
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
输入文件input为xxx-config.h.in,输出文件output为xxx-config.h,@ONLY:在 文件中只使用 @VAR@ 的方式获取变量值,不适用 ${VAR} 的方式;
#cmakedefine VAR
如果 CMakeLists.txt 文件中,定义了变量 VAR,那么在转化出来的文件中就会存在 #define VAR 的语句。否则,在文件中就会显示 /*undef VAR*/
。然后,在源码中使用 #ifdef 语句进行使用——#ifdef VAR。
#cmakedefine01 VAR
CMakelists.txt 中的 option(VAR …) 用于开关操作,并且可以使用 cmake -DVAR=ON/OFF … 修改其变量值。上述指令根据 CMakeLists.txt 中 VAR 的值为 ON 或 OFF,将其转换为 #define VAR 1 或 #define VAR 0。然后在源码中使用 #if 进行引用——#if VAR。
#cmakedefine VAR @VAR@
或
#cmakedefine VAR ${VAR}
或
#define SELF_DEFINE_MACRO_NAME @VAR@
CMakeLists.txt 文件中,变量 VAR 多用于定义某些信息,比如版本号,作者,项目描述,调试等级等。然后在源码中输出这些值到固定位置,起到提示的作用。
如果想要在命令行中修改通过 set() 自定义变量的值,那么需要在定义变量时指定 CACHE 参数。比如:
set(DEBUG_LDEVL 1 CACHE STRING "set debug level")
便可以使用cmake -DDEBUG_LEVEL=4
修改它的值。
set命令可以设置普通变量、缓存条目、环境变量
set(<variable> <value>... [PARENT_SCOPE]) #设置普通变量
set(<variable> <value>... CACHE <type> <docstring> [FORCE]) #设置缓存条目
set(ENV{<variable>} [<value>]) #设置环境变量
…表示可以给变量设置0个或者多个值,当设置多个值时(大于2个),多个值会通过分号连接符连接成一个真实的值赋值给变量,当设置0个值时,实际上是把变量变为未设置状态,相当于调用unset命令。
# 写明版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名
project(Tutorial)
set (var dd)
message (">>> value = ${var}")
输出:
>>> value = dd
# 写明版本号
cmake_minimum_required(VERSION 3.10)
# 设置项目名
project(Tutorial)
set (var dd ee ff)
message (">>> value = ${var}")
set (var1)
message (">>> value = ${var1}")
>>> value = dd;ee;ff
>>> value =
# CMakeLists.txt
cmake_minimum_required (VERSION 3.10.2)
project (set_test)
function (test_fn arg1)
set (normal_var_in_fn ${arg1} PARENT_SCOPE)
message (">>> in function, value = ${normal_var_in_fn}")
endfunction (test_fn)
function (test_fn_parent arg1)
test_fn (${arg1})
message (">>> in parent function, value = ${normal_var_in_fn}")
endfunction (test_fn_parent)
test_fn_parent (hello)
输出
>>> in function, value =
>>> in parent function, value = hello
# CMakeLists.txt
cmake_minimum_required (VERSION 3.10.2)
project (set_test)
function (test_fn arg1)
set (normal_var_fn ${arg1} PARENT_SCOPE)
message (">>> in function, value = ${normal_var_fn}")
endfunction (test_fn)
test_fn(hello)
message (">>> in directory, value = ${normal_var_fn}")
输出
>>> in function, value =
>>> in directory, value =
# CMakeLists.txt
cmake_minimum_required (VERSION 3.10.2)
project (set_test)
function (test_fn arg1)
set (normal_var_in_fn hello)
set (normal_var_in_fn ${arg1} PARENT_SCOPE)
message (">>> in function, value = ${normal_var_in_fn}")
endfunction (test_fn)
test_fn (hello)
输出
>>> in function, value = hello
相当于一个全局变量,在同一个CMake工程中都可以用到
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
将缓存条目variable设置为值…,除非用户进行设置或使用了选项FORCE,默认情况下缓存条目的值不会被覆盖。缓存条目可以通过CMAKE的GUI界面的add entry按钮来增加。
缓存条目的主要有以下几类:
缓存条目的几个注意事项:
1)如果变量先前未定义或者使用了FORCE选项,则缓存条目会直接被赋值。
2)可以在使用cmake构建的使用通过-D选项来给缓存条目赋值,这样CMakeLists.txt内的set命令只会为缓存条目添加类型。
3)如果变量类型是目录或者文件路径,通过-D选项传入的若只是相对路径,那么set会给这个相对路径前添加当前的工作目录以变成绝对路径(如果已经是绝对路径则不会处理)。
# CMakeLists.txt
cmake_minimum_required (VERSION 3.10.2)
project (set_test)
set (cache_entry_val ON OFF CACHE BOOL "choose ON to enable")
message (">>> value = ${cache_entry_val}")
set (cache_entry_val2 ON CACHE BOOL "choose ON to enable" FORCE)
message (">>> value2 = ${cache_entry_val2}")
set (cache_entry_val3 ON)
set (cache_entry_val3 OFF CACHE BOOL "choose ON to enable")
message (">>> value3 = ${cache_entry_val3}")
set (cache_entry_input OFF CACHE BOOL "choose ON to enable")
message (">>> value4 = ${cache_entry_input}")
set (mypath "test" CACHE FILEPATH "choose a file path")
message (">>> value5 = ${mypath}")
打印
>>> value = ON;OFF
>>> value2 = ON
>>> value3 = OFF
>>> value4 = OFF
>>> value5 = test
set(ENV{<variable>} [<value>])
命令含义:将环境变量设置为值(注意没有…),接着使用$ENV{}会得到新的值。cmake中的环境变量可以参考:环境变量。
环境变量设置的几个注意事项:
# CMakeLists.txt
cmake_minimum_required (VERSION 3.10.2)
project (set_test)
message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
set (ENV{CMAKE_PREFIX_PATH} "/test/sub")
message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
set (ENV{CMAKE_PREFIX_PATH})
message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
set (ENV{CMAKE_PREFIX_PATH} "/test/top/")
message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
set (ENV{CMAKE_PREFIX_PATH} "")
message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
打印
>>> value =
>>> value = /test/sub
>>> value =
>>> value = /test/top/
>>> value =
CMake中的option用于控制编译流程,相当于C语言中的宏条件编译。
option(<variable> "<help_text>" [value])
可以在执行CMake时,在命令里面直接改选项值
$cmake .. -D<variable>=OFF
CMake执行完后,选项的值会保存到CMakeCache.txt中。
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(test)
option(USE_NEW_METHOD "option for debug" OFF)
if(USE_NEW_METHOD)
add_definitions(-DUSE_NEW_METHOD)
endif()
add_executable(test main.cpp)
install(TARGETS test RUNTIME DESTINATION bin)
main.cpp
#include <iostream>
#include <vector>
//#define USE_NEW_METHOD //不用在这里再开关此行代码了
int main(int argc, char **argv) {
std::cout << "Hello, world!" << std::endl;
#ifdef USE_NEW_METHOD
std::cout << "USE NEW METHOD " << std::endl;
#else
std::cout << "USE DEFAULT METHOD" << std::endl;
#endif
std::cout << "END" << std::endl;
return 0;
}
指令:cmake -DUSE_NEW_METHOD=ON ...
通过命令行指令,将USE_NEW_METHOD变量置为ON,使得CMakeLists.txt中USE_NEW_METHOD变量开启,从而通过add_definitions函数在C程序中添加定义USE_NEW_METHOD。
对于同一选项,子项目值遵循主项目的定义。也就是说子项目会被主项目覆盖
现在我们将向项目中添加一个库,这个库包含计算数字平方根的实现,可执行文件使用这个库,而不是编译器提供的标准平方根函数。
我们把库放在名为 MathFunctions 的子目录中。此目录包含头文件 MathFunctions.h 和源文件 mysqrt.cpp。源文件有一个名为 mysqrt 的函数,它提供了与编译器的 sqrt 函数类似的功能,MathFunctions.h 则是该函数的声明。
在 MathFunctions 目录下创建一个 CMakeLists.txt 文件,并添加以下一行:
add_library(MathFunctions mysqrt.cpp)
CMake 中的 target 有可执行文件和库文件,分别使用 add_executable 和 add_library 命令生成,除了指定生成的可执行文件名/库文件名,还需要指定相关的源文件。
此时文件结构为:
step3/
build/
MathFunctions/
CMakeLists.txt
MathFunctions.h
mysqrt.cpp
CMakeLists.txt
tutorial.cpp
TutorialConfig.h.in
为了使用 MathFunctions 这个库,我们将在根目录 CMakeLists.txt 文件中添加一个 add_subdirectory(MathFunctions) 命令指定库所在子目录,该子目录下应包含 CMakeLists.txt 文件和代码文件。
可执行文件要使用库文件,需要能够找到库文件和对应的头文件,可以分别通过 target_link_libraries 和 target_include_directories 来指定。
使用 target_link_libraries 将新的库文件添加到可执行文件中,使用 target_include_directories 将 MathFunctions 添加为头文件目录,添加到 Tutorial 目标上,以便 mysqrt.h 可以被找到。
根目录 CMakeLists.txt 的最后几行如下所示:
# add the MathFunctions library
add_subdirectory(MathFunctions)
# add the executable
add_executable(${PROJECT_NAME} tutorial.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC MathFunctions)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/MathFunctions
)
MathFunctions 库就算添加完成了,接下来就是在主函数使用该库中的函数,先在 tutorial.cpp 文件中添加头文件:
#include "MathFunctions.h"
然后可以使用mysqrt函数
const double outputValue = mysqrt(inputValue);
可以将标准库下的一些库定义为自己写的同名库
在子目录 fun/CMakeList.txt文件里添加:
install (TARGETS function DESTINATION bin)
install (FILES function.h DESTINATION include)
在根目录的CMakeList.txt的末尾添加:
install (TARGETS Main DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)
通过上面的定制,生成的 Main文件和 function 函数库 libfunction.o 文件将会被复制到 /usr/local/bin 中,而 function.h 和生成的 config.h 文件则会被复制到 /usr/local/include 中。我们可以验证一下(顺带一提的是,这里的 /usr/local/ 是默认安装到的根目录,可以通过修改 CMAKE_INSTALL_PREFIX 变量的值来指定这些文件应该拷贝到哪个根目录)。
CMake 提供了一个称为 CTest 的测试工具。我们要做的只是在项目根目录的 CMakeLists 文件中调用一系列的 add_test 命令。
enable_testing()
# 测试程序是否成功运行
add_test (test_run Demo 5 2)
# 测试帮助信息是否可以正常提示
add_test (test_usage Demo)
set_tests_properties (test_usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")
# 测试 5 的平方
add_test (test_5_2 Demo 5 2)
set_tests_properties (test_5_2
PROPERTIES PASS_REGULAR_EXPRESSION "is 25")
# 测试 10 的 5 次方
add_test (test_10_5 Demo 10 5)
set_tests_properties (test_10_5
PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")
# 测试 2 的 10 次方
add_test (test_2_10 Demo 2 10)
set_tests_properties (test_2_10
PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")
一般在project命令后加上这两行
# 主版本号
set (Demo_VERSION_MAJOR 1)
# 副版本号
set (Demo_VERSION_MINOR 0)
在config.h.in中预定义,以便在代码中获取版本信息。
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@
在主函数中输出版本号
作者:Linux嵌入式
链接:https://zhuanlan.zhihu.com/p/534439206
来源:知乎
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "config.h"
#include "math/MathFunctions.h"
int main(int argc, char *argv[])
{
if (argc < 3){
// print version info
printf("%s Version %d.%d\n",
argv[0],
Demo_VERSION_MAJOR,
Demo_VERSION_MINOR);
printf("Usage: %s base exponent \n", argv[0]);
return 1;
}
double base = atof(argv[1]);
int exponent = atoi(argv[2]);
#if defined (HAVE_POW)
printf("Now we use the standard library. \n");
double result = pow(base, exponent);
#else
printf("Now we use our own Math library. \n");
double result = power(base, exponent);
#endif
printf("%g ^ %d is %g\n", base, exponent, result);
return 0;
}
配置生成各种平台上的安装包,包括二进制安装包和源码安装包。为了完成这个任务,我们需要用到 CPack ,它同样也是由 CMake 提供的一个工具,专门用于打包。首先在顶层的 CMakeLists.txt 文件尾部添加下面几行:
# 构建一个 CPack 安装包
# 导入InstallRequiredSystemLibraries,以便之后导入CPack模块
include (InstallRequiredSystemLibraries)
# 设置版权
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
# 设置主版本号
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
# 设置副版本号
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
include (CPack)
执行cpack命令
# 生成二进制安装包
$cpack -C CPackConfig.cmake
# 生成源码安装包
$cpack -C CPackSourceConfig.cmake
之后生成3个不同格式的二进制文件
执行其中一个,就可以生成安装界面
参考:知乎-Linux嵌入式 : https://zhuanlan.zhihu.com/p/534439206
set函数:https://blog.csdn.net/sinat_31608641/article/details/123101969