【caffe-Windows】添加工程-以classification为例

前言

兴趣所向,研究一下如何在caffe工程之外建立一个属于自己的工程,这里以分类为例,将classification.cpp提取出来,然后调用相应的三方库和libcaffe.lib进行编译。这里比较建议有一丢丢C++功底的同志参考学习,主要涉及到利用VS新建工程,添加lib库文件,包含头文件,解决dll丢失问题。看完博客可以学会,如何不在复制别人的各种路径的情况下,依据caffe-windows自行为新建的工程设置调用caffe的路径。

国际惯例,贴一堆网址:

caffe下新建工程及编译

caffe-window搭建自己的小项目例子

使用libcaffe为工程添加深度学习功能

利用caffe建立自己的工程

caffe C++接口使用配置

caffe框架在添加自己的MFC程序(上)

文章结束提供本文编译所用代码。

做这次笔记主要是,网上找的方法都有复杂的各种路径的添加,包括上面的各个参考博客,各种lib,不可能每次新建项目我都要打开别人博客,然后把所有的lib文件复制下来。在编译caffe-windows的时候,大家肯定发现这样一个问题:我没有手动加任何路径,只需要它自动下载NugetPackages三方库,然后就能编译了。这就说明在某个地方肯定定义过路径了,编译时候直接调用。这就启发我们找到,按照 就可以在不看任何博客情况下独立编写路径信息。

【注】方法严格建立在BVLC或者微软的caffe-Windows能够正常使用的情况下,由于C++还不熟练,直接以classification.cpp为例。

建立新工程

创建项目

随便在磁盘某个地方新建一个空文件夹,用于存储我们所要新建的工程。
这里写图片描述

打开VS2013,新建一个工程,记得选空项目

这里写图片描述

添加源代码信息

  • 源文件->添加->新建项->classification.cpp
  • 将caffe-windows路径(E:\CaffeDev\caffe-master\examples\cpp_classification)里面的classification.cpp的内容拷贝,丢到新建的工程中的classification.cpp中去
  • 看看配置管理器是什么,如果是Win32,就改成X64,最好是release

这里写图片描述

这里写图片描述

这就算是搞定了工程的创建,与我们写控制台helloword的步骤完全一样。接下来就是解决各种编译错误了。

逐步解决错误

caffe头文件

首先引入眼帘的是

这里写图片描述

解决方法:加头文件,把caffe-windows的include文件夹整体拷贝过来,我是放入到sln并列的地方了,这个路径与后面要加的路径要对应,这是后话

这里写图片描述

拷贝完毕,就去设置头文件的包含目录

这里写图片描述

三方库头文件

然后出现了更多的错误
这里写图片描述

不要慌,这个地方就是与网上的解决方法的不同之处了,当然你也可以按照前言中的博客配置。我这里主要是应对没有联网的,无法打开别人博客复制路径的情况。

观察原始caffe-Windows下E:\CaffeDev\caffe-master\windows下的任何一个工程,比如compute_image_mean文件夹下的compute_image_mean.vcxproj,有兴趣可以搜一下这个vcxproj的文件包含什么信息,答案是路径。那么我们就利用这里面的路径去设置自己工程的路径了,当然首先是把NugetPackages的三方库拷贝到当前工程下,路径自定,我的路径如下

这里写图片描述

然后加入路径的方法就在我们的E:\caffe-myproject\my_classification\my_classification\my_classification.vcxproj中了,我这里是对比着原始caffe的compute_image_mean.vcxproj和当前工程的my_classification.vcxproj修改的。我就不分析了,直接把关键点列出来:

【注意】以下步骤与路径关系很大,../是跳转一个目录,起始位置是vcxproj所在当前文件夹。

  • 首先是三个props
  <Import Project="..\..\NugetPackages\gflags.2.1.2.1\build\native\gflags.props" Condition="Exists('..\..\NugetPackages\gflags.2.1.2.1\build\native\gflags.props')" /><Import Project="..\..\NugetPackages\glog.0.3.3.0\build\native\glog.props" Condition="Exists('..\..\NugetPackages\glog.0.3.3.0\build\native\glog.props')" /><Import Project="..\..\NugetPackages\OpenCV.2.4.10\build\native\OpenCV.props" Condition="Exists('..\..\NugetPackages\OpenCV.2.4.10\build\native\OpenCV.props')" />
  • 随后是CommonSettings.props

    如果不加入CommonSettings.props,会在后面提示opencv未启用问题,为了方便,直接把caffe-windows的拷贝CommonSettings.props过来使用

    <ImportGroup Label="PropertySheets" Condition="Exists('$(SolutionDir)\CommonSettings.props')"><Import Project="..\CommonSettings.props" />
    </ImportGroup>

