CMake:pkgConfig.cmake
在CMake中,CMakeLists.txt是项目的配置文件。编译时,常需要包含第三方库的头文件和链接库文件。以OpenCV为例,在CMakeLists.txt中使用 find_package搜索OpenCV的头文件位置和库文件, OpenCVConfig.cmake可以告诉find_package这些信息。下面介绍如何自己写pkgConfig.cmake。
1. pkgConfig.cmake语法
以OpenCV为例,OpenCVConfig.cmake可以这样写:
#set(OpenCV_CONFIG_PATH ${CMAKE_CURRENT_LIST_DIR})
get_filename_component(OpenCV_INSTALL_PATH ${OpenCV_LOC} REALPATH)
set(OpenCV_INCLUDE_DIRS
${OpenCV_INSTALL_PATH}/include
${OpenCV_INSTALL_PATH}/include/opencv)
set(OpenCV_LIB_COMPONENTS
opencv_calib3d; opencv_core; opencv_cudaarithm; opencv_cudabgsegm;
opencv_cudacodec; opencv_cudafeatures2d; opencv_cudafilters; opencv_cudaimgproc;
opencv_cudalegacy; opencv_cudaobjdetect; opencv_cudaoptflow; opencv_cudastereo;
opencv_cudawarping; opencv_cudev; opencv_features2d; opencv_flann;
opencv_highgui; opencv_imgcodecs; opencv_imgproc; opencv_ml;
opencv_objdetect; opencv_photo; opencv_shape; opencv_stitching;
opencv_superres; opencv_video; opencv_videoio; opencv_videostab;
opencv_viz)
foreach(__cvcomponent ${OpenCV_LIB_COMPONENTS})
add_library(${__cvcomponent} SHARED IMPORTED)
set_property(TARGET ${__cvcomponent} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(${__cvcomponent} PROPERTIES
IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE ${OpenCV_LIB_COMPONENTS}
IMPORTED_LOCATION_RELEASE ${OpenCV_INSTALL_PATH}/lib/lib${__cvcomponent}.so.3.2.0
IMPORTED_SONAME_RELEASE lib${__cvcomponent}.so.3.2)
set(OpenCV_LIBS ${OpenCV_LIBS} ${__cvcomponent})
endforeach()
1.1 指出安装位置
指出第三方库的include和lib文件夹位置,头文件和链接库就在这些文件夹内。
set(OpenCV_CONFIG_PATH ${CMAKE_CURRENT_LIST_DIR})
get_filename_component(OpenCV_INSTALL_PATH ${OpenCV_LOC} REALPATH)
- ${CMAKE_CURRENT_LIST_DIR}是该文件(OpenCVConfig.cmake)所在路径。
- ${OpenCV_LOC}是CMakeLists.txt中设置的变量,指出OpenCV位置。如果该pkgConfig.cmake文件位置固定,可以使用${CMAKE_CURRENT_LIST_DIR}指出OpenCV位置,而不需另设${OpenCV_LOC}。
1.2 指出头文件位置
指出头文件位置很容易:
set(OpenCV_INCLUDE_DIRS XXX)
1.3 指出库文件
- 先用lib文件夹中的库文件名创建列表:
set(OpenCV_LIB_COMPONENTS XX1; XX2)
- 对于库libXX1.so和libXX1.so.3.2.0等,只添加一个XX1,不要前缀和后缀。
- 多个库名用分号隔开。
- 把第三方库中的链接库指定到${OpenCV_LIBS}变量中:
foreach(__cvcomponent ${OpenCV_LIB_COMPONENTS})
...
endforeach()
- 查看lib文件夹中链接库的名字,把它们写到这里。
- 有些库只有libXX1.so,没有libXX1.so.3.2.0这样后缀带数字的库,在set_target_properties标签中就可能要注释掉对应的行。
- IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE指出该库与其它库的依赖关系。为了方便使用循环,这里把所有库(${OpenCV_LIB_COMPONENTS})都列出来。这样做,使用有些第三方库时会指出这里有错误,这时需要注释掉出错的行,甚至注释掉set_target_properties标签。
2. find_package查找
- 可以使用set(OpenCV_DIR path/to/OpenCVConfig.cmake)来添加find_package的查找路径,即指出OpenCVConfig.cmake路径。
- OpenCV_DIR和OpenCVConfig.cmake的前缀要保持一致。
- find_package语法
find_package(OpenCV 3.2.0 EXACT REQUIRED
PATHS path/to/OpenCVConfig.cmake
NO_DEFAULT_PATH
)
- 只加3.2.0:要求的最低版本。
- 加3.2.0和EXACT:一定要该版本。
- PATH:在此路径下找OpenCVConfig.cmake文件。
- NO_DEFAULT_PATH:只在上面指定的位置找OpenCVConfig.cmake,找不到就报错。
- 版本信息:OpenCVConfig-version.cmake要和OpenCVConfig.cmake放在同一文件夹,这样find_package就可以读取版本信息,OpenCVConfig-version.cmake的内容如下:
set(OpenCV_VERSION 3.2.0)
set(PACKAGE_VERSION ${OpenCV_VERSION})
set(PACKAGE_VERSION_EXACT False)
set(PACKAGE_VERSION_COMPATIBLE False)
if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT True)
set(PACKAGE_VERSION_COMPATIBLE True)
endif()
if(PACKAGE_FIND_VERSION_MAJOR EQUAL 3
AND PACKAGE_FIND_VERSION VERSION_LESS PACKAGE_VERSION)
set(PACKAGE_VERSION_COMPATIBLE True)
endif()
- 不同的库,只需要修改第一行。