栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

ubuntu18.04下--CMake教程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ubuntu18.04下--CMake教程

CMake 教程

文章目录

CMake 教程

0. CMake安装及卸载1. 创建简单的实例2. CMake 重要参数3. 构建项目结构4. CMakeList.txt 模板

CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的CMakeList.txt,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,无需修改,非常方便。

参考网站:

[1] Cmake官网

[2] Cmake github网址

[3] Cmake documentation

[4] Linux下CMake简明教程

[5] Modern CMake 简体中文版

0. CMake安装及卸载
    sh文件安装
sudo sh cmake-3.22.3-linux-x86_64.sh --prefix=/usr/local --exclude-subdir
    apt-get 方式
sudo apt-get install cmake
    源代码方式
# 下载 cmake-3.22.3.tar.gz
wget https://github.com/Kitware/CMake/releases/download/v3.22.3/cmake-3.22.3.tar.gz

# 解压 cmake-3.21.0-rc2.tar.gz

tar -zxvf cmake-3.22.3.tar.gz

# 切换到 CMake 源目录并执行 bootstrap 脚本

cd cmake-3.22.3.tar.gz
./bootstrap --parallel=32

# 执行 make
make -j32
make install -j32
ln -s /usr/local/bin/cmake /usr/bin/cmake 
# 软连接 ln [original filename] [link name]

# 查看 cmake 工具版本
cmake --version
    CMake 卸载
sudo apt-get autoremove cmake
1. 创建简单的实例

main.cpp

#include 

int main() {

    std::cout << "Hello, World!" << std::endl;

    return 0;

}

CMakeList.txt

# cmake 最低版本需求
cmake_minimum_required(VERSION 3.13)

# 工程名称
project(cmake_study)

# 设置
set(CMAKE_CXX_STANDARD 11)

# 编译源码生成目标
add_executable(cmake_study src/main.cpp)

文件列表

CMake 编译

# 创建文件夹
mkdir build
# cd 到build 文件夹
cd build
# cmake 编译CMakeList.txt
cmake .. 
# make 产生可执行文件
make
# 运行
./cmake_study 


2. CMake 重要参数

设置项目名称 project()

project(MyProject)

执行:project(MyProject),就是定义了一个项目的名称为:MyProject,对应的就会生成两个变量:_BINARY_DIR和_SOURCE_DIR,但是cmake中其实已经有两个预定义的变量:PROJECT_BINARY_DIR和PROJECT_SOURCR_DIR ;

编译

# 内部构建
cmake ./ 
make

# 外部构建:外部构建的话, 中间文件和可执行文件会放在build目录
mkdir build
cd ./build
cmake ../ 
make

获取文件路径中的所有源文件

aux_sourcr_directory( )

aux_sourcr_directory(. DIR_SRCS)
# 将aux_sourcr_directory(. DIR_SRCS)当前目录下的源文件名字存放 到变量DIR_SRCS里面 ,如果源文件比较多,直接用DIR_SRCS变量即可

编译源码生成目标

add_executable(exename srcname)
# exename : 生成的可执行文件的名字
# srcname : 源文件

add_executable(Demo ${DIR_SRCS})
# 可执行文件为 Demo 
./Demo #运行可执行文件

生成静态库dll

add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)

说明:

libname : 生成的库文件的名字

[SHARED|STATIC|MODULE] :生成库文件的类型(动态库|静态库|模块)

[EXCLUDE_FROM_ALL] :有这个参数表示该库不会被默认构建

source1 source2 … sourceN: 生成库依赖的源文件

# 实例1
add_library(ALib SHARE alib.cpp)
# 实例2
aux_sourcr_directory(. DIR_SRCS)
add_library(ALib STATIC ${DIR_SRCS})

添加头文件目录

# 方法1
target_include_directories( [SYSTEM] [BEFORE]  [items1...] [ [items2...] ...])

# 当我们添加子项目之后还需要设置一个include路径,例子: eg:target_include_directories(RigelEditor PUBLIC ./include/rgeditor),表示给 RigelEditor 这个子项目添加一个库文件的路径

# 方法2
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
# [AFTER|BEFORE]:指定了要添加路径是添加到原有列表之前还是之后 
# [SYSTEM]:若指定了system参数,则把被包含的路径当做系统包含路径来处理
# dir1 [dir2 …]把这些路径添加到CMakeLists及其子目录的CMakeLists的头文件包含项目中
include_directories("/opt/MATLAB/R2012a/extern/include")

引入opencv实例

引入opencv头文件和库说明:

