CMake基础语法与应用总结归纳

CMake简介

CMake是一个跨平台的编译工具,可以用简单的语句来描述所有平台的编译过程。程序猿利用cmake语句编写工程编译过程语句形成CMakeList.txt文件,利用cmake指令执行该cmake文件,生成对应不同平台的makefile文件,由其来进行不同平台编译过程的批处理操作,最终生成库文件或可执行文件。类似于编译器要执行的基本任务。

CMake框架

首先对CMake文件的框架做一个大致了解。在学习开始前,读者首先还应对工程编译过程、库文件相关知识有一定了解。

command(arg1 arg2)          #运行命令
set(var_name var_value)     #设置变量值
command(arg1 ${var_name})   #使用变量

#********************工程配置部分*****************
cmake_minium_required(VERSION num)
project(cur_project_name)
set(CMAKE_CXX_FLAGS "xxx")  #设置编译器类型,如-std=c+11
set(CMAKE_BUILD_TYPE)       #设定编译模式,如DEBUG/RELEASE

#********************依赖执行部分****************
find_package(std_lib_name VERSION REQUIRED)   #引入外部库
add_library(<name> [lib_type] source_name)    #生成库类型(动态.so.dll/静态.a)
include_directories(${std_lib_name_INCLUDE_DIRS})
add_excutable(cur_project_name main.cpp)
target_link_libraries(${std_lib_name_LIBRARIES})

#*******************其他辅助部分*****************
function(function_name arg)      #定义一个函数
add_subdirectory(dir)    #增加一个子目录
AUX_SOURCE_DIRECTORY(. src_list) #查找当前目录所有文件并存储到变量src_list中
FOREACH(one_dir ${src_list})
	MESSAGE(${one_dir})
ENDFOREACH(one_dir)

#******************判断控制部分*****************
IF(EXPRESSION)
	COMMAND(arg1)
ELSE
	COMMAND(arg2)
ENDIF(EXPRESSION)

WHILE(condition)
	COMMAND(arg1)
ENDWHILE(condition)

IF(var)
IF(NOT var)
IF(var1 AND var2)
IF(var1 OR var2)
IF(COMMAND cmd)   #如果cmd是指令
IF(EXISTS dir)
IF(EXISTS file)
IF(is_directory dir)
IF(file1 IS_NEWER_THAN file2)

CMake常用指令

注:CMake指令不区分大小写

1.基本指令

PROJECT
ADD_EXCUTABLE
ADD_SUBDIRECTORY
INCLUDE_DIRECTORIES
TARGETS_LINK_DIRECTORIES
ADD_LIBRARY
AUX_SOURCE_DIRECTORY
FOREACH
MESSAGE
IF ESLE ENDIF
WHILE ENDWHILE
FIND_PACKAGE
SET

2.其他指令

ADD_DEFINATIONS

为源文件添加由 -D 引入的宏定义
add_definations(-DMAX)

OPTION

提供用户可以选择的选项
option( “description” [initial value])

option(
		USE
		"use state"
		ON
)

ADD_CUSTOM_COMMAND

为工程添加一条自定义的构建规则

ADD_CUSTOM_TARGET

用于给指定名称的目标执行指定的命令,该目标没有输出文件,并始终被构建

ADD_DEPENDENCIES

当定义的一个target依赖于另一个target时,为了保证编译本target之前另一个target已经被编译,使用此语句,解决链接依赖问题

INSTALL

  • 用于定义库的安装规则,安装的内容涵盖目标二进制、动态库、静态库、文件、目录、脚本等
  • 常用库安装到系统目录,如/usr/lib,/usr/include,/usr/bin
    一些参数:

各参数可以参考CMake手册介绍

INSTALL(
	TARGETS myrun mylib mtStaticLib
	RUNTIME DESTINATION bin
	LIBRAYR DESTINATION lib
	ARCHIVE DESTINATION binstatic
)

以上实例中,RUNTIME用于标记可执行文件的安装路径,LIBRAYR用于标记动态库的安装路径,ARCHIVE用于标记静态库的安装路径。其中,是否属于RUNTIME类型还与文件本身属性有关,而LIBRAYR还与执行平台有关,详细信息可参考上述手册链接,下文摘选有关内容。

