Skip to content

cmake: Enable cross-compilation for non-Android ARM64 targets #6115

@devathul

Description

@devathul

SUMMARY:
LiteRT's CMake build system currently only supports native builds and Android
cross-compilation. When cross-compiling for non-Android targets (e.g.,
Linux on aarch64), the build fails in several places due to
Android-specific assumptions, missing guards, and CMake version requirements.

Offering 6 fixes to enable generic cross-compilation via CMake.

PATCH 1: Generic cross-compile toolchain forwarding
File: litert/CMakeLists.txt

PROBLEM:
The TFLite auto-build uses execute_process(cmake ...) which creates an isolated
CMake subprocess. The toolchain forwarding is gated by:
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
This means non-Android cross-compilation does not forward the toolchain file, causing TFLite to build for the host instead of the
target architecture.

WHY IT'S NEEDED:
Any non-Android cross-compilation scenario is broken. The TFLite subprocess builds x86 libraries while LiteRT expects aarch64, causing link failures.

FIX:
Change the Android-specific check to generic CMAKE_CROSSCOMPILING. Forward CMAKE_TOOLCHAIN_FILE and custom toolchain variables so the TFLite subprocess
inherits the correct cross-compilation settings.

BEFORE: if(CMAKE_SYSTEM_NAME STREQUAL "Android")
AFTER: if(CMAKE_CROSSCOMPILING)
+ forward CMAKE_TOOLCHAIN_FILE and custom vars

PATCH 2: Remove LINK_GROUP:RESCAN generator expression
File: litert/CMakeLists.txt (~line 392)

PROBLEM:
The tensorflow-lite IMPORTED target uses:
INTERFACE_LINK_LIBRARIES "$<LINK_GROUP:RESCAN,...>"
LINK_GROUP is a CMake 3.24+ feature. Many cross-compilation toolchains ship
CMake 3.20-3.22 which do not support this generator expression, causing a
configure-time error.

WHY IT'S NEEDED:
LiteRT already specifies cmake_minimum_required(VERSION 3.20) but uses a 3.24+
feature. This is an upstream compatibility bug.
FIX:
Replace the LINK_GROUP:RESCAN expression with a flat library list. The rescan
behavior is already handled by the c/CMakeLists.txt shared library target which
uses -Wl,--whole-archive.

BEFORE: INTERFACE_LINK_LIBRARIES "$<LINK_GROUP:RESCAN,...>"
AFTER: INTERFACE_LINK_LIBRARIES ""

PATCH 3: Guard add_subdirectory(vendors) with LITERT_SKIP_VENDORS
File: litert/CMakeLists.txt (~line 417)

PROBLEM:
add_subdirectory(vendors) is unconditional. The vendors/ directory downloads
third-party SDKs during configure. When building for a platform that uses none of these vendors, the
downloads fail or add unnecessary dependencies.

WHY IT'S NEEDED:
Custom NPU integrations (e.g., via dispatch plugins) don't use the built-in vendor delegates. There is no way to skip vendor downloads without this guard.

FIX:
Add a new option LITERT_SKIP_VENDORS (default OFF) and wrap add_subdirectory:

if(NOT LITERT_SKIP_VENDORS)
add_subdirectory(vendors)
endif()

PATCH 4: Fix constexpr on Layout constructor
File: litert/cc/litert_layout.h (~line 103)

PROBLEM:
The Layout constructor is declared constexpr:
constexpr explicit Layout(const Dimensions& d, const Strides& s)
It calls strides.empty() where Strides = absl::InlinedVector. In the bundled Abseil version, InlinedVector::empty() is NOT constexpr, making this a hard compilation error with GCC 12.x:
error: call to non-constexpr function 'bool InlinedVector::empty() const'

WHY IT'S NEEDED:
GCC enforces constexpr correctness more strictly than Clang. This affects any
GCC-based cross-compilation toolchain. The -fpermissive flag does not help

FIX:
Remove constexpr from the two-argument Layout constructor. The default and
single-argument constructors remain constexpr (they don't call non-constexpr
functions).

NOTE: This may already be fixed in LiteRT v2.1.2+

PATCH 5: Respect pre-set FLATC_EXECUTABLE and generic cross-compile
File: litert/core/model/CMakeLists.txt (~line 64)

PROBLEM:
The upstream code unconditionally wipes FLATC_EXECUTABLE:
set(FLATC_EXECUTABLE "")
Then only searches for a host flatc when CMAKE_SYSTEM_NAME is "Android".
This has two issues:

  1. Parent CMake cannot pre-set FLATC_EXECUTABLE (it gets wiped)
  2. Non-Android cross-compilation gets a target-arch flatc

WHY IT'S NEEDED:
When cross-compiling for Linux, a host-built flatc must be used to generate FlatBuffers headers. Without this fix, the build either uses a
target-arch flatc (which can't execute on the build host) or falls back to
FetchContent which builds flatc for the target).

FIX:

  1. Guard the wipe: if(NOT FLATC_EXECUTABLE) set(FLATC_EXECUTABLE "") endif()
  2. Change Android check to generic: if(CMAKE_CROSSCOMPILING)

BEFORE: set(FLATC_EXECUTABLE "")
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
AFTER: if(NOT FLATC_EXECUTABLE)
set(FLATC_EXECUTABLE "")
endif()
if(CMAKE_CROSSCOMPILING)

PATCH 6: Guard OpenCL sources with LITERT_HAS_OPENCL_SUPPORT
File: litert/runtime/CMakeLists.txt (~line 64)

PROBLEM:
OpenCL sources (open_cl_memory.cc, open_cl_sync.cc) are added unconditionally:
target_sources(litert_runtime PRIVATE open_cl_memory.cc open_cl_sync.cc)
These files #include <CL/cl.h> which requires OpenCL headers. On platforms
without GPU/OpenCL support, these headers don't exist, causing compilation failure.

WHY IT'S NEEDED: targets without GPU support have no OpenCL headers installed.
The build fails with: fatal error: CL/cl.h: No such file or directory.
LITERT_ENABLE_GPU=OFF should be sufficient to skip GPU-related compilation.

FIX:
Wrap with an existing-style guard:
if(LITERT_HAS_OPENCL_SUPPORT)
target_sources(litert_runtime PRIVATE open_cl_memory.cc open_cl_sync.cc)
endif()
Also wrap the opencl_headers include directory with the same guard.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions