diff --git a/android/libass/src/main/cpp/CMakeLists.txt b/android/libass/src/main/cpp/CMakeLists.txt index 261a5c45..d1017738 100644 --- a/android/libass/src/main/cpp/CMakeLists.txt +++ b/android/libass/src/main/cpp/CMakeLists.txt @@ -13,28 +13,39 @@ if(NOT DEFINED LIBASS_CACHE_DIR) set(LIBASS_CACHE_DIR "${CMAKE_BINARY_DIR}/libass-prebuilt") endif() set(LIBASS_ROOT "${LIBASS_CACHE_DIR}/libass-android-${LIBASS_VERSION}") +set(LIBASS_ARCHIVE "${LIBASS_ROOT}/lib/${ANDROID_ABI}/libass.a") +set(LIBASS_HEADER "${LIBASS_ROOT}/include/ass/ass.h") -if(NOT EXISTS "${LIBASS_ROOT}/lib/${ANDROID_ABI}/libass.a") - set(_libass_zip "${LIBASS_CACHE_DIR}/libass-android-${LIBASS_VERSION}.zip") - message(STATUS "Fetching fork libass ${LIBASS_VERSION} from ${LIBASS_ZIP_URL}") - file(DOWNLOAD "${LIBASS_ZIP_URL}" "${_libass_zip}" - EXPECTED_HASH "SHA256=${LIBASS_SHA256}" - TLS_VERIFY ON - STATUS _libass_dl) - list(GET _libass_dl 0 _libass_dl_code) - if(NOT _libass_dl_code EQUAL 0) - file(REMOVE "${_libass_zip}") - message(FATAL_ERROR "Failed to download libass: ${_libass_dl}") - endif() - file(ARCHIVE_EXTRACT INPUT "${_libass_zip}" DESTINATION "${LIBASS_CACHE_DIR}") -endif() +# The downloaded archive lives under Flutter's root build/ directory, which can +# be deleted without invalidating android/libass/.cxx. Model it as a Ninja output +# so stale CMake configure caches can regenerate it during the build step. +file(MAKE_DIRECTORY "${LIBASS_ROOT}/include") +add_custom_command( + OUTPUT "${LIBASS_ARCHIVE}" "${LIBASS_HEADER}" + COMMAND "${CMAKE_COMMAND}" + "-DLIBASS_VERSION=${LIBASS_VERSION}" + "-DLIBASS_SHA256=${LIBASS_SHA256}" + "-DLIBASS_ZIP_URL=${LIBASS_ZIP_URL}" + "-DLIBASS_CACHE_DIR=${LIBASS_CACHE_DIR}" + "-DLIBASS_ROOT=${LIBASS_ROOT}" + "-DLIBASS_ARCHIVE=${LIBASS_ARCHIVE}" + "-DLIBASS_HEADER=${LIBASS_HEADER}" + "-DANDROID_ABI=${ANDROID_ABI}" + -P "${CMAKE_CURRENT_LIST_DIR}/FetchLibass.cmake" + COMMENT "Preparing fork libass ${LIBASS_VERSION} for ${ANDROID_ABI}" + VERBATIM) + +string(REPLACE "-" "_" LIBASS_ABI_TARGET "${ANDROID_ABI}") +add_custom_target(libass_prebuilt_${LIBASS_ABI_TARGET} + DEPENDS "${LIBASS_ARCHIVE}" "${LIBASS_HEADER}") add_library(ass STATIC IMPORTED) set_target_properties(ass PROPERTIES - IMPORTED_LOCATION "${LIBASS_ROOT}/lib/${ANDROID_ABI}/libass.a") + IMPORTED_LOCATION "${LIBASS_ARCHIVE}") target_include_directories(ass INTERFACE "${LIBASS_ROOT}/include") add_library(${CMAKE_PROJECT_NAME} SHARED AssKt.c SurfaceTxProbe.c) +add_dependencies(${CMAKE_PROJECT_NAME} libass_prebuilt_${LIBASS_ABI_TARGET}) # HarfBuzz brings C++; link the shared STL that the app already packages. # (SurfaceTxProbe resolves its libandroid/libsync entry points via dlsym, so no extra link.) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE diff --git a/android/libass/src/main/cpp/FetchLibass.cmake b/android/libass/src/main/cpp/FetchLibass.cmake new file mode 100644 index 00000000..14757602 --- /dev/null +++ b/android/libass/src/main/cpp/FetchLibass.cmake @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.22.1) + +foreach(_var IN ITEMS + LIBASS_VERSION + LIBASS_SHA256 + LIBASS_ZIP_URL + LIBASS_CACHE_DIR + LIBASS_ROOT + LIBASS_ARCHIVE + LIBASS_HEADER + ANDROID_ABI) + if(NOT DEFINED ${_var} OR "${${_var}}" STREQUAL "") + message(FATAL_ERROR "${_var} is required") + endif() +endforeach() + +get_filename_component(_cache_parent "${LIBASS_CACHE_DIR}" DIRECTORY) +file(MAKE_DIRECTORY "${_cache_parent}") + +# Android Gradle can build ABI variants in parallel; serialize the shared cache. +file(LOCK "${LIBASS_CACHE_DIR}.lock" GUARD PROCESS TIMEOUT 300) + +if(NOT EXISTS "${LIBASS_ARCHIVE}" OR NOT EXISTS "${LIBASS_HEADER}") + file(MAKE_DIRECTORY "${LIBASS_CACHE_DIR}") + set(_libass_zip "${LIBASS_CACHE_DIR}/libass-android-${LIBASS_VERSION}.zip") + + message(STATUS "Fetching fork libass ${LIBASS_VERSION} from ${LIBASS_ZIP_URL}") + file(DOWNLOAD "${LIBASS_ZIP_URL}" "${_libass_zip}" + EXPECTED_HASH "SHA256=${LIBASS_SHA256}" + TLS_VERIFY ON + STATUS _libass_dl) + list(GET _libass_dl 0 _libass_dl_code) + if(NOT _libass_dl_code EQUAL 0) + file(REMOVE "${_libass_zip}") + message(FATAL_ERROR "Failed to download libass: ${_libass_dl}") + endif() + + file(REMOVE_RECURSE "${LIBASS_ROOT}") + file(ARCHIVE_EXTRACT INPUT "${_libass_zip}" DESTINATION "${LIBASS_CACHE_DIR}") +endif() + +if(NOT EXISTS "${LIBASS_ARCHIVE}") + message(FATAL_ERROR "libass archive for ${ANDROID_ABI} was not extracted: ${LIBASS_ARCHIVE}") +endif() +if(NOT EXISTS "${LIBASS_HEADER}") + message(FATAL_ERROR "libass headers were not extracted: ${LIBASS_HEADER}") +endif()