如何在 CMake 中正确使用 Tensorflow Lite?

Posted

技术标签:

【中文标题】如何在 CMake 中正确使用 Tensorflow Lite?【英文标题】:How to properly use Tensorflow Lite with CMake? 【发布时间】:2021-12-31 12:55:07 【问题描述】:

我的目标是在一个相当复杂的 CMake C++ 项目中使用 TF Lite,该项目已经有各种其他第三方库(dlib、opencv、...)。

我尝试在 Windows 10 上使用 cmake+ninja+msvc 制作它,但我也尝试在 Ubuntu 20.04 cmake+ninja+gcc 上制作它,但遇到了同样的问题。

TF版本为:2.6.0

我尝试了两种方法:

    按原样编译和链接,并按照TF first steps 中的说明使用:
cmake ../tensorflow_src/tensorflow/lite -DCMAKE_BUILD_TYPE=Debug
cmake --build . -j

...

cmake_minimum_required(VERSION 3.16)
project(minimal C CXX)

set(TENSORFLOW_SOURCE_DIR "" CACHE PATH
  "Directory that contains the TensorFlow project" )
if(NOT TENSORFLOW_SOURCE_DIR)
  get_filename_component(TENSORFLOW_SOURCE_DIR
    "$CMAKE_CURRENT_LIST_DIR/../../../../" ABSOLUTE)
endif()

add_subdirectory(
  "$TENSORFLOW_SOURCE_DIR/tensorflow/lite"
  "$CMAKE_CURRENT_BINARY_DIR/tensorflow-lite" EXCLUDE_FROM_ALL)

它编译得很好,我可以安装等,但是当我像这样将它插入到已经存在的 CMakeList.txt 中时:

target_link_libraries(myproject ... tensorflow-lite)
...
install(
    TARGETS 
    ...
    tensorflow-lite
    ...)

它要求 TFLite 的所有目标(absl-...等)超过 80 个。我尝试将它们全部添加(我知道这不好,但想确保它是否有效),然后它在源目录中向所有这些错误抛出前缀:

Severity    Code    Description Project File    Line    Suppression State
Error       CMake Error in tensorflow/tensorflow/lite/tools/cmake/modules/ruy/CMakeLists.txt:
  Target "ruy" INTERFACE_INCLUDE_DIRECTORIES property contains path:

    "C:/work/project/out/build/x64-Debug/ruy"

  which is prefixed in the build directory.Target "ruy"
  INTERFACE_INCLUDE_DIRECTORIES property contains path:

    "C:/work/project/out/build/x64-Debug/ruy"

  which is prefixed in the source directory.        

所以我被困在这一边,但后来我尝试:

    将其构建为共享库并像这样使用它

为此我打开了-DBUILD_SHARED_LIBS,设置了最大路径长度以避免与此相关的问题,开始构建然后:

[302/970] Linking C shared library _deps\fft2d-build\fft2d_fftsg2d-debug.dll
FAILED: _deps/fft2d-build/fft2d_fftsg2d-debug.dll _deps/fft2d-build/fft2d_fftsg2d-debug.lib
cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_dll --intdir=_deps\fft2d-build\CMakeFiles\fft2d_fftsg2d.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100203~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100203~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~1\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo _deps\fft2d-build\CMakeFiles\fft2d_fftsg2d.dir\__\__\fft2d\fftsg2d.c.obj  /out:_deps\fft2d-build\fft2d_fftsg2d-debug.dll /implib:_deps\fft2d-build\fft2d_fftsg2d-debug.lib /pdb:_deps\fft2d-build\fft2d_fftsg2d-debug.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL  _deps\fft2d-build\fft2d_fftsg-debug.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib  && cd ."
LINK Pass 1: command "C:\PROGRA~2\MICROS~1\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo _deps\fft2d-build\CMakeFiles\fft2d_fftsg2d.dir\__\__\fft2d\fftsg2d.c.obj /out:_deps\fft2d-build\fft2d_fftsg2d-debug.dll /implib:_deps\fft2d-build\fft2d_fftsg2d-debug.lib /pdb:_deps\fft2d-build\fft2d_fftsg2d-debug.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL _deps\fft2d-build\fft2d_fftsg-debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:_deps\fft2d-build\CMakeFiles\fft2d_fftsg2d.dir/intermediate.manifest _deps\fft2d-build\CMakeFiles\fft2d_fftsg2d.dir/manifest.res" failed (exit code 1104) with the following output:
LINK : fatal error LNK1104: cannot open file '_deps\fft2d-build\fft2d_fftsg-debug.lib'
[315/970] Building CXX object CMakeFiles\tensorflow-lite.dir\kernels\gru_cell.cc.obj
ninja: build stopped: subcommand failed.

当然,因为这是一个共享版本,所以该文件夹包含一个 fft2d_fftsg-debug.dll 所以对我来说,似乎 fft2d 也是共享构建的,当 TF Lite 构建尝试链接时,它会失败。

所以这也不起作用,我很困惑,我知道 Bazel 更常用于 TF,但由于 TF 网站本身说这是可能的,而且我的项目也在 CMake 中,我真的很想完成这项工作。

我可能认为有可能迈出下一步(如果有一些kickstart,我将不胜感激):

    以某种方式自动添加所有目标和正确的包含库。 如果 TF Lite 构建为共享库,它如何找到 fft2d 的一些见解。 (也许缺少一些开关?)

【问题讨论】:

根据 [line]((github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/…)) target_include_directories(tensorflow-lite PUBLIC $TFLITE_INCLUDE_DIRS),不打算安装目标 tensorflow-lite。适合安装的库通常在其包含目录中包含BUILD_INTERFACEINSTALL_INTERFACE 【参考方案1】:

我设法让它工作。这不是最好的,但它有效。 因此,由于 TFLite 没有构建接口,因此无法像评论中指出的那样安装它,但可以将其作为子目录(带有包含)添加到需要安装的项目中,而无需 tensorflowlite 目标,如果它是有针对性的在***程序(不再需要安装)。

【讨论】:

以上是关于如何在 CMake 中正确使用 Tensorflow Lite?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将库与 cmake 链接?

如何在 cmake 中正确链接库?

如何在 CMake 中正确创建目标之间的依赖关系?

CMake项目结构:如何正确地将库合并在一起并将它们包含在多个可执行文件中

如何在Tensorflow中使用自定义/非默认tf.Graph正确的方法?

如何使用 cmake 正确链接库?