Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)

Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)

  • 0、建议预先下载的几个包
  • 1、VS2019, anaconda, bazel, msys2 下载、安装、路径设置
    • 1.1、VS 2019
    • 1.2、anaconda
      • 创建python环境
    • 1.3、msys2 & bazel
    • 1.4、创建编译环境
      • pip安装一些东西
  • 2、configure.py配置,准备开始编译
      • 为了解决一些报错问题
    • 2.1、configure配置
      • protobuf版本
    • 2.2、编译
      • 一开始让预先下载的包
  • 参考链接


这篇更好:在windows环境下离线编译tensorflow2.2.0的C++动态链接库


首先,感谢各位前辈的分享。搜索到的教程、文章太多,没有全部记录下来,很抱歉不能一一感谢,一开始也没想到能写这么一篇文,以后注意…

【目前只编译出dll lib,正在研究怎么调用……应该还有一些其他的小坑,】

(有些步骤可能是多余的,我就不去一个个排除了…总之能编译。以下链接,第一个是tensorflow官网,不过有些按照官网的话行不通…)

0、建议预先下载的几个包

后续会说为什么要下载,保存到自己能想起来的地方,先放着就行,后续可能会用到。

# llvm-project-387c3f74fd8efdc0be464b0e1a8033cc1eeb739c
https://github.com/llvm/llvm-project/archive/387c3f74fd8efdc0be464b0e1a8033cc1eeb739c.tar.gz

# b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd (这个是 com_github_grpc_grpc )
https://github.com/grpc/grpc/archive/b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd.tar.gz

# boringssl-7f634429a04abc48e2eb041c81c5235816c96514
https://storage.googleapis.com/mirror.tensorflow.org/github.com/google/boringssl/archive/7f634429a04abc48e2eb041c81c5235816c96514.tar.gz

# icu-release-64-2 
https://github.com/unicode-org/icu/archive/release-64-2.zip

# aws-sdk-cpp-1.7.266
https://github.com/aws/aws-sdk-cpp/archive/1.7.266.tar.gz

1、VS2019, anaconda, bazel, msys2 下载、安装、路径设置

注意,bazel 编译的时候占用C盘的空间可能比较大,所以下载安装,还有tensorflow源码包,请各位自己找其他盘符的位置。(我自己的电脑只有C盘,所以所有东西都放在C盘里了。)

1.1、VS 2019

VS2019去官网下载就可以。SDK版本好像没有要求,只安装一个,记住是哪个SDK版本就好。系统变量的设置后面会说,除了VS的还有bazel、msys2的。
另外,tensorflow官网说需要VS2019 生成工具,但不用另外下载安装生成工具……但还是都安装吧。
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第1张图片

1.2、anaconda

anaconda清华镜像 链接是anaconda的清华镜像源(感谢),下载安装好之后,参照链接内的说明修改C:\Users\Administrator目录下的*.condarc*文件 ,复制粘贴上去就好啦。

(Administrator是自己电脑的用户名,比如自己的电脑叫xiaobai,那目录就是C:\Users\xiaobai。)

【如果没有.condarc文件的话】,打开终端,桌面任务栏点击**[开始]->[Windows系统]->[命令提示符]win+r** 输入:

conda config --set show_channel_urls yes

执行之后就可以在C:\Users\Administrator目录下找到.condarc文件啦~
然后参照链接内的说明修改*.condarc*文件。

创建python环境

# -n py37 设置环境名
conda create -n py37 python==3.7
# 试试激活环境
conda activate py37

下载几个包。注意,protobuf 要 3.8.0 版本。(后面会说明为什么)

conda install protobuf==3.8.0 numpy keras-preprocessing patch

1.3、msys2 & bazel

https://www.msys2.org/ msys2下载地址。
github bazel 下载 bazel 2.0.0 版本,bazel-2.0.0-windows-x86_64.exe。不需要安装,将下载好的 bazel200.exe 文件重命名为 bazel.exe,放到 msys2 的根目录下。

C:\Users\Administrator\Anaconda3\envs\tf37\Library\bin,在Anaconda 目录下找到 patch.exe 文件以及 patch.exe.manifest 复制粘贴到 msys2 根目录下。(或者,anaconda\pkgs\patch-2.5.9-1\Library\bin 也可以)

添加系统变量:

