我成功地构建了一个简单的C++应用程序,运行TF Lite模型,并将我的源代码添加到tensorflow/lite/examples
中,与官方的C++ 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目标,因为tensorflow/lite/examples/minimal
的BUILD
文件把它们作为依赖项,并且在我使用TF repo中的Bazel构建代码时它们对我有效。不确定这是否足够。
然后我手动收集包含目录(使用丑陋的临时硬编码路径)和库:
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吗?
bazel-genfiles/external
(构建后)收集 flatbuffers 标头而不是从~/.cache/...
。 - jdehesa.a
只包含其目标的.c
代码,而不包含依赖项。此外,我还没有找到任何跟踪头文件的好方法。我的解决方法是在TF树中添加一个代码文件和一个新目标(在新的子目录中),并将其依赖于我所需的内容。使用cc_library
,我不确定是否可以通过选项获取包含所有内容的.a
,使用cc_binary
,您至少可以在bazel-bin
下获得一个.params
文件,其中包含所有.a
依赖项,您可以扫描它,或者您可以制作一个.so
(我个人在Windows上制作DLL)。 - jdehesa.pb
模型文件并为给定的输入运行它),隐藏每个本地TF类型(主要是pimpl)。这需要一些技巧,但现在我只需要我的几个头文件和这个DLL。 - jdehesabazel-tensorflow/external
中找到了外部头文件。对于链接,我真的不想向TF树添加任何代码,而是将TF视为通常的依赖项,因此我最终将所有所需的目标文件添加到了上面的TFLite_LIBS
变量中,并且现在它可以工作了。我编写了一个脚本,遍历每个未定义的引用,并在bazel-bin
中查找定义它的目标文件,在几次迭代后,我收集了所需的一切。 - Andrii Zymohliad