win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)

1 安装msys2

msys2是一个在Windows上的Linux虚拟环境,在Linux上写的程序,可以使用msys2编译为Windows上的exe或者dll。
msys2官网上下载msys2程序:下载链接
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
下载完成后进行安装,安装成功后将安装目录C:\msys64和安装目录下的usr/bin目录C:\msys64\usr\bin添加到系统环境变量path中
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
以管理权限打开cmd,依次安装msys2的一些环境包

pacman -Syu
pacman -S git
pacman -S patch unzip grep
pacman -S git patch unzip

win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)

2 在msys2中配置bazel

GitHub上官方地址上下载bazel0.26.0这个版本:下载链接
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
将下载好的bazel-0.26.0-windows-x86_64.exe复制到C:\msys64目录下,并将其重命名为bazel.exe

win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
接下来添加三个环境变量:
msys2中bash路径:
BAZEL_SH=C:\msys64\usr\bin\bash.exe
vs路径:
BAZEL_VS=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise
vc路径:
BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)

3 配置Python环境

对于我的电脑里安装是anaconda,使用的Python环境是3.6的版本
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
激活Python368环境,安装如下几个包:
numpy 1.19.0
six 1.15.0
wheel 0.34.2
Keras-Applications 1.0.8
Keras-Preprocessing 1.1.2

4 编译TensorFlow

GitHub官网上下载TensorFlow1.15.3版本:
下载地址
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
压缩包下载完成后解压。
以管理员权限打开cmd,使用命令activate python368激活anaconda中的Python3.6环境
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
然后使用cd命令进入TensorFlow1.15.3解压后的目录:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
使用Python指令配置编译设置

python ./configure.py

接下来会弹出一些配置的选择,对每个选择进行讲解下
Please specify the location of python
这个是确认Python环境的安装目录,无误的话直接按enter键确认。

Please input the desired Python library path to use
这个是确认Python的第三方模块安装目录,也就是numpy等模块安装的site-packages目录

Do you wish to build TensorFlow with XLA JIT support? [y/N]:
XLA 利用 JIT 编译技术分析用户在运行时创建的 TensorFlow 图表,根据实际运行时维度和类型将其专门化,将多个运算融合在一起并为它们生成高效的本机代码——适用于 CPU、GPU 之类的设备和自定义加速器(例如,Google 的 TPU)。目前XLA是实验性的。大多数使用情况在性能(加快速度或减少内存使用)方面都没有改进。
因此这个地方我选择N

Do you wish to build TensorFlow with ROCm support? [y/N]
AMD显卡系列的GPU加速,由于我没有使用A卡,因此这里也选择N

Do you wish to build TensorFlow with CUDA support? [y/N]
这个就是通常所说的N卡GPU使用cuda进行加速计算,编译GPU版本的下个博客里会说,这次是编译CPU版本的,因此这个地方也选择N

Would you like to override eigen strong inline for some C++ compilation to reduce the compilation time? [Y/n]
由于TensorFlow的C++版本关于多维数据使用eigen计算,这个意思是使内联函数加快eigen编译速度,因此这个地方选择Y
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
输入命令编译生成仅支持CPU版的C++ dll库

bazel build --config=opt --copt=-nvcc_options=disable-warnings --define=no_tensorflow_py_deps=true //tensorflow:tensorflow_cc.dll

接下来就是要耗费一定时间的下载和编译了,由于TensorFlow在编译的过程中要下载很多依赖资源,这些资源基本都是需要*才能下载的,因此需要使用VPN。
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
只要以上配置没问题,就可以编译成功
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
生成的dll在这个位置:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
生成lib文件,命令如下:

bazel build --config=opt --copt=-nvcc_options=disable-warnings //tensorflow:tensorflow_cc_dll_import_lib

win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
其实也可以不用这个命令生成lib文件,因为在编译生成dll的时候,生成了一个tensorflow_cc.dll.if.lib,只需要把这个文件重命名为tensorflow_cc.dll.lib就行了

生成头文件,命令如下:

bazel build --config=opt --copt=-nvcc_options=disable-warnings //tensorflow:install_headers

win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
图上所示就是TensorFlow编译得到的头文件、dll文件、lib文件。

5 在vs中调用出现的问题以及解决办法

新建一个vs2019 C++控制台工程
vc++目录–包含目录,设置头文件:
D:\tensorflow-1.15.3\bazel-bin\tensorflow\include
D:\tensorflow-1.15.3\bazel-bin\tensorflow\include\src
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
vc++目录–库目录,设置lib文件目录,也就是刚才生成的tensorflow_cc.lib所在目录:
D:\tensorflow-1.15.3\bazel-bin\tensorflow

链接器–输入–附加依赖项,添加lib文件名:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
然后将tensorflow_cc.dll复制到工程的x64/Releas目录下:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
Main.cpp中代码如下:

#define COMPILER_MSVC
#define NOMINMAX
#define PLATFORM_WINDOWS 

#include <iostream>
#include <vector>
#include <tensorflow/core/public/session.h>
#include <iostream>

using namespace std;
using namespace tensorflow;

int main()
{
    Session* session;
    Status status = NewSession(SessionOptions(), &session);
    if (!status.ok()) {
        std::cout << status.ToString() << std::endl;
    }
    else {
        std::cout << "Session created successfully" << std::endl;
    }
    cout << "Session successfully created.\n";

    getchar();
    return 0;
}

运行工程,结果如下:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
出现无法解析的外部符号:

无法解析的外部符号 "class tensorflow::Status __cdecl tensorflow::NewSession(struct tensorflow::SessionOptions const &,class tensorflow::Session * *)" (?NewSession@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@PEAPEAVSession@1@@Z)
无法解析的外部符号 "public: __cdecl tensorflow::SessionOptions::SessionOptions(void)" (??0SessionOptions@tensorflow@@QEAA@XZ)

解决办法是找到tensorflow\tools\def_file_filter\def_file_filter.py.tpl这个文件,用notepad打开,使用查找功能,搜索args.target找到这个地方
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
在这里添加刚才vs调试时提示无法解析的两个函数:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)

    def_fp.write("\t ?NewSession@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@PEAPEAVSession@1@@Z\n")
    def_fp.write("\t ??0SessionOptions@tensorflow@@QEAA@XZ\n")

还有一个问题需要注意的是需要打开notepad的视图-显示符号-显示空格和列表符,当我们添加新的函数时一定要注意前面的符号是空格而不是制表符
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
将文件保存,然后重新编译,输入命令

bazel build --config=opt --copt=-nvcc_options=disable-warnings --define=no_tensorflow_py_deps=true //tensorflow:tensorflow_cc.dll

这个重新生成动态库的过程会很快,生成dll成功
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
接着重新生成lib文件

bazel build --config=opt --copt=-nvcc_options=disable-warnings //tensorflow:tensorflow_cc_dll_import_lib

然后将新的dll和lib文件替换到vc工程里,运行工程:
win10下使用bazel从源码编译TensorFlow1.15.3的C++动态库(CPU版本)
可以看到程序运行成功,由于示例程序比较简单,因此只缺少两个函数,如果对于自己的其它工程运行后提示无法解析的符号比较多,也是按照这种方式把缺少的函数加到那个文件里,重新编译生成dll和lib。

上一篇:美丽乡村建筑建设新农村规划设计农村改造调研报告城乡统筹规划(共2383份,15.50G)


下一篇:文件对比工具(主要针对多个版本的代码合并)