通过将我的源代码添加到tensorflow/lite/examples
中,我已经成功构建了一个运行TF Lite模型的简单C ++应用程序,类似于the official C++ TF guide提出的完整TF的建议。现在,我想将其构建为一个单独的项目(共享库),以静态方式链接到TF Lite,并使用CMake作为构建系统。
我尝试向CMakeLists.txt
添加自定义目标,该目标将使用Bazel构建TF Lite:
set(TENSORFLOW_DIR ${CMAKE_SOURCE_DIR}/thirdparty/tensorflow)
add_custom_target(TFLite
COMMAND bazel build //tensorflow/lite:framework
COMMAND bazel build //tensorflow/lite/kernels:builtin_ops
WORKING_DIRECTORY ${TENSORFLOW_DIR})
我之所以选择这些Bazel目标,是因为BUILD
中的tensorflow/lite/examples/minimal
文件将它们作为依赖项,并且在我构建时它们对我有用
我在TF回购中使用Bazel编写的代码。不确定是否足够。
然后我手动收集包括dirs(具有丑陋的临时硬编码路径)和libs:
set(TFLite_INCLUDES
${TENSORFLOW_DIR}
~/.cache/bazel/_bazel_azymohliad/ec8567b83922796adb8477fcbb00a36a/external/flatbuffers/include)
set(TFLite_LIBS
${TENSORFLOW_DIR}/bazel-bin/tensorflow/lite/libframework.pic.a)
target_include_directories(MyLib ... PRIVATE ... ${TFLite_INCLUDES})
target_link_libraries(MyLib ... ${TFLite_LIBS})
通过这种配置,我在链接期间获得了许多对TFLite东西的未定义引用。我用nm
进行了检查,发现libframework.pic.a
中确实缺少这些符号,我在Bazel输出的各种.o
文件中找到了其中一些符号。手动选择所有这些.o
文件似乎是错误的。
那么,是否有可能像我想的那样从CMake很好地链接到TF Lite?也许有一些神奇的bazel query include_dirs(//tensorflow/lite:framework)
命令可以为我提供所有必要的包含目录的路径,以及一个类似的库链接命令,以便我可以将此信息传递给CMake?
答案 0 :(得分:2)
我最终手动为CMake的target_link_libraries
(在TFLite_LIBS
中列出了所有必需的TFLite对象文件,并且可以正常工作。
我使用了一个简单的shell脚本来获取必要的目标文件列表。 首先,我将构建日志中所有未定义的引用收集到bash数组中,如下所示:
SYMBOLS=(\
'tflite::CombineHashes('\
'tflite::IsFlexOp('\
'tflite::ConvertArrayToTfLiteIntArray('\
'tflite::EqualArrayAndTfLiteIntArray('\
...
'tflite::ConvertVectorToTfLiteIntArray(')
然后针对该数组中的每个符号,遍历bazel构建输出中的每个*.o
文件:
for SYMBOL in $SYMBOLS[@]; do
for OBJ in $(find -L /path/to/tensorflow/bazel-bin/ -name '*.o'); do
nm -C $OBJ | grep "T $SYMBOL" > /dev/null && echo $OBJ
done
done | sort | uniq
,然后将输出添加到CMake的TFLite_LIBS
中(当然,路径前缀正确)。之后,我得到了未定义引用的新部分,但经过几次迭代,它解决了所有问题。
也许我也可以从我最初的树内构建的*-params
文件中获取依赖项的完整列表,但是快速检查表明它有一些冗余项,并且脚本仅收集了必要的项。 / p>
对于包含位置,我用${TENSORFLOW_DIR}/bazel-tensorflow/external/flatbuffers/include/
替换了bazel缓存中平面编码的硬编码路径。感谢jdehesa的提示。
更新:
包含全包TF Lite静态库的本机构建可以使用普通的旧make来非常类似于RPi,iOS或ARM64的官方构建说明:
1. ./tensorflow/lite/tools/make/download_dependencies.sh
2. make -f tensorflow/lite/tools/make/Makefile
输出库将存储为<tensorflow-root>/tensorflow/lite/tools/make/gen/<platform>/lib/libtensorflow-lite.a
。外部相关性及其标头将进入<tensorflow-root>/tensorflow/tensorflow/lite/tools/make/downloads
(例如flatbuffers
标头位于<tensorflow-root>/tensorflow/tensorflow/lite/tools/make/downloads/flatbuffers/include
中)。
指南没有提到可以直接调用make。有用于不同交叉编译目标的包装器脚本,它们仅设置适当的变量并运行make。但是默认情况下,make只会执行本机构建。可以在CMakeLists.txt
中将此定制发票添加为自定义命令。