blob: 9dd678d20329799d8120e04b4b32e8944cc2f259 [file] [log] [blame]
#
# 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()