这里写图片描述

  • 然后是libcaffe.lib
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"><Link><AdditionalDependencies>libcaffe.lib;$(CudaDependencies);%(AdditionalDependencies)</AdditionalDependencies><SubSystem>Console</SubSystem></Link></ItemDefinitionGroup><ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"><Link><AdditionalDependencies>libcaffe.lib;$(CudaDependencies);%(AdditionalDependencies)</AdditionalDependencies><SubSystem>Console</SubSystem></Link>
  • 最后是所有的NugetPackage的头文件相关文件包含
   <ImportGroup Label="ExtensionTargets"><Import Project="..\..\NugetPackages\OpenCV.2.4.10\build\native\OpenCV.targets" Condition="Exists('..\..\NugetPackages\OpenCV.2.4.10\build\native\OpenCV.targets')" /><Import Project="..\..\NugetPackages\OpenBLAS.0.2.14.1\build\native\openblas.targets" Condition="Exists('..\..\NugetPackages\OpenBLAS.0.2.14.1\build\native\openblas.targets')" /><Import Project="..\..\NugetPackages\glog.0.3.3.0\build\native\glog.targets" Condition="Exists('..\..\NugetPackages\glog.0.3.3.0\build\native\glog.targets')" /><Import Project="..\..\NugetPackages\hdf5-v120-complete.1.8.15.2\build\native\hdf5-v120.targets" Condition="Exists('..\..\NugetPackages\hdf5-v120-complete.1.8.15.2\build\native\hdf5-v120.targets')" /><Import Project="..\..\NugetPackages\gflags.2.1.2.1\build\native\gflags.targets" Condition="Exists('..\..\NugetPackages\gflags.2.1.2.1\build\native\gflags.targets')" /><Import Project="..\..\NugetPackages\boost_chrono-vc120.1.59.0.0\build\native\boost_chrono-vc120.targets" Condition="Exists('..\..\NugetPackages\boost_chrono-vc120.1.59.0.0\build\native\boost_chrono-vc120.targets')" /><Import Project="..\..\NugetPackages\boost_date_time-vc120.1.59.0.0\build\native\boost_date_time-vc120.targets" Condition="Exists('..\..\NugetPackages\boost_date_time-vc120.1.59.0.0\build\native\boost_date_time-vc120.targets')" /><Import Project="..\..\NugetPackages\boost_filesystem-vc120.1.59.0.0\build\native\boost_filesystem-vc120.targets" Condition="Exists('..\..\NugetPackages\boost_filesystem-vc120.1.59.0.0\build\native\boost_filesystem-vc120.targets')" /><Import Project="..\..\NugetPackages\boost_system-vc120.1.59.0.0\build\native\boost_system-vc120.targets" Condition="Exists('..\..\NugetPackages\boost_system-vc120.1.59.0.0\build\native\boost_system-vc120.targets')" /><Import Project="..\..\NugetPackages\boost.1.59.0.0\build\native\boost.targets" Condition="Exists('..\..\NugetPackages\boost.1.59.0.0\build\native\boost.targets')" /><Import Project="..\..\NugetPackages\boost_thread-vc120.1.59.0.0\build\native\boost_thread-vc120.targets" Condition="Exists('..\..\NugetPackages\boost_thread-vc120.1.59.0.0\build\native\boost_thread-vc120.targets')" /><Import Project="..\..\NugetPackages\boost_python2.7-vc120.1.59.0.0\build\native\boost_python-vc120.targets" Condition="Exists('..\..\NugetPackages\boost_python2.7-vc120.1.59.0.0\build\native\boost_python-vc120.targets')" /><Import Project="..\..\NugetPackages\protobuf-v120.2.6.1\build\native\protobuf-v120.targets" Condition="Exists('..\..\NugetPackages\protobuf-v120.2.6.1\build\native\protobuf-v120.targets')" /><Import Project="..\..\NugetPackages\LevelDB-vc120.1.2.0.0\build\native\LevelDB-vc120.targets" Condition="Exists('..\..\NugetPackages\LevelDB-vc120.1.2.0.0\build\native\LevelDB-vc120.targets')" /><Import Project="..\..\NugetPackages\lmdb-v120-clean.0.9.14.0\build\native\lmdb-v120-clean.targets" Condition="Exists('..\..\NugetPackages\lmdb-v120-clean.0.9.14.0\build\native\lmdb-v120-clean.targets')" /></ImportGroup>

这几步很容易遇到这样的问题

这里写图片描述

这里写图片描述

提示很明显了,看看第77行对应的 少了对应的 ,加上即可。

cuda相关头文件

编译运行发现出现下列错误

这里写图片描述

这个一看就可能是cuda的问题了,文件可以在C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include中找到,当然不同的安装位置由不同的路径寻找,相同的是这个文件一定存在。加入到VS路径中,操作同上面加caffe的include一样,注意红线部分

这里写图片描述

拷贝libcaffe

最后一个问题是

这里写图片描述

原因很简单,因为我们上面只加了libcaffe.lib的路径,并没有指引它所在地方,这个就与你的VS功底有关了,详细请看“如何调用C++的dll与lib文件”相关博客。我们这里直接把原始的caffe-windows下的release版本的libcaffe.lib拷贝到新建文件夹lib中去,路径如下

这里写图片描述

拷贝进去以后,在VS中加入lib所在目录

这里写图片描述

编译工程

上述步骤都搞定以后,重新生成我们的工程

这里写图片描述

然后设置一下将警告视为错误

这里写图片描述

然后就看到了满意的结果啦

这里写图片描述

解决dll相关问题

有时候会遇到这个问题,有时候不会遇到,可以先直接跳过此步骤,直接进行分类使用步骤,如果出现dll缺失问题,再回来添加dll。

方案1

当前编译了不一定能运行,还有dll没拷贝呢,网上博客说dll的使用方法是,将dll拷贝到一个文件夹,比如将caffe-windows的release下的所有dll全部拷贝到我们工程的如下新建文件夹中

这里写图片描述

然后在VS中

这里写图片描述

但是设置完毕以后,还是提示缺少dll,以后再试试,是不是哪里出问题了

方案2

跟前面一样,把编译的caffe-windows下的release文件夹加入到系统环境变量path中去,不再赘述,因为前面的caffe-Windows配置好像有过这个步骤,就是单纯的将E:\CaffeDev\caffe-master\Build\x64\Release加入path,仅此而已。

方案3

最简单粗暴的方法,上面编译工程完事以后,可以发现我们的工程多了个build文件夹,那么把所有的dll拷贝到E:\caffe-myproject\Build\x64\Release即可,如果你发现这个文件夹中有dll,就不用拷贝了,应该不会提示缺dll的问题,如果还是提示,那就拷贝吧,如果还是不行,自行百度。

这里写图片描述

分类使用

准备相关文件

使用方法就是先将所有的文件准备好

这里写图片描述

分别是待分类图片、模型结构、训练好的模型参数、均值、标签。前面cifar的模型建立和使用都介绍过这些东西的生成方法。

【注】按照上述方法完全不会出问题,最好最好是在原始的caffe-windows的基础下操作,如果是自己改动的caffe-windows的话,可能会出现一些不必要的问题。

运行方法-bat形式

老样子,直接写bat文件:

E:\caffe-myproject\Build\x64\Release\my_classification.exe lenet.prototxt lenet_iter_10000.caffemodel mean.binaryproto synset_words.txt 2.bmp
pause

运行出错

F0411 12:20:34.327227 14000 layer_factory.hpp:81] Check failed: registry.count(t
ype) == 1 (0 vs. 1) Unknown layer type: Input (known types: )
*** Check failure stack trace: ***

此博客【边喝caffee边Caffe 】(三) Check failed: registry.count(t ype) == 1 (0 vs. 1) Unknown layer type有讲解为什么,那么就直接按照方法,建立一个head.h

