如何编译libgfortran适配iOS arm64架构?解决链接符号缺失问题
我之前帮朋友搞定过类似的iOS上跑Fortran代码的需求,手动在Xcode里逐文件编译gfortran确实会踩一堆莫名其妙的坑,用configure+make做交叉编译是更靠谱的路子,给你一步步捋清楚:
一、先搞定交叉编译环境准备
首先要确保你装了Xcode命令行工具,然后设置好iOS交叉编译的环境变量——这些变量会告诉编译器我们要针对arm64 iOS编译:
# 获取iOS SDK路径 export SDKROOT=$(xcrun --sdk iphoneos --show-sdk-path) # 指定交叉编译用的clang export CC=$(xcrun --sdk iphoneos clang) export CXX=$(xcrun --sdk iphoneos clang++) # 设置编译参数:指定arm64架构、SDK路径、最低支持iOS版本(按需改) export CFLAGS="-arch arm64 -isysroot $SDKROOT -miphoneos-version-min=12.0" export CXXFLAGS="$CFLAGS" export LDFLAGS="$CFLAGS"
注意:-miphoneos-version-min可以根据你的App最低兼容版本调整,比如改成15.0之类的
二、编译gfortran依赖的数学库(gmp/mpfr/mpc)
gfortran编译依赖这三个数学库,得先交叉编译它们到arm64 iOS:
1. 编译gmp
从GNU官方仓库获取gmp稳定版本的源码包(比如6.2.1),解压后进入目录,执行以下命令:
# 配置编译:指定目标架构、安装目录、静态库模式 ./configure --target=arm64-apple-ios \ --prefix=$HOME/ios-gfortran \ --host=arm64-apple-ios \ --enable-static \ --disable-shared \ --with-sysroot=$SDKROOT # 编译并安装(-j后面是CPU核心数,加速编译) make -j$(sysctl -n hw.ncpu) make install cd ..
2. 编译mpfr
从GNU官方仓库获取mpfr稳定版本的源码包(比如4.2.0),解压后进入目录:
./configure --target=arm64-apple-ios \ --prefix=$HOME/ios-gfortran \ --host=arm64-apple-ios \ --enable-static \ --disable-shared \ --with-sysroot=$SDKROOT \ --with-gmp=$HOME/ios-gfortran make -j$(sysctl -n hw.ncpu) make install cd ..
3. 编译mpc
从GNU官方仓库获取mpc稳定版本的源码包(比如1.3.1),解压后进入目录:
./configure --target=arm64-apple-ios \ --prefix=$HOME/ios-gfortran \ --host=arm64-apple-ios \ --enable-static \ --disable-shared \ --with-sysroot=$SDKROOT \ --with-gmp=$HOME/ios-gfortran \ --with-mpfr=$HOME/ios-gfortran make -j$(sysctl -n hw.ncpu) make install cd ..
三、交叉编译arm64 iOS版本的gfortran
现在可以编译gfortran了,建议选一个对iOS交叉编译支持较好的版本,比如gcc-12.x系列:
从GNU官方仓库获取对应版本的gcc源码包,解压后进入目录,执行以下配置和编译命令:
# 配置编译:只编译fortran、静态库、指定依赖路径 ./configure --target=arm64-apple-ios \ --prefix=$HOME/ios-gfortran \ --enable-languages=fortran \ --disable-shared \ --with-sysroot=$SDKROOT \ --disable-bootstrap \ --disable-multilib \ --with-gmp=$HOME/ios-gfortran \ --with-mpfr=$HOME/ios-gfortran \ --with-mpc=$HOME/ios-gfortran # 编译(这个过程会比较久,耐心等) make -j$(sysctl -n hw.ncpu) make install
*解释下关键参数:
--enable-languages=fortran:只编译Fortran相关模块,节省编译时间--disable-shared:编译静态库,iOS上静态库更容易集成--disable-bootstrap:避免gcc二次自编译,减少报错概率*
四、在Xcode项目中集成这些库
编译完成后,~/ios-gfortran目录下就是我们需要的库和头文件:
- 打开你的Xcode项目,把
~/ios-gfortran/lib下的libgfortran.a、libquadmath.a、libgmp.a、libmpfr.a、libmpc.a拖到项目的Link Binary With Libraries里 - 在Build Settings中,把Header Search Paths添加
~/ios-gfortran/include(记得选"Recursive"或者"Non-recursive",看你需求) - 在Other Linker Flags里加上
-lgfortran -lquadmath(如果拖了静态库可能不用,但加上更保险)
五、编译你的Fortran代码并链接
现在可以用我们编译好的交叉编译器来编译Fortran代码:
# 编译单个Fortran文件成arm64目标文件 $HOME/ios-gfortran/bin/arm64-apple-ios-gfortran -c -arch arm64 -isysroot $SDKROOT -miphoneos-version-min=12.0 your_fortran_code.f90 -o your_fortran_code.o
把生成的your_fortran_code.o文件加到Xcode项目里,就能按照你原来的调用流程(Objective-C -> C -> Fortran)正常运行了,不会再出现gfortran库符号缺失的问题。
如果之前用dragonegg编译Fortran遇到问题,建议直接换成这个交叉编译器,兼容性会好很多。
内容的提问来源于stack exchange,提问作者Ammo

