文章目录
cmakelist.txt
Cmake中的包头和库的指定
cmake提供更简单的方式来解决编译依赖问题,通常遇到编译时,需要指定包来进行编译,可通过如下几种方式来指定参与链接的包
1、通过find_package查找包
1) find_package自动查找
在以下环境变量中查找cmake文件
<package>_DIR
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
PATH
1\通常ROS环境下:CMAKE_PREFIX_PATH
为/opt/ros/<melodic>
,
因此ROS环境下find_package()
首先会在/opt/ros/<melodic>
下寻找,如/opt/ros/melodic/share/<packages>
能找到关于集成在ros下的package的Config.cmake
文件。
2\对于根目录PATH下的查找:
cmake会自动去/usr/(lib/<arch>|lib|share)/cmake/<name>*/
寻找模块,这使得绝大部分我们直接通过apt-get安装的库可以被找到。
find_package()
会在~/.cmake/packages/
或/usr/local/share/
中的各个包目录中查找,寻找<库名字的大写>Config.cmake
或者 <库名字的小写>-config.cmake
(比如库Opencv
,它会查找/usr/local/share/OpenCV
中的OpenCVConfig.cmake或opencv-config.cmake)。
常用两种Config.cmake系统查找路径:
/usr/local/share/<package>
/usr/local/lib/cmake/<package>
以上来自:https://www.jianshu.com/p/243ff97bbbc6
2)package_DIR设定包的位置
比较重要的是<package>_DIR
。我们可以在调用cmake时将这个目录传给cmake。由于其优先级最高,因此cmake会优先从该目录中寻找,当我们不想安装某些自编译的包时,可以通过这种方法来指定find_package的指定寻找路径。
如:
set(G2O_DIR ${PROJECT_SOURCE_DIR}/lib/g2o/build)
find_package(G2O REQUIRED)
include_directories(${G2O_INCLUDE_DIRS})
link_directories(${G2O_LIBRARY_DIRS})
link_libraries(${G2O_LIBRARIES})
find_package根据package名称寻找指定的package的.cmake文件,并对应赋值包对应的头文件地址(如${OpenCV_INCLUDE_DIRS}
)及库(如${OpenCV_LIBRARIES}
)
${OpenCV_LIBRARIES}
不是库的存放地址,而是-lxxx,即用pkg-config opencv –libs打印出的内容,如:
-L/usr/local/lib -lopencv_dnn -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_shape -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_features2d -lopencv_video -lopencv_photo -lopencv_imgproc -lopencv_flann -lopencv_viz -lopencv_core
2、设定包的头文件及库
也可以通过cmakelist的set()
重设${xxxINCLUDE_DIRS}
和${xxx_LIBRARIES}
,以及自定义变量,用法,set(变量名 变量值)
,如:
set(LIBS ${OpenCV_LIBS}
${PROJECT_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so
-lboost_system)
3、使用pkg-config
在cmakelist中指定包
set(ENV{PKG_CONFIG_PATH} /packname.pc_path)
find_package(PkgConfig)
pkg_search_module(MyDepName REQUIRED packname)
之后可以使用${MyDepName_LIBRARIES}
和${MyDepName_INCLUDE_DIRS}
来指定包的头文件及库
https://www.jianshu.com/p/eb6b06463da9
为编译指定全部头文件及库地址以及库名
通过include_directories
和link_directories
指定额外的头文件及库文件路径。分别对应g++的-I和-L操作。
link_libraries
添加需要链接的库文件路径,注意这里是全路径,如:
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
通过target_link_libraries
指定链接库,即执行编译中对应的-lxxx
操作
add_executable(GNtest src/test.cpp)
target_link_libraries(GNtest ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${PCL_LIBRARIES} -lgtsam)
遇到问题
Q1:Could not find a package configuration file
By not providing "FindNLOPT.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "NLOPT", but
CMake did not find one.
Could not find a package configuration file provided by "NLOPT" with any of
the following names:
NLOPTConfig.cmake
nlopt-config.cmake
Add the installation prefix of "NLOPT" to CMAKE_PREFIX_PATH or set
"NLOPT_DIR" to a directory containing one of the above files. If "NLOPT"
provides a separate development package or SDK, be sure it has been
installed.
R1:首先请确保是否是因为缺包引起的。
(1)是的话安装对应包,不是则找到xxx.cmake的存放位置
在CMakelist.txt中添加xxx.cmake所在的路径到查找路径。
解决以上报错的两种方法:
- 添加
set (CMAKE_PREFIX_PATH "pathtoxxx.cmake")
- 添加
list(APPEND CMAKE_FIND_ROOT_PATH "pathtoxxx.cmake")
如果直接xxx.cmake直接在项目目录下,添加list(APPEND CMAKE_FIND_ROOT_PATH ${PROJECT_SOURCE_DIR})
即可。
CMAKE_SOURCE_DIR does indeed refer to the folder where the top-level CMakeLists.txt is defined.
PROJECT_SOURCE_DIR refers to the folder of the CMakeLists.txt containing the most recent project() command.
(2)若包已安装,但是没有对应的xxx.cmake文件,find_package找不到xxx.cmake文件。
则可以利用pkg-config 找到对应的库。
在要编译的包的CMakeList.txt中对应修改,以下以fcl包为例。
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBFCL_PC REQUIRED fcl)
# find *absolute* paths to LIBFCL_INCLUDE_DIRS and LIBFCL_LIBRARIES
find_path(LIBFCL_INCLUDE_DIRS fcl/config.h HINTS ${LIBFCL_PC_INCLUDE_DIR} ${LIBFCL_PC_INCLUDE_DIRS})
find_library(LIBFCL_LIBRARIES fcl HINTS ${LIBFCL_PC_LIBRARY_DIRS})
include_directories(SYSTEM ${catkin_INCLUDE_DIRS}
...
${LIBFCL_INCLUDE_DIRS}
)
catkin_package(
...
DEPENDS
Boost
EIGEN3
LIBFCL
)
opencv solve test:cvsolve.cpp
#include <iostream>
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
using namespace std;
int main()
{
cv::Mat A = (cv::Mat_<float>(2, 2) << 1,2,3,4);
cv::Mat B = (cv::Mat_<float>(2, 1) <<5,11);
cv::Mat C;
cout << "A" << endl << A << endl;
cout << "B" << endl << B << endl;
cv::solve(A, B, C, CV_LU);
cout << "X" << endl << C << endl;
return 0;
}
编译命令:要主动链上opencv 否则会报未定义的错误。
g++ `pkg-config --libs --cflags opencv` -ldl xx.cpp
#下边这个命令常用
g++ opencv_test.cpp `pkg-config --cflags --libs opencv`
以上命令会自动找到并连接opencv的库。而不用在手动指定。
pkg-config 用于获得某一个库/模块的所有编译相关的信息。寻找对应的xxx.pc文件,来获取包及库的相关信息。
ldl: 链接动态库
如果你的程序中使用dlopen、dlsym、dlclose、dlerror 显示加载动态库,需要设置链接选项 -ldl
输出结果:
cmake用法:
add_subdirectory 添加下级编译目录,下级有CMakelist.txt的目录
add_definitions 添加可配置的宏定义:
#eg:如下示例可置宏定义ADVANCED_SENSING为1或0,进而可以再代码终用#ifdef打开或关闭对应的代码。
option(ADVANCED_SENSING "ADVANCED_SENSING set" ON)
if (ADVANCED_SENSING)
add_definitions(-DADVANCED_SENSING)
endif()
cmake . -DADVANCED_SENSING=0
add_dependencies:添加编译依赖顺序,检查上级编译是否已经编译,否则先编译依赖上级