按照此路径,cmake可以找到一个opencv的设置文件OpenCVConfig.cmake,其中预定义变量OpenCV_INCLUDE_DIRS,OpenCV_VERSION,OpenCV_LIBS

# ===================================================================================
#  The OpenCV CMake configuration file
#
#             ** File generated automatically, do not modify **
#
#  Usage from an external project:
#    In your CMakeLists.txt, add these lines:
#
#    find_package(OpenCV REQUIRED)
#    include_directories(${OpenCV_INCLUDE_DIRS}) # Not needed for CMake >= 2.8.11
#    target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})
#
#    Or you can search for specific OpenCV modules:
#
#    find_package(OpenCV REQUIRED core videoio)
#
#    You can also mark OpenCV components as optional:

#    find_package(OpenCV REQUIRED core OPTIONAL_COMPonENTS viz)
#
#    If the module is found then OPENCV__FOUND is set to TRUE.
#
#    This file will define the following variables:
#      - OpenCV_LIBS                     : The list of all imported targets for OpenCV modules.
#      - OpenCV_INCLUDE_DIRS             : The OpenCV include directories.
#      - OpenCV_COMPUTE_CAPABILITIES     : The version of compute capability.
#      - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API.
#      - OpenCV_VERSION                  : The version of this OpenCV build: "3.4.6"
#      - OpenCV_VERSION_MAJOR            : Major version part of OpenCV_VERSION: "3"
#      - OpenCV_VERSION_MINOR            : Minor version part of OpenCV_VERSION: "4"
#      - OpenCV_VERSION_PATCH            : Patch version part of OpenCV_VERSION: "6"
#      - OpenCV_VERSION_STATUS           : Development status of this build: ""
#
#    Advanced variables:
#      - OpenCV_SHARED                   : Use OpenCV as shared library
#      - OpenCV_INSTALL_PATH             : OpenCV location
#      - OpenCV_LIB_COMPonENTS           : Present OpenCV modules list
#      - OpenCV_USE_MANGLED_PATHS        : Mangled OpenCV path flag
#
#    Deprecated variables:
#      - OpenCV_VERSION_TWEAK            : Always "0"
#
# ===================================================================================

# ======================================================
#  Version variables:
# ======================================================
# 实例:引入opencv库和头文件
cmake_minimum_required( VERSION 3.15 )
project( mainwindow )
 
# 添加c++ 11标准支持
set( CMAKE_CXX_FLAGS "-std=c++11" )
 
# 寻找OpenCV库
set(OpenCV_DIR /home/ubuntu/opt/opencv-3.4.6/release)
find_package( OpenCV 3 REQUIRED )
# 添加头文件
include_directories( ${OpenCV_INCLUDE_DIRS} )
 
add_executable( mainwindow mainwindow.cpp )
# 链接OpenCV库
target_link_libraries( mainwindow ${OpenCV_LIBS} )

# 第一个: 添加头文件

# 第二个:找到源文件

# 第三个:与目标链接起来

参考:

使用CMake构建OpenCV项目

Linux 使用cmake构建OpenCV项目

添加库文件

# 命令1:
target_link_libraries( [item1 [item2 [...]]] [[debug|optimized|general] ] ...)

