文章目录
完整的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