博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GNU开发工具——CMake模块
阅读量:6603 次
发布时间:2019-06-24

本文共 6677 字,大约阅读时间需要 22 分钟。

GNU开发工具——CMake模块

一、find_packge高级功能

1、find_package的模式

find_package()有Module模式(基本用法)和Config模式(完全用法),其中Module模式是基础,Config模式则提供复杂高级功能。

find_package是否使用Config模式可以通过下列条件判断:
(1)find_package()中指定CONFIG关键字
(2)find_package()中指定NO_MODULE关键字
(3)find_package()中使用了不再Module模式下所有支持配置的关键字

2、find_package工作流程

GNU开发工具——CMake模块

3、find_package的Module模式

find_package(
[version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...][NO_POLICY_SCOPE])

version和EXACT,可选,version指定版本,如果指定就必须检查找到的包的版本是否和version兼容。如果指定EXACT则表示必须完全匹配的版本而不是兼容版本就可以。

QUIET,可选字段,表示如果查找失败,不会在屏幕进行输出(但如果指定了REQUIRED字段,则QUIET无效,仍然会输出查找失败提示语)。
MODULE,可选字段。前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不回落到Config模式查找。
REQUIRED可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED则cmake会继续执行。
COMPONENTS,components:可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于REQUIRED,导致cmake停止执行。
Module模式下需要查找到名为FindPackageName.cmake的文件。
先在CMAKE_MODULE_PATH变量对应的路径中查找。如果路径为空,或者路径中查找失败,则在cmake module directory(cmake安装时的Modules目录,比如/usr/local/share/cmake/Modules)查找。

4、find_package的Config模式

