利用VScode和cmake编译构建C++工程代码

2023-10-19 10:46:28 浏览数 (1)

前言

可能我们有时候已经习惯了使用大型IDE去编写一些C 工程,经常使用大型IDE例如VS、Clion、VC 6.0,这些大型的软件都已经为我们提供好了编译链接工具,我们不需要自己去手动设置编译器,也不需要了解相关知识就可以写代码进行编译运行。

但有时候我们还需要去了解这些知识,虽然可能与编写代码关系不大,但是当我们实际拿大型工程落地时,这些技能就是必要的。

当然本文并不是要详细讲解make、cmake等工具的使用,这篇文章主要是借助VSCODE这个非常灵活的平台,利用cmake工具完整地过一边代码,并且经过cmake处理编译后执行的过程。这样可以对整个项目的编译过程有一个比较明确的理解。

如果对以上一些概念不是很熟悉的可以看这里:编译器gcc、clang、make、cmake辨析。

正文

关于如何利用VScode和C 构建大型项目的教程,官方已经提供了一份关于C 的配置指南:https://code.visualstudio.com/docs/languages/cpp

但是这份配置指南仅仅适合比比较小型的项目,当我们识图自己设计或者编译类似于OpenCV等大型项目时,光使用简单的搭建方式是不够用的,因此,无论是小项目还是大项目都有必要使用跨平台的构建工具:cmake,当然VScode中也是有cmake插件的,它可以自动检测我们系统内的cmake并且使用它。

那么我们开始吧,首先我们创建一个测试文件夹,再打开VScode,然后添加一个main.cpp

其中的代码来自于利用Pytorch的C 前端(libtorch)读取预训练权重并进行预测,使用的库为OpenCVlibtorch(如果不明白这是什么库的童鞋只知道是两个库就可以,在这里我们的程序中要链接它们)。

可以看到我们这段代码中需要这两个库,而上面的绿色波浪线显示这两个库的头文件还没有找到。

代码语言:javascript复制
#include <torch/script.h>           // libtorch
#include <opencv2/opencv.hpp>       // OpenCV

这两个库怎么找,我们交给cmake吧~

cmake

首先我们找到cmake(CMake Tools)插件并且重新激活下使其生效,

然后我们编写自己的CMakeLists.txt文件:

代码语言:javascript复制
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(example-app)

find_package(Torch REQUIRED)     // 这里使用命令查找libtorch库
find_package(OpenCV REQUIRED)    // 这里使用命名查找OpenCV库

if(NOT Torch_FOUND)
    message(FATAL_ERROR "Pytorch Not Found!")
endif(NOT Torch_FOUND)

message(STATUS "Pytorch status:")
message(STATUS "    libraries: ${TORCH_LIBRARIES}")

message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

