c++ cmakelist 详解
基本元素
首先cmaklist必须包括以下几个部分:
#工程名
project(study_case)
#cmake最低版本需求
cmake_minimum_required(VERSION 2.8.3)
#添加添加需要的库
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/share/OpenCV")
find_package(OpenCV 3.2.0 REQUIRED)
#确定需要的头文件
include_directories(
include
)
#确定编译语言
#1
set(CMAKE_CXX_STANDARD 11)
#2. or
add_definitions(-std=c++11)
#设置二进制文件目录
SET(BIN_DESTINATION ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_DESTINATION})
#如果多个文件相关,则添加源代码(可选)
set(SRC
${PROJECT_SOURCE_DIR}/src/detector.cpp
${PROJECT_SOURCE_DIR}/src/demo.cpp
${PROJECT_SOURCE_DIR}/src/test.cpp
)
#如果需要编译动态库并链接库文件(可选)
link_directories(${PROJECT_SOURCE_DIR})
add_library(overload SHARED ${SRC})
target_link_libraries(overload -llianghao -lpthread -lm -lstdc++)
#生成可执行文件
link_directories(${PROJECT_SOURCE_DIR})
#添加可执行文件
#1. 如果文件之间没有关联
add_executable(overload src/overload.cpp)
#2. or 如果多个文件相关
add_executable(overload src/overload.cpp ${SRC})
#如果有依赖外部库则需要添加以下命令(可选)
target_link_libraries(overload -llianghao -lpthread -lm -lstdc++)
其他功能
1. 使其包含c++11特性(-std=c++11如何写进cmakeList.txt)
#1
set(CMAKE_CXX_STANDARD 11)
#2. or
add_definitions(-std=c++11)
#3. or
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
2. 设定可执行文件的输出目录
SET(BIN_DESTINATION ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN_DESTINATION})
3. 生成so库
3.1 想生成多个so库
# 设置构建本地库所需的最小版本的cbuild。
cmake_minimum_required(VERSION 3.4.1)
# 创建并命名一个库,将其设置为静态
# 或者共享,并提供其源代码的相对路径。
# 您可以定义多个库,而cbuild为您构建它们。
# Gradle自动将共享库与你的APK打包。
add_library( hello-lib #设置库的名称。即SO文件的名称,生产的so文件为“libhello-lib.so”,在加载的时候“System.loadLibrary("hello-lib");”
SHARED # 将库设置为共享库。
src/main/jni/hello.cpp # 提供一个源文件的相对路径
src/main/jni/helloJni.cpp # 提供同一个SO文件中的另一个源文件的相对路径
)
#搜索指定的预构建库,并将该路径存储为一个变量。因为cbuild默认包含了搜索路径中的系统库,所以您只需要指定您想要添加的公共NDK库的名称。cbuild在完成构建之前验证这个库是否存在。
find_library(log-lib # 设置path变量的名称。
log # 指定NDK库的名称 你想让CMake来定位。
)
#指定库的库应该链接到你的目标库。您可以链接多个库,比如在这个构建脚本中定义的库、预构建的第三方库或系统库。
target_link_libraries( hello-lib #指定目标库中。与 add_library的库名称一定要相同
${log-lib} # 将目标库链接到日志库包含在NDK。
)
#如果需要生产多个SO文件的话,写法如下
add_library( natave-lib #设置库的名称。另一个so文件的名称
SHARED # 将库设置为共享库。
src/main/jni/nataveJni.cpp # 提供一个源文件的相对路径
)
target_link_libraries( natave-lib #指定目标库中。与 add_library的库名称一定要相同
${log-lib} # 将目标库链接到日志库包含在NDK。
)
这里还有一个坑在里面,就是如果你的库的名字起得不是叫xx-lib的话,编译是通不过的,亲测,比如起个so库名叫test,cpp文件叫做test.cpp,这样是编译不过的,不会生成多个so库。
3.1 生成一个so库,多个cpp文件
# 查找cpp目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(src/main/cpp/ DIR_LIB_SRCS)
# 生成链接库
add_library (native-lib SHARED ${DIR_LIB_SRCS})
# 导入cpp目录下的所有头文件
include_directories(src/main/cpp/)
替换原有的add_library命令就可以了,其实就是生成一个变量,指定cpp的文件路径
4. 设置编译类型
#set release
if (NOT CMAKE_BUILD_TYPE)
message("not defined Build Type:auto define it to Debug" )
set (CMAKE_BUILD_TYPE Debug)
endif (NOT CMAKE_BUILD_TYPE)
if (CMAKE_BUILD_TYPE MATCHES "Debug" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")
elseif (CMAKE_BUILD_TYPE MATCHES "Release" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 ")
elseif (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O2 ")
else()
message("unkown defined Build Type:same handle with Debug" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ")
endif (CMAKE_BUILD_TYPE MATCHES "Debug")
5. 外部库FIND_PACKAGE
格式:
FIND_PACKAGE(<name> [version] [EXACT] [QUIET] [NO_MODULE] [ [ REQUIRED | COMPONENTS ] [ componets... ] ] )
5.1 查找*.cmake的顺序
1、 find_package(<Name>)命令首先会在模块路径中寻找Find<name>.cmake
这是查找库的一个典型方式,具体查找路径依次为CMake:
变量${CMAKE_MODULE_PATH}中的所有目录。
如果没有, 然后再查看它自己的模块目录: /share/cmake-x.y/Modules/ 。
这称为模块模式。
2、如果没找到这样的文件:
find_package()会在:
~/.cmake/packages/
或/usr/local/share/
中的各个包目录中查找,寻找:
<库名字的大写>Config.cmake
或 <库名字的小写>-config.cmake
(比如库Opencv,它会查找/usr/local/share/OpenCV中的OpenCVConfig.cmake或opencv-config.cmake)。**这称为配置模式。
不管使用哪一种模式,只要找到.cmake,.cmake里面都会定义下面这些变量:
例子<NAME>: OpenCVConfig.cmake
<NAME>_FOUND
<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES
<NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS
<NAME>_DEFINITIONS
注意大部分包的这些变量中的包名是全大写的,如 LIBFOO_FOUND ,有些包则使用包的实际大小写,如 LibFoo_FOUND
如果找到这个包,则可以通过在工程的顶层目录中的CMakeLists.txt 文件添加 include_directories(_INCLUDE_DIRS) 来包含库的头文件,添加target_link_libraries(源文件 _LIBRARIES)命令将源文件与库文件链接起来。
5.2 使用外部库的方式
为了能支持各种常见的库和包,CMake自带了很多模块。可以通过命令cmake --help-module-list得到你的CMake支持的模块的列表,或者直接查看模块路径。比如Ubuntu上,模块的路径是:
/usr/share/cmake/Modules/
让我们以bzip2库为例。CMake中有个FindBZip2.cmake 模块。只要使用 find_package(BZip2) 调用这个模块,cmake会自动给一些变量赋值,然后就可以在CMakelists.txt中使用它们了。变量的列表可以查看cmake模块文件,或者使用命令 cmake –help-module FindBZip2 。
比如一个使用bzip2的简单程序,编译器需要知道 bzlib.h 的位置,链接器需要找到bzip2库(动态链接的话,Unix上是 libbz2.so 类似的文件,Windows上是 libbz2.dll )。
cmake_minimum_required(VERSION 2.8)
project(helloworld)
add_executable(helloworld hello.c)
find_package(BZip2)
if (BZIP2_FOUND)
include_directories(${BZIP_INCLUDE_DIRS})
target_link_libraries (helloworld ${BZIP2_LIBRARIES})
endif (BZIP2_FOUND)
5.3 find_package中的参数定义
FIND_PACKAGE(<name> [version] [EXACT] [QUIET] [[REQUIRED|COMPONENTS] [ componets... ] ] )
1 version参数
需要一个版本号,它是正在查找的包应该兼容的版本号。
eg:
find_package(Boost ${boost_version})
2 EXACT选项
要求版本号必须精确匹配。如果在find-module内部对该命令的递归调用没有给定[version]参数,那么[version]和EXACT选项会自动地从外部调用前向继承。对版本的支持目前只存在于包和包之间。
eg:
find_package(Boost ${boost_version} EXACT REQUIRED)
3 QUIET 参数:
会禁掉包没有被发现时的警告信息。对应于Find.cmake模块中的 NAME_FIND_QUIETLY。
eg:
find_package(Boost ${boost_version} EXACT QUIET)
4 REQUIRED 参数
其含义是指是工程必须的,表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。对应于Find.cmake模块中的 NAME_FIND_REQUIRED 变量。
eg:
find_package(Boost REQUIRED COMPONENTS system)
COMPONENTS参数
在REQUIRED选项之后,或者如果没有指定REQUIRED选项但是指定了COMPONENTS选项,在它们的后面可以列出一些与包相关(依赖)的部件清单(components list)
eg:
find_package(Boost REQUIRED COMPONENTS system)
6. 其他
cmake中一些预定义变量
- PROJECT_SOURCE_DIR 工程的根目录
- PROJECT_BINARY_DIR 运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build
- CMAKE_INCLUDE_PATH 环境变量,非cmake变量
- CMAKE_LIBRARY_PATH 环境变量
- CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在的路径
- CMAKE_CURRENT_BINARY_DIR target编译目录
- 使用ADD_SURDIRECTORY(src bin)可以更改此变量的值
- SET(EXECUTABLE_OUTPUT_PATH <新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径
- CMAKE_CURRENT_LIST_FILE 输出调用这个变量的CMakeLists.txt的完整路径
- CMAKE_CURRENT_LIST_LINE 输出这个变量所在的行
- CMAKE_MODULE_PATH 定义自己的cmake模块所在的路径
- SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
- EXECUTABLE_OUTPUT_PATH 重新定义目标二进制可执行文件的存放位置
- LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置
- PROJECT_NAME 返回通过PROJECT指令定义的项目名称
- CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 用来控制IF ELSE语句的书写方式
系统信息
- CMAKE_MAJOR_VERSION cmake主版本号,如2.8.6中的2
- CMAKE_MINOR_VERSION cmake次版本号,如2.8.6中的8
- CMAKE_PATCH_VERSION cmake补丁等级,如2.8.6中的6
- CMAKE_SYSTEM 系统名称,例如Linux-2.6.22
- CAMKE_SYSTEM_NAME 不包含版本的系统名,如Linux
- CMAKE_SYSTEM_VERSION 系统版本,如2.6.22
- CMAKE_SYSTEM_PROCESSOR 处理器名称,如i686
- UNIX 在所有的类UNIX平台为TRUE,包括OS X和cygwin
- WIN32 在所有的win32平台为TRUE,包括cygwin
开关选项
- BUILD_SHARED_LIBS 控制默认的库编译方式。如果未进行设置,使用ADD_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库 (可在t3中稍加修改进行验证)
- CMAKE_C_FLAGS 设置C编译选项
- CMAKE_CXX_FLAGS 设置C++编译选项
运行
cmake .
make
c++ cmakelist 详解的更多相关文章
- 远程文件同步详解(Remote File Sync)
1. 远程文件同步的常见方式: 1.cron + rsync 优点: 简单 缺点:定时执行,实时性比较差:另外,rsync同步数据时,需要扫描所有文件后进行比对,进行差量传输.如果文件数量达到了百万甚 ...
- 详解如何在RVIZ中用Marker显示机器人运动路径
写在前面 最近有道作业题需要将机器人的历史路径显示出来,但是网上很多相关的教程都是搬运了官网的链接,并没有详细的操作流程...因此我又花费了很多时间去ros官网上学习marker的用法,学习怎么写pu ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
随机推荐
- django框架基本介绍
一.mvc和mtv 1.mvc介绍 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器( ...
- Oracle初级第一天
oracle卸载 运行regedit,删除HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ ...
- mycat高可用集群搭建
本文来源于:https://blog.csdn.net/u012758088/article/details/78741567 Mycat 本身是无状态的,可以用 HAProxy 或四层交换机等设备组 ...
- linux中权限对文件和目录的意义
1.权限对文件的意义: 读:可查看文件的内容 写:可修改文件的内容(但不能删除文件) 执行:可执行文件 2.权限对目录的意义: 读:可以查看目录下的内容,即可以读取该目录下的结构列表 写:可修改目录下 ...
- 【题解】Luogu P1648 看守
原题传送门:P1648 看守 这题目让求得的是d维( d <=4 )空间中n个点( 2 <= N <= 1000000 )之间最大的哈曼顿距离 模拟,emm,能拿30分,不错 因为d ...
- 一个随机验证码且不重复的小程序以及求随机输入一组数组中的最大值(Java)
1.代码: package day20181015;import java.util.Arrays;/** * 验证码的实现 * @author Administrator */public clas ...
- 11: python中的轻量级定时任务调度库:schedule
1.1 schedule 基本使用 1.schedule 介绍 1. 提到定时任务调度的时候,相信很多人会想到芹菜celery,要么就写个脚本塞到crontab中. 2. 不过,一个小的定时脚本,要用 ...
- C语言三个结束符:EOF ‘\0’ '\n'
- iOS字体大小
1,iOS 字体大小单位是pt——磅. 英文字体的1磅,相当于1/72 英寸,约等于1/2.8mm. px:相对长度单位.像素(Pixel).(PS字体) pt:绝对长度单位.点(Point).(iO ...
- Bootstrap3基础 container 浏览器宽度与容器宽度的四种配合
内容 参数 OS Windows 10 x64 browser Firefox 65.0.2 framework Bootstrap 3.3.7 editor ...