如何将TensorFlow Lite构建为静态库并从单独的(CMake)项目链接到它?

问题描述 投票:3回答:1

我已经成功构建了一个运行TF Lite模型的简单C ++应用程序,通过将我的源添加到tensorflow/lite/examples,类似于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目标,因为来自BUILDtensorflow/lite/examples/minimal文件将它们作为依赖项,当我在TF repo中使用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)命令,它会给我所有必要的包括dirs的路径,以及类似的命令,以便库链接反对,以便我可以将此信息传递给CMake?

c++ tensorflow cmake bazel tensorflow-lite
1个回答
3
投票

我最终手动为CMake的target_link_libraries(在TFLite_LIBS中)列出了所有必要的TFLite对象文件,并且它有效。

我使用一个简单的shell脚本来获取必要的目标文件列表。首先,我将构建日志中的所有未定义引用收集到bash-array中,如下所示:

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(当然,使用正确的路径前缀)。之后,我获得了一部分未定义的引用,但经过几次迭代后,它解决了所有问题。

可能我也可以从我最初的in-tree构建中获取*-params文件中的完整依赖列表,但是快速检查表明它有一些冗余项,脚本只收集了必要的内容。

对于包含位置,我用${TENSORFLOW_DIR}/bazel-tensorflow/external/flatbuffers/include/将该硬编码路径替换为bazel缓存中的flatbuffers。感谢jdehesa的提示。

更新: 全包TF Lite静态库的本机构建可以使用普通旧制作非常类似于RPiiOSARM64的官方构建说明: 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会做本机构建。这使得invokation可以作为CMakeLists.txt中的自定义命令添加。

© www.soinside.com 2019 - 2024. All rights reserved.