The TARGETS form specifies rules for installing targets from a project. There are five kinds of target files that may be installed: ARCHIVE, LIBRARY, RUNTIME, FRAMEWORK, and BUNDLE. Executables are treated as RUNTIME targets, except that those marked with the MACOSX_BUNDLE property are treated as BUNDLE targets on OS X. Static libraries are always treated as ARCHIVE targets. Module libraries are always treated as LIBRARY targets. For non-DLL platforms shared libraries are treated as LIBRARY targets, except that those marked with the FRAMEWORK property are treated as FRAMEWORK targets on OS X. For DLL platforms the DLL part of a shared library is treated as a RUNTIME target and the corresponding import library is treated as an ARCHIVE target. All Windows-based systems including Cygwin are DLL platforms. The ARCHIVE, LIBRARY, RUNTIME, and FRAMEWORK arguments change the type of target to which the subsequent properties apply. If none is given the installation properties apply to all target types. If only one is given then only targets of that type will be installed (which can be used to install just a DLL or just an import library). The INCLUDES DESTINATION specifies a list of directories which will be added to the INTERFACE_INCLUDE_DIRECTORIES target property of the when exported by the install(EXPORT) command. If a relative path is specified, it is treated as relative to the $<INSTALL_PREFIX>.

DESTINATION的目标安装路径如使用相对路径,应注意设置相对路径变量CMAKE_INSTALL_PREFIX

TARGET_INCLUDE_DIRECTORIES

设置include文件查找的目录,具体包含头文件应用形式(接口、公有、私有)、安装位置等
target_include_directories( [INTERFACE|PUBLIC|PRIVATE] )

SET_TARGET_PROPERITIES

设置目标的一些属性来改变他们的构建方式
set_target_properities(target1 target2 PROPERITIES prop1 value1 prop2 value2)

set_target_properities(example
	PROPERITIES
	ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINAYR_DIR}/lib"
	LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINAYR_DIR}/lib"
)

ENABLE_TESTING/ADD_TEST

构建并开启构建test目标

ADD_TEST(mytest ${PROJECT_BINAYR_DIR}/bin/main)
ENABLE_TESTING()

CMake常用环境变量

变量含义
CMAKE_INSTALL_PREFIX构建install的路径
$ENV{HOME}HOME环境下的目录路径
PROJECT_NAME工程名
package_INCLUDE_DIR导入包头文件目录
package_LIBRAYIES导入库文件的全路径
PROJECT_SOURCE_DIR当前工程的全路径
CMAKE_VIRSIONcmake版本号

编译方法

采用外部编译
工程文件夹目录设置为:src、include、build
mkdir build
cd build
cmake … #利用上一级目录的CMkeList.txt文件生成makefile
make #编译makefile文件,生成bin文件
./hello_world #执行文件

附:工程文件夹组织框架

├── build
| └── bin
| | └── <project_name.exe>
├── install
| └── include
| | ├── xxx.h
| | └── xxx.h
| └── lib
| | ├── xxx.so
| | └── xxx.a
├── include
| ├── xxx.h
| └── xxx.h
├── src
| ├── xxx.cpp
| └── xxx.cpp
├── CMakeLists.txt
├── README
└── run<project_name>.sh

一些实例

以上列举的一些常用命令和变量,较为零碎,建议结合以下实例进一步体会各命令、变量的用法

最简单的例子——执行编译工程

CMakelist.txt文件

cmake_minium_required(VIRSION 2.8.3)
project(hello_world)

add_compile_option(-std=c++11)

include_directiories(include)
add_excutable(hello_world src/hello_world.cpp src/main.cpp)

生成静态库

cmake_minium_required(VIRSION 2.8.3)
project(hello_world_static_lib)

add_compile_option(-std=c++11)

include_directiories(include)
add_library(hello_world_static_lib STATIC src/hello_world.cpp)

生成指定路径的动态库

cmake_minium_required(VIRSION 2.8.3)
project(hello_world_shared_lib)

