问题描述
我想从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_VERSION4.3)
SET(CMAKE_SYSTEM_PROCESSORarm)
SET(CMAKE_CROSSCOMPILING TRUE)
SET(SDKVER4.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_ARCHITECTURESarmv6armv7)
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)
并执行。
cmake -DCMAKE_TOOLCHAIN_FILE = .. / CMAKE_IPHONEOS_TOOLCHAIN.cmake ../bullet-2.78
cmake
本身做得很好。 make
做得很好。所有构建完成没有任何错误。然而,构建的二进制是 x64
非脂肪二进制而不是 armv6 / armv7
fat二进制。生成的 Makefile
不能用于交叉编译。在构建时似乎不使用编译器和标志(包括 -isysroot
)。如何使用参数?
我解决了这个问题,并为iOS构建Bullet Physics。
解决方案
这是我使用的工具链配置。
INCLUDE(CMakeForceCompiler)
SET(CMAKE_CROSSCOMPILING TRUE)
SET(CMAKE_SYSTEM_NAMEDarwin)
SET(CMAKE_SYSTEM_PROCESSOR) )
SET(SDKROOT/ Developer / Platforms /)
SET(SDKVER4.3)
SET(DEVROOT/Developer/Platforms/iPhoneOS.platform/Developer ($DEVROOT} / usr / bin / clang)
SET(CXX$ {DEVROOT} / iPhone / OS / 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)
SET(仅限CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
和构建脚本。 这很重要!
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将跳过编译器验证阶段。
需要通过构建脚本中的shell变量导出提供交叉编译。这是非常粗糙的选项,但重要的是我们必须通过shell变量。 配置会影响生成的 Makefile
。我们必须指定正确的 CMAKE_SYSTEM_NAME
( Darwin
)和 CMAKE_SYSTEM_PROCESSOR
( arm
)。
更新
还有另一个试验。
这里有一个。这看起来很有前途。
Update 2
现在Bullet包含一个iOS平台的构建脚本。无论如何它的不方便,因为它不处理模拟器东西的特殊需要,我写了另一个构建脚本,使远程库调试/释放模式。
I'm trying to cross-compiling from Mac OS X to iOS. It was easy using clang
to cross-compile a source to iOS target. We need only 3 parameters get it to work.
clang
-arch armv6
-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk
-miphoneos-version-min=4.3
But the problem is I have to build a library (Bullet Physics) packaged with Cmake. And as far as I know, Cmake has no iOS support yet.
So, I made a toolchain file.
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)
And executed.
cmake -DCMAKE_TOOLCHAIN_FILE=../CMAKE_IPHONEOS_TOOLCHAIN.cmake ../bullet-2.78
cmake
itself done well. make
done well. All build complete without any error. However built binary was x64
non-fat binary instead of armv6/armv7
fat binary. Generated Makefile
doesn't work for cross-compile. It doesn't seem to use compiler and flags (including -isysroot
) when building. How can I make it use the parameters?
I solved this and built Bullet Physics for iOS.
Solution
Here's toolchain configuration that I used.
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)
And the build script. This is important!
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
This is very minimal configuration. However you got the idea.
Description
First, the toolchain configuration is just a stage figuring out features available on target machine. But cross compilation to iOS require some special compiler flags, and this is exception situation described on Cmake wiki.
So I just forced specific compiler, and Cmake will skip compiler verification stage.
Second, all compiler flags needed for cross compilation offered via shell variable export in build script. This is very rough options, however important is we have to pass via shell variables. Not with toolchain configuration.
However some kind of toolchain configuration affects on generated Makefile
. We have to specify correct CMAKE_SYSTEM_NAME
(Darwin
) and CMAKE_SYSTEM_PROCESSOR
(arm
).
Update
There is another trials. Anyway these don't work for me anymore.
Here's one more. This looks promising.
Update 2
Now Bullet includes a build script for iOS platforms. Anyway it's inconvenient because it does not handle special needs for simulator stuffs, and I wrote another build script which makes far library for debug/release mode.
https://github.com/Eonil/Bullet-PhysicsEngine-BuildScript
这篇关于如何在最终编译阶段而不是检测时使Cmake使用特定的编译器和标志?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!