如何使Cmake在最终编译阶段而不是检测时使用特定的编译器和标志?
我正在尝试从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
但问题是我必须build立一个与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
本身做得很好。 做得好。 所有构build完成没有任何错误。 但是,构build的二进制文件是x64
非胖二进制文件,而不是armv6/armv7
胖二进制文件。 生成的Makefile
不适用于交叉编译。 它似乎没有使用编译器和标志(包括-isysroot
)build设时。 我怎样才能使用参数?
我解决了这个问题,并为iOS构build了Bullet Physics。
解
这是我使用的工具链configuration。
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)
和构build脚本。 这个很重要!
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
这是非常小的configuration。 不过你有这个想法。
描述
首先, 工具链configuration只是找出目标机器上可用function的一个阶段。 但是交叉编译到iOS需要一些特殊的编译器标志,这是Cmake wiki上描述的exception情况。
所以我只是强制特定的编译器,Cmake会跳过编译器validation阶段。
其次,在构build脚本中通过shellvariables导出提供交叉编译所需的所有编译器标志。 这是非常粗糙的选项,但重要的是我们必须通过shellvariables。 不与工具链configuration。
但是某些工具链configuration会影响生成的Makefile
。 我们必须指定正确的CMAKE_SYSTEM_NAME
( Darwin
)和CMAKE_SYSTEM_PROCESSOR
( arm
)。
更新
还有另一个试验。 无论如何,这些不再适用于我了。
这里还有一个。 这看起来很有希望
更新2
现在Bullet包含一个iOS平台的构build脚本。 无论如何,这是不方便的,因为它不处理模拟器的东西的特殊需求,我写了另一个构build脚本,使远库debugging/释放模式。