前言
可能我们有时候已经习惯了使用大型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)读取预训练权重并进行预测,使用的库为OpenCV和libtorch(如果不明白这是什么库的童鞋只知道是两个库就可以,在这里我们的程序中要链接它们)。
可以看到我们这段代码中需要这两个库,而上面的绿色波浪线显示这两个库的头文件还没有找到。
#include <torch/script.h> // libtorch #include <opencv2/opencv.hpp> // OpenCV
这两个库怎么找,我们交给cmake吧~
cmake
首先我们找到cmake(CMake Tools)插件并且重新激活下使其生效,
然后我们编写自己的CMakeLists.txt文件:
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的配置参数:
{ ... "cmake.configureArgs":["-DCMAKE_PREFIX_PATH=/home/prototype/Desktop/Cuda-project/libtorch"], }
好,然后我们执行Cmake的confit命令,我们直接调用命令台工具(Ctrl + Shift + P),然后选择Cmake Config:
这时候输出配置信息:
[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按钮:
就可以进行编译了:
[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文件夹执行一下我们生成的可执行文件:
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
:
{ "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
如下:
{ // 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
,执行后会出现:
> 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模式:
{ // 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
感谢分享!
谢谢支持哦