#include "caffe/common.hpp"
#include "caffe/layers/input_layer.hpp"
#include "caffe/layers/inner_product_layer.hpp"
#include "caffe/layers/dropout_layer.hpp"
#include "caffe/layers/conv_layer.hpp"
#include "caffe/layers/relu_layer.hpp"#include "caffe/layers/pooling_layer.hpp"
#include "caffe/layers/lrn_layer.hpp"
#include "caffe/layers/softmax_layer.hpp"namespace caffe
{extern INSTANTIATE_CLASS(InputLayer);extern INSTANTIATE_CLASS(InnerProductLayer);extern INSTANTIATE_CLASS(DropoutLayer);extern INSTANTIATE_CLASS(ConvolutionLayer);REGISTER_LAYER_CLASS(Convolution);extern INSTANTIATE_CLASS(ReLULayer);REGISTER_LAYER_CLASS(ReLU);extern INSTANTIATE_CLASS(PoolingLayer);REGISTER_LAYER_CLASS(Pooling);extern INSTANTIATE_CLASS(LRNLayer);REGISTER_LAYER_CLASS(LRN);extern INSTANTIATE_CLASS(SoftmaxLayer);REGISTER_LAYER_CLASS(Softmax);}

然后在classification.cpp头部引用一下,注意是双引号而非尖括号引用,以有智能提示为基准

#include "head.h"

重新编译以后,然后运行bat的结果:


E:\caffe-myproject\test\mnist>E:\caffe-myproject\Build\x64\Release\my_classifica
tion.exe lenet.prototxt lenet_iter_10000.caffemodel mean.binaryproto synset_word
s.txt 2.bmp
---------- Prediction for 2.bmp ----------
1.0000 - "2"
0.0000 - "0"
0.0000 - "3"
0.0000 - "1"
0.0000 - "4"E:\caffe-myproject\test\mnist>pause
请按任意键继续. . .

运行方法-修改cpp方法

改一下main函数

int main(int argc, char** argv) {//if (argc != 6) {//  std::cerr << "Usage: " << argv[0]//      << " deploy.prototxt network.caffemodel"//      << " mean.binaryproto labels.txt img.jpg" << std::endl;//  return 1;//}::google::InitGoogleLogging(argv[0]);argv[1] = "E:\\caffe-myproject\\test\\cifar\\cifar10_quick.prototxt";argv[2] = "E:\\caffe-myproject\\test\\cifar\\cifar10_quick_iter_4000.caffemodel.h5";argv[3] = "E:\\caffe-myproject\\test\\cifar\\mean.binaryproto";argv[4] = "E:\\caffe-myproject\\test\\cifar\\synset_words.txt";argv[5] = "E:\\caffe-myproject\\test\\cifar\\dog.jpg";string model_file = argv[1];string trained_file = argv[2];string mean_file = argv[3];string label_file = argv[4];Classifier classifier(model_file, trained_file, mean_file, label_file);string file = argv[5];std::cout << "---------- Prediction for "<< file << " ----------" << std::endl;cv::Mat img = cv::imread(file, -1);CHECK(!img.empty()) << "Unable to decode image " << file;std::vector<Prediction> predictions = classifier.Classify(img);/* Print the top N predictions. */for (size_t i = 0; i < predictions.size(); ++i) {Prediction p = predictions[i];std::cout << std::fixed << std::setprecision(4) << p.second << " - \""<< p.first << "\"" << std::endl;}
}

然后ctrl+F5运行结果

这里写图片描述

后记

一定要不断编译、不断尝试、不断查错、不断修改,此外熟能生巧。还有两点强调:路径路径路径原版caffe原版caffe原版caffe

编译方法多种多样,上述步骤肯定有不必要的地方,后期逐步修改

  • 第一次尝试编译的代码

    链接:http://pan.baidu.com/s/1i5vBPaP 密码:x7ee

  • 第二次尝试编译的代码
    链接:http://pan.baidu.com/s/1skIfYkH 密码:w69a
    主要相对于第一次编译的代码,删除了部分冗余的文件,也就是不从原版的caffe-Windows拷贝的东西,包括:

    • CommonSettings.targets,在my_classification.vcxproj中不需要添加的话语是
    <ItemGroup><ClInclude Include="head.h" />
    </ItemGroup>
    • 下面这句话删除也没影响
    <ItemGroup><None Include="packages.config" />
    </ItemGroup>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MKL学习——数学运算库安装调试

