前言
本文介绍了构建支持iOS的tensorflow静态库。
从Pod中引入tensorflow库
tensorflow对 python 和 Android 的支持较好,但是在 iOS 项目中使用比较麻烦。
cocoapods 中在 TensorFlow-experimental 提供了一个tensorflow_experimental.framework,当前版本为1.1.1。
TensorFlow-experimental在 cocoapods 中的最新release时间为May, 2017(2018-03-20查看)。
通过 Pod 可以快速引入 tensorflow 库。
1 | $ pod 'TensorFlow-experimental' |
从source中build支持iOS的tensorflow库
但是在最新的版本(version 1.1.1)中,有一个bug导致如下错误:
1 | Could not create TensorFlow Graph: Not found: Op type not registered 'DecodeWav'. |
原因是由于在 tensorflow/tensorflow/blob/master/tensorflow/contrib/makefile/tf_op_files.txt 中缺少了 tensorflow/core/ops/audio_ops.cc。
bug详细可见here。
这个 bug 在 2018-02 被修复,所以在当前最新的 tensorflow_experimental.framework 依然存在。
所以需要手动从 tensorflow 源码中编译静态库。
tensorflow 文档中提到:
if you are building for iOS, you currently need to use the Makefile.
Before you start
- 从 Github 中 clone
tensorflow.
1 | $ git clone https://github.com/tensorflow/tensorflow.git |
- 下载所有的编译依赖,官方提供了脚本,只需要运行就行。
1 | $ cd tensorflow |
脚本运行结束后,所有的依赖库会被下载到 tensorflow/contrib/makefile/downloads/ 文件夹下面。
Building on Mac
- 需要Xcode 7.3及之上的版本,安装
command-line tools
1 | $ xcode-select --install |
如果是第一安装command-line tools,需要先运行一次 XCode 并同意license。
安装Homebrew,具体方法在
Homebrew官网中,这里不详细描述。安装
automake和libtool
1 | $ brew install automake |
- 下载
tensorflow_inception_graph
这个对于编译静态库不是必须的,tensorflow_inception_graph用来测试。
1 | $ mkdir -p ~/graphs |
快速编译
所有准备做好后就可以编译了,执行以下命令:
1 | $ tensorflow/contrib/makefile/build_all_ios.sh |
这个时间可能需要较久的时间,编译完成后会生成一个包括 iOS 平台所有架构的静态库(i386sim, x86_64sim, armv7, armv7s and arm64)。
当然,如果需要某一个架构的库,比如只需要arm64架构的静态库,可以执行以下代码。
1 | $ tensorflow/contrib/makefile/build_all_ios.sh -a arm64 |
如果之前已经编辑过所有架构的静态库,那么就没有必要重新编译,只需要添加-T来修改已有的文件,这只需要话费几秒时间生成新的静态库。
1 | $ tensorflow/contrib/makefile/build_all_ios.sh -a arm64 -T |
编译结束后,在 tensorflow/contrib/makefile/gen/lib/ 中生成一个静态库 libtensorflow-core.a。
创建自己的App
配置Xcode是一个坑,花了一天的时间才爬过这个坑,配置出错会一直link失败。
Xcdoe 项目里面需要设置非常多的配置,按照以下步骤一步一步来。
添加库
静态库有4个:
tensorflow/contrib/makefile/gen/lib/libtensorflow-core.atensorflow/contrib/makefile/gen/protobuf_ios/lib/libprotobuf.atensorflow/contrib/makefile/gen/protobuf_ios/lib/libprotobuf-lite.atensorflow/contrib/makefile/downloads/nsync/builds/lipo.ios.c++11/nsync.a
系统动态库有1个:
Accelerate.framework
库需要通过 TARGET -> Linked Frameworks and Libraries 添加。
添加 Library Search Paths
在 PROJECT -> Build Settings -> Search Paths -> Library Search Paths 中添加静态库的路径。
1 | tensorflow/contrib/makefile/gen/lib |
Tips:
要注意必须是相对路径,可以直接用拖文件夹的方式加入。
添加头文件路径
在 PROJECT -> Build Settings -> Search Paths -> Header Search Paths 中添加头文件路径。
1 | the root folder of tensorflow, |
Other Linker Flags
在 PROJECT -> Build Settings -> Linking -> Other Linker Flags 中对 TensorFlow 静态库添加 -force_load 标识,如下:
1 | -force_load |
使用 -force_load 可以指定要载入的库,避免因为使用 -all_load 导致的链接错误。
同时,需要移除所有的 -all_load,如果是为了避免 Objective-C 静态库中 categories 的问题,可以使用 -ObjC。
C++支持
在 PROJECT -> Build Settings -> C++ Language Dialect 中选择 GNU++11 或 GNU++14 。
在 PROJECT -> Build Settings -> C++ Standard Library 中选择 libc++ 。
Bitcode
tensorflow 库不支持 bitcode ,所以要把 PROJECT -> Build Settings -> Build Options -> Enable Bitcode 设置为 NO 。