cmake交叉编译:寻找工具
Cmake cross compiling: finding tools
我正在使用由 android ndk13b 制作的独立工具链。它工作正常,但要找到所有工具(链接器、存档器等),我的工具链文件中有一个非常冗长的部分。 有没有办法让它更紧凑?
SET(COMPILER_PATH "<path_to_my_llvm_directory>")
SET(CMAKE_TOOLCHAIN_PREFIX aarch64-linux-android-) #In theory should allow to find minor tools like ar and objdump, see
find_program(CMAKE_C_COMPILER clang.cmd PATH ${COMPILER_PATH})
find_program(CMAKE_CXX_COMPILER clang++.cmd PATH ${COMPILER_PATH})
find_program(CMAKE_AR ${CMAKE_TOOLCHAIN_PREFIX}ar.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_RANLIB ${CMAKE_TOOLCHAIN_PREFIX}ranlib.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_LINKER ${CMAKE_TOOLCHAIN_PREFIX}ld.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_NM ${CMAKE_TOOLCHAIN_PREFIX}nm.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_OBJCOPY ${CMAKE_TOOLCHAIN_PREFIX}objcopy.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_OBJDUMP ${CMAKE_TOOLCHAIN_PREFIX}objdump.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_STRIP ${CMAKE_TOOLCHAIN_PREFIX}strip.exe PATHS ${COMPILER_PATH})
什么不起作用:
- 没有明确使用
find_program
-> 它从我路径中的其他一些 mingw 工具链中找到了一些其他工具
- 正在将
CMAKE_FIND_ROOT_PATH
设置为 ${COMPILER_PATH}
。那时它甚至找不到编译器。我可以通过将编译器设置为 SET(CMAKE_C_COMPILER ${COMPILER_PATH}/clang.cmd)
来解决这个问题(对于 clang++ 也是如此),但它仍然找不到其他工具
- 尝试使用
find_program
的各种标志,尤其是 ONLY_CMAKE_FIND_ROOT_PATH
请注意,我发现 find_program
是找到这些工具的唯一解决方法,因为例如以下内容将不起作用:
SET(CMAKE_AR ${COMPILER_PATH}/${CMAKE_TOOLCHAIN_PREFIX}ar.exe
(归档操作会失败,我从cmake-gui中可以看到变量没有设置)。
好消息是 Android NDK 支持在最新的 CMake 3.7 版本中变得更加容易。参见 Kitware Increases Android Support in CMake 3.7 and Cross Compiling for Android。
编辑: 我已经成功 运行 使用 CMake 3.7 进行测试(例如,在我的 Windows PC 上安装 ADK 到 root):
toolchain.cmake
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSROOT "C:/android-ndk-r13b/platforms/android-24/arch-arm64")
并使用例如Ninja
makefile 生成器:
> cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake -G "Ninja" ..
-- Android: Targeting API '24' with architecture 'arm64', ABI 'arm64-v8a', and processor 'aarch64'
-- Android: Selected GCC toolchain 'aarch64-linux-android-4.9'
-- The C compiler identification is GNU 4.9.0
-- The CXX compiler identification is GNU 4.9.0
通用的简化工具链
我在使用最少的工具链文件方面取得了一些很好的经验,并且通常 - 如果您想专门指定工具路径 - 使用工具链文件中的缓存变量。
请参阅 CMake 文档中的 this minimal example,在您的情况下,它会转化为类似以下内容:
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER <path_to_my_llvm_directory>/clang.cmd)
set(CMAKE_C_COMPILER_TARGET aarch64-linux-android)
set(CMAKE_CXX_COMPILER <path_to_my_llvm_directory>/clang++.cmd)
set(CMAKE_CXX_COMPILER_TARGET aarch64-linux-android)
请注意,指定 CMAKE_SYSTEM_NAME
对启用交叉编译至关重要。
为什么指定 CMAKE_AR
不起作用
关于您的 CMAKE_AR
问题,请注意 CMake 本身确实使用 find_program()
来查找 ar.exe
。由于 find_program()
确实会缓存其结果,因此您还必须预填充 CMAKE_AR
作为缓存变量(请参阅 0013038: cannot set CMAKE_AR when cross-compiling Fortran-only project)。
我正在使用由 android ndk13b 制作的独立工具链。它工作正常,但要找到所有工具(链接器、存档器等),我的工具链文件中有一个非常冗长的部分。 有没有办法让它更紧凑?
SET(COMPILER_PATH "<path_to_my_llvm_directory>")
SET(CMAKE_TOOLCHAIN_PREFIX aarch64-linux-android-) #In theory should allow to find minor tools like ar and objdump, see
find_program(CMAKE_C_COMPILER clang.cmd PATH ${COMPILER_PATH})
find_program(CMAKE_CXX_COMPILER clang++.cmd PATH ${COMPILER_PATH})
find_program(CMAKE_AR ${CMAKE_TOOLCHAIN_PREFIX}ar.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_RANLIB ${CMAKE_TOOLCHAIN_PREFIX}ranlib.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_LINKER ${CMAKE_TOOLCHAIN_PREFIX}ld.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_NM ${CMAKE_TOOLCHAIN_PREFIX}nm.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_OBJCOPY ${CMAKE_TOOLCHAIN_PREFIX}objcopy.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_OBJDUMP ${CMAKE_TOOLCHAIN_PREFIX}objdump.exe PATHS ${COMPILER_PATH})
find_program(CMAKE_STRIP ${CMAKE_TOOLCHAIN_PREFIX}strip.exe PATHS ${COMPILER_PATH})
什么不起作用:
- 没有明确使用
find_program
-> 它从我路径中的其他一些 mingw 工具链中找到了一些其他工具 - 正在将
CMAKE_FIND_ROOT_PATH
设置为${COMPILER_PATH}
。那时它甚至找不到编译器。我可以通过将编译器设置为SET(CMAKE_C_COMPILER ${COMPILER_PATH}/clang.cmd)
来解决这个问题(对于 clang++ 也是如此),但它仍然找不到其他工具 - 尝试使用
find_program
的各种标志,尤其是ONLY_CMAKE_FIND_ROOT_PATH
请注意,我发现 find_program
是找到这些工具的唯一解决方法,因为例如以下内容将不起作用:
SET(CMAKE_AR ${COMPILER_PATH}/${CMAKE_TOOLCHAIN_PREFIX}ar.exe
(归档操作会失败,我从cmake-gui中可以看到变量没有设置)。
好消息是 Android NDK 支持在最新的 CMake 3.7 版本中变得更加容易。参见 Kitware Increases Android Support in CMake 3.7 and Cross Compiling for Android。
编辑: 我已经成功 运行 使用 CMake 3.7 进行测试(例如,在我的 Windows PC 上安装 ADK 到 root):
toolchain.cmake
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSROOT "C:/android-ndk-r13b/platforms/android-24/arch-arm64")
并使用例如Ninja
makefile 生成器:
> cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake -G "Ninja" ..
-- Android: Targeting API '24' with architecture 'arm64', ABI 'arm64-v8a', and processor 'aarch64'
-- Android: Selected GCC toolchain 'aarch64-linux-android-4.9'
-- The C compiler identification is GNU 4.9.0
-- The CXX compiler identification is GNU 4.9.0
通用的简化工具链
我在使用最少的工具链文件方面取得了一些很好的经验,并且通常 - 如果您想专门指定工具路径 - 使用工具链文件中的缓存变量。
请参阅 CMake 文档中的 this minimal example,在您的情况下,它会转化为类似以下内容:
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER <path_to_my_llvm_directory>/clang.cmd)
set(CMAKE_C_COMPILER_TARGET aarch64-linux-android)
set(CMAKE_CXX_COMPILER <path_to_my_llvm_directory>/clang++.cmd)
set(CMAKE_CXX_COMPILER_TARGET aarch64-linux-android)
请注意,指定 CMAKE_SYSTEM_NAME
对启用交叉编译至关重要。
为什么指定 CMAKE_AR
不起作用
关于您的 CMAKE_AR
问题,请注意 CMake 本身确实使用 find_program()
来查找 ar.exe
。由于 find_program()
确实会缓存其结果,因此您还必须预填充 CMAKE_AR
作为缓存变量(请参阅 0013038: cannot set CMAKE_AR when cross-compiling Fortran-only project)。