CMAKE超级简单入门

常见编译选项

预处理

  • -D 编译宏定义:-D<标识符>相当于#define <标识符>,如-DDBUG
  • -I 头文件包含路径:-I/backup/include
  • -sysroot 系统头文件路径:-sysroot=/home/sysroot
  • -MD 自动生成依赖文件:-MD,
  • -MP 为依赖项生成假目标:
  • -MT 更改目标名称:

编译选项

  • -Wall 打开所有警告
  • -Werror 提高警告级别
  • -Wcomment 注释不规范
  • -Warray-bounds 数组越界
  • -Wstrict-aliasing 严格别名
  • -g 生成调试信息
  • -On 代码优化级别,若n不存在,则不优化,n越大优化越大
  • -march 为CPU架构
  • -mtune 为CPU性能调优
  • -mcpu CPU名称
  • -fPIC 生成位置无关代码
  • -fstack-protector 栈保护

屏蔽警告

  • -w 屏蔽所有警告
  • -Wno-comment
  • -Wno-array-bounds
  • -fno-strict-aliasing
  • -fno-common

链接

  • -l 链接库文件
  • -L 链接库路径
  • -shared
  • -rdynamic
  • -pie
  • -Wl,-z,relro
  • -Wl,-z,noexecstack
  • -Wl,-z,now
  • -Wl,–disable-new-dtags,-rpath

一般Cmake编译实例文件目录结构

构建工程

  • add_subdirectory()会处理下层文件夹中的CMakeLists.txt文件
  • cmake -P

主要文件介绍

  • CMakeLists.txt:cmake配置文件,与代码同路径存放,共同进行配置管理
  • *.sh:编译入口,调用cmake和make,执行编译
  • config_***.cmake:编译器配置文件,包括编译类型的输出条件开关标志,输出文件名称、输出文件配置文件名称和输出文件存放路径等,一般存放在根目录下,单独的文件中重用

根目录结构

CMakeLists.txt 主CmakeLists.txt,cmake函数执行的入口

build

build.sh 编译工程入口,设置编译环境变量

build_all.sh

cmake_and_compile.sh 编译入口,开始工程编译

cmake 编译器配置文件

user_config

user_config.cmake

...

project_config 工程输出文件的配置文件夹

project_config.cmake

...

toolchain 针对某个工程的编译器配置文件夹

toolchain_config.cmake

...

output 编译输出目录

usrcodefile 源代码目录

CMakeLists.txt 告知cmake处理下层目录的CMakeLists.txt

appFile 源代码文件夹

CMakeLists.txt 底层源代码的CmakeLists.txt

...

otherSourceFile 源代码文件夹

CMakeLists.txt

...

...

Cmake编译

内部编译

  • 进入主目录
  • 执行:cmake . (命令后面的点号,表示本目录)

外部编译

  • 清除主目录中,除了源代码、CmakeLists.txt之外的所有中间文件
  • 在主目录中新建build目录,或其他地方建立build目录
  • 进入build目录,运行cmake … (…代表父目录,如果在其他地方建立build目录,则需要运行cmake <程目录的主路径>),查看build目录,就会产生编译需要的Makefile以及其他的中间文件
  • 在build中运行make构建工程,会在当前目录(build目录)获得目标文件,其中PROJECT_SOURCE_DIR指代码工程路径(代码主目录)PROJECT_BINARY_DIR指代码编译路径(buil目录路径)

