win10+bazel编译Tensorflow1.12.0 C++接口 cpu版本

参考资料:
win10下Bazel编译tensorflow源码并用c++接口调用tensorflow模型超详细教程
WIN10 + Tensorflow1.12 C++接口 + Cmake编译失败 + Bazel编译成功 + C++接口
win10 + bazel-0.20.0 + tensorflow-1.13.1 编译tensorflow GPU版本的C++库
Bazel编译Tensorflow C++ 版本CPU/GPU DLL动态库(附tensorflow CPU/GPU开)发包
感谢大佬们的无私奉献!!!

环境:
tensorflow 1.12.0
bazel 0.15.0
win10
vs2015
python3.6.4
msys64
release版本

我不怎么打算图文并茂的一步步写了,我主要想写写我的一些坑和一些想法

  1. 我看人家都是用的powershell来编译的,但是我对这玩意不熟悉,平时不怎么用,所以刚开始的时候就选择了bazel,因为我ubuntu上是编译成功的,所以我很坚定我的想法,但是后来复制文件的时候我还是用了powershell,相见恨晚的感觉!
    powershell的位置:
C:\Windows\System32\WindowsPowerShell\v1.0

然后啥命令都跟ubuntu类似,真香!!
2. 安装需要MSYS64 + bazel.exe两个文件,msys64直接解压到了默认路径,bazel-0.15.0-windows-x86_64.exe改名为bazel.exe扔进C:\msys64,具体的看这个链接,很详细bazel+msys64具体操作
3. 这部分编译tensorflow1.12.0源码:

python ./configure.py

在这里插入图片描述
编译c++ dll:

bazel build --config=opt --config=monolithic //tensorflow:libtensorflow_cc.so tensorflow:install_headers

编译好长这样:
在这里插入图片描述
我已经不知道我多少次看到这个界面了!!!
将bazel-bin\tensorflow下两个文件重命名

libtensorflow_cc.so.if.lib  -->  libtensorflow_cc.lib 

libtensorflow_cc.so -->  libtensorflow_cc.dll

注意:
我看其他人的教程lib文件叫libtensorflow_cc.so.ifso,我的libtensorflow_cc.so.if.lib,我并不是很清楚windows下带GPU的结尾是ifso,不带GPU的结尾是if.lib?至少我每次编译出来的都是if.lib。

我这么编译的结果用的时候报了相当多的error:

1>源.obj : error LNK2019: 无法解析的外部符号 "public: __cdecl tensorflow::internal::LogMessage::LogMessage(char const *,int,int)" (??0LogMessage@internal@tensorflow@@QEAA@PEBDHH@Z),该符号在函数 main 中被引用
1>源.obj : error LNK2019: 无法解析的外部符号 "public: virtual __cdecl tensorflow::internal::LogMessage::~LogMessage(void)" (??1LogMessage@internal@tensorflow@@UEAA@XZ),该符号在函数 "public: void __cdecl tensorflow::internal::LogMessage::`vbase destructor'(void)" (??_DLogMessage@internal@tensorflow@@QEAAXXZ) 中被引用
...

截图长这样
在这里插入图片描述
这部分费了很多时间,各种找资料,各种查资料,各种编译,后来看到了我最终成功的博客给出来的方法,修改tensorflow\BUILD最后一个tf_cc_shared_object的内容

tf_cc_shared_object(
    name = "libtensorflow_cc.so",
    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 = [
		"//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.lds

*tensorflow*
*perftools*gputools*
*tf_*
*TF_*
*TFE_*
*nsync_*
*pywrap_xla*

修改tf_exported_symbols_msvc.lds:
将你报无法解析的外部命令这些都加到tf_exported_symbols_msvc.lds的后面,具体加的内容就是将该符号在函数前面那个括号的内容都加进去,我报了29个,我加了29次,要是有两个括号的就加前面那个括号里的内容,再进行编译,直到这些不报错为止!!

  1. 配环境,这部分我也费了好多时间,因为我看人家把文件整理了,我就不明白为什么要整理文件,为什么要搞来搞去,笼统那么多东西,在磁盘的哪里就直接给个路径不完事了嘛,我到处找那些文件,各种对比,头疼要死,最后我也试过不整理这些文件也能正常运行!
    VC++目录下包含目录里的内容:
    在这里插入图片描述
    VC++目录下库目录里的内容:
    在这里插入图片描述
    C/C++/常规/附加包含目录的内容:
    在这里插入图片描述
    链接器\输入\附加依赖项的内容:
    在这里插入图片描述
    环境配置好后,复制tensorflow_cc.dll 到与工程文件 .sln 同级的 x64\Release 文件夹下
    到这环境是配完了。
  2. 调用的时候还会发生max问题
    对这三个函数进行修改: logging.h, tensor_shape.h, string_view.h
    改前
if (TF_PREDICT_FALSE(v2 >= std::numeric_limits<int>::max())) {
    
          \

改后

if (TF_PREDICT_FALSE(v2 >= (std::numeric_limits<int>::max)())) {
    
          \

这三个文件都是这种方式修改!!
6. 还报了一个错

1>d:\vs2015\install\vc\include\xutility(2458): error C4996: 'std::copy_n::_Unchecked_iterators::_Deprecate': Call to 'std::copy_n' with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'

解决方法:
在stdafx.h中添加一宏定义

#define _SCL_SECURE_NO_WARNINGS

或者属性-> c/c++ -> 预处理器 -> 预处理器定义 里添加
_SCL_SECURE_NO_WARNINGS

  1. 测试代码:
    新建源文件, 叫TestTensorFlow.cpp
#include "TestTensorFlow.h"
#include "tensorflow/cc/client/client_session.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include "tensorflow/core/framework/tensor.h"

int main() {
    
    
	using namespace tensorflow;
	using namespace tensorflow::ops;
	Scope root = Scope::NewRootScope();
	// Matrix A = [3 2; -1 0]
	auto A = Const(root, {
    
     {
    
     3.f, 2.f },{
    
     -1.f, 0.f } });
	// Vector b = [3 5]
	auto b = Const(root, {
    
     {
    
     3.f, 5.f } });
	// v = Ab^T
	auto v = MatMul(root.WithOpName("v"), A, b, MatMul::TransposeB(true));
	std::vector<Tensor> outputs;
	ClientSession session(root);
	// Run and fetch v
	TF_CHECK_OK(session.Run({
    
     v }, &outputs));
	// Expect outputs[0] == [19; -3]
	LOG(INFO) << outputs[0].matrix<float>();
	return 0;
}

新建头文件,叫TestTensorFlow.h

#pragma once  //这一句防止重复include头文件

#define COMPILER_MSVC
#define NOMINMAX  //这一句防止max/min函数命名冲突

测试你的配置环境吧!!!
这是我的结果
在这里插入图片描述
至此,算是完事了。

中间出现的问题及解决的结果:
在这里插入图片描述

我刚开始编译的是debug版本,因为我需要调试程序,但是我始终报错,报错以上截图,当时以为环境配的不对或者编译的不对,就切换了release版本的,居然成功了,那就是我的debug版本有问题,就各种上网搜原因,Debug version is known to not work on Window…看到这个帖子我还不死心,又找了其他方法,看到这个人这样做的link然后报错

(290) : error C4716: “tensorflow::io::GetTempFilename”: 必须返回一个值

网上搜了很久,无解,就不想再弄这个了,我打算ubuntu上写好了拿windows跑下,这样就有dll文件了,不然就是直接找后台联调,配置环境到此收手了,不得不说一句我怎么这么菜!!

猜你喜欢

转载自blog.csdn.net/weixin_43868576/article/details/108491879
今日推荐