How 2 use CMakeLists

1、单目录下,单个源文件或多个源文件的编译

假如某个项目的目录下只有一个源文件main.cpp或者有几个cpp文件,那么,CMakeLists应该这么写:

# 当前你的项目只有一个源文件main.cpp
# 此时只需要在main.cpp的相同目录下新建CMakeLists文件

# 规定cmake程序的最低版本
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )

# 添加c++ 11标准支持
set( CMAKE_CXX_FLAGS "-std=c++11" )

# ADD_EXECUTABEL定义了这个工程会生成一个名为Main的可执行文件
# 相关的源文件是SRC_LIST中定义的源文件列表
# 方式1
set( SRC_LIST main.cpp
	#子目录1/fun1.cpp
	#子目录2/fun2.cpp
	#...
    )
# 利用${}取变量的地址,但是在IF控制语句中是直接使用变量名
# 方式1对应
ADD_EXECUTABLE( Main ${SRC_LIST} )



# 方式2
# 直接使用ADD_EXECUTABLE
#ADD_EXECUTABLE( Main main.cpp ... ... )

2、多目录下,多个源文件的编译

假如项目的tree如下

其中,main函数包含两个子目录的头文件,子目录下的源文件包含上层目录对应的头文件

可以有两种方式编写CMakeLists.txt

1)只在项目根目录下编写唯一一个CMakeLists.txt

2)每个目录下均编写一个CMakeLists.txt

# ~/workspace/CMakeLists.txt
# 规定cmake程序的最低版本
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )

# ADD_SUBDIRECTORY命令用于向当前工程添加存放源文件的子目录,并且可以制定中间二进制和目标二进制存放的位置
# ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
ADD_SUBDIRECTORY( mod1 )
ADD_SUBDIRECTORY( mod2 )

# ADD_EXECUTABLE定义了这个工程会生成一个文件名为Main的可执行文件
# 相关的源文件是通过SET命令定义的参数SRC_LIST定义的源文件列表
SET( SRC_LIST main.cpp )
ADD_EXECUTABLE( Main ${SRC_LIST} )

# TARGET_LINK_LIBRARIES命令指定在链接目标文件的时候需要链接的外部库,解决外部库的依赖问题
# 它会自动寻找对应名称的库文件,而无需书写完整的路径
# 这里的mod1和mod2是在子目录的CMakeLists中用ADD_LIBRARY命令将子目录下的源文件生成的链接文件
TARGET_LINk_LIBRARIES( Main mod1 mod2 )
# ~/workspace/mod1/CMakeLists.txt

# 规定cmake程序的最低版本
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )

# ADD_LIBRARY命令将指定的源文件生成链接文件

# ADD_LIBRARY( <lib_name> ------表示库文件的名字
#	       [STATIC | SHARED | MODULE]  
#	       [EXCLUDE_FROM_ALL]
#	       [sourcefile1] [sourcefile2] [...] )

# STATIC库是目标文件的归档文件(静态库),在链接其他目标时使用
# SHARED库会被动态链接(动态链接库),在运行时会被加载
# 下面会生成mod1/libmod1.a文件
SET( MOD1_LIST mod1fun1.cpp mod1fun2.cpp )
ADD_LIBRARY( mod1 STATIC ${MOD1_LIST} )

# ~/workspace/mod2/CMakeLists.txt

# 规定cmake程序的最低版本
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )

# ADD_LIBRARY命令将指定的源文件生成链接文件

# ADD_LIBRARY( <lib_name> ------表示库文件的名字
#	       [STATIC | SHARED | MODULE]  
#	       [EXCLUDE_FROM_ALL]
#	       [sourcefile1] [sourcefile2] [...] )

# STATIC库是目标文件的归档文件(静态库),在链接其他目标时使用
# SHARED库会被动态链接(动态链接库),在运行时会被加载
# 下面会生成mod2/lib_mod2.a文件
SET( MOD2_LIST mod2fun1.cpp mod2fun2.cpp )
ADD_LIBRARY( mod2 STATIC ${MOD2_LIST} )

接下来进行外部编译以后,在build文件夹内,会生成可执行文件Main,mod1目录,mod2目录,以及其他一些中间文件

其中,mod1和mod2目录下是这样的,可以看到,生成了libxxx.a文件

假如将子目录下的CMakeLists中ADD_EXECUTABLE命令中的参数改成SHARED,那么就是这样的

可以看到,生成了libxxx.so文件

3、使用OpenCV

那么,假如我想使用OpenCV,那应该怎么做呢

因为这是一个外部库,我事先并不知道它的头文件和链接库的位置,所以要在编译命令中加上包含它们的查找路径

可以在项目目录下的CMakeLists中使用FIND_PACKAGE命令来寻找OpenCV库

并用INCLUDE_DIRECTORIES命令来添加头文件

# 寻找OpenCV库
FIND_PACKAGE( OpenCV REQUIRED )
# 添加头文件
INCLUDE_DIRECTORIES( ${OpenCV_INCLUDE_DIRS} )

可以用MESSAGE命令输出OpenCV相关信息

MESSAGE(STATUS "OpenCV library status:")
MESSAGE(STATUS "    version: ${OpenCV_VERSION}")
MESSAGE(STATUS "    libraries: ${OpenCV_LIBS}")
MESSAGE(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

最后,在利用ADD_EXECUTABLE命令生成可执行文件以后,将其与OpenCV库链接起来(与mod1类似)

# 链接OpenCV库
TARGET_LINK_LIBRARIES( Main ${OpenCV_LIBS} )

 注意,这里是将OpenCV的库与可执行文件链接起来,而不是使用PROJECT命令指定的工程名

而PROJECT指定的是工程名,项目最终编译生成的可执行文件并不一定是这个项目名称,而是由ADD_EXECUTABLE命令确定的。
但是PROJECT指定的项目名称还是必要的,因为在cmake中有两个预定义变量:

< projectname >_BINARY_DIR      以及      < projectname >_SOURCE_DIR

内部编译情况下两者相同,而在外部编译的情况下两者所指代的内容会有所不同。

同时cmake还预定义了

PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR

在项目中,PROJECT_BINARY_DIR等同于< projectname >_BINARY_DIR,

PROJECT_SOURCE_DIR等同于< projectname >_SOURCE_DIR。

在实际的应用中,应使用PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR变量,这样即使项目名称发生变化也不会影响CMakeLists.txt文件。

如此,即可在main.cpp中包含opencv的头文件,并做一个简单的矩阵显示了

一些需要注意的地方:

1)注意几个的区别

A.INCLUDE_DIRECTORIES命令添加头文件目录,比如

INCLUDE_DIRECTORIES("/opt/MATLAB/R2012a/extern/include")

B. LINK_LIBRARIES命令添加需要链接的库文件目录

相当于环境变量添加LD_LIBRARY_PATH的路径的作用,比如

#LINK_DIRECTORIES(directory1 directory2 ...)
LINK_DIRECTORIES("/opt/MATLAB/R2012a/bin/glnxa64")

C.LINK_LIBRARIES命令添加需要链接的库文件路径,注意这里是全路径,比如

LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

D.TARGET_LINK_LIBRARIES命令设置要链接的库文件名称,比如

TARGET_LINK_LIBRARIES(myProject hello),连接libhello.so库
TARGET_LINK_LIBRARIES(myProject libhello.a)
TARGET_LINK_LIBRARIES(myProject libhello.so)

猜你喜欢

转载自blog.csdn.net/CSDN_dzh/article/details/82025921