常用命令

  • cmake_mininum_required():设置cmake的最低版本要求,如cmake_mininum_required(VERSION 2.6)
  • project():定义项目名称,如project(Tutorial)
  • message():输出信息,可以输出cmake中的变量信息,如message(“linker:${LINKER}”)
  • include():该命令可以包含一个cmake支持的文件,严禁包含CmakeLists.txt,只能包含*.cmake,如include(common_config.cmake)
  • set():该命令可以修改cmake的环境变量和添加自定义变量,如设置系统变量set(CMAKE_SYSTEM_NAME linux),设置自定义变量set(usr_root ${CODE_ROOT_PATH}/usr)
  • target_sources():向编译目标添加源文件,如target_sources(project_name PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.c)
  • STREQUAL:判断两个字符串是否相等,一般与条件判断一起使用
  • add_subdirectory():该命令处理下层文件夹中的CmakeLists.txt文件,如add_subdirectory(subfile_name)
  • add_executable():用于创建一个可执行的Target
  • add_library():可以创建动态库shared,静态库static,对象列表object,如生成动态库add_library( M O D U L E N A M E S H A R E D " " ) , 生 成 对 象 列 表 a d d l i b r a r y ( {MODULE_NAME} SHARED " "),生成对象列表add_library( MODULENAMESHARED"")addlibrary({MODULE_NAME} SOBJECT " ")
  • add_custom_target():添加一个目标
  • add_definitions():向C/C++编译器添加-D宏定义,如add_definitions(-DABC -DDEG),参数使用空格间隔
  • add_dependencies():定义target依赖的其他target,确保在编译本target之前,其他的target以及被构建,如add_dependencies(target detarget1 detarget2 …)

命令详解

  • PROJECT(project_name [CXX] [C] [Java])
    这条指令隐式定义两个变量:<project_name>_BINARY_DIR、<project_name>_SOURCE_DIR,内部编译变量所指的都是工程所在路径,外部编译时所指代的内容有所不同,同时cmake系统也预定义PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR变量,变量值与<project_name>一致
  • SET(var [value] [CACHE TYPE DOCSRING [FORCE]])
  • MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message” …)
    这个指令用于向终端输出用户定义的信息,SEND_ERROR产生错误,生成过程被跳过,STATUS输出前缀为_的信息,FATAL_ERROR立即终止所有cmake过程
  • ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
    指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制文件存放的位置。EXCLUDE_FROM_ALL参数的含义是将这个目录从编译过程中排除。将source_dir子目录加入工程,并指定编译输出(包括中间结果)存放路径binary_dir目录下,如果不进行binary目录的指定,那么编译结果将存放build/source_dir目录中,与原有的source_dir目录对应。
    可以通过set指令,重新指定最终的目标二进制文件(可执行文件和共享库)的位置:set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 和set(LIBBARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

使用外部共享库和头文件

  • INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 …)
    用于向工程添加多个特定的头文件搜索路径,路径之间使用空格分隔,如果路径包含空格,可以使用双引号括起来,默认的行为是追加到当前的头文件搜索路径的后面
  • LINK_DIRECTORIES(dir1 dir2 …)
    添加共享库搜索路径
  • TARGET_LINK_LIBRARIES(target library1<debug | optimized> library2 …)
    用来为taget添加需要链接的共享库

静态库与动态库构建

ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXECLUDE_FROM_ALL] source1 source2 … sourceN)

  • 不需要写全libname.so,只需要填写name即可,cmake自动生成

常用变量

  • CMAKE_SYSTEM_NAME:编译系统的类型,例如set(CMAKE_SYSTEM_NAME linux)
  • CMAKE_SYSTEM_PROCESSOR:编译系统处理器类型,如set(CMAKE_SYSTEM_PROCESSOR arm)
  • CMAKE_CXX_COMPILER:C++编译时使用的编译器,如set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++)
  • CMAKE_C_COMPILER:C编译时使用的编译器set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
  • CXX_FLAGS:C++文件编译时的编译参数
  • MACRO_DEFS:源文件编译时,编译宏定义
  • CMAKE_CURRENT_SOURCE_DIR:调用CMakeLists.txt时,所在目录的绝对路径,使用ADD_SUBDIRECTORY(src bin)可以更改这个变量的值,但是使用set(EXECUTABLE_OUTPUT_PATH )不会改变这个变量,仅仅修改最终目标文件存放路径
  • CMAKE_BINARY_DIR、PROJECT_BINARY_DIR、<project_name>_BINARY_DIR 工程编译产生的目录
  • CMAKE_SOURCE_DIR、PROJECT_SOURCE_DIR、<project_name>_SOURCE_DIR
  • CMAKE_CURRENT_LIST_FILE 输出调用这个变量的CMakeLists.txt的完整路径
  • CMAKE_CURRENT_LIST_LINE 输出这个变量所在的行
  • CMAKE_MODULE_PATH 用来自定义cmake模块所在的路径
  • EXECUTABLE_OUTPUT_PATH 、LIBBARY_OUTPUT_PATH 分别用来重新定义可执行文件和库文件存放路径

