|  | # | 
|  | # Copyright (c) 2021, Alliance for Open Media. All rights reserved | 
|  | # | 
|  | # This source code is subject to the terms of the BSD 3-Clause Clear License and | 
|  | # the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear | 
|  | # License was not distributed with this source code in the LICENSE file, you can | 
|  | # obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the Alliance | 
|  | # for Open Media Patent License 1.0 was not distributed with this source code in | 
|  | # the PATENTS file, you can obtain it at aomedia.org/license/patent-license/. | 
|  | # | 
|  | if(AOM_BUILD_CMAKE_TENSORFLOW_LITE_CMAKE_) | 
|  | return() | 
|  | endif() # AOM_BUILD_CMAKE_TENSORFLOW_LITE_CMAKE_ | 
|  | set(AOM_BUILD_CMAKE_TENSORFLOW_LITE_CMAKE_ 1) | 
|  |  | 
|  | include(ExternalProject) | 
|  | include(FindGit) | 
|  |  | 
|  | # Checks if Tensorflow has been checked out -- if not, uses the git submodule | 
|  | # command to fetch it. | 
|  | function(checkout_submodule_) | 
|  | # As a quick sanity check, see if at least 1 expected file or directory is | 
|  | # present in each submodule. If so, assume they are all checked out (if they | 
|  | # are not, then the base directory will be empty). | 
|  | if(EXISTS "${AOM_ROOT}/third_party/tensorflow/tensorflow") | 
|  | return() | 
|  | endif() | 
|  | if(NOT GIT_FOUND) | 
|  | message( | 
|  | FATAL_ERROR | 
|  | "Tensorflow-Lite not present; " "git could not be found; " | 
|  | "please check out submodules with 'git submodule update --init'") | 
|  | endif() | 
|  | # Note that "git submodule update --init" must be run from inside the git | 
|  | # repository; the --git-dir flag does not work. | 
|  | message("Checking out Tensorflow-Lite submodule") | 
|  | execute_process( | 
|  | COMMAND "${GIT_EXECUTABLE}" submodule update --init | 
|  | WORKING_DIRECTORY "${AOM_ROOT}" | 
|  | OUTPUT_VARIABLE submodule_out | 
|  | ERROR_VARIABLE submodule_err | 
|  | RESULT_VARIABLE submodule_result) | 
|  | if(NOT ${submodule_result} EQUAL 0) | 
|  | message( | 
|  | FATAL_ERROR | 
|  | "Unable to run 'git submodule update --init': " | 
|  | "Return code: " | 
|  | ${submodule_result} | 
|  | ", STDOUT: " | 
|  | ${submodule_out} | 
|  | ", STDERR: " | 
|  | ${submodule_err}) | 
|  | endif() | 
|  | endfunction() | 
|  |  | 
|  | # Add the TF-lite link-related library to the named target (e.g., an executable | 
|  | # or library). This function handles the different naming conventions of | 
|  | # operating systems. | 
|  | function(target_link_tf_lite_dep_ named_target subdir libname) | 
|  | if(NOT (("${subdir}" STREQUAL "") OR ("${subdir}" MATCHES "/$"))) | 
|  | message( | 
|  | FATAL_ERROR "sub-directory must be empty or end with a slash: ${subdir}") | 
|  | endif() | 
|  |  | 
|  | set(STATIC_LIBRARY_DIR "") | 
|  | if(MSVC) | 
|  | set(STATIC_LIBRARY_DIR "$<CONFIG>/") | 
|  | endif() | 
|  | target_link_libraries( | 
|  | ${named_target} | 
|  | PRIVATE | 
|  | "${CMAKE_BINARY_DIR}/tensorflow_lite/${subdir}${STATIC_LIBRARY_DIR}${CMAKE_STATIC_LIBRARY_PREFIX}${libname}${CMAKE_STATIC_LIBRARY_SUFFIX}" | 
|  | ) | 
|  | endfunction() | 
|  |  | 
|  | # Add TF-lite libraries onto the named target at link time (e.g., an executable | 
|  | # or library). For enabling TF-lite for experiments, prefer the | 
|  | # "experiment_requires_tf_lite" function. | 
|  | function(target_link_tf_lite_libraries named_target) | 
|  | target_link_libraries(${named_target} ${AOM_LIB_LINK_TYPE} Threads::Threads) | 
|  | target_link_libraries(${named_target} PRIVATE fake_dl) | 
|  | target_link_tf_lite_dep_(${named_target} "" tensorflow-lite) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/flags/ | 
|  | absl_flags) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/flags/ | 
|  | absl_flags_internal) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/flags/ | 
|  | absl_flags_config) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/flags/ | 
|  | absl_flags_program_name) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/flags/ | 
|  | absl_flags_marshalling) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/hash/ | 
|  | absl_hash) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/hash/ | 
|  | absl_city) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/status/ | 
|  | absl_status) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/types/ | 
|  | absl_bad_optional_access) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/strings/ | 
|  | absl_cord) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/strings/ | 
|  | absl_str_format_internal) | 
|  | target_link_tf_lite_dep_( | 
|  | ${named_target} _deps/abseil-cpp-build/absl/synchronization/ | 
|  | absl_synchronization) | 
|  | target_link_tf_lite_dep_( | 
|  | ${named_target} _deps/abseil-cpp-build/absl/debugging/ absl_stacktrace) | 
|  | target_link_tf_lite_dep_( | 
|  | ${named_target} _deps/abseil-cpp-build/absl/debugging/ absl_symbolize) | 
|  | target_link_tf_lite_dep_( | 
|  | ${named_target} _deps/abseil-cpp-build/absl/debugging/ | 
|  | absl_debugging_internal) | 
|  | target_link_tf_lite_dep_( | 
|  | ${named_target} _deps/abseil-cpp-build/absl/debugging/ | 
|  | absl_demangle_internal) | 
|  | target_link_tf_lite_dep_( | 
|  | ${named_target} _deps/abseil-cpp-build/absl/synchronization/ | 
|  | absl_graphcycles_internal) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/base/ | 
|  | absl_malloc_internal) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/time/ | 
|  | absl_time) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/strings/ | 
|  | absl_strings) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/strings/ | 
|  | absl_strings_internal) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/base/ | 
|  | absl_throw_delegate) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/base/ | 
|  | absl_base) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/base/ | 
|  | absl_spinlock_wait) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/numeric/ | 
|  | absl_int128) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/time/ | 
|  | absl_civil_time) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/time/ | 
|  | absl_time_zone) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/types/ | 
|  | absl_bad_variant_access) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/base/ | 
|  | absl_raw_logging_internal) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/abseil-cpp-build/absl/base/ | 
|  | absl_log_severity) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/farmhash-build/ farmhash) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/fft2d-build/ fft2d_fftsg2d) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/fft2d-build/ fft2d_fftsg) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/flatbuffers-build/ flatbuffers) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/xnnpack-build/ XNNPACK) | 
|  | target_link_tf_lite_dep_(${named_target} _deps/ruy-build/ ruy) | 
|  | target_link_tf_lite_dep_(${named_target} cpuinfo/ cpuinfo) | 
|  | target_link_tf_lite_dep_(${named_target} clog/ clog) | 
|  | target_link_tf_lite_dep_(${named_target} pthreadpool/ pthreadpool) | 
|  | endfunction() | 
|  |  | 
|  | # Can Tensorflow-Lite be enabled with the current build system? Sets the | 
|  | # variable with either 0 or 1 as the value. If 0, also prints an explanatory | 
|  | # message. | 
|  | function(is_tflite_supported result) | 
|  | # Cross-compile is not currently implemented. | 
|  | if(CMAKE_TOOLCHAIN_FILE) | 
|  | message("TOOLCHAIN: ${CMAKE_TOOLCHAIN_FILE}") | 
|  | message(WARNING "No cross-compile support for TensorFlow Lite; disabling") | 
|  | set(${result} | 
|  | 0 | 
|  | PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  | # TF-Lite specifies a minimum CMake version of 3.16, but Jenkins uses 3.7.2. | 
|  | # Until Jenkins is upgraded, disable TF-Lite if a lower version of CMake is | 
|  | # detected. | 
|  | if(${CMAKE_VERSION} VERSION_LESS "3.16") | 
|  | message( | 
|  | WARNING "Tensorflow Lite requres CMake version 3.16 or higher; version " | 
|  | "${CMAKE_VERSION} detected; disabling") | 
|  | set(${result} | 
|  | 0 | 
|  | PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  | set(${result} | 
|  | 1 | 
|  | PARENT_SCOPE) | 
|  | endfunction() | 
|  |  | 
|  | # Adds appropriate build rules / targets. Only invoke this function if | 
|  | # is_tf_lite_supported returns true. | 
|  | function(setup_tensorflow_lite) | 
|  | if("${AOM_ROOT}" STREQUAL "") | 
|  | message(FATAL_ERROR "AOM_ROOT variable must not be empty.") | 
|  | endif() | 
|  |  | 
|  | if(MSVC) | 
|  | add_compile_definitions(NOMINMAX=1) | 
|  | endif() | 
|  | checkout_submodule_() | 
|  |  | 
|  | # Allow code to reference TF. | 
|  | include_directories("${AOM_ROOT}/third_party/tensorflow") | 
|  |  | 
|  | externalproject_add( | 
|  | tensorflow_lite | 
|  | SOURCE_DIR "${AOM_ROOT}/third_party/tensorflow/tensorflow/lite" | 
|  | PREFIX "${CMAKE_BINARY_DIR}/tensorflow_lite" | 
|  | BINARY_DIR "${CMAKE_BINARY_DIR}/tensorflow_lite" | 
|  | DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/tensorflow_lite" | 
|  | CMAKE_ARGS "-DCMAKE_BUILD_TYPE=Release" | 
|  | LOG_BUILD 1) | 
|  |  | 
|  | # TF-Lite uses dlsym and dlopen for delegation, but linking with -ldl is not | 
|  | # supported in static builds. Use a dummy implementation (callers must not use | 
|  | # delegation). | 
|  | add_library(fake_dl OBJECT "${AOM_ROOT}/common/fake_dl.h" | 
|  | "${AOM_ROOT}/common/fake_dl.cc") | 
|  |  | 
|  | # TF-Lite depends on this, and downloads it during compilation. | 
|  | include_directories( | 
|  | "${CMAKE_CURRENT_BINARY_DIR}/tensorflow_lite/flatbuffers/include/") | 
|  |  | 
|  | add_dependencies(aom_av1_common tensorflow_lite fake_dl) | 
|  | foreach(aom_app ${AOM_APP_TARGETS}) | 
|  | add_dependencies(${aom_app} tensorflow_lite fake_dl) | 
|  | target_link_tf_lite_libraries(${aom_app}) | 
|  | endforeach() | 
|  | endfunction() | 
|  |  | 
|  | # Signal that the experiment needs TF-lite enabled. | 
|  | function(experiment_requires_tf_lite experiment_name) | 
|  | # Experiment is not enabled, no need to include TF-Lite in the build. | 
|  | if(NOT ${${experiment_name}}) | 
|  | return() | 
|  | endif() | 
|  | set(supported 0) | 
|  | is_tflite_supported(supported) | 
|  | if(NOT ${supported}) | 
|  | # Disable the experiment so Gerrit will not test this case. | 
|  | message(WARNING "Disabling ${experiment_name}.") | 
|  | set(${experiment_name} | 
|  | 0 | 
|  | PARENT_SCOPE) | 
|  | set(CONFIG_TENSORFLOW_LITE | 
|  | 0 | 
|  | PARENT_SCOPE) | 
|  | return() | 
|  | endif() | 
|  | # Otherwise, enable TF-lite. | 
|  | set(CONFIG_TENSORFLOW_LITE | 
|  | 1 | 
|  | PARENT_SCOPE) | 
|  | endfunction() |