Как собрать TensorFlow Lite как статическую библиотеку и связать ее с отдельным (CMake) проектом? - PullRequest
3 голосов
/ 12 марта 2019

Я успешно создал простое приложение C ++, работающее на модели TF Lite , добавив мои источники в tensorflow/lite/examples, аналогично тому, что официальное руководство по C ++ TF предлагает для полной TF.Теперь я хочу собрать его в виде отдельного проекта (совместно используемой библиотеки), статически связанного с TF Lite и использующего CMake в качестве системы сборки.

Я попытался добавить пользовательскую цель в CMakeLists.txt, которая создаст TFLite с Bazel:

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 имеет их как зависимости, и они работают для меня, когда я создаю свой код с Bazel в репозитории TF.Не уверен, что этого достаточно.

Затем я вручную собираю include 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, я нашел некоторые из них в различных .o файлах в выводе Bazel.Выбор всех этих .o файлов вручную кажется неправильным.

Итак, можно ли красиво соединиться с TF Lite из CMake, как я пытаюсь?Может быть, есть какая-то волшебная команда bazel query include_dirs(//tensorflow/lite:framework), которая дала бы мне пути ко всем необходимым каталогам include и аналогичной команде для библиотек, с которыми можно связываться, чтобы я мог передать эту информацию в CMake?

1 Ответ

3 голосов
/ 13 марта 2019

Я закончил перечислять все необходимые объектные файлы TFLite вручную для CMake target_link_librariesTFLite_LIBS), и это работает.

Я использовал простой скрипт оболочки, чтобы получить список необходимых объектных файлов.Сначала я собрал все неопределенные ссылки из журнала сборки в массив bash следующим образом:

SYMBOLS=(\
    'tflite::CombineHashes('\
    'tflite::IsFlexOp('\
    'tflite::ConvertArrayToTfLiteIntArray('\
    'tflite::EqualArrayAndTfLiteIntArray('\
    ...
    'tflite::ConvertVectorToTfLiteIntArray(')

Затем для каждого символа в этом массиве я просмотрел каждый файл *.o в выводе сборки bazel:

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

и добавил вывод к TFLite_LIBS в CMake (с правильным префиксом пути, конечно).После этого я получил новую порцию неопределенных ссылок, но после нескольких итераций все решилось.

Возможно, я мог бы также получить полный список зависимостей из файла *-params из моей первоначальной сборки в дереве, но быстрая проверка показала, что в нем были некоторые избыточные элементы, и сценарий собрал только необходимые.

Для местоположений включений я заменил этот жестко закодированный путь к планшетам в кэше базелей на ${TENSORFLOW_DIR}/bazel-tensorflow/external/flatbuffers/include/.Спасибо jdehesa за подсказку.

ОБНОВЛЕНИЕ :
Собственная сборка статической библиотеки TF Lite с полным набором функций может быть очень похожа на официальные инструкции по сборке для 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 будет просто делать нативную сборку.Этот вызов make можно добавить как пользовательскую команду в CMakeLists.txt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...