me
me copied to clipboard
Swift & C (Part 0)
还没想好,先记录
- linux c通过ar将.o生成lib,macOS需要通过
libtool -static -o libxxx xxx.o
- 在Xcode中,将arm64的lib复制到项目目录中,会自动添加到target的library中,也可以直接添加外部library
- 然后需要在bridge header中增加c definition,或者直接将lib的header复制到项目中,然后在bridge中引用
- 从swift到c还是会很曲折,比如需要用到pointer,然后不支持可变参数等等兼容性问题,所以需要通过package或者framework做一层转换,提供给swift调用方native的接口,就是在swift和c lib中做一个转换层
Mach-O
- Mach-O是Mach Object文件格式的缩写,等同于Windows上的PE,Linux上的elf
- Object file: .o
- Library: .a, .dylib, .Framework
- Executable file
foo.c
int biubiubiu(void) { return 666; }
通过clang -c foo.c
就可以生成object file
➜ clang -c foo.c
➜ file foo.o
foo.o: Mach-O 64-bit object x86_64
➜ nm foo.o
0000000000000000 T _HUI_Version
➜ lipo -info foo.o
Non-fat file: foo.o is architecture: x86_64
ok,我们可以分别单独编译出arm64和x86_64的object file,然后通过lipo打成一个fat binary
➜ clang -c -arch arm64 -o foo.o.arm64 foo.c
➜ clang -c -arch x86_64 -o foo.o.x86_64 foo.c
➜ lipo foo.o.arm64 foo.o.x86_64 -create -output foo.o
➜ libtool -static -o libfoo.a foo.o
➜
➜ file foo.o
foo.o: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit object x86_64Mach-O 64-bit object x86_64] [arm64:Mach-O 64-bit object arm64Mach-O 64-bit object arm64]
foo.o (for architecture x86_64): Mach-O 64-bit object x86_64
foo.o (for architecture arm64): Mach-O 64-bit object arm64
➜ lipo -info libfoo.a
Architectures in the fat file: libfoo.a are: x86_64 arm64
➜ lipo -archs libfoo.a
x86_64 arm64
对应的Makefile
all: libfoo.a
foo.o.arm64: foo.c
clang -c -arch arm64 -o $@ $<
foo.o.x86_64: foo.c
clang -c -arch x86_64 -o $@ $<
foo.o: foo.o.arm64 foo.o.x86_64
lipo $^ -create -output $@
libfoo.a: foo.o
libtool -static -o $@ $^
clean:
rm *.a *.o*
.PHONY: all clean
更新May 22: BigNerd书p57: gcc -arch arm64 -arch x86_64 app.c
可以直接生成fat binary.
Framework
- Frameworks are packaged in bundle structure, 后缀采用.framework
- 分为standard frameworks和umbrella frameworks. umbrella frameworks比标准的高级一点,支持包含其他框架等额外的特性
- Layout
- MyFramework.framework/
- MyFramework -> Versions/Current/MyFramework
- Resources -> Versions/Current/Resources
- Versions/
- A/ :MyFramework, Resources
- B/ :MyFramework, Resources
- Current -> B
- MyFramework.framework/
不清楚的花,直接去看下xcrun --show-sdk-path
下系统的framework,交叉比对一下。
所以,如果是需要vscode的方式,则需要手动建立目录和link,然后对整个目录进行code sign
- app bundle参考: #238
- code sign参考: #212
- code sign是针对foo.framework, 而不是里面的lib
- libfoo.a放到framework后需要命名为foo,和framework的name一致
- 必须要有Resources/Info.plist, 这个直接从Xcode framework复制出来就行
- 如果格式有问题,在codesign会提示错误
使用时,
- 新建macOS SwiftUI项目
- 新建一个.c,目的是为了引入Bridging-Header
- 在target中添加framework
- 如果framework不在系统framework path中,则需要在building/Search Paths中指定Framework Search Paths
- 然后添加Header Search Paths,和framework一致
- 最后在Bridging-Header中添加header files
Test-Bridging-Header
#import <foo/foo.h>
- framework本质上就是对资源的package,1来解决了version,2来解决了header, libs散落在全局路径上,还是为了安全。
SwiftPM
Command Tools
- clang
- lipo
- libtool
- otool
- nm
参考文档
- Anatomy of Framework Bundles
- About Bundles | Bundle programming Guide
- The Swift compiler for beginners - The.Swift.Dev.
- A Brief Overview of Swift Compiler | by Shashikant Jagtap | XCBlog | Medium
- Building a Universal macOS Binary | Apple Developer Documentation
- MachO | 不会飞的小白
- A deep dive on macOS universal binaries - Juan Cruz Viotti
- Mach-O 文件格式探索 · GitBook
- (iOS)年轻人,听说你想使用Framework - 基礎觀念 - 掘金
- 系统理解 iOS 库与框架 | 楚权的世界
- tvm_phone/tvm-cmake-ios.md at master · zhaowd2001/tvm_phone
- 在 Swift Framework 中使用 C 文件的过程探索 - 开发者头条
- WWDC 2013 Session笔记 - Xcode5和ObjC新特性 | OneV's Den
- Xcode 构建幕后原理 | 楚权的世界
- 使用 Developer ID 为 Mac app 签名 | Nix 的自我修养