You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android项目CMAKE_TOOLCHAIN_FILE中正确设置CMAKE_SYSROOT?

问题

为Android项目编写CMAKE_TOOLCHAIN_FILE时遇到路径错误:

设置的CMAKE_SYSROOT:

set(CMAKE_SYSROOT "${ANDROID_TOOLCHAIN_ROOT}/sysroot")

该路径展开为${CMAKE_SOURCE_DIR}/external/cmdline-tools/latest/../.sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/sysroot,是实际存在的目录。

但执行CMake配置时出现错误:

-- CMAKE_SYSROOT /home/user/demo_project/external/cmdline-tools/latest/../.sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/sysroot
-- Android: Selected Clang toolchain 'aarch64-linux-android-clang' with GCC toolchain ''
-- The C compiler identification is Clang 14.0.7
-- The CXX compiler identification is Clang 14.0.7
-- Check for working C compiler: /home/user/demo_project/external/cmdline-tools/latest/../.sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
CMake Error at /usr/share/cmake-3.10/Modules/Platform/Android-Initialize.cmake:31 (message):
  Android: The system root directory needed for the selected Android version
  and architecture does not exist:

    /home/user/demo_project/CMakeFiles/CMakeTmp/external/cmdline-tools/latest/../.sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/sysroot

操作步骤:

~/demo_project$ mkdir build
~/demo_project$ cd build
~/demo_project$ cmake ../ -DCMAKE_TOOLCHAIN_FILE=../tool/buildtools/cmake_toolchain/android.cmake

注意到错误中的路径比STATUS输出多了CMakeFiles/CMakeTmp/前缀,导致路径无效。完整的CMAKE_TOOLCHAIN_FILE内容如下:

set(HOST_TAG "linux-x86_64")
set(ANDROID_API 31)
set(SDK "../.sdk")
set(ANDROID_CMD ${CMAKE_SOURCE_DIR}/external/cmdline-tools/latest) #for android_sdkmanager_install macro to work, set this
set(ANDROID_PACKAGES "")
set(NDK_PATH ${ANDROID_CMD}/${SDK}/ndk/25.2.9519653)
set(CMAKE_ANDROID_NDK ${NDK_PATH})
set(CMAKE_ANDROID_API ${ANDROID_API})
set(ANDROID_TARGET aarch64-linux-android${ANDROID_API})
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)

set(ANDROID_TARGET_TRIPLE "aarch64-linux-android")
set(ANDROID_TARGET_ARCH "armv8")
set(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")

set(CMAKE_SYSTEM_NAME Android)

SET(ANDROID_TOOLCHAIN_ROOT ${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64)
set(CMAKE_SYSROOT "${ANDROID_TOOLCHAIN_ROOT}/sysroot")
# Disable some features that are not available on Android
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

用于配置NDK的脚本:

SCRIPT_DIR="$( dirname -- "${BASH_SOURCE[0]}"; )"
SCRIPT_DIR=$(realpath $SCRIPT_DIR)

ANDROID_API=31

cd $SCRIPT_DIR/../external/cmdline-tools/latest/

echo Handle android licenses
yes | ./bin/sdkmanager --sdk_root=../.sdk --licenses

sdk_install() {
    PACKAGE_NAME=$1
    echo Handle package "$PACKAGE_NAME"
    ./bin/sdkmanager --sdk_root=../.sdk --install "$PACKAGE_NAME"

}

sdk_install "build-tools;34.0.0-rc4"
sdk_install "ndk;25.2.9519653"
sdk_install "platforms;android-$ANDROID_API"

PLATFORMS_DIR=$(realpath $SCRIPT_DIR/../external/cmdline-tools/.sdk/platforms)
ln -sf $PLATFORMS_DIR ../.sdk/ndk/25.2.9519653/platforms

原因分析

错误核心是相对路径在CMake测试编译阶段被错误解析:

  • 你设置的CMAKE_SYSROOT包含../相对路径,在项目根目录下解析正确。
  • 但CMake检测编译器可用性时,会切换到临时目录build/CMakeFiles/CMakeTmp执行测试编译,此时../会指向demo_project/CMakeFiles而非项目根目录,导致拼接后的路径多出CMakeFiles/CMakeTmp前缀,最终路径不存在。

解决方法

将所有路径转换为绝对路径,避免相对路径在不同工作目录下的解析错误,有两种实现方式:

方式1:基于toolchain文件位置构建绝对路径

修改CMAKE_TOOLCHAIN_FILE中路径相关配置,用CMAKE_CURRENT_LIST_DIR(当前toolchain文件的绝对路径)定位项目根目录,再构建其他绝对路径:

set(HOST_TAG "linux-x86_64")
set(ANDROID_API 31)

# 获取当前toolchain文件的绝对路径,假设该文件在 tool/buildtools/cmake_toolchain/ 下
set(TOOLCHAIN_ABS_DIR ${CMAKE_CURRENT_LIST_DIR})
# 向上三级目录到达项目根目录(根据实际目录结构调整层级)
set(PROJECT_ROOT_ABS ${TOOLCHAIN_ABS_DIR}/../../..)

# 用绝对路径定义所有路径变量
set(ANDROID_CMD ${PROJECT_ROOT_ABS}/external/cmdline-tools/latest)
set(SDK ${PROJECT_ROOT_ABS}/.sdk)
set(NDK_PATH ${SDK}/ndk/25.2.9519653)

set(CMAKE_ANDROID_NDK ${NDK_PATH})
set(CMAKE_ANDROID_API ${ANDROID_API})
set(ANDROID_TARGET aarch64-linux-android${ANDROID_API})
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)

set(ANDROID_TARGET_TRIPLE "aarch64-linux-android")
set(ANDROID_TARGET_ARCH "armv8")
set(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")

set(CMAKE_SYSTEM_NAME Android)

SET(ANDROID_TOOLCHAIN_ROOT ${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64)
set(CMAKE_SYSROOT "${ANDROID_TOOLCHAIN_ROOT}/sysroot")

# Disable some features that are not available on Android
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

方式2:用file(REAL_PATH)转换相对路径为绝对路径

如果不想调整目录层级,可以用CMake的file(REAL_PATH)命令将相对路径解析为绝对路径:

set(HOST_TAG "linux-x86_64")
set(ANDROID_API 31)
set(SDK "../.sdk")
set(ANDROID_CMD ${CMAKE_SOURCE_DIR}/external/cmdline-tools/latest)
set(ANDROID_PACKAGES "")

# 将相对路径转换为绝对路径
file(REAL_PATH "${ANDROID_CMD}/${SDK}/ndk/25.2.9519653" NDK_PATH)

set(CMAKE_ANDROID_NDK ${NDK_PATH})
set(CMAKE_ANDROID_API ${ANDROID_API})
set(ANDROID_TARGET aarch64-linux-android${ANDROID_API})
set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)

set(ANDROID_TARGET_TRIPLE "aarch64-linux-android")
set(ANDROID_TARGET_ARCH "armv8")
set(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")

set(CMAKE_SYSTEM_NAME Android)

SET(ANDROID_TOOLCHAIN_ROOT ${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64)
set(CMAKE_SYSROOT "${ANDROID_TOOLCHAIN_ROOT}/sysroot")

# Disable some features that are not available on Android
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

两种方式都能确保CMAKE_SYSROOT是绝对路径,无论CMake在哪个目录执行测试编译,都能正确定位到NDK的sysroot目录。


内容的提问来源于stack exchange,提问作者Silver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:14:57