iOS开发人员,送你一份用得上的编译命令。

前言

学如逆水行舟,不进则退。共勉!

最近刚完成一个项目。就自己整理成了一份编译命令。我也不知道能否对大家有帮助,就分享出来了。也算是全当我开发这个项目的一些笔记吧。

iOS资料白嫖渠道请关注主页,加入圈子获取。

一份编译命令

生成目标文件

目标文件包含了机器指令代码、数据,链接时需要的信息,符号表、调试信息,字符串表。

  1. 不指定target,默认是Mach-O 64-bit object x86_64:
clang -x c -g -c a.c -o a.o
-x:指定编译文件语言类型
-g:生成调试信息
-c:生成目标文件,只运行preprocess҅ compile҅ assemble,不链接
-o:输出文件
-I在指定目录寻找头文件
-L 指定库文件路径(.a\.dylib库文件)
-F在指定目录寻找framework头文件
-framework 在指定链接的framework名称
生成相应的LLVM文件格式,来进行链接时间优化
当我们配合-s使用时,生成汇编语言文件,否则生成bitcode格式的目标文件
flto=设置LTO的模式:full or thin
-flto 设置LTO的模式:full
-flto=full,默认值,单片(monolithic)LTO通过将所有输入合并到单个模块中来实现此目的
-flto=thin,使用ThinLTO代替
-emit-llvm
-install_name 指定动态库初次安装时的默认路径,向'LC_ID_DYLIB'添加安装路径,该路径作为dyld定位该库

clang –o是将.c源文件编译成为一个可执行的二进制代码(-o选项其实是指定输出文件文件名,如果不加-c选项,clang默认会编译链接生成可执行文件,文件的名称由-o选项指定)。

clang-c是使用LLVM汇编器将源文件转化为目标代码

  1. 指定生成Mach-O 64-bit x86-64目标文件格式:
clang -x c -target x86_64-apple-macos10.15 -g -c a.c -o a.o
  1. 如果指定target不带apple系统版本(包括macOS҅,ipadOS҅,iOS,真机和模拟器)。例如x86_64,那么生成的目标文件是Linux的ELF 64-bit:
clang -x c -target x86_64 -g -c a.c -o a.o
  1. 编译.m:
clang -x objective-c -target x86_64-apple-macos10.15 -fobjc-arc -fmodules -isysroot /Applications/Xcode.app/C
ontents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.15.sdk -c test.m -o test.o
clang -x c -g -target arm64-apple-ios13.5 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
/Developer/SDKs/iPhoneOS13.6.sdk -c a.c -o a.o
  1. 编译.mm:
  • 在mac上编译;
clang -x objective-c++ -target x86_64-apple-macos10.15 -std=c++11 -stdlib=libc++ 
-fobjc-arc -fmodules -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer
/SDKs/MacOSX10.15.sdk -c test.mm -o test.o
  • 在模拟器上编译:
clang -x objective-c -target x86_64-apple-ios13.5-simulator -fobjc-arc 
-fmodules -isysroot /Applications/Xcod
e.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer
/SDKs/iPhoneSimulator13.6.sdk -c test.m -o test.o 
  • 在模拟器上链接其他三方库:
image.png
  • 编译成arm64真机:
clang -target arm64-apple-ios13.5 -isysroot 
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/S
DKs/iPhoneOS13.6.sdk -L/Users/ws/Desktop/课程/Library/代码库 -fobjc-arc -
lAFNetworking test.o -o testclang -target arm64-apple-ios13.5 -isysroot 
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/S
DKs/iPhoneOS13.6.sdk -F/Users/ws/Desktop/课程/Library/代码库 -fobjc-arc -framework 
AFNetworking test.o -o test 
  1. 生成dsym文件