# 命令2:
link_libraries()
# 给当前工程链接需要的库文件(全路径)
link_libraries(("/opt/MATLAB/R2012a/bin/glnxa64/ ") #必须添加带名字的全路径 libeng.so

控制目标属性

set_target_properties()
set_target_properties(target1 target2 ... PROPERTIES 属性名称1 值 属性名称2 值 ... )

变量与缓存

局部变量

变量的名称通常大写 ;

 # 设置局部变量
set(MY_VARIABLE "value")
# 引用局部变量
${MY_VARIABLE}

缓存

缓存变量就是cache变量,相当于全局变量;

set(MY_CACHE_VALUE "cache_value" CACHE INTERNAL "THIS IS MY CACHE VALUE")
# THIS IS MY CACHE VALUE,这个字符串相当于对变量的描述说明,不能省略,但可 以自己随便定义

环境变量

# 设置环境变量:
set(ENV{variable_name} value) 

# 获取环境变量:
$ENV{variable_name} 

内置变量

CMake里面包含大量的内置变量,和自定义的变量相同,常用的有以下:

内置变量说明备注
CMAKE_C_COMPILER指定C编译器
CMAKE_CXX_COMPILER指定C++编译器
EXECUTABLE_OUTPUT_PATH指定可执行文件的存放路径
LIBRARY_OUTPUT_PATH指定库文件的放置路径
CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径
CMAKE_BUILD_TYPE控制构建的时候是Debug还是Releaseset(CMAKE_BUILD_TYPE Debug)
CMAKE_SOURCR_DIRCMAKE_SOURCR_DIR
CMAKE_BINARY_DIRCMAKE_BINARY_DIR:内部构建指的是工程顶层目录,外部构建指的是工程发生编译的目录
CMAKE_CURRENT_LIST_LINE输出这个内置变量所在的行

缓存

# 缓存就是之前提到的CMakeCache文件,参见:CMake命令行选项的设置- >CMakeCache.txt文件

CMake 基本语法

不太完善后续补充一下

if …else…

if (expression)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
... 
else (expression)
COMMAND1(ARGS ...) 
COMMAND2(ARGS ...)
... 
endif (expression)

while

WHILE(condition)
COMMAND1(ARGS ...) 
COMMAND2(ARGS ...) 
... 
ENDWHILE(condition)

Foreach

FOREACH(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
... 
ENDFOREACH(loop_var)

# 实例
AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F ${SRC_LIST})
MESSAGE(${F})
ENDFOREACH(F)

3. 构建项目结构
.
├── CMakeList.txt
├── include/
│   ├── CMakeList.txt
│   ├── includeA.h
│   └── includeB.h
├── lib/
│   ├── CMakeList.txt
│   ├── libA.c
│   └── libB.c
└── main.cpp

第一层CMakeList.txt

# 内容如下:
# 项目名称 
project(main)
#需要的cmake最低版本
cmake_minium_required(VERSION 2.8)
#将当前目录下的源文件名都赋给DIR_SRC目录
aux_source_directories(. DIR_SRC)
#添加include目录
include_directories(include)
#生成可执行文件
add_executable(main ${DIR_SRC})
#添加子目录
add_subdirectories(lib)
#将生成的文件与动态库相连
target_link_libraries(main test)
#test是lib目录里面生成的

lib目录CMakeList.txt

#内容如下: 
#将当前的源文件名字都添加到DIR_LIB变量下
aux_source_director(. DIR_LIB)
#生成库文件命名为test
add_libraries(test ${DIR_LIB})

include目录

# include目录的CMakeLists可以为空,因为我们已经将include目录包含在第一层的文件里面
4. CMakeList.txt 模板

单个CMakeList.txt模板

cmake_minimum_required(VERSION 3.5)
                           
project(main)         
## MESSAGE(FATAL_ERROR "${CMAKE_BUILD_TYPE}")

if(CMAKE_COMPILER_IS_GNUCC)
    message("COMPILER IS GNUCC")    
    ADD_DEFINITIONS ( -std=c++11 )  
endif(CMAKE_COMPILER_IS_GNUCC)

# 1. protobuf
# 1.1. Find required protobuf package
find_package(Protobuf REQUIRED)
if(PROTOBUF_FOUND)
    message(STATUS "protobuf library found")
else()
    message(FATAL_ERROR "protobuf library is needed but cant be found")
endif()
# 1.2. 生成pb.h、pb.cc必须要加的指令    
include_directories(${PROTOBUF_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${CMAKE_SOURCE_DIR}/include/protobuf/proto/config.proto)
# 1.3. head file path,头文件目录
message(${PROTO_HDRS})
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/protobuf)

# 2. CUDA
set(CUDA_DIR "/usr/local/cuda")
find_package(CUDA)
SET(CUDA_NVCC_FLAGS --disable-warnings;-std=c++11;-O3;-gencode arch=compute_75,code=sm_75)
##	CUDA_ADD_LIBRARY(${PROJECT_NAME} SHARED)
message(${CUDA_NVCC_FLAGS})

# 3. opencv
##	set(OpenCV_DIR "/data/wuh/open_source/opencv-3.4.6/build")
##	find_package(OpenCV REQUIRED)
## 	include_directories(${OpenCV_INCLUDE_DIRS})
link_directories("/usr/local/lib")
include_directories("/usr/local/include/opencv4")
link_directories("")

#message(${SOURCE_FILES})

# 4. tensorRT
include_directories(/data/wuh/software/TensorRT-5.1.2.2/include)
link_directories(/data/wuh/software/TensorRT-5.1.2.2/lib)
link_directories(/data/wuh/project/test_algorithm_module/algorithm_module/build/)
link_LIBRARIES(algorithm)


# 5. 头文件
# 5.1. 定义函数,用于递归添加头文件
function(include_sub_directories_recursively root_dir)
    if (IS_DIRECTORY ${root_dir})               # 当前路径是一个目录吗,是的话就加入到包含目录
        message("include dir: " ${root_dir})
        include_directories(${root_dir})
    endif()

    file(GLOB ALL_SUB RELATIVE ${root_dir} ${root_dir}/*) # 获得当前目录下的所有文件,让如ALL_SUB列表中
    foreach(sub ${ALL_SUB})
        if (IS_DIRECTORY ${root_dir}/${sub})
            include_sub_directories_recursively(${root_dir}/${sub}) # 对子目录递归调用,包含
        endif()
    endforeach()
endfunction()
# 5.2. 添加头文件
include_sub_directories_recursively(${CMAKE_SOURCE_DIR}/include) # 对子目录递归调用,包含
MESSAGE(STATUS "CMAK_SOURCE_DIR" ${CMAKE_SOURCE_DIR})

# 6. 添加源文件
FILE(GLOB_RECURSE SOURCE_FILES ${CMAKE_SOURCE_DIR}/src/*.cu  ${CMAKE_SOURCE_DIR}/src/*.cpp)
#message(${SOURCE_FILES})

# 7. 添加链接库
link_LIBRARIES(opencv_ml opencv_objdetect opencv_imgproc opencv_core opencv_highgui opencv_imgcodecs opencv_shape opencv_videoio opencv_video)
link_LIBRARIES(nvcaffe_parser nvinfer nvinfer_plugin nvparsers)
link_LIBRARIES(avcodec avformat swscale avutil)
link_LIBRARIES(cuda nvcuvid)
## link_LIBRARIES(algorithm)
link_LIBRARIES(glog)

# 8.source directory,源文件目录
AUX_SOURCE_DIRECTORY(test DIR_SRCS)

# 9. 设置环境变量,编译用到的源文件全部都要放到这里,否则编译能够通过,
# 但是执行的时候会出现各种问题,比如"symbol lookup error xxxxx , undefined symbol"
SET(ALL_SRCS ${DIR_SRCS} ${PROTO_SRCS} ${SOURCE_FILES} ${M_INCLUDE_FILES})

# 10.add executable file,添加要编译的可执行文件
##  ADD_EXECUTABLE(${PROJECT_NAME} ${ALL_SRCS})
CUDA_ADD_EXECUTABLE(${PROJECT_NAME} ${ALL_SRCS})

# 11. 链接目标文件与库文件,添加可执行文件所需要的库,比如我们用到了libm.so(命名规则:lib+name+.so),就添加该库的名称
TARGET_link_LIBRARIES(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})
target_link_libraries(${PROJECT_NAME} /usr/local/cuda-10.1/lib64/libcudart.so)
target_link_libraries(${PROJECT_NAME} /usr/local/cuda-10.1/lib64/libcudnn.so)

多个CMakeList.txt模板

主目录

文件目录结构;
├── CMakeLists.txt
├── fileA/
│ ├── CMakeLists.txt
│ ├── fileA.cpp
│ └── fileA.h
├── fileB/
│ ├── CMakeLists.txt
│ ├── fileB.cpp
│ └── fileB.h
└── main.cpp

// main.cpp
#include 
#include "fileA.h"
#include "fileB.h"
int main()
{
    fileA();
    fileB();
    return 0;
}
# 主目录下的CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)

project (cmake_files)

# Add header file include directories
include_directories(./fileA ./fileB)

# Add block directories
set(FILEA_SRC fileA/fileA.cpp)
set(FILEB_SRC fileB/fileB.cpp)

# Target
add_executable(cmake_files main.cpp ${FILEA_SRC} ${FILEB_SRC})

子目录FileA

// 子目录FileA 头文件
#ifndef FILEA_H
#define FILEA_H
#include 
void fileA();
#endif
// 子目录FileA 源文件
#include "fileA.h"
#include
void fileA()
{
    std::cout<<"FileA--Start"< 
  # 子目录FileA下的CMakeLists.txt
  aux_source_directory(. DIR_FILEA_SRCS)
  add_library(fileA ${DIR_FILEA_SRCS})

子目录FileB

// 子目录FileB 头文件
#ifndef FILEB_H
#define FILEB_H
#include 
void fileB();
#endif
// 子目录FileB 源文件
#include "fileB.h"
#include
void fileB()
{
    std::cout<<"FileB--Start"< 
  # 子目录FileB下的CMakeLists.txt
  aux_source_directory(. DIR_FILEB_SRCS)
  add_library(fileB ${DIR_FILEB_SRCS})

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/757171.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号