Linking against libtensorflow-lite built outside of cmake project?

Hi all -

I have a CMakeLists.txt that links an application library (call it libfoo.a) against libtensorflow-lite.a
The thing is I don’t know how it finds all the TFLite dependent libs and puts them in the demo app’s linker command. Here’s the cmake file:

# CMakeLists for spoof detection demo
# Source:

# Build TensorFlow Lite with CMake: https://www.tensorflow.org/lite/guide/build_cmake

project(foo_demo)

cmake_minimum_required(VERSION 3.16)

find_package(OpenCV REQUIRED)
find_package(ZLIB REQUIRED)

option(DEMO "build the demo" ON)
option(TFLITE_ENABLE_GPU "enable gpu"  ON)

set(fdt_base_dir   ${PROJECT_SOURCE_DIR})
set(fdt_src_dir    ${fdt_base_dir}/cvml-lib/src)
set(fdt_inc_dir    ${fdt_base_dir}/cvml-lib/inc)
set(tiny_npy_dir   ${PROJECT_SOURCE_DIR}/third-party/TinyNPY)

set(TENSORFLOW_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/../third-party/tensorflow_src")
set(TFLITE_SOURCE_DIR "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite")

#CM - Point of uncertainty #1 - looks like we're building TFLite along with the application?
add_subdirectory(
  ${TFLITE_SOURCE_DIR}  
  "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite"
  EXCLUDE_FROM_ALL
)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")

include_directories(
  ${fdt_inc_dir}
  ${TENSORFLOW_SOURCE_DIR}
  ${OpenCV_INCLUDE_DIRS}
  ${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include
  ${tiny_npy_dir}
)

# Create library with all other files except npy_spoof_demo and tif_spoof_demo
file(GLOB fdt_lib_source_files ${fdt_src_dir}/*.cpp ${tiny_npy_dir}/*.cpp)
add_library(fdt_lib STATIC ${fdt_lib_source_files})

#CM - I don't understand this line!  There's a lot going on under the hood here!
#Without the 'PRIVATE' clause, this fails...why?
target_link_libraries(fdt_lib PRIVATE tensorflow-lite)

# Create npy input demo. OpenCV is required.
if (DEMO)
  set(foo_files ${fdt_base_dir}/example/myfooapp.cpp)
  add_executable(myfooapp ${foo_files})

#CM - somehow this command links against libfdt_lib.a, AND the TF-Lite lib deps.  How?
  target_link_libraries(myfooapp PRIVATE fdt_lib ${OpenCV_LIBRARIES} ZLIB::ZLIB boost_filesystem boost_system)
endif()

So, if I keep that target_link_libraries(fdt_lib PRIVATE tensorflow-lite), I get this linker command:
It includes a large number of libs that follow libtensorflow-lite (libabsl*, libruy*, etc)

[100%] Linking CXX executable tif_spoof_demo

/usr/bin/cmake -E cmake_link_script CMakeFiles/tif_spoof_demo.dir/link.txt --verbose=1

/usr/bin/c++  -march=native -O3  -flto CMakeFiles/tif_spoof_demo.dir/example/tif_spoof_detect.cpp.o -o tif_spoof_demo  -Wl,-rpath,/usr/local/lib libfdt_lib.a /usr/local/lib/libopencv_gapi.so.4.6.0 /usr/local/lib/libopencv_highgui.so.4.6.0 /usr/local/lib/libopencv_ml.so.4.6.0 /usr/local/lib/libopencv_objdetect.so.4.6.0 /usr/local/lib/libopencv_photo.so.4.6.0 /usr/local/lib/libopencv_stitching.so.4.6.0 /usr/local/lib/libopencv_video.so.4.6.0 /usr/local/lib/libopencv_videoio.so.4.6.0 /usr/lib/x86_64-linux-gnu/libz.so -lboost_filesystem -lboost_system **tensorflow-lite/libtensorflow-lite.a _deps/abseil-cpp-build/absl/flags/libabsl_flags.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_internal.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_marshalling.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_reflection.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_config.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_program_name.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_private_handle_accessor.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_commandlineflag.a _deps/abseil-cpp-build/absl/flags/libabsl_flags_commandlineflag_internal.a _deps/abseil-cpp-build/absl/status/libabsl_status.a _deps/abseil-cpp-build/absl/strings/libabsl_str_format_internal.a _deps/abseil-cpp-build/absl/base/libabsl_strerror.a _deps/farmhash-build/libfarmhash.a _deps/fft2d-build/libfft2d_fftsg2d.a _deps/fft2d-build/libfft2d_fftsg.a -lm _deps/flatbuffers-build/libflatbuffers.a _deps/ruy-build/ruy/libruy_context_get_ctx.a _deps/ruy-build/ruy/libruy_context.a _deps/ruy-build/ruy/libruy_frontend.a _deps/ruy-build/ruy/libruy_kernel_arm.a _deps/ruy-build/ruy/libruy_kernel_avx.a _deps/ruy-build/ruy/libruy_kernel_avx2_fma.a _deps/ruy-build/ruy/libruy_kernel_avx512.a _deps/ruy-build/ruy/libruy_apply_multiplier.a _deps/ruy-build/ruy/libruy_pack_arm.a _deps/ruy-build/ruy/libruy_pack_avx.a _deps/ruy-build/ruy/libruy_pack_avx2_fma.a _deps/ruy-build/ruy/libruy_pack_avx512.a _deps/ruy-build/ruy/libruy_prepare_packed_matrices.a _deps/ruy-build/ruy/libruy_trmul.a _deps/ruy-build/ruy/libruy_ctx.a _deps/ruy-build/ruy/libruy_allocator.a _deps/ruy-build/ruy/libruy_prepacked_cache.a _deps/ruy-build/ruy/libruy_system_aligned_alloc.a _deps/ruy-build/ruy/libruy_have_built_path_for_avx.a _deps/ruy-build/ruy/libruy_have_built_path_for_avx2_fma.a _deps/ruy-build/ruy/libruy_have_built_path_for_avx512.a _deps/ruy-build/ruy/libruy_thread_pool.a _deps/ruy-build/ruy/libruy_blocking_counter.a _deps/ruy-build/ruy/libruy_wait.a _deps/ruy-build/ruy/libruy_denormal.a _deps/ruy-build/ruy/libruy_block_map.a _deps/ruy-build/ruy/libruy_tune.a _deps/ruy-build/ruy/libruy_cpuinfo.a _deps/ruy-build/ruy/profiler/libruy_profiler_instrumentation.a -pthread -ldl _deps/abseil-cpp-build/absl/types/libabsl_bad_any_cast_impl.a _deps/abseil-cpp-build/absl/hash/libabsl_hash.a _deps/abseil-cpp-build/absl/types/libabsl_bad_variant_access.a _deps/abseil-cpp-build/absl/hash/libabsl_city.a _deps/abseil-cpp-build/absl/hash/libabsl_low_level_hash.a _deps/abseil-cpp-build/absl/strings/libabsl_cord.a _deps/abseil-cpp-build/absl/strings/libabsl_cordz_info.a _deps/abseil-cpp-build/absl/strings/libabsl_cord_internal.a _deps/abseil-cpp-build/absl/strings/libabsl_cordz_functions.a _deps/abseil-cpp-build/absl/strings/libabsl_cordz_handle.a _deps/abseil-cpp-build/absl/container/libabsl_raw_hash_set.a _deps/abseil-cpp-build/absl/types/libabsl_bad_optional_access.a _deps/abseil-cpp-build/absl/container/libabsl_hashtablez_sampler.a _deps/abseil-cpp-build/absl/profiling/libabsl_exponential_biased.a _deps/abseil-cpp-build/absl/synchronization/libabsl_synchronization.a _deps/abseil-cpp-build/absl/debugging/libabsl_stacktrace.a _deps/abseil-cpp-build/absl/debugging/libabsl_symbolize.a _deps/abseil-cpp-build/absl/debugging/libabsl_debugging_internal.a _deps/abseil-cpp-build/absl/debugging/libabsl_demangle_internal.a _deps/abseil-cpp-build/absl/synchronization/libabsl_graphcycles_internal.a _deps/abseil-cpp-build/absl/base/libabsl_malloc_internal.a _deps/abseil-cpp-build/absl/time/libabsl_time.a _deps/abseil-cpp-build/absl/strings/libabsl_strings.a _deps/abseil-cpp-build/absl/strings/libabsl_strings_internal.a _deps/abseil-cpp-build/absl/base/libabsl_throw_delegate.a _deps/abseil-cpp-build/absl/numeric/libabsl_int128.a _deps/abseil-cpp-build/absl/time/libabsl_civil_time.a _deps/abseil-cpp-build/absl/time/libabsl_time_zone.a _deps/abseil-cpp-build/absl/base/libabsl_base.a _deps/abseil-cpp-build/absl/base/libabsl_raw_logging_internal.a _deps/abseil-cpp-build/absl/base/libabsl_log_severity.a _deps/abseil-cpp-build/absl/base/libabsl_spinlock_wait.a -lrt _deps/xnnpack-build/libXNNPACK.a -lm _deps/cpuinfo-build/libcpuinfo.a _deps/cpuinfo-build/deps/clog/libclog.a pthreadpool/libpthreadpool.a** /usr/local/lib/libopencv_imgcodecs.so.4.6.0 /usr/local/lib/libopencv_dnn.so.4.6.0 /usr/local/lib/libopencv_calib3d.so.4.6.0 /usr/local/lib/libopencv_features2d.so.4.6.0 /usr/local/lib/libopencv_flann.so.4.6.0 /usr/local/lib/libopencv_imgproc.so.4.6.0 /usr/local/lib/libopencv_core.so.4.6.0 

If I take the ‘PRIVATE’ clause away, I lose these libraries, and I get undefined refs errors everywhere

Basically, is there a way to integrate libtensorflow-lite, if it’s pre-built outside of my app cmake project? I do not want to rebuild TF-Lite as part of building my TF-Lite app.

Thanks, Charles

I guess I’ll provide a simpler example. I’m taking this snippet directly from the current documentation

cmake_minimum_required(VERSION 3.16)
project(minimal C CXX)

#So, this tells cmake where to find the TF source...ok...but it's in the cache path?
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()

#CM questions:
#Q1 - We're setting up a Make target called ./tensorflow-lite?
#Q2 - what's EXCLUDE_FROM_ALL?
add_subdirectory(
  "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite"
  "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL)

add_executable(minimal minimal.cc)
target_link_libraries(minimal tensorflow-lite)

So it seems to me that this ‘minimal’ app will always require TF-lite to build, so it can properly link.

Is there a similar way to do the above by using a PRE-BUILT tensorflow-lite?
Or, do I have to figure out which dependent libs to use? Some additional documentation would be nice!

Thanks, Charles.