BAZEL_SH C:\path\MSYS2\usr\bin\bash.exe
BAZEL_VC C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC
BAZEL_VS C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional
BAZEL_VC_FULL_VERSION 14.28.29333
BAZEL_WINSDK_FULL_VERSION 10.0.19041.0

BAZEL_VC_FULL_VERSION 的变量值

C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC

BAZEL_WINSDK_FULL_VERSION 的变量值,按照Visual Studio安装的Windows SDK版本。
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第2张图片
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第3张图片

Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第4张图片
打开下载好的msys2,不是终端
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第5张图片
依次执行以下三个命令(不要复制粘贴,手打进去)。

pacman -Syu
pacman -Su
pacman -S patch, unzip, grep

cd到自己想要的文件夹,比如cd D:\tf,然后下载tensorflow。

git clone https://github.com/tensorflow/tensorflow.git

git速度太慢的话

git clone https://gitee.com/mirrors/tensorflow.git

下载好tensorflow之后依次输入以下命令,执行完之后就可以关闭msys2啦

cd tensorflow
git checkout v2.2.0

Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第6张图片
git checkout 是切换版本的命令,v后面如果是2.4.0的话切换的就是2.4.0,这里编译的是2.2.0。

1.4、创建编译环境

接下来,注意,在**[开始]->[Visual Sdutio 2019]** 下找到 [x64 Native Tools Command Prompt for VS 2019] ,如下图。它和终端很像,【但是编译是要在这里编译的!】(感谢 @JayKay-x的分享)。
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第7张图片
打开 [x64 Native Tools Command Prompt for VS 2019] ,输入以下命令。

conda activate py37
python -m venv C:\tf\tensorflow\.venv

C:\tf\tensorflow 是自己 clone 的 tensorflow 源码位置。这之后 C:\tf\tensorflow 目录下就会出现一个 .venv 文件夹,打开这个文件夹,重新打开 [x64 Native Tools Command Prompt for VS 2019],将 .venv 文件夹里打开 Script文件夹,找到 activate.bat 文件拖入进去,然后回车执行。
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第8张图片

conda deactivate
python --version

执行之后,【注意】要退出 tf37 环境,检查一下 python 的版本是不是 3.7.* 。
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第9张图片

pip安装一些东西

确认无误后,开始 pip 一些东西,注意,要在 .venv 这个编译环境里面 pip安装。(其实一行 pip install 就可以,只不过这样看起来好看一些)

python -m pip install --upgrade pip
pip install absl-py astunparse==1.6.3 backports.weakref enum34 gast==0.3.3 google_pasta
pip install h5py==2.10.0 keras_preprocessing numpy==1.18.0 opt_einsum
pip install tensorboard==2.2.0 tensorflow_estimator==2.2.0 termcolor wrapt wheel six
pip install protobuf==3.8.0
pip install patch

