| # |
| # 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_registry) |
| 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_dynamic_annotations) |
| 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() |