前言 最近要用C折腾一些东西&#xff0c;涉及到矩阵运算&#xff0c;看了一下网上推荐的数学库&#xff0c;貌似MKL还是蛮不错滴&#xff0c;放到VS2013里面试试 国际惯例&#xff0c;来波地址 blas, cblas, openblas, atlas, lapack, mkl性能对比 Compiling and Linking I…

MKL学习——向量操作

前言 推荐两个比较好的教程: BLAS (Basic Linear Algebra Subprograms) LAPACK for Windows 命名规范 BLAS基本线性代数子程序的函数命令都有一定规范&#xff0c;便于记忆 <character> <name> <mod> () character 定义的是数据类型 s实数域&#…

【caffe-Windows】识别率批量输出——matlab实现

前言 今天看到群里有人问”用matlab输出测试集的精度“&#xff0c;瞎试了一下&#xff0c;好像还成功了。主要还是依据前面所有在matlab中操作caffe的博客。 这里说一下&#xff1a;classification.m是适用单张图片的精度&#xff0c;类似于classification.exe的功能&#x…

相机矩阵(Camera Matrix)

前言 最近翻阅关于从2D视频或者图片中重构3D姿态的文章及其源码&#xff0c;发现都有关于摄像机参数的求解&#xff0c;查找了相关资料&#xff0c;做一下笔记。 国际惯例&#xff0c;来一波参考网址 透视变换、透镜畸变及校正模型、相机校正(Camera Calibration)、Matlab相…

损失函数梯度对比-均方差和交叉熵

前言 我们都知道在机器学习中&#xff0c;希望算法或者网络收敛更快&#xff0c;有些是对数据预处理&#xff0c;尤其是Batch Normalization&#xff0c;有些是采用不同的激活函数&#xff0c;尤其是Relu激活函数取得了巨大的成功&#xff0c;还有一种加速收敛方法是更换损失函…

如何选择深度学习优化器

前言 转载地址&#xff1a;如何选择深度学习优化器 作者&#xff1a;不会停的蜗牛 CSDN AI专栏作家 在很多机器学习和深度学习的应用中&#xff0c;我们发现用的最多的优化器是 Adam&#xff0c;为什么呢&#xff1f; 下面是 TensorFlow 中的优化器&#xff0c; https://w…

【caffe-Windows】基于Python多标签方法——VOC2012数据集

前言 按照上一篇博客所遗留的话题&#xff1a;多标签分类&#xff0c;进行初步探索&#xff0c;此篇博客针对caffe官网的多分类进行配置&#xff0c;只不过是Python接口的&#xff0c;不过官网在开头说明可以使用HDF5或者LMDB进行操作&#xff0c;只不过Python更加方便罢了 国…

【theano-windows】学习笔记二——theano中的函数和共享参数

前言 上一篇博客中学到了theano中的变量类型&#xff0c;也就是dscalar、dvector之类的, 然后还有一个theano.function和eval函数, 将我们所定义的操作转换成theano可执行的函数&#xff0c;类似于def, 还有就是简单的线性代数运算操作。 在神经网络(NN)中, 我们声明了权重、…

【theano-windows】学习笔记三——theano中的导数

前言 就一个NN而言&#xff0c;包含梯度、偏置、参数更新&#xff0c;而前面第一篇博客学习了theano中符号变量的定义, 第二篇博客学习了变量的随机初始化, 变量之间的互相操作(类似于sigmoid(w∗xb)), 但是参数更新还应涉及到损失函数的偏导计算&#xff0c;这一章节就是看看…

【theano-windows】学习笔记五——theano中张量部分函数

前言 至此感觉应该可以写出一个logistic回归程序了&#xff0c;但是为了达到对theano中张量的更灵活的使用, 还是先看一下thenao.tensor对变量都提供了哪些操作&#xff0c;最全的文档戳这里或者这里, 这里就稍微摘取一点自我感觉以后可能用得多的函数 基本张量函数 创建张量…

