4.4.1.1. 编译tensorflow_cc.dll
bazel build --config=opt --define=no_tensorflow_py_deps=true --copt=-DTHRUST_IGNORE_CUB_VERSION_CHECK --copt=-nvcc_options=disable-warnings --local_ram_resources=10240 --local_cpu_resources=3 //tensorflow:tensorflow_cc.dll
4.4.1.2. 编译tensorflow_cc.lib
bazel build --config=opt --define=no_tensorflow_py_deps=true --copt=-DTHRUST_IGNORE_CUB_VERSION_CHECK --copt=-nvcc_options=disable-warnings --local_ram_resources=10240 --local_cpu_resources=3 //tensorflow:tensorflow_cc.lib
4.4.1.3. 编译include
bazel build --config=opt --define=no_tensorflow_py_deps=true --copt=-DTHRUST_IGNORE_CUB_VERSION_CHECK --copt=-nvcc_options=disable-warnings --local_ram_resources=10240 --local_cpu_resources=3 //tensorflow:install_headers4.4.2. debug编译
编译时,通过添加”-c dbg”来实现debug版的编译。编译过程中遇到问题较多,未能成功编译。
bazel build -c dbg --config=opt --define=no_tensorflow_py_deps=true --copt=-DTHRUST_IGNORE_CUB_VERSION_CHECK --copt=-nvcc_options=disable-warnings --local_ram_resources=10240 --local_cpu_resources=3 //tensorflow:tensorflow_cc.dll4.4.3.编译结果
编译结果位于bazel_bin中,bazel_bin实际是一个软链接,真实数据存储在C:Usersstone_bazel_stone7t3zwoz4execrootorg_tensorflow
将编译结果整理到Tensorflow的安装目录下:4.4.4. 【坑】C++开发时报缺少外部符号错误的解决办法
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::Subtract::Subtract(class tensorflow::Scope const &,class tensorflow::Input,class tensorflow::Input)" (??0Subtract@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::Squeeze::Squeeze(class tensorflow::Scope const &,class tensorflow::Input)" (??0Squeeze@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::DecodeGif::DecodeGif(class tensorflow::Scope const &,class tensorflow::Input)" (??0DecodeGif@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::TopK::TopK(class tensorflow::Scope const &,class tensorflow::Input,class tensorflow::Input)" (??0TopK@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::ExpandDims::ExpandDims(class tensorflow::Scope const &,class tensorflow::Input,class tensorflow::Input)" (??0ExpandDims@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::ResizeBilinear::ResizeBilinear(class tensorflow::Scope const &,class tensorflow::Input,class tensorflow::Input)" (??0ResizeBilinear@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "class tensorflow::Output __cdecl tensorflow::ops::Const(class tensorflow::Scope const &,struct tensorflow::Input::Initializer const &)" (?Const@ops@tensorflow@@YA?AVOutput@2@AEBVScope@2@AEBUInitializer@Input@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::DecodePng::DecodePng(class tensorflow::Scope const &,class tensorflow::Input,struct tensorflow::ops::DecodePng::Attrs const &)" (??0DecodePng@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::Placeholder::Placeholder(class tensorflow::Scope const &,enum tensorflow::DataType)" (??0Placeholder@ops@tensorflow@@QEAA@AEBVScope@2@W4DataType@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::Cast::Cast(class tensorflow::Scope const &,class tensorflow::Input,enum tensorflow::DataType)" (??0Cast@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@W4DataType@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::DecodeJpeg::DecodeJpeg(class tensorflow::Scope const &,class tensorflow::Input,struct tensorflow::ops::DecodeJpeg::Attrs const &)" (??0DecodeJpeg@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::DecodeBmp::DecodeBmp(class tensorflow::Scope const &,class tensorflow::Input)" (??0DecodeBmp@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::Div::Div(class tensorflow::Scope const &,class tensorflow::Input,class tensorflow::Input)" (??0Div@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::Operation::Operation(class tensorflow::Node *)" (??0Operation@tensorflow@@QEAA@PEAVNode@1@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "private: class tensorflow::Scope __cdecl tensorflow::Scope::WithOpNameImpl(class std::basic_string
1>main.obj : error LNK2001: 无法解析的外部符号 "public: class tensorflow::Status __cdecl tensorflow::Scope::ToGraphDef(class tensorflow::GraphDef *)const " (?ToGraphDef@Scope@tensorflow@@QEBA?AVStatus@2@PEAVGraphDef@2@@Z)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: static class tensorflow::Scope __cdecl tensorflow::Scope::NewRootScope(void)" (?NewRootScope@Scope@tensorflow@@SA?AV12@XZ)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::Scope::~Scope(void)" (??1Scope@tensorflow@@QEAA@XZ)
1>main.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::Input::Initializer::Initializer(class std::initializer_list
1>main.obj : error LNK2001: 无法解析的外部符号 "class tensorflow::Status __cdecl tensorflow::NewSession(struct tensorflow::SessionOptions const &,class tensorflow::Session * *)" (?NewSession@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@PEAPEAVSession@1@@Z)
1>ModelLoader.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ops::ReadFile::ReadFile(class tensorflow::Scope const &,class tensorflow::Input)" (??0ReadFile@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z)
1>ModelLoader.obj : error LNK2001: 无法解析的外部符号 "public: class tensorflow::Status __cdecl tensorflow::ClientSession::Run(class std::vector
1>ModelLoader.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ClientSession::~ClientSession(void)" (??1ClientSession@tensorflow@@QEAA@XZ)
1>ModelLoader.obj : error LNK2001: 无法解析的外部符号 "public: __cdecl tensorflow::ClientSession::ClientSession(class tensorflow::Scope const &)" (??0ClientSession@tensorflow@@QEAA@AEBVScope@1@@Z)
整理后主要是下面这些符号:
??0Cast@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@W4DataType@2@@Z
?Const@ops@tensorflow@@YA?AVOutput@2@AEBVScope@2@AEBUInitializer@Input@2@@Z
??1ClientSession@tensorflow@@QEAA@XZ
??0ClientSession@tensorflow@@QEAA@AEBVScope@1@@Z
??0DecodeGif@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z
??0DecodePng@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Z
??0DecodeJpeg@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Z
??0DecodeBmp@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z
??0Div@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z
??0ExpandDims@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z
??0Initializer@Input@tensorflow@@QEAA@AEBV?$initializer_list@UInitializer@Input@tensorflow@@@std@@@Z
?NewRootScope@Scope@tensorflow@@SA?AV12@XZ
?NewSession@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@PEAPEAVSession@1@@Z
??0Operation@tensorflow@@QEAA@PEAVNode@1@@Z
??0ResizeBilinear@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z
??0ReadFile@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z
?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
??1Scope@tensorflow@@QEAA@XZ
??0Subtract@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z
??0Squeeze@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Z
??0TopK@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Z
??0Placeholder@ops@tensorflow@@QEAA@AEBVScope@2@W4DataType@2@@Z
?ToGraphDef@Scope@tensorflow@@QEBA?AVStatus@2@PEAVGraphDef@2@@Z
?WithOpNameImpl@Scope@tensorflow@@AEBA?AV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
4.4.4.1. 【不推荐】方式一:声明TF_EXPORT
在相关类声明的头文件添加TF_EXPORT后,重新编译dll、lib和include。增加TF_EXPORT时需要视情添加头文件引用#include "tensorflow/core/platform/macros.h。
主要需修改的头文件有:
tensorflow/cc/client/client_session.h
tensorflow/cc/framework/scope.h
tensorflow/core/public/session.h
tensorflow/core/public/session_options.h
tensorflow/cc/framework/ops.h
bazel-bin/tensorflow/cc/ops/ image_ops.h
bazel-bin/tensorflow/cc/ops/io_ops.h
bazel-bin/tensorflow/cc/ops/array_ops.h
bazel-bin/tensorflow/core/framework/graph.pb.h
bazel-bin/tensorflow/core/protobuf/meta_graph.pb.h
bazel-bin/tensorflow/core/protobuf/config.pb.h
bazel-bin/tensorflow/cc/ops/nn_ops.h
这种方式,修改的地方太多了,不推荐。
4.4.4.1. 方式二:修改def_file_filter.py.tpl文件
通过在tensorflowtoolsdef_file_filterdef_file_filter.py.tpl文件中增加符号后,重新编译dll、lib和include。
特别注意格式,每行前面不能用TAB键,只能用4个空格,行尾不能有空格。
def_fp.write("t ??0SessionOptions@tensorflow@@QEAA@XZn")
def_fp.write("t ?NewSession@tensorflow@@YAPEAVSession@1@AEBUSessionOptions@1@@Zn")
def_fp.write("t ??1SavedModelBundleInterface@tensorflow@@UEAA@XZn")
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@@Zn")
def_fp.write("t ?MaybeSavedModelDirectory@tensorflow@@YA_NAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Zn")
def_fp.write("t ?_TensorShapeProto_default_instance_@tensorflow@@3VTensorShapeProtoDefaultTypeInternal@1@An")
def_fp.write("t ??0Cast@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@W4DataType@2@@Zn")
def_fp.write("t ?Const@ops@tensorflow@@YA?AVOutput@2@AEBVScope@2@AEBUInitializer@Input@2@@Zn")
def_fp.write("t ??1ClientSession@tensorflow@@QEAA@XZn")
def_fp.write("t ??0ClientSession@tensorflow@@QEAA@AEBVScope@1@@Zn")
def_fp.write("t ??0DecodeGif@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Zn")
def_fp.write("t ??0DecodePng@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Zn")
def_fp.write("t ??0DecodeJpeg@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@AEBUAttrs@012@@Zn")
def_fp.write("t ??0DecodeBmp@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Zn")
def_fp.write("t ??0Div@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Zn")
def_fp.write("t ??0ExpandDims@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Zn")
def_fp.write("t ??0Initializer@Input@tensorflow@@QEAA@AEBV?$initializer_list@UInitializer@Input@tensorflow@@@std@@@Zn")
def_fp.write("t ?NewRootScope@Scope@tensorflow@@SA?AV12@XZn")
def_fp.write("t ?NewSession@tensorflow@@YA?AVStatus@1@AEBUSessionOptions@1@PEAPEAVSession@1@@Zn")
def_fp.write("t ??0Operation@tensorflow@@QEAA@PEAVNode@1@@Zn")
def_fp.write("t ??0ResizeBilinear@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Zn")
def_fp.write("t ??0ReadFile@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Zn")
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@@Zn")
def_fp.write("t ??1Scope@tensorflow@@QEAA@XZn")
def_fp.write("t ??0Subtract@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Zn")
def_fp.write("t ??0Squeeze@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@@Zn")
def_fp.write("t ??0TopK@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1@Zn")
def_fp.write("t ??0Placeholder@ops@tensorflow@@QEAA@AEBVScope@2@W4DataType@2@@Zn")
def_fp.write("t ?ToGraphDef@Scope@tensorflow@@QEBA?AVStatus@2@PEAVGraphDef@2@@Zn")
def_fp.write("t ?WithOpNameImpl@Scope@tensorflow@@AEBA?AV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Zn")
4.4.4.3. 【推荐】方式三:修改tensorflow_filtered_def_file文件
在tensorflow_filtered_def_file.def文件中添加外部符号,然后利用link.exe重新生成dll、lib。
为了便于后续开发过程中遇到其他未知外部符号的解决,可以将tensorflow编译过程中生成的各个依赖lib文件收集在一处,然后修改tensorflow_cc.dll-2.params文件中每个lib的路径,最后使用link.exe重新生成dll和lib。
tensorflow_filtered_def_file.def需要增加的外部符号如下图:
tensorflow_cc.dll-2.params修改前后如下所示:
link.exe执行过程:
(1)以管理员权限启动VS命令行工具
(2)在命令行下定位到tensorflow_cc.dll-2.params和tensorflow_filtered_def_file.def所在目录。
(3)执行命令:link.exe @tensorflow_cc.dll-2.params4.4.5.MFC测试TensorFlow
4.4.5.1. 新建MFC项目
新建MFC对话框程序,并添加按钮“TensorFlow测试”。
4.4.5.2. 为MFC程序开启命令行窗口
为了便于调试分析,为MFC程序开启命令行窗口。
在应用程序App类实现文件中添加下面的代码:
//增加下面这行代码,控制台输出信息会更多
#pragma comment( linker, "/subsystem:console /entry:wWinMainCRTStartup" )
#include
#include
void InitConsole()
{
::AllocConsole();
FILE* fp;
freopen_s(&fp, "CONOUT$", "w+t", stdout);
}
在应用程序App类的初始化函数InitInstance中调用InitConsole函数初始化控制台资源。
在应用程序App类的退出函数ExitInstance中调用FreeConsole函数释放控制台资源。
4.4.5.3. 配置项目Release属性—头文件和库文件目录
由于我们编译的只有Release版的TensorFlow,因此在VS中只需要配置项目Release的属性即可。
加入tensorflow的include和lib目录。
为了使用方便,将编译好的tensorflow的安装目录配置为系统环境变量$(THIRDPARTY_HOME)。
4.4.5.4. 配置项目Release属性—加入预定义宏NOMINMAX
配置项目Release属性,在C/C++预处理器定义中加入NOMINMAX。
在MFC中调用TensorFlow时,会报错,主要是因为tensorflow调用的min,max函数是std命名空间下的,而MFC使用的min,max是Windows SDK提供的(头文件minwindef.h),这会导致下面的错误。
解决办法:在工程项目的预处理器中定义:NOMINMAX,这样MFC中就不会调用minwindef.h中的min,max宏。
4.4.5.5. 配置项目pch.h文件—为Gdiplus指定min,max
在pch.h的头文件中,在#include “framework.h”之前为gdiplus指定使用的min,max函数。
#include
namespace Gdiplus
{
using std::min;
using std::max;
}
注意:在项目属性配置时加入预定义宏NOMINMAX,会导致gdiplustypes.h中找不到min,max的错误出现:
查看minwindef.h文件中有明确的定义:只有在没有定义NOMINMAX宏的情况下,才会有min,max宏定义。
解决办法:在MFC所有头文件引用之前,为Gdiplus命名空间指定使用std::min和std::max函数。
4.4.5.6. 配置项目pch.h文件—引入tensorflow头文件和库文件
在pch.h的头文件中,在#include “framework.h”之后加入引入tensorflow的头文件和库文件的代码。
#pragma warning (disable: 4995)
#include
#include
#pragma comment(lib,"tensorflow_cc.lib")
4.4.5.7. 编写测试代码
在对话框类中添加testtf函数。
void CTFTestDlg::testtf()
{
tensorflow::Session* session;
tensorflow::Status status = tensorflow::NewSession(tensorflow::SessionOptions(), &session);
if (!status.ok()) {
std::cout << status.ToString() << std::endl;
return;
}
std::cout << "Session successfully created.n";
}
在对话框类的按钮“TensorFlow测试”BN_CLICK消息响应函数中调用testtf()。
4.4.5.8. 编译程序的Release版
注意要选择Release项进行编译。
4.4.5.9. 执行测试程序
运行程序界面如下。
点击“Tensorflow测试”按钮后,命令行窗口出现“Session successfully created.”,测试通过。
后记:
整个编译测试过程还是挺艰辛曲折的。如果有需要编译好的动态库和python安装包,可以私信我。
本人第一次发博客,想请教一个问题:如何将word内容直接发布到CSDN?按照网上教程,添加URL: http://write.blog.csdn.net/xmlrpc/index 后,输入用户名和密码点击“确定”,提示无法注册账户。已确认用户名和密码是正确的。有谁知道,烦请告知,谢谢!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)