find_package(
[version] [EXACT] [QUIET][REQUIRED] [[COMPONENTS] [components...]][CONFIG|NO_MODULE][NO_POLICY_SCOPE][NAMES name1 [name2 ...]][CONFIGS config1 [config2 ...]][HINTS path1 [path2 ... ]][PATHS path1 [path2 ... ]][PATH_SUFFIXES suffix1 [suffix2 ...]][NO_DEFAULT_PATH][NO_PACKAGE_ROOT_PATH][NO_CMAKE_PATH][NO_CMAKE_ENVIRONMENT_PATH][NO_SYSTEM_ENVIRONMENT_PATH][NO_CMAKE_PACKAGE_REGISTRY][NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.[NO_CMAKE_SYSTEM_PATH][NO_CMAKE_SYSTEM_PACKAGE_REGISTRY][CMAKE_FIND_ROOT_PATH_BOTH |ONLY_CMAKE_FIND_ROOT_PATH |NO_CMAKE_FIND_ROOT_PATH])

Config模式下的查找顺序,比Module模式下要多得多,新版本的CMake比老版本的有更多的查找顺序(新增的在最优先的查找顺序)。Config模式下需要查找到名为lower-case-package-name-config.cmake或PackageNameConfig.cmake文件。查找顺序如下:

(1)名为PackageName_ROOT的cmake变量或环境变量。CMake3.12新增。设定CMP0074 Policy来关闭。如果定义了PackageName_DIR cmake变量,那么PackageName_ROOT 不起作用。

cmake_minimum_required(VERSION 3.13)project(OpenCVDemo)set(OpenCV_ROOT "/usr/local/lib/opencv_249/build")set(OpenCV_DIR "/usr/local/lib/opencv_300/build")find_package(OpenCV QUIET    NO_MODULE    NO_DEFAULT_PATH    NO_CMAKE_PATH    NO_CMAKE_ENVIRONMENT_PATH    NO_SYSTEM_ENVIRONMENT_PATH    NO_CMAKE_PACKAGE_REGISTRY    NO_CMAKE_BUILDS_PATH    NO_CMAKE_SYSTEM_PATH    NO_CMAKE_SYSTEM_PACKAGE_REGISTRY)message(STATUS "OpenCV library status:")message(STATUS "    version: ${OpenCV_VERSION}")message(STATUS "    libraries: ${OpenCV_LIBS}")message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

上述代码会找到opencv300,OpenCV_DIR变量的值有效OpenCV_ROOT变量无效。

(2)cmake特定的缓存变量

CMAKE_PREFIX_PATHCMAKE_FRAMEWORK_PATHCMAKE_APPBUNDLE_PATH

可以通过设定NO_CMAKE_PATH来关闭特定缓存变量的查找顺序

(3)CMake特定的环境变量

PackageName_DIRCMAKE_PREFIX_PATHCMAKE_FRAMEWORK_PATHCMAKE_APPBUNDLE_PATH

可以通过NO_CMAKE_ENVIRONMENT_PATH来跳过。

(4)HINT字段指定的路径
(5)搜索标准的系统环境变量PATH。
其中如果是以/bin或者/sbin结尾的,会自动转化为其父目录。
通过指定NO_SYSTEM_ENVIRONMENT_PATH来跳过。
(6)存储在CMake的"User Package Registry"(用户包注册表)中的路径。
通过设定NO_CMAKE_PACKAGE_REGISTRY,或设定CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY为true,来避开。
(7)设定为当前系统定义的cmake变量:
CMAKE_SYSTEM_PREFIX_PATH
CMAKE_SYSTEM_FRAMEWORK_PATH
CMAKE_SYSTEM_APPBUNDLE_PATH
通过设定NO_CMAKE_SYSTEM_PATH来跳过。
(8)在cmake的"System Package Registry"(系统包注册表)中查找。
通过设定NO_CMAKE_SYSTEM_PACKAGE_REGISTRY跳过,或者通过设定CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY为true避开。
(9)从PATHS字段指定的路径中查找。

二、CMake自定义模块

1、find_xxx指令

FIND_FILE(VAR name path1 path2 …)

VAR变量代表找到的文件全路径,包含文件名。
FIND_LIBRARY(VAR name path1 path2 …)
VAR变量代表找到的库全路径,包含库文件名。
FIND_PATH(VAR name path1 path2 …)
VAR变量代表包含文件的路径
FIND_PROGRAM(VAR name path1 path2 …)
VAR变量代表包含程序的全路径
FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED | COMPONENTS] [componets …]])
用来调用预定义在CMAKE_MODULE_PATH下的Findname.cmake模块,可以自己定义Findname模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录供工程使用。

FIND_LIBRARY(libX X11 /usr/lib)IF (NOT libx)    MESSAGE(FATAL_ERROR "libX not found")ENDIF(NOT libX)

2、系统预定义模块使用

系统预定义了各种模块,通常需要使用INCLUDE指令显式的调用, 但FIND_PACKAGE指令是一个特例,可以直接调用预定义的模块。

每一个模块都会定义以下3个变量:

_FOUND
_INCLUDE_DIR or
_INCLUDES
_LIBRARY or
_LIBRARIES

因此,可以通过name_FOUND来判断模块是否被找到,如果没有找到,按照工程的需要关闭某些特性、给出提醒或者中止构建。

对于系统预定义的Findname.cmake模块,使用方法如下:

FIND_PACKAGE(NAME)IF(NAME_FOUND)    INCLUDE_DIRECTORIES(${NAME_INCLUDE_DIR})    TARGET_LINK_LIBRARIES(targetname ${NAME_LIBRARY})ELSE(NAME_FOUND)    MESSAGE(FATAL_ERROR ”NAME library not found”)ENDIF(NAME_FOUND)

工程实践中使用示例如下:

