小白学习大型C++源码项目系列之为什么要用CMakeLists.txt

完整的CMakeLists.txt

CMakeLists.txt文件大小写不敏感,
根目录和子目录都会有CMakeLists.txt文件。

CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) #设定版本
PROJECT( slam ) #设定工程名
SET( CMAKE_CXX_COMPILER "g++") #设定编译器
set( CMAKE_BUILD_TYPE "Release" )  # 设定编译类型 debug 和release两种
SET( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #设定生成的可执行二进制文件存放的存放目录
SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #设定生成的库文件的存放目录
LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib)#并且把该目录设为链接目录
INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include)#设定头文件目录
ADD_SUBDIRECTORY( ${PROJECT_SOURCE_DIR}/src)#增加子文件夹,也就是进入源代码文件夹继续构建

编译后的文件结构与含义

  • bin 用来放编译好的可执行二进制文件。
  • src 用来放源代码。
  • lib 用来放编译好的库文件。
  • include 用来放头文件。

编译安装的一般流程

mkdir build
cd build
cmake ..
make
sudo make install

CMake是跨平台编译工具,主要编写CMakeLists.txt文件,
用cmake命令将CMakeLists.txt文件转化为make所需要的Makefiles文件,
CMakefiles.txt和用来生成 Makefiles 的文件是一致的,
用make命令编译源码生成可执行程序或共享库。

声明 cmake 最低版本

定义cmake的最低版本时2.8
cmake_minimun_required(VERSION 2.8)

终端查看cmake的版本
输入:cmake -version
输出:cmake version 3.2.2

声明 cmake 工程名字

project( HelloSLAM )

还可以增加版本号码
project(HelloSLAM VERSION 0.0.1)

项目根目录

PROJECT_SOURCE_DIR
项目根目录是CmakeLists.txt目录的绝对路径。

设置 cmake 编译模式

set( CMAKE_BUILD_TYPE “Debug” )

添加c++11标准支持

set(CMAKE_CXX_FLAGS “-std=c++11”)
set(CMAKE_CXX_FLAGS “-std=c++11 -O3”)
有的时候可能会遇到,一定要注意是大写的O,不是数字0

参数CMAKE_CXX_FLAGS含义是: set compiler for c++ language
而后面的-O3(是字母opq的o,大写的欧)是用来调节编译时的优化程度的,最高为-O3,最低为-O0(即不做优化)

-Ox这个参数只有在CMake -DCMAKE_BUILD_TYPE=Release时有效,
因为debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化,而 release 版的不需要调试信息但需要优化。

添加变量

set(KEY VALUE)接受两个参数,用来声明变量。
在camke语法中使用KEY并不能直接取到VALUE,必须使用${KEY}这种写法来取到VALUE。

添加依赖

find_package( Sophus REQUIRED )
find_package( OpenCV REQUIRED )
find_package( PCL REQUIRED COMPONENT common io )

find_package的作用就是去寻找该库的头文件位置、库文件位置以及库文件名称,并将其设为变量,
返回提供给CMakeLists.txt其他部分使用。

在CMakeLists.txt如果需要使用第三方库三部曲

find_package、include_directories、target_link_libraries

find_package(Boost REQUIRED COMPONENTS filesystem)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries( ${Boost_LIBRARIES})

去哪里找头文件(.h等) INCLUDE_DIRECTORIES()
去哪里找库文件(.so/.lib/.ddl等) LINK_DIRECTORIES()
需要链接的库文件名称 LINK_LIBRARIES(库名称即可)

添加一个可执行程序

语法:add_executable( 程序名 源代码文件 )
add_executable( SLAM SLAM.cpp )

构建静态库

add_library( hello libHelloSLAM.cpp )
生成静态库".a"文件

构建共享库

add_library( hello_shared SHARED libHelloSLAM.cpp )

生成共享库".so"文件
add_executable( useHello useHello.cpp )

构建大型项目时可以为使用这个库添加一个开关
在项目根目录下的CMakeLists.txt文件中添加如下代码:
option (USE_MYMATH “Use tutorial provided math implementation” ON)

将库文件链接到可执行程序上