【theano-windows】学习笔记六——theano中的循环函数scan

前言 Scan是Theano中最基础的循环函数, 官方教程主要是通过大量的例子来说明用法. 不过在学习的时候我比较习惯先看看用途, 然后是参数说明, 最后再是研究实例. 国际惯例, 参考网址 官网关于Scan的11个例子 官网更全面的介绍 简介 用途 递归的一般形式, 可以被用于循环s…

【theano-windows】学习笔记九——softmax手写数字分类

前言 上一篇博客折腾了数据集的预备知识, 接下来按照官方的Deep learning 0.1 documentation一步步走, 先折腾softmax, 关于softmax和logistic回归分类的联系, 我在之前写过一个小博客 国际惯例, 参考博客走一波: Classifying MNIST digits using Logistic Regression soft…

【theano-windows】学习笔记十——多层感知机手写数字分类

前言 上一篇学习了softmax, 然后更进一步就是学习一下基本的多层感知机(MLP)了. 其实多层感知机同时就是w*xb用某个激活函数激活一下, 得到的结果作为下一层神经元的输入x, 类似于 output⋯f3(f2(f1(x∗w1b2)∗w2b2)∗w3b3)⋯output=\cdots f^3(f^2(f^1(x*w^1+b^2)*w^2+b^2)*…

【theano-windows】学习笔记十一——theano中与神经网络相关函数

前言 经过softmax和MLP的学习, 我们发现thenao.tensor中除了之前的博客【theano-windows】学习笔记五——theano中张量部分函数提到的张量的定义和基本运算外, 还有一个方法称为nnet, 如果自己实现过前面两篇博客中的代码就会发现用到了theano.tensor.nnet.sigmoid和thenao.te…

【caffe-windows】全卷积网络特征图分析

前言 突然就想分析一下全卷积网络的转置卷积部分了, 就是这么猝不及防的想法, 而且这个网络对图片的输入大小无要求&#xff0c;这么神奇的网络是时候分析一波了&#xff0c;我个人的学习方法调试代码&#xff0c;然后对照论文看理论 本次分析主要针对每层的权重大小和特征图…

【theano-windows】学习笔记十二——卷积神经网络

前言 按照进度, 学习theano中的卷积操作 国际惯例, 来一波参考网址 Convolutional Neural Networks (LeNet) 卷积神经网络如何应用在彩色图像上&#xff1f; 卷积小知识 三大特性&#xff1a;局部感知(稀疏连接), 权值共享, 池化 上图很重要, 描述的是前一个隐层m-1具有四…

【theano-windows】学习笔记十三——去噪自编码器

前言 上一章节学习了卷积的写法,主要注意的是其实现在theano.tensor.nnet和theano.sandbox.cuda.dnn中都有对应函数实现, 这一节就进入到无监督或者称为半监督的网络构建中. 首先是自编码器(Autoencoders)和降噪自编码器(denoising Autoencoders) 国际惯例, 参考网址: Denoi…

【theano-windows】学习笔记十四——堆叠去噪自编码器

前言 前面已经学习了softmax,多层感知器,CNN&#xff0c;AE&#xff0c;dAE&#xff0c;接下来可以仿照多层感知器的方法去堆叠自编码器 国际惯例&#xff0c;参考文献&#xff1a; Stacked Denoising Autoencoders (SdA) Greedy Layer-Wise Training of Deep Networks 理…

【theano-windows】学习笔记十五——受限玻尔兹曼机

前言 终于到了最喜欢的模型: 受限玻尔兹曼机(RBM)了, 发现关于RBM是如何从能量模型发展过来的介绍非常不错, 而关于详细理论证明, 可以去看我前面的受限玻尔兹曼机的一系列博客. 国际惯例, 参考博客,超级强推第二个博客, 证明过程很给力: Restricted Boltzmann Machines (R…

【Ogre-windows】环境配置

前言 由于工程原因, 学习一下Ogre面向对象图形渲染开源引擎, 慢慢爬坑吧。首先还是环境的配置问题哎. 其实最重要的是要预先编译三方库, 虽然官方说可以自动编译, 但是在自己电脑上还是出现了无法解析外部符号之类的问题, 正常情况下我就认为是三方库的lib出现了问题, 最后额外…