这篇更好:在windows环境下离线编译tensorflow2.2.0的C++动态链接库
首先,感谢各位前辈的分享。搜索到的教程、文章太多,没有全部记录下来,很抱歉不能一一感谢,一开始也没想到能写这么一篇文,以后注意…
【目前只编译出dll lib,正在研究怎么调用……应该还有一些其他的小坑,】
(有些步骤可能是多余的,我就不去一个个排除了…总之能编译。以下链接,第一个是tensorflow官网,不过有些按照官网的话行不通…)
后续会说为什么要下载,保存到自己能想起来的地方,先放着就行,后续可能会用到。
# 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
注意,bazel 编译的时候占用C盘的空间可能比较大,所以下载安装,还有tensorflow源码包,请各位自己找其他盘符的位置。(我自己的电脑只有C盘,所以所有东西都放在C盘里了。)
VS2019去官网下载就可以。SDK版本好像没有要求,只安装一个,记住是哪个SDK版本就好。系统变量的设置后面会说,除了VS的还有bazel、msys2的。
另外,tensorflow官网说需要VS2019 生成工具,但不用另外下载安装生成工具……但还是都安装吧。
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*文件。
# -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
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版本。
打开下载好的msys2,不是终端
依次执行以下三个命令(不要复制粘贴,手打进去)。
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
git checkout 是切换版本的命令,v后面如果是2.4.0的话切换的就是2.4.0,这里编译的是2.2.0。
接下来,注意,在**[开始]->[Visual Sdutio 2019]** 下找到 [x64 Native Tools Command Prompt for VS 2019] ,如下图。它和终端很像,【但是编译是要在这里编译的!】(感谢 @JayKay-x的分享)。
打开 [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 文件拖入进去,然后回车执行。
conda deactivate
python --version
执行之后,【注意】要退出 tf37 环境,检查一下 python 的版本是不是 3.7.* 。
确认无误后,开始 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需要的各种包,就全都安排了。
(辛苦辛苦,喝口水歇一歇)
其实还是要继续下载。下面的跳过,直接开始编译,编译成功之后在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
cd 到 已经转换成 2.2.0 版本的 tensorflow 文件夹,执行以下指令,开始配置。
python configure.py
配置到这里就ok了。接下来开始编译,不过先说一下前面提到的 protobuf 、 bazel 的版本。
之前说的 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.
【稍等,开始编译之前还有一件事,编译的时候会下载很多包,其中可能会有包下载不了的情况,会报以下错误。尤其llvm建议先下载好,请自行百度搭建本地服务器,更换相应文件中的URL设置。具体方法放在本文最后,但建议提前按照这种方法准备好,因为llvm包比较大】
no such package '@llvm//' Error downloading
connected time out
开始编译,执行以下指令,过程需要下载,全部下载完毕之后,自动开始编译,然后会生成 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
长时间的等待之后,就编译好了。
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 文件里,总之方法都一样。
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加速 - 迷途小书童