cmake调用环境变量

  • $ENV{name}:调用系统环境变量,如MESSAGE(STATUS “home dir:$ENV{HOME}”)
  • SET(ENV{name} value):设置环境变量

控制指令

IF

IF(expr)
	commands
	...
ELSE(expr)
	commands
	...
ENDIF(expr)
  • 另外一个指令是ELSEIF,凡是出现IF的地方一定要有对应的ENDIF,出现ELSEIF的地方,ENDIF是可选的
  • 如果SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON),则可以写成:
IF(expr)
	commands
	...
ELSE()
	commands
	...
ENDIF()
#或
IF(expr1)
	commands
	...
ELSEIF(expr2)
	commands
	...
ELSEIF(expr3)
	commands
	...
ENDIF(expr1)

表达式的使用方法:

  • IF(var):如果变量不是空、O、N、NO、OFF、FALSE、NOTT-OUND、_NOTFOUND时为真
  • IF(NOT var):
  • IF(var1 AND var2):当两个变量都为真时为真
  • IF(var1 OR var2):当两个变量其中一个变量为真时为真
  • IF(COMMAND cmd):当给定的cmd为命令,并可以调用时为真
  • IF(EXISTS dir) 或 IF(EXISTS file):当目录或文件存在时为真
  • IF(file1 IS_NEWER_THAN file2):当file1比file2新,或者file1/file2其中一个不存在时为真
  • IF(IS_DIRECTORY dirname):当dirname为目录时为真
  • IF(variable MATCHES regex):给定的变量能够匹配正则表达式时为真
  • IF(string MATCHES regex):给定的字符串能够匹配正则表达式时为真
  • IF(variable LESS/GREATER/EQUAL number):数字比较
  • IF(string STRLESS/STRGREATER/STREQUAL string):按照字母序的排列进行比较
  • IF(DEFINED variable):如果变量被定义,则为真

WHILE

WHILE(condition)
	commands
	...
ENDWHILE(condition)

FOREACH

只有遇到ENDFOREACH指令,整个语句才会真正执行
列表循环

FOREACH(loop_var arg1 arg2)
	commands
	...
ENDFOREACH(loop_var )

范围循环

FOREACH(var RANGE total)
	commands
	...
ENDFOREACH(var)

范围和步进循环

FOREACH(var RANGE start stop [step])
	commands
	...
ENDFOREACH(var)

FUNCTION

文件安装

普通文件安装

如果安装非目标文件的可执行程序安装,如脚本,则把FILES改成PROGRAMS

INSTALL(FILES files...
	DESRINATION <dir>
	[PERMISSIONS permissions ...]
	[CONFIGURATIONS [Debug | Release | ...]]
	[COMPONENT <component>]
	[RENAME <name>]
	[OPTIONAL]
)

目标文件安装

INSTALL(TARGETS targets...
	[[ARCHIVE | LIBRARY | RUNTIME]
	 [DESRINATION <dir>]
	 [PERMISSIONS permissions ...]
	 [CONFIGURATIONS [Debug | Release | ...]]
	 [COMPONENT <component>]
	 [OPTIONAL]
	] [...]
)

案例:

INSTALL(TARGETS myrun mylib mystaticlib
	RUNTIME DESRINATION bin
	LIBRARY DESRINATION lib
	ARCHIVE DESRINATION libstatic
)

目录安装

