cmake实战记录(一)

一. 一个简单的例子

工程目录如下:

├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── libmy_add.so
│   ├── Makefile
│   └── my_test
├── CMakeLists.txt
├── include
│   └── my_add.h
├── my_test.cpp
└── src
    └── my_add.cpp

my_add.h

#include <iostream>

int my_add(int x, int y);

my_add.cpp

#include "my_add.h"

int my_add(int x, int y)
{
    return x+y;
}

my_test.cpp

#include<iostream>
#include "my_add.h"

int main()
{
    int c;
    c = my_add(2,3);
    std::cout << "test my_add:" << c << std::endl;
    std::cout << "success" << std::endl;

}

CMakeLists.txt

#要求的Cmake最低版本
cmake_minimum_required(VERSION 3.18)

#工程名称
project(my_test)

set(CMAKE_CXX_STANDARD 11)

set(my_add ${PROJECT_SOURCE_DIR}/src/my_add.cpp)

include_directories("${PROJECT_SOURCE_DIR}/include")

#生成共享库
add_library(my_add SHARED ${my_add})

#生成可以执行的文件
add_executable(my_test my_test.cpp)

#连接共享库
target_link_libraries(my_test my_add)

编译

mkdir build
cd build
cmake ..
make

build文件夹下面有共享库 libmy_add.so,可执行文件my_test

二. 调用自己的共享库文件

所有的外部依赖库都是这样的,比如opencv ,openni, eigen等等,原理是一样的,只不过他们已经安装在系统里面了,可以查找,而这个则是需要我们自己去配置。
即我上面生成的共享库文件本质上和opencv的库是相同的。只不过这个共享库需要自己手动配置。
比如我又新建了一个工程,需要调用上面的共享库 libmy_add.so。
工程目录如下:

.
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── Makefile
│   └── my_test
├── CMakeLists.txt
├── include
│   └── my_add.h
├── lib
│   └── libmy_add.so
├── my_test.cpp
└── src
    └── my_add.cpp

CMakeLists.txt

#要求的Cmake最低版本
cmake_minimum_required(VERSION 3.18)

#工程名称
project(my_test)

set(CMAKE_CXX_STANDARD 11)

include_directories("${PROJECT_SOURCE_DIR}/include")

set(ADD_SO "${PROJECT_SOURCE_DIR}/lib/libmy_add.so")

#生成可以执行的文件
add_executable(my_test my_test.cpp)

#连接共享库
target_link_libraries(my_test ${ADD_SO})

其实主要的就是指明这个调用这个共享库的时候,使用的头文件,以及共享库本身所在的位置,然后包含链接就可以了。

三.调用安装过的共享库

Opencv的依赖添加
比如Opencv, 它的头文件和.so文件都已经放在了系统变量里面,不用向上面自己定义了(上面例子里面的头文件和共享库文件的地址都是我自己设置的)
它的CMakeLists.txt如下:
find_package(OpenCV REQUIRED)
include_directories(${OPENCV_INCLUDE_DIRS})
target_link_libraries(MAIN ${OpenCV_LIBS})
只需要查找就可以了,OpenCV_LIBS 和 OPENCV_INCLUDE_DIRS 都是系统帮我们已经定义好的,所以比较容易
工程目录如下:

.
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── cv_example
│   └── Makefile
├── CMakeLists.txt
├── cv_example.cpp
└── test.jpg

cv_example.cpp

#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"


int main() {
    std::string img_path = "../test.jgp";
    cv::Mat M = cv::imread(img_path);
    std::cout << "load img success" << std::endl;
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.18)

project(cv_example)

set(CMAKE_CXX_STANDARD 14)

add_executable(cv_example cv_example.cpp)

find_package(OpenCV REQUIRED)

include_directories(${OPENCV_INCLUDE_DIRS})

target_link_libraries(cv_example ${OpenCV_LIBS})

编译执行:

mkdir build
cd build
cmake ..
make
./cv_example

四. 一个完整工程的CMakeLists.txt

#工程名字
project(Camera_sugan)                  
 
#编译最低cmake版本
cmake_minimum_required(VERSION 2.6)    
 
#设置c++编译器
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )  
 
#在整个电脑上找opencv包
find_package(OpenCV REQUIRED)    
 
#包含头文件路径
include_directories(             
    ./include/inudev/
    ./src/
)
 
#将所有的源文件列为一个集合,集合名字叫做SRC_LISTS
set(SRC_LISTS                   
    ./src/inuitive.cpp
    ./src/runCamera_Qfeeltech.cpp
)
 
#将集合里的所有的源文件生成一个静态库,该静态库的名字libsugan,
# 注意,在整个CmakeLists里都要用libsugan这个
add_library(libsugan ${SRC_LISTS})   
 
#名字来代替之前那个集合生成的库。
target_link_libraries(libsugan    #链接静态库需要的依赖库
    ${OpenCV_LIBS}
    ${PROJECT_SOURCE_DIR}/lib/libCommonUtilities.so
    ${PROJECT_SOURCE_DIR}/lib/libInuStreams.so
)

五. CMake指定g++版本编译

在CMakeLists.txt中调用编译器之前添加:

SET(CMAKE_C_COMPILER "/usr/local/bin/gcc")

执行cmake命令之前,在shell终端先设置如下两个变量:

export CXX=/usr/local/bin/g++
# /usr/local/gcc-xxx/lib 是你的新gcc的lib位置
export LD_LIBRARY_PATH=/usr/local/gcc-xxx/lib:$LD_LIBRARY_PATH

六. 设置编译时和程序运行时去哪个目录找动态库

程序运行时,搜索动态库的顺序(优先级)优先级是这样的:

  1. RPATH ,编译链接时加入 -rpath 参数 指定的目录
  2. LD_LIBRARY_PATH 这个环境变量指定的目录
  3. /etc/ld.so.conf 配置文件。
  4. /usr/lib 、 /lib 和 /usr/local/lib ,系统默认路径。
    所以我们设置了RPATH ,并且RPATH 下有要找的动态库,程序就首先加载它
    注意:
    可以看到,RPATH与RUNPATH中间隔着LD_LIBRARY_PATH。为了让用户可以通过修改LD_LIBRARY_PATH来指定.so文件,大多数编译器都将输出的RPATH留空,并用RUNPATH代替RPATH。

七. 其他

# 把当前目录/src下的文件,指定在变量SRC_LIST中
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/ SRC_LIST)

add_subdirectory(my-sdk)

# 添加本地的so
set_target_properties(decode PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/fastertransformer.so)

参考:https://blog.csdn.net/bandaoyu/article/details/115165199
https://blog.csdn.net/Guo_Python/article/details/124846646?spm=1001.2014.3001.5501

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2022年5月25日
下一篇 2022年5月25日

相关推荐