什么是交叉编译
在一个平台上编译生成其他平台可运行的程序, 我们称之为交叉编译
以c语言为例, 在Mac平台编译出来的程序只能在Mac平台运行, 将其拷贝到Windows平台则无法识别, 解决这个问题的办法就是将源代码移至Windows平台 然后重新编译一次 这种做法属于原始的常规编译
那能不能在Mac平台编译生成能在Windows平台运行的程序呢, 可以, 只要借助交叉编译工具即可实现, 而这种非常规编译手段也叫做交叉编译
关于交叉编译实操, 详见之前的文章《android设备上如何运行C语言原生程序》
针对C/C++语言目前主流的交叉编译有:
- GCC:
GNU旗下的一款编译工具 - CLANG: 苹果主导编写的一款基于
LLVM的编译工具 - MSVC: 微软旗下的一款编译工具
为什么使用Clang
相较之下, Clang编译速度更快, 占用内存更小, 错误提示更加人性化
Clang常规使用
我们先以一个C语言小程序来示范clang的编译流程
编写
c程序代码 文件名为main,c1
2
3
4
5
6
7
int main(int argc, char** argv){
printf("Hello World!\n");
return 0;
}编译程序源码为当前平台可执行文件
1
clang main.c -o main
-o:指定输出执行文件路径和程序名称编译时顺带打印编译日志
添加一个
-v即可1
clang main.c -o main -v
编译生成预处理文件
使用
-E, 区分大小写1
clang -E main.c -o main
编译生成汇编代码
使用
-s, 区分大小写1
clang -S main.c -o main
编译生成obj文件
使用
-c, 区分大小写1
clang -c main.c -o main
Clang交叉编译
指定
cpu架构使用
-arch, 比如我们要编译生成arm64位架构平台可执行的程序1
clang main.c -o main -arch arm64
正常情况下 上述指令会执行失败, 那是因为
clang默认会使用本平台的SDK进行链接编译, 而本平台的SDK如果不支持arm的话自然无法编译 目前大部分电脑用的cpu依然还是x86架构的既然如此 倘若我们需要编译能在
iPhone上运行的程序, 那么就需要指定可以支持arm的SDK来进行编译, 比如iphoneOS_SDK指定编译SDK
在
clang中, 通过来-isysroot指定编译SDK, 如下:1
clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.5.sdk main.c -o main -arch arm64
编译成功后 生成的可执行文件即可在苹果手机上运行
指定操作系统
1
clang main.c -o main -target x86_64-apple-darwin-eabi
这里使用
-target同时指定cpu架构和操作系统,-target的参数一共分为四部分:- arch:
cpu架构 比如arm,x86_64 - vendor: 工具连提供厂商 比如
pc,apple,nvidia,ibm,等 - os: 操作系统 比如
darwin,linux,win32 - abi:应用程序二进制接口, 描述了程序在目标平台的运行规则, 比如
eabi,androidabi,gnueabi等
每部分用横杆隔开, 合起来就是
arch-vendor-os-abi- arch:
示例
Mac编译android平台程序这里我使用的是
ndk包下的clang进行编译1
ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang --target=armv7-none-linux-androideabi16 --sysroot=/Users/songjian/Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/sysroot main.c -o androidExc
Mac编译iphone平台程序1
clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.5.sdk main.c -o main -arch arm64
lua源码交叉编译
接下来 我们在Mac平台上编译生成android上可执行的lua程序
由于lua源码文件比较多, 手敲命令编译太过繁琐, 因此我这里使用gradle+cmake构建工具进行快速编译
其中build.gradle配置如下:
1 | apply plugin: 'c' |
这里 我将所有lua源码放置在了lua目录当中
CMakeLists.txt配置如下:
1 | # 限定cmake最小版本号 当前使用的版本必须在这个之上 |
编译工程后我们在build目录可以查看到生成的程序:

将其push到root过的android设备上即可正常运行
关于工程配置, 如有疑问 可参考文章《使用Android Studio进行C/C++的开发》
附加
Mac平台上查看可执行文件的架构1
file 程序名 或 lipo –info 程序名
如果你的电脑安装了
xcode, 那么可以使用xcrun来查看sdk路径查看当前平台
SDK路径:1
xcrun --show-sdk-path
查看
iphone平台SDK路径:1
xcrun --sdk iphoneos --show-sdk-path
甚至可以用
xcrun配合clang简化编译指令:1
2
3xcrun -sdk iphoneos clang -arch arm64 -o main main.c
或者
clang -isysroot `xcrun --sdk iphoneos --show-sdk-path` main.c -o main -arch arm64以及本机平台
1
clang -isysroot `xcrun --show-sdk-path` main.c -o main -arch x86_64
目前
iphoneOS_SDK支持的cpu架构有1
2
3
4arm64
armv7s
armv7
armv6x86系列处理器暂不支持
总结
关于GCC和Clang的使用对比:
GCC 会针对每一个编译主机和目标架构提供一套完整的套件,包含了二进制、头文件和库等。所以通常使用起来比较简单
而Clang 是复用一套编译系统去负责多个目标的编译任务,通过 -target选项来区分, 各个平台对应的头文件和库需要自己单独准备 编译的时候将路径通过参数告知给Clang, 使用起来相对会麻烦一些
本文为作者原创转载时请注明出处 谢谢