clang -x c -g1 a.c -o a.o
-g1: 将调试信息写入DWARF`格式文件

查看调试信息

dwarfdump取出并验证DWARF格式调试信息:

dwarfdump a.o

dwarfdump a.dSYM

dwarfdump --lookup 0x100000f20 --arch=x86_64 a.dSYM

--lookup 查看地址的调试信息,将显示出所在的目录,文件,函数等信息

查看文件内容

otool用来查看Mach-o文件内部结构:

otool -l liba.dylib
otool -h libTest.a

-l:显示解析后的mach header和load command
-h:显示未解析的mach header
-L:打印所有链接的动态库路径
-D:打印当前动态库的install_name

objdump用来查看文件内部结构,包括ELF和Mach-o:

objdump --macho -h a.o 
objdump --macho -x a.o 
objdump --macho -s -d a.o
objdump --macho --syms a.o 

-macho:指定Mach-o类型
-h:打印各个段的基本信息
-x:打印各个段更详细的信息
-d:将所有包含指定的段反汇编
-s:将所有段的内容以16进制的方式打印出来
-lazy-bind:打印lazy binding info
--syms打印符号表

静态库的压缩和解压缩

ar压缩目标文件,并对其进行编号和索引,形成静态库。同时也可以解压缩静态库,查看有哪些目标文件:

ar -rc a.a a.o
-r:添加or替换文件
-c:不输出任何信息
-t: 列出包含的目标文件

创建静态库

创建库命令:libtool。可以创建静态库和动态库:

image.png

创建动态库

clang -dynamiclib -target arm64-apple-ios13.5 -isysroot 
/Applications/Xcode.app/Contents/Developer/Platforms
/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk a.o -o a.dylib

查看符号表

nm命令:

nm -pa a.o
-a: 显示符号表的所有内容
-g: 显示全局符号
-p: 不排序,显示符号表本来的顺序
-r: 逆转顺序
-u: 显示未定义符号

生成dsYM文件

dsymutil可以被理解为是调试信息链接器。它按照上面的步骤执行:

  • 读取debug map
  • 从.o文件中加载DWARF
  • 重新定位所有地址
  • 最后将全部的DWARF打包成dsYMBundle. 有了dsYM后,我们就拥有了最标准的DWARF的文件,任何可以dwarf读取工具(可以出来Mach-o二进制文件)都可以处理该标准DWARF。

dsymutill操作DWARF格式的debug symbol。可以将可执行文件debug symbol的生成DWARF格式的文件:

dsymutil -f a -o a.dSYM
-f: .dwarf格式文件
-o : 输出.dSYM格式文件

移除符号

strip用来移除和修改符号表:

image.png

链接器

ld

image.png

链接动态库与静态库

ld -dylib -arch x86_64 -macosx_version_min 10.13 a.dylib -o a 
ld -static -arch x86_64 -e _main a.a -o a

Xcode打印加载的库

Pre-main Time指main函数执行之前的加载时间,包括dylib动态库加载,Mach-O文件加载,Rebase/Binding,Objective-C Runtime加载等。

Xcode自身提供了一个在控制台打印这些时间的方法:在Xcode中Edit Scheme -> Run -> Auguments添加环境变量DYLD_PRINT_STATISTICS并把其值设为1.

DYLD_PRINT_LIBRARIES:打印出所有被加载的库。

DYLD_PRINT_LIBRARIES_POST_LAUNCH:打印的是通过dlopen调用返回的库,包括动态库的依赖库,主要发生在main函数运行之后。

二进制重排

链接order.file

image.png

生成Link Map文件

ld -map output.map -lsystem -lc++ -framework Foundation test.o -o output

map map_file_path 生成map文件
主要包括三大部分:

Object Filesғ:生成二进制用到的link单元的路径和文件编号
Sections: 记录 Mach-O每个Segment/section的地址范围
Symbols:  按顺序记录每个符号的地址范围

install_name_tool

更改动态共享库的安装名称并操纵运行路径。

install_name_tool -add_rpath  libs_File
install_name_tool -delete_rpath  libs_File
install_name_tool -rpath   libs_File
image.png
image.png
image.png
image.png
image.png

最后,点点赞点点关注,优秀的人应该都做了。需要白嫖腾讯课堂和iOS资料可关注主页。加入圈子哦。

你可能感兴趣的:(iOS开发人员,送你一份用得上的编译命令。)