INSTALL(DIRECTOR dir...
	[DESRINATION <dir>]
	[FILE_PERMISSIONS permissions...]
	[DIRECTORY_PERMISSIONS permissions...]
	[USE_SOURCE_PERMISSIONS permissions...]
	[CONFIGURATIONS [Debug | Release | ...]]
	[COMPONENT <component>]
	[[PATTERN <patern> | REGEX <regex>]
	 [EXCLUDE] [PERMISSIONS permissions...]]
	[...]
)
  • DIRECTORY后面连接的是所在source目录的相对路径,但abc和abc/有很大区别,如果目录不以/结尾,那么这个目录被安装为目标路径下的abc,如果目录名以/结尾,则将这个目录的内容安装到目标路径下,但不包括这个目录本身
  • PATERN用于使用正则表达式进行过滤
  • PERMISSIONS 用于指定PATERN过滤后的文件权限
    案例:
INSTALL(DIRECTOR icons script/
	DESRINATION share/myproj
	PATTERN "cvs" EXCLUDE #不包含目录名为cvs的目录
	PATTERN "script/*"
	PERMISSIONS OWNER_EXECUTE OWNER_WRITE GROUP_READ
)

安装CMAKE脚本

INSTALL(
	[[SCRIPT <file>] [CODE <code>]]
	[...]
)
  • SCRIPT参数用于在安装时调用cmake脚本文件(.cmake文件)
  • CODE参数用于执行CMAKE指令,必须双引号括起来
    案例:
INSTALL(
	CODE ”MESSAGE(\"sample install message.\")"
)

Cmake案例

顶层CmakeLists.txt

cmake_minimum_required(VERSION 2.6) 
project(Tutorial) 
//版本号,在源代码中可以直接使用
set(Tutorial_VERSION_MAJOR 1) 
set(Tutorial_VERSION_MINOR 0) 

//设置C/C++的通用版本可以分别使用变量CMAKE_C_STANDARD(接受值为98,99和11)和CMAKE_CXX_STANDARD (接受值为CMAKE_CXX_STANDARD和14)全局指定
//set(CMAKE_C_STANDARD 99)
//set(CMAKE_CXX_STANDARD 11)

//本系统是否提供 log 和 exp 函数? 
include(${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) 
check_function_exists(log HAVE_LOG) 
check_function_exists(exp HAVE_EXP) 
//我们应该使用自己的 math 函数吗? 
option(USE_MYMATH "Use tutorial provided math implementation" ON) 
//配置一个头文件来向源代码传递一些 CMake 设置。
configure_file( 
	"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
	"${PROJECT_BINARY_DIR}/TutorialConfig.h"
) 
//为包含文件的搜索路径添加二进制树,这样才能发现 TutorialConfig.h 头文件。
include_directories("${PROJECT_BINARY_DIR}") 
//添加 MathFunctions 库吗
if(USE_MYMATH) 
	include_directories("${PROJECT_SOURCE_DIR}/MathFunctions") 
	//生成库
	add_subdirectory(MathFunctions) 
	set(EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 
endif(USE_MYMATH) 
//添加可执行文件
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) 
//测试 1 :应用程序可以运行吗? 
add_test(TutorialRuns Tutorial 25) 
//测试 2 : 使用信息可用吗? 
add_test(TutorialUsage Tutorial) 
set_tests_properties(TutorialUsage PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
) 
//定义一个可以简化引入测试过程的宏
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(4 "4 is 2") 
do_test(9 "9 is 3") 
do_test(5 "5 is 2.236")<BR>do_test (7 "7 is 2.645") 
do_test(25 "25 is 5") 
do_test(-25 "-25 is 0") 
do_test(0.0001 "0.0001 is 0.01")

TutorialConfig.h.in配置文件

//Tutorial 的配置选项与设置如下
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ 
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ 
#cmakedefine USE_MYMATH 
//该平台提供 exp 和 log 函数吗? 
//使用#define 或 #cmakedefine可以在源代码中直接使用,如
/*
printf(“Version %d.%d\n", Tutorial_VERSION_MAJOR)
#define HAVE_LOG
...
#endif
*/
#cmakedefine HAVE_LOG 
#cmakedefine HAVE_EXP

引入库源代码目录的CMakeLists.txt

//把库文件放到一个子目录 MathFunctions
add_library(MathFunctions mysqrt.cxx)
install(TARGETS MathFunctions DESTINATION bin) 
install(FILES MathFunctions.h DESTINATION include)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值