target_link_libraries( useHello hello_shared )
target_link_libraries( imageBasics ${OpenCV_LIBS} )
target_link_libraries( joinMap ${OpenCV_LIBS} ${PCL_LIBRARIES} )

指定安装地址

第一种方式在终端输入:
使用 CMAKE_INSTALL_PREFIX 来指定

cmake -DCMAKE_INSTALL_PREFIX=/usr ..  

第二种方式在文件CMakeLists.txt中写入:

SET(CMAKE_INSTALL_PREFIX < install_path >) 

Debug和Release版本

debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化
release 版的不需要调试信息但需要优化。
这些特性在 gcc/g++ 中是通过编译时的参数来决定的,如果将优化程度调到最高需要设置参数-O3,最低是 -O0 即不做优化;
添加调试信息的参数是 -g -ggdb ,如果不添加这个参数,调试信息就不会被包含在生成的二进制文件中。

SET(CMAKE_CXX_FLAGS_DEBUG"$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE"$ENV{CXXFLAGS} -O3 -Wall")

两个变量 CMAKE_CXX_FLAGS_DEBUG 和CMAKE_CXX_FLAGS_RELEASE,
分别用于 debug 和 release 的编译选项。

调试手段

message打印信息,类似于 echo/printf ,主要用于查cmake文件的语法错误。

set(mysql_use_test_sources ${SOURCES_DIRECTORY}/test_sources/mysql_user_accounts.cpp)
message(“mysql_use_test_sources : ${mysql_use_test_sources}”)

CMake常用变量

CMAKE_STATIC_LIBRARY_PREFIX 静态库前缀, Linux下默认为lib
CMAKE_STATIC_LIBRARY_SUFFIX 静态库后缀,Linux下默认为.a
CMAKE_SHARED_LIBRARY_PREFIX 动态库前缀,Linux下默认为lib
CMAKE_SHARED_LIBRARY_SUFFIX 动态库后缀,Linux下默认为.so

CMAKE_BUILD_TYPE 指定基于make的产生器的构建类型(Release,Debug)
CMAKE_C_FLAGS *.C文件编译选项,如 -std=c99 -O3 -march=native
CMAKE_CXX_FLAGS *.CPP文件编译选项,如 -std=c++11 -O3 -march=native

CMAKE_RUNTIME_OUTPUT_DIRECTORY 生成可执行文件路径
CMAKE_LIBRARY_OUTPUT_DIRECTORY 生成库的文件夹路径

在这里插入图片描述

CMakeLists.txt 与 cmake_modules.cmake

cmake_modules .cmake 文件把CMakeLists.txt里的内容分出来,用来找特定的库。
编译时库在usr/local/lib里,提示找不到,可以手动添加寻找目录。
终端输入:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

或者
gedit ~/.bashrc
在bashrc文件最后面添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
之后保存退出再更新文件:source ~/.bashrc

暴力链接指定库的方法
知道要链接库的位置:/usr/local/lib/libabc.a
可以这样写:target_link_libraries(def /usr/local/lib/libabc.a)

查找相关的软件包

apt-cache search 软件包名字
sudo apt-get install 软件包名字

检测安装路径
dpkg -L 软件包名字

查找头文件路径
pkg-config --cflags 软件包名字
pkg-config --libs 软件包名字

补充

而set命令设置CMAKE_C_FLAGS或CMAKE_CXX_FLAGS变量则是分别只针对c和c++编译器的。

project(x800_loopclosure_beta_ros VERSION 0.0.1)

为源文件的编译添加由-D定义的标志。add_definitions(-DFOO -DBAR …)

aux_source_directory 命令,
该命令会查找指定目录下的所有源文件,
然后将结果存进指定变量名。
其语法如下:
aux_source_directory(

)

ADD_LIBRARY()语法

add_library( [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 …])

:库的名字,直接写名字即可,不要写lib,会自动加上前缀的哈。

SHARED,动态库
STATIC,静态库

SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})

一般我们使用的静态库/动态库只是后缀名不同而已,
上面构建的libhello.so与libhello_static.a

猜你喜欢

转载自blog.csdn.net/qq_21950671/article/details/105674514