ios - 如何让 Cmake 在最终编译阶段而不是检测阶段使用特定的编译器和标志?

标签 ios cmake cross-compiling

我正在尝试从 Mac OS X 交叉编译到 iOS。使用 clang 将源代码交叉编译为 iOS 目标很容易。我们只需要 3 个参数就可以让它工作。

clang
-arch armv6
-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk
-miphoneos-version-min=4.3

但问题是我必须构建一个用 Cmake 打包的库 (Bullet Physics)。据我所知,Cmake 还没有 iOS 支持。

所以,我制作了一个工具链文件。

SET (CMAKE_SYSTEM_NAME      "Generic")
SET (CMAKE_SYSTEM_VERSION   "4.3")
SET (CMAKE_SYSTEM_PROCESSOR "arm")
SET (CMAKE_CROSSCOMPILING   TRUE)

SET (SDKVER "4.3")
SET (DEVROOT "/Developer/Platforms/iPhoneOS.platform/Developer")
SET (SDKROOT "/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk")
SET (CMAKE_OSX_SYSROOT "${SDKROOT}")
SET (CMAKE_OSX_ARCHITECTURES "armv6" "armv7")

SET (CMAKE_C_COMPILER   "${DEVROOT}/usr/bin/clang")
SET (CMAKE_CXX_COMPILER "${DEVROOT}/usr/bin/clang++")
SET (CMAKE_C_FLAGS      "-arch armv6 -arch armv7 -isysroot ${SDKROOT} -std=c99 -x objective-c -DNDEBUG=1")
SET (CMAKE_CXX_FLAGS    "-arch armv6 -arch armv7 -isysroot ${SDKROOT} -x objective-c++ -DNDEBUG=1")

SET (CMAKE_EXE_LINKER_FLAGS    "-miphoneos-version-min=${SDKVER}")
SET (CMAKE_SHARED_LINKER_FLAGS "-miphoneos-version-min=${SDKVER}")
SET (CMAKE_MODULE_LINKER_FLAGS "-miphoneos-version-min=${SDKVER}")

SET (CMAKE_FIND_ROOT_PATH              "${SDKROOT}" "${DEVROOT}")
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   -DCMAKE_TOOLCHAIN_FILE=../CMAKE_IPHONEOS_TOOLCHAIN.cmake ../bullet-2.78

cmake 本身做得很好。 make 做得很好。所有构建完成,没有任何错误。但是,构建的二进制文件是 x64 非胖二进制文件,而不是 armv6/armv7 胖二进制文件。生成的 Makefile 不适用于交叉编译。构建时似乎没有使用编译器和标志(包括 -isysroot)。如何让它使用参数?

最佳答案

我解决了这个问题并为 iOS 构建了 Bullet Physics。

解决方案

这是我使用的工具链配置。

INCLUDE(CMakeForceCompiler)

SET (CMAKE_CROSSCOMPILING   TRUE)
SET (CMAKE_SYSTEM_NAME      "Darwin")
SET (CMAKE_SYSTEM_PROCESSOR "arm")

SET (SDKVER     "4.3")
SET (DEVROOT    "/Developer/Platforms/iPhoneOS.platform/Developer")
SET (SDKROOT    "/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${SDKVER}.sdk")
SET (CC         "${DEVROOT}/usr/bin/clang")
SET (CXX        "${DEVROOT}/usr/bin/clang++")

CMAKE_FORCE_C_COMPILER          (${CC} CLang)
CMAKE_FORCE_CXX_COMPILER        (${CXX} CLang)

SET (CMAKE_FIND_ROOT_PATH               "${SDKROOT}" "${DEVROOT}")
SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM  NEVER)
SET (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY  ONLY)
SET (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE  ONLY)

还有构建脚本。 这很重要!

PKG_NAME=bullet-2.78
BUILD_DIR=build

rm      -rf ${PKG_NAME} ${BUILD_DIR}
tar     -x -f ${PKG_NAME}-r2387.tar

mkdir   build
cd      build

DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
SYSROOT=$DEVROOT/SDKs/iPhoneOS4.3.sdk
CC=$DEVROOT/usr/bin/clang
CXX=$DEVROOT/usr/bin/clang++
CFLAGS="-arch armv6 -arch armv7 -isysroot $SYSROOT -miphoneos-version-min=4.0"
CXXFLAGS=$CFLAGS
LDFLAGS=$CFLAGS

export  CC=$CC
export  CXX=$CXX
export  CFLAGS=$CFLAGS
export  CXXFLAGS=$CXXFLAGS
export  LDFLAGS=$LDFLAGS

cmake   ../$PKG_NAME -DCMAKE_TOOLCHAIN_FILE=../CMAKE_IPHONEOS_TOOLCHAIN.cmake
make
lipo    -info src/LinearMath/libLinearMath.a

这是非常简单的配置。不管你怎么想。

描述

首先,工具链 配置只是确定目标机器上可用功能的一个阶段。但是到 iOS 的交叉编译需要一些特殊的编译器标志,这是 Cmake wiki 中描述的异常情况。 .

所以我只是强制特定的编译器,Cmake 将跳过编译器验证阶段。

其次,交叉编译所需的所有编译器标志都通过构建脚本中的 shell 变量导出提供。这是非常粗略的选项,但重要的是我们必须通过 shell 变量传递。不适用于工具链配置。

但是,某种工具链 配置会影响生成的Makefile。我们必须指定正确的 CMAKE_SYSTEM_NAME (Darwin) 和 CMAKE_SYSTEM_PROCESSOR (arm)。


更新

还有一个试炼。无论如何,这些不再适合我了。

还有一个。这看起来很有希望。

更新2

现在 Bullet 包含一个适用于 iOS 平台的构建脚本。不管怎样,这很不方便,因为它不能处理模拟器的特殊需求,我写了另一个构建脚本,它为调试/ Release模式创建了 far 库。

https://github.com/Eonil/Bullet-PhysicsEngine-BuildScript

关于ios - 如何让 Cmake 在最终编译阶段而不是检测阶段使用特定的编译器和标志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6476203/

相关文章:

ios - 如何知道对象识别机器学习模型 (CoreML) 的可能输出是什么

ios - 需要有关 viewDidLayoutSubviews 的帮助

c++ - 如何将 CMake 命令转换为 bash\cmd 并将其作为参数传递给其他 cmake 命令?

c++ - 在源代码中使用 C++ 库的 CMakeLists

c - 交叉编译时如何使用外部库?

c++ - 无需运行即可构建 CLion

ios - 如何在 iOS 中放大 UIImage 以清除像素而不变得模糊?

ios - 显示 "Cannot find iBeacon"消息

c++ - Target Clean (CMake) 后打印消息

scala - 如何为多个 Scala 版本和差异依赖项组织代码