如果pip速度慢的话,按以下。(以下是aliyun镜像,也可以换成其他).
安装pip报错:WARNING: Retrying (Retry(total=4,…
pip 添加trusted host 一劳永逸

【检查需要pip安装哪些】可以在此链接 中查看 REQUIRED_PACKAGES= [……] 内写出的东西。如果是 tensorflow 其他版本的话切换一下对应版本,本文只是 tensorflow2.2.0。

此外需要注意最后两个,一个是 protobuf 版本需要 3.8.0 ,后面步骤中执行 configure.py 文件之后可以找到这个要求,总之下载 3.8.0 就对啦,tensorflow 其他版本可能不一样。另一个是 patch ,在上面的链接里没有写,但需要(也可以不安装试试,不行就再装呗)。

到此,vs路径、msys2路径、bazel路径、编译环境、pip需要的各种包,就全都安排了。
(辛苦辛苦,喝口水歇一歇)

2、configure.py配置,准备开始编译

为了解决一些报错问题

其实还是要继续下载。下面的跳过,直接开始编译,编译成功之后在vs中测试,如果报错无法识别的外部符号,再按照这种方法修改。

# 打开文件 
# tensorflow\tensorflow\tools\def_file_filter\def_file_filter.py.tpl,
# 定位到下面内容的位置,看到缺的就往上加。


# Header for the def file.
    if args.target:
      def_fp.write("LIBRARY " + args.target + "\n")
    def_fp.write("EXPORTS\n")
    def_fp.write("\t ??1OpDef@tensorflow@@UEAA@XZ\n")
    def_fp.write("\t ?NewSession@tensorflow@@YAPEAVSession@1@AEBUSessionOptions@1@@Z\n")
    def_fp.write("\t ??0SessionOptions@tensorflow@@QEAA@XZ\n")
    def_fp.write("\t ??0ReadFile@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z\n")
    def_fp.write("\t ??0ExpandDims@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z\n")
    def_fp.write("\t ??0Cast@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@W4DataType@2@@Z\n")
    def_fp.write("\t ??0DecodeJpeg@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Z\n")
    def_fp.write("\t ??0Operation@tensorflow@@QEAA@PEAVNode@1@@Z\n")
    def_fp.write("\t ?WithOpNameImpl@Scope@tensorflow@@AEBA?AV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z\n")
    def_fp.write("\t ?ToGraphDef@Scope@tensorflow@@QEBA?AVStatus@2@PEAVGraphDef@2@@Z\n")
    def_fp.write("\t ?NewRootScope@Scope@tensorflow@@SA?AV12@XZ\n")
    def_fp.write("\t ??1Scope@tensorflow@@QEAA@XZ\n")
    def_fp.write("\t ?Run@ClientSession@tensorflow@@QEBA?AVStatus@2@AEBV?$vector@VOutput@tensorflow@@V?$allocator@VOutput@tensorflow@@@std@@@std@@PEAV?$vector@VTensor@tensorflow@@V?$allocator@VTensor@tensorflow@@@std@@@5@@Z\n")
    def_fp.write("\t ??1ClientSession@tensorflow@@QEAA@XZ\n")
    def_fp.write("\t ??0ClientSession@tensorflow@@QEAA@AEBVScope@1@@Z\n")
    def_fp.write("\t ?LoadSavedModel@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@AEBVRunOptions@1@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV?$unordered_set@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$hash@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@U?$equal_to@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@6@QEAUSavedModelBundle@1@@Z\n")
    def_fp.write("\t ??1SavedModelBundleInterface@tensorflow@@UEAA@XZ\n")
    def_fp.write("\t ??0CombinedNonMaxSuppression@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@11111AEBUAttrs@012@@Z\n")
    def_fp.write("\t ??0CombinedNonMaxSuppression@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@11111@Z\n")

例子
报错 (巴拉巴拉) ??1OpDef@tensorflow@@UEAA@XZ <- 把这段复制粘贴到
def_fp.write(“\t … \n”) -> ‘…’ 复制到这里,粘贴加上去就行,报错报了几个就加进去多少个。

【不用按下面方法的改,上面的就可以解决报错了。如果不行再用以下方法。】
Bazel编译Tensorflow C++ 版本CPU/GPU DLL动态库(附tensorflow CPU/GPU开)发包
打开 tensorflow/BUILD 文件,添加以下内容。

tf_cc_shared_object(
    name = "libtensorflow_cc.so",  #  不知道要不要改成tensorflow_cc.so / tensorflow_cc.dll
    linkopts = select({
        "//tensorflow:darwin": [
            "-Wl,-exported_symbols_list",  # This line must be directly followed by the exported_symbols.lds file
            "$(location //tensorflow:tf_exported_symbols.lds)",
        ],
        "//tensorflow:windows": [
            "-def:" +   # This line must be directly followed by the exported_symbols_msvc.lds file
            "$(location //tensorflow:tf_exported_symbols_msvc.lds)",
        ],
        "//conditions:default": [
            "-z defs",
            "-Wl,--version-script",  #  This line must be directly followed by the version_script.lds file
            "$(location //tensorflow:tf_version_script.lds)",
        ],
    }),
    visibility = ["//visibility:public"],
    deps = [    # 以下cc的文件夹有些对应不上,可能是因为tensorflow版本不同
		"//tensorflow:tf_exported_symbols.lds",
		"//tensorflow:tf_exported_symbols_msvc.lds",
        "//tensorflow:tf_version_script.lds",
        "//tensorflow/c:c_api",
        "//tensorflow/c/eager:c_api",
        "//tensorflow/cc:cc_ops",
        "//tensorflow/cc:client_session",
        "//tensorflow/cc:scope",
        "//tensorflow/cc/profiler",
        "//tensorflow/core:tensorflow",
    ] + if_ngraph(["@ngraph_tf//:ngraph_tf"]),
)

新建 tf_exported_symbols_msvc.lds 文件,保存到 tensorflow 根目录,也就是BUILD文件所在的目录。

LIBRARY libtensorflow_cc # 不知道要不要改成 tensorflow_cc
EXPORTS
    ??0MetaGraphDef@tensorflow@@QEAA@XZ
    ??1MetaGraphDef@tensorflow@@UEAA@XZ
    ??0LogMessageFatal@internal@tensorflow@@QEAA@PEBDH@Z
    ??1LogMessageFatal@internal@tensorflow@@UEAA@XZ
    ?CheckDimsEqual@TensorShape@tensorflow@@AEBAXH@Z
    ?CheckDimsAtLeast@TensorShape@tensorflow@@AEBAXH@Z
    ??0Tensor@tensorflow@@QEAA@XZ
    ??0GraphDef@tensorflow@@QEAA@XZ
    ??1GraphDef@tensorflow@@UEAA@XZ
    ?CheckType@Tensor@tensorflow@@AEBAXW4DataType@2@@Z
    ?CopyFromInternal@Tensor@tensorflow@@AEAAXAEBV12@AEBVTensorShape@2@@Z
    ??1NodeDef@tensorflow@@UEAA@XZ
    ??0NodeDef@tensorflow@@QEAA@AEBV01@@Z
    ??0RunOptions@tensorflow@@QEAA@XZ
    ??1RunOptions@tensorflow@@UEAA@XZ
    ?IgnoreError@Status@tensorflow@@QEBAXXZ
    ?LoadSavedModel@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@AEBVRunOptions@1@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV?$unordered_set@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$hash@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@U?$equal_to@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@6@QEAUSavedModelBundle@1@@Z
    ?NewSession@tensorflow@@YAPEAVSession@1@AEBUSessionOptions@1@@Z

2.1、configure配置

cd 到 已经转换成 2.2.0 版本的 tensorflow 文件夹,执行以下指令,开始配置。

python configure.py


配置到这里就ok了。接下来开始编译,不过先说一下前面提到的 protobuf 、 bazel 的版本。

protobuf版本

之前说的 protobuf 版本,在执行 configure.py 文件之后,用Notepad++或者其他编译器打开 \tensorflow\tensorflow\workspace.bzl 文件,搜索protobuf,能找到一段说明。没试过其他版本的protobuf能不能行,3.8.0 是没问题的。bazel 版本在 tensorflow 官网可以看到, tensorflow 2.2.0 对应的是 bazel 2.0.0 。

# 310ba5ee72661c081129eb878c1bbcec936b20f0 is based on 3.8.0 with a fix for protobuf.bzl.

Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第10张图片
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第11张图片

【稍等,开始编译之前还有一件事,编译的时候会下载很多包,其中可能会有包下载不了的情况,会报以下错误。尤其llvm建议先下载好,请自行百度搭建本地服务器,更换相应文件中的URL设置。具体方法放在本文最后,但建议提前按照这种方法准备好,因为llvm包比较大】

no such package '@llvm//' Error downloading
connected time out

2.2、编译

开始编译,执行以下指令,过程需要下载,全部下载完毕之后,自动开始编译,然后会生成 dll 文件。过程……一两个小时?如果下载断了就重新执行下面的指令。

bazel build //tensorflow:tensorflow_cc.dll

成功之后 会提示 [INFO: Build completed successfully, **** total actions],我就不为了截图去重新编译了……

接下来执行下面指令,编译 lib 文件,这个比较快。

bazel build //tensorflow:tensorflow_cc_dll_import_lib

输出头文件,指令如下。

bazel build //tensorflow:install_headers

长时间的等待之后,就编译好了。

Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第12张图片
debug版本的,在下面文章最后部分,不赘述了。
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件

一开始让预先下载的包

【大坑之 llvm】

以下五个链接都是大包,115MB / 16MB / 25MB / 65MB / 26MB。

建议提前下载好。前三个在 ./tensorflow/workspace.bzl 文件里。aws 和 icu 在 ./third_party,aws文件夹下的 workspace.bzl 和 icu文件夹下的 workspace.bzl。

llvm-project-387c3f74fd8efdc0be464b0e1a8033cc1eeb739c
b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd
boringssl-7f634429a04abc48e2eb041c81c5235816c96514
icu-release-64-2
aws-sdk-cpp-1.7.266

下载地址:

#llvm-project-387c3f74fd8efdc0be464b0e1a8033cc1eeb739c
https://github.com/llvm/llvm-project/archive/387c3f74fd8efdc0be464b0e1a8033cc1eeb739c.tar.gz

#b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd (这个是 com_github_grpc_grpc )
https://github.com/grpc/grpc/archive/b54a5b338637f92bfcf4b0bc05e0f57a5fd8fadd.tar.gz

#boringssl-7f634429a04abc48e2eb041c81c5235816c96514
https://storage.googleapis.com/mirror.tensorflow.org/github.com/google/boringssl/archive/7f634429a04abc48e2eb041c81c5235816c96514.tar.gz

#icu-release-64-2 
https://github.com/unicode-org/icu/archive/release-64-2.zip

#aws-sdk-cpp-1.7.266
https://github.com/aws/aws-sdk-cpp/archive/1.7.266.tar.gz

如下图,复制其中白色部分,一定只要白色部分,否则搜索不到。复制之后打开 ./tensorflow/tensorflow/workspace.bzl 文件,Ctrl+F 搜索。或者在 workspace.bzl 文件夹中搜索LLVM。(不搜索也行,直接复制后面我给的也可以,但其他版本的TensorFlow可能不一样。)

除了llvm其他都还好,直接复制粘贴就能找到。如果 workspace.bzl 文件中实在找不到的话,看看报错信息,也可能不在 workspace.bzl 文件里,总之方法都一样。

在这里插入图片描述
Windows编译Tensorflow2.2.0 C++ dll (CPU bazel)_第13张图片

387c3f74fd8efdc0be464b0e1a8033cc1eeb739c
#(直接复制下面链接,打开浏览器,粘贴自动下载 -_- 其他版本tensorflow请自行查看workspace.bzl文件)
https://github.com/llvm/llvm-project/archive/387c3f74fd8efdc0be464b0e1a8033cc1eeb739c.tar.gz

添加搭建好的本地服务器下载地址,本地服务器就是做个网页骗自己的电脑,从把自己指定的文件夹中下载好的文件,通过本地服务器搭建的本地网址“下载”到 bazel需要的地方。

# Check out LLVM and MLIR from llvm-project.
    LLVM_COMMIT = "387c3f74fd8efdc0be464b0e1a8033cc1eeb739c"
    LLVM_SHA256 = "5648d1bdd933f45aa6556cf104b32a0418121ce6961f5f47e8ef5bc6e428434f"
    LLVM_URLS = [  【添加到下面位置,我就不费劲去重新做一个截图了】
【看!】"https://本地服务器/包名+后缀", 【记得两边的 "" 引文双引号 以及 最后的英文逗号 [ , ]"https://storage.googleapis.com/mirror.tensorflow.org/github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
        "https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
    ]
    tf_http_archive(
        name = "llvm-project",
        sha256 = LLVM_SHA256,
        strip_prefix = "llvm-project-" + LLVM_COMMIT,
        urls = LLVM_URLS,
        additional_build_files = {
            clean_dep("//third_party/llvm:llvm.autogenerated.BUILD"): "llvm/BUILD",
            "//third_party/mlir:BUILD": "mlir/BUILD",
            "//third_party/mlir:test.BUILD": "mlir/test/BUILD",
        },
    )

tensorflow/tensorflow/workspace.bzl 文件中,除了llvm(115.9mb)以外,还有boringssl(25.9mb)建议先下载好。

另外还有 tensorflow/third_party/icu/workspace.bzl , icu(48.6mb)。

—2021年1月30日 更新—

unsolved symbol 无法识别的外部符号 问题,按照上面提到的方法之后还是不可行的话,应该是库没有连接好。

—未完待续—

(一些碎碎念)

还望通过这篇文章编译成功了的各位,如果有新的发现,或是可以精简之处,自己也能写一份出来,给更多的后来人提供便利。这篇文章终将泯灭在历史的长河中,而未来虽会曲折,但一定会更加美好。

参考链接

最新tensorflow 2.2.0源码编译,支持gpu加速,附python、c++验证
TF官网文档
win10+vs2019+bazel+编译tensorflow2.1-CPU-only版
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件
JayKay-x:Win10 VS2019+Cuda10.2+bazel编译tensorflow-2.1.0
TensorFlow 1.13 在 windows 上的构建
Bazel编译Tensorflow C++ 版本CPU/GPU DLL动态库(附tensorflow CPU/GPU开)发包

Linux Ubuntu的看这个 源码编译tensorflow-2.2.0,支持gpu加速 - 迷途小书童

你可能感兴趣的:(windows,python)