add_compile_option(-std=c++11)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
include_directiories(include)
add_library(hello_world_shared_lib SHARED src/hello_world.cpp)

同时生成动态库和静态库

添加库时的目标(hello_world_lib)不能使用一样的名字,添加库后设置目标输出名字属性设置为一样的即可

cmake_minium_required(VIRSION 2.8.3)
project(hello_world_lib)

add_compile_option(-std=c++11)

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
include_directiories(include)

add_library(hello_world_lib STATIC src/hello_world.cpp)
add_library(hello_world_lib_shared SHARED src/hello_world.cpp)

set_target_properities(hello_world_lib_shared PROPERITIES OUTPUT_NAME "hello_world_lib")

库的安装和导入

库文件分为

方式一:利用绝对路径导入

cmake_minium_required(VIRSION 2.8.3)
project(hello_world)

add_compile_option(-std=c++11)

set(P /home/project/src/hello_lib)
include_directiories(${P}/include include)
add_excutable(${PROJECT_NAME} src/hello_world.cpp src/main.cpp)
target_link_library(${PROJECT_NAME} ${P}/lib/hello.so)

方式二:利用INSTALL导入

若未得到库文件,首先利用源程序进行库文件安装

cmake_minium_required(VIRSION 2.8.3)
project(hello_lib)
add_compile_option(-std=c++11)

include_directiories(include)
add_library(libhello STATIC src/hello_lib.cpp)

set(CMAKE_INSTALL_PREFIX /usr)
install(FILE include/hello.h DESTINATION include)
install(TARGET libhello ARCHIVE DESTINATION lib)

确定了库文件和头文件的位置后,就可以在需要的工程中导入需要的库文件了

cmake_minium_required(VIRSION 2.8.3)
project(hello_world)
add_compile_option(-std=c++11)

include_directiories(include /usr/include)
add_excutable(hello_world src/hello_world.cpp src/hello_main.cpp)
target_link_libraries(${PROJECT_NAME} /usr/lib/libhello.a)

方式三:利用find_package进行

该方式分为两种模式:模块模式和配置模式,这里只介绍较为简便的模块模式。首先介绍该模式下的常用变量:

变量含义
_FOUND库是否找到
_INCLUDE_DIR库的头文件路径
_LIBRARY库文件路径

模块模式除了要进行库文件的安装和导入外,首先还要进行cmake文件的编写,供后期指令查找使用

1.Findxxxx.cmake文件编写

放置在cmake文件夹下

find_include( hello_lib_INCLUDE_DIR
NAMES hello.h
#必须是绝对路径 
PATHS "/media/hello/install/include/")

find_library(hello_lib_LIBRARY
NAMES libhello
PATHS "/media/hello/install/lib/")

if(hello_lib_INCLUDE_DIR AND hello_lib_LIBRARY)
	set(hello_lib_FOUND true)
endif(hello_lib_INCLUDE_DIR AND hello_lib_LIBRARY)

if(hello_lib_FOUND)
	message("YES!")
else
	message("NO")
endif(hello_lib_FOUND)

2.库文件的安装

安装共三个步骤,分别为cmake文件的安装、头文件安装和库文件安装

cmake_minium_required(VERSION 2.8.3)
project(hello_lib)
add_compile_option(-std=c++11)
include_directories(include)
add_library(libhello STATIC src/hello.cpp)

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)

install(FILE Findhello_lib.cmake DESTINATION cmake)
install(FILE hello_lib.h DESTINATION install)
install(TARGET libhello ARCHIVE DESTINATION lib)

3.库文件的导入

cmake_minium_required(VIRSION 2.8.3)
project(hello_world)
add_compile_option(-std=c++11)

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../libhello/install/cmake)

find_package(libhello REQUIRED)
if(libhello_FOUND)
	include_directories(include ${libhello_INCLUDE_DIR})
	add_excutable(hello_world src/hello_world.cpp src/main.cpp)
	target_link_libraries(hello_world ${libhello_LIBRARY})
else
	message("error!")
endif(libhello_FOUND)	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值