add_executable(example-app main.cpp)
# link_directories(/usr/local/lib)   'find_package' has already done this
target_link_libraries(example-app "${TORCH_LIBRARIES}")
target_link_libraries(example-app "${OpenCV_LIBS}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 11)

因为我们的libtorch并不是安装到了系统路径上(例如/usr/bin /usr/local/),所以直接使用Cmake命令是查找不出来的(但是OpenCV我们安装到了系统路径上,所以不用担心就可以找到),因此我们需要在Cmake的参数中添加libtorch库的路径。

CMake传递命令的参数我们在哪儿添加呢?

打开当前工作目录的setting界面,例如USER SETTINGS,添加我们Cmake的配置参数:

代码语言:javascript复制
{
    ...
    "cmake.configureArgs":["-DCMAKE_PREFIX_PATH=/home/prototype/Desktop/Cuda-project/libtorch"],
}

好,然后我们执行Cmake的confit命令,我们直接调用命令台工具(Ctrl Shift P),然后选择Cmake Config:

这时候输出配置信息:

代码语言:javascript复制
[cmake] Looking for pthread.h
[cmake] Looking for pthread.h - found
[cmake] Looking for pthread_create
[cmake] Looking for pthread_create - not found
[cmake] Looking for pthread_create in pthreads
[cmake] Looking for pthread_create in pthreads - not found
[cmake] Looking for pthread_create in pthread
[cmake] Looking for pthread_create in pthread - found
[cmake] Found Threads: TRUE  
[cmake] Found CUDA: /usr/local/cuda (found suitable version "9.2", minimum required is "7.0") 
[cmake] Caffe2: CUDA detected: 9.2
[cmake] Caffe2: CUDA nvcc is: /usr/local/cuda/bin/nvcc
[cmake] Caffe2: CUDA toolkit directory: /usr/local/cuda
[cmake] Caffe2: Header version is: 9.2
[cmake] Found CUDNN: /usr/local/cuda/include  
[cmake] Found cuDNN: v7.4.1  (include: /usr/local/cuda/include, library: /usr/local/cuda/lib64/libcudnn.so)
[cmake] Autodetected CUDA architecture(s): 6.1;6.1
[cmake] Added CUDA NVCC flags for: -gencode;arch=compute_61,code=sm_61
[cmake] Found torch: /home/prototype/Desktop/Cuda-project/libtorch/lib/libtorch.so  
[cmake] Found OpenCV: /usr/local (found version "4.0.0") 
[cmake] Pytorch status:
[cmake]     libraries: torch;caffe2_library;caffe2_gpu_library;/usr/lib/x86_64-linux-gnu/libcuda.so;/usr/local/cuda/lib64/libnvrtc.so;/usr/local/cuda/lib64/libnvToolsExt.so;/usr/local/cuda/lib64/libcudart_static.a;-lpthread;dl;/usr/lib/x86_64-linux-gnu/librt.so
[cmake] OpenCV library status:
[cmake]     version: 4.0.0
[cmake]     libraries: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio
[cmake]     include path: /usr/local/include/opencv4
[cmake] Configuring done
[cmake] Generating done

提示所有库都找到了。

然后我们点击下面的build按钮:

就可以进行编译了:

代码语言:javascript复制
[build] Starting build
[proc] Executing command: /home/prototype/anaconda3/bin/cmake --build /home/prototype/test/build --config Debug --target all -- -j 14
[build] Scanning dependencies of target example-app
[build] [ 50%] Building CXX object CMakeFiles/example-app.dir/main.cpp.o
[build] [100%] Linking CXX executable example-app
[build] [100%] Built target example-app
[build] Build finished with exit code 0

这里也是提示我们编译成功,成功后我们的目录是这样的:

所有的编译后的东西自动被这个cmake插件放入了build文件夹中,这个文件夹也是cmake插件自动生成的。

我们进入build文件夹执行一下我们生成的可执行文件:

代码语言:javascript复制
prototype@prototype-X299-UD4-Pro:~/test$ cd build/
prototype@prototype-X299-UD4-Pro:~/test/build$ ./example-app
usage: example-app <path-to-exported-script-module>
prototype@prototype-X299-UD4-Pro:~/test/build$ ./example-app /home/prototype/Desktop/Deep-Learning/Pytorch-Learn/test/mobilenetv2-trace.pt
Time used:2521.94 ms

很快便输出了执行结果。

但是现在仍然还有两个问题:

  • 代码中的头文件依然显示没有找到,也就是之前所说的两个波浪线依然存在
  • 每次我们执行程序都需要进入终端然后执行命令行,稍微有点麻烦

下面我们便解决这两个问题:

C/C 拓展

下面这个插件是官方推荐的,在VScode端编写C 代码必备的插件:

我们安装后直接在VScode的工具台启动它:

这时候会在.vscode中生成一个配置文件c_cpp_properties.json

代码语言:javascript复制
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c  17",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}

然后我们加入这一句:"configurationProvider": "vector-of-bool.cmake-tools",

意思是我们C 的配置信息由之前的Cmake插件提供,这样之后,我们就可以在浏览代码中正常显示我们的头文件了(可以看到头文件下面没有绿色波浪线了):

C 编译器在不同的操作平台上式不同的。在window下,推荐使用mingw-w64,对于mac来说就是XCode自带的Clang。对于Linux来说就是我们经常见到的GCC,之前我们并没有说我们的编译器是什么,因为我们在配置Cmake的时候其会自动搜索当前系统中所有存在编译器然后让我们去选择:

当然我们在选择后也可以在setting中修改,这里不多说了,尽情地探索吧~

tasks.json

之前提到我们在执行编译好的文件后总是需要进入终端再执行命令,很是麻烦,所以我们使用tasks.json

点击配置后,我们选择最后一个配置档(other config),然后我们的task.json如下:

代码语言:javascript复制
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",     <-- 这个是我们设置的task的名字
            "type": "shell",
            "command": "echo Hello"
        }
    ]
}

我们把上面的command指令换成"command": "build/example-app /home/prototype/Desktop/Deep-Learning/Pytorch-Learn/test/mobilenetv2-trace.pt",也就是我们之前手动执行编译好的程序时输入的指令,我们修改后在命令台运行Task:run,选择echo,执行后会出现:

代码语言:javascript复制
> Executing task: build/example-app /home/prototype/Desktop/Deep-Learning/Pytorch-Learn/test/mobilenetv2-trace.pt <

Time used:2535.58 ms

Terminal will be reused by tasks, press any key to close it.

可以看到和之前的一样,但是我们不需要自己手动输入一些其他信息了,很是方便。

DEBUG

Debug也一样,我们点击VScode左侧的debug图标,配置launch.json即可,注意"program": "${command:cmake.launchTargetPath}",设置为Cmake插件的debug模式:

代码语言:javascript复制
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${command:cmake.launchTargetPath}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

这样,我们选择Debug模式的Cmake后,然后build,然后再点击最下方的debug按钮即可进行调试:

后记

上面的这些操作只是简单的操作,我们可以根据项目的需求,自己进行拓展延伸从而可以对大型项目进行编译构造。

参考资料

https://stackoverflow.com/questions/39126648/cmake-does-not-find-includes-libraries

http://www.cnblogs.com/feifanrensheng/p/9695749.html

0 人点赞