#通过
_FOUND来控制工程特性:SET(SOURCES Viewer.cpp)SET(OptionalSources)SET(OptionalLibs)FIND_PACKAGE(JPEG)IF(JPEG_FOUND) SET(OptionalSources ${OptionalSources} JPEGView.cpp) INCLUDE_DIRECTORIES( ${JPEG_INCLUDE_DIR} ) SET(optionalLibs ${OptionalLibs} ${JPEG_LIBRARIES} ) ADD_DEFINITIONS(-DENABLE_JPEG_SUPPORT)ENDIF(JPEG_FOUND)IF(PNG_FOUND) SET(OptionalSources ${OptionalSources} PNGView.cpp) INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} ) SET(OptionalLibs ${OptionalLibs} ${PNG_LIBRARIES} ) ADD_DEFINITIONS(-DENABLE_PNG_SUPPORT)ENDIF(PNG_FOUND)ADD_EXECUTABLE(viewer ${SOURCES} ${OptionalSources} )TARGET_LINK_LIBRARIES(Viewer ${OptionalLibs})#通过判断系统是否提供了JPEG、PNG模块来决定程序是否支持JPEG、PNG功能。

3、自定义模块实现

本文基于libHello动态库,编写一个FindHelo.cmake模块。

创建一个FindHello项目目录,进入FindHello。
创建一个Hello目录,进入Hello目录,创建FindHelo.cmake文件,FindHelo.cmake文件如下:

#查找hello库头文件的安装路径FIND_PATH(HELLO_INCLUDE_DIR Hello.h /usr/local/include/hello)#查找hello库的安装路径FIND_LIBRARY(HELLO_LIBRARY NAMES hello /usr/local/lib/libhello.so)IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)    SET(HELLO_FOUND TRUE)ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)IF (HELLO_FOUND)    IF (NOT HELLO_FIND_QUIETLY)    MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")    ENDIF (NOT HELLO_FIND_QUIETLY)ELSE (HELLO_FOUND)    IF (HELLO_FIND_REQUIRED)    MESSAGE(FATAL_ERROR "Could not find hello library")    ENDIF (HELLO_FIND_REQUIRED)ENDIF (HELLO_FOUND)

返回FindHello目录,创建main.cpp文件:

#include 
int main(int argc, char* argv[]){ Hello hello; hello.Print(); return 0;}

创建工程CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 2.8)PROJECT(FindHello)# 设置自定义模块路径SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/Hello/")MESSAGE(STATUS "CMAKE_MODULE_PATH " ${PROJECT_SOURCE_DIR}/Hello)#查找自定义Hello模块FIND_PACKAGE(Hello)IF(HELLO_FOUND)    ADD_EXECUTABLE(hello main.cpp)    INCLUDE_DIRECTORIES(${HELLO_INCLUDE_DIR})    MESSAGE(STATUS "LINK " ${HELLO_LIBRARY})    TARGET_LINK_LIBRARIES(hello ${HELLO_LIBRARY})ELSE(HELLO_FOUND)    MESSAGE(STATUS "Could not find hello library")ENDIF(HELLO_FOUND)

创建build目录,进行build目录进行构建。

cmake ../
make
./hello
结果打印出Hello world.

转载于:https://blog.51cto.com/9291927/2396884

你可能感兴趣的文章
repquota命令--Linux命令应用大词典729个命令解读
查看>>
我的友情链接
查看>>
设置vs解决方案跟随右边cpp
查看>>
Linux Administration
查看>>
如何使版面富有节奏感
查看>>
rabbitmq 管理及常用命令
查看>>
iphone导航控制器的开发与使用
查看>>
debian python library re-install
查看>>
如何用转义来给JS添加的input元素设置单引号
查看>>
J2E——网络编程练习
查看>>
VirtualBox移植
查看>>
HTTP要被抛弃? 亚洲诚信携手宝塔开启HTTPS加密快速通道
查看>>
Chrome: 完全移除对WoSign和StartCom证书的信任
查看>>
RecyclerView侧滑删除功能
查看>>
记一个hystrix异常
查看>>
9.02-Spring IOC 容器中Bean的生命周期
查看>>
6.6 tar打包
查看>>
微信自动抢红包的实现(Demo已增加查看TopActivity功能)
查看>>
Spring MVC核心技术
查看>>
TCP协议如何保证传输的可靠性
查看>>