当前位置: 首页 > news >正文

网站数据库设计模板微网站建设及微信推广方案ppt模板

网站数据库设计模板,微网站建设及微信推广方案ppt模板,做直播网站找哪家网站,电影海报模板哪个网站好简介源码到可执行文件流程编译器 编译流程预处理(preprocessor)词法分析(lexical anaysis)语法分析(semantic analysis)CodeGen生成汇编代码生成目标文件生成可执行文件Xcode中查看Clang编译.m文件信息 Xcode常见编译报错分析1. duplicate symbols报错2. symbol(s) not found f…简介源码到可执行文件流程编译器 编译流程预处理(preprocessor)词法分析(lexical anaysis)语法分析(semantic analysis)CodeGen生成汇编代码生成目标文件生成可执行文件Xcode中查看Clang编译.m文件信息 Xcode常见编译报错分析1. duplicate symbols报错2. symbol(s) not found for architecture x86_64/arm64 应用场景Clang AttributesClang警告处理预处理Clang插件开发总结简介拖更很久了今天水文一篇。简单介绍下iOS底层编译的相关知识帮助我们充分理解了iOS编译的过程相信会对我们后续的开发有一定帮助。源码到可执行文件流程首先看一下iOS代码是如何从源码变成可执行文件的有助于我们了解程序从编译到运行的全流程编译器Clang会将源码XXX.m编译为目标文件XXX.o链接器会将目标文件链接打包进最终的可执行文件Mach-O中点击App ICON时动态链接器dyld会加载可执行文件以及依赖的动态库并最终执行到main.m里至此App启动完成编译器编译器是将编程语言转换为目标语言的程序大多数编译器由两部分组成前端和后端。前端负责词法分析语法分析生成中间代码后端以中间代码作为输入进行行架构无关的代码优化接着针对不同架构生成不同的机器码。前后端依赖统一格式的中间代码(IR)使得前后端可以独立的变化。新增一门语言只需要修改前端而新增一个CPU架构只需要修改后端即可。Objective C/C/C使用的编译器前端是clangswift是swift后端都是LLVM。LLVM是一个模块化和可重用的编译器和工具链技术的集合Clang 是 LLVM 的子项目是 CC 和 Objective-C 编译器目的是提供惊人的快速编译比 GCC 快3倍LLVM 还可以提供一种代码编写良好的中间表示 IR这意味着它可以作为多种语言的后端这样就能够提供语言无关的优化同时还能够方便的针对多种 CPU 的代码生成。编译流程Objective-C的编译器前端是Clang诞生之初是为了替代GCC提供更快的编译速度。我们可以通过下面这张图来了解Clang编译的大致流程br (二维码自动识别)下面我们通过clang命令来具体分析下源码编译的流程首先在命令行里输入clang -ccc-print-phases main.m可以看到源文件编译需要的几个不同的阶段➜ clang -ccc-print-phases main.m 0: input, main.m, objective-c 1: preprocessor, {0}, objective-c-cpp-output //预编译 2: compiler, {1}, ir //编译成中间代码ir 3: backend, {2}, assembler //生成汇编 4: assembler, {3}, object //生成目标文件.O 5: linker, {4}, image //链接成可执行文件 6: bind-arch, x86_64, {5}, image接下来我们新建一个main.m并详细来看下每个步骤分别做了什么main.m #include stdio.hint main() {printf(hello worldn);return 0; }预处理(preprocessor)我们用下面的命令来查看clang预处理的结果clang -E main.m注如果main.m中用到了UIKit等类可以在命令后添加-sysroot参数记得将sdk换成你本机的版本后续命令解决方法相同。如下所示clang -E main.m -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk可以看到预处理后的文件行数有很多在最后可以找到main函数# 13 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/ShareSheet.h 2 3 # 17 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIKit.h 2 3 # 10 main.m 2 # 1 ./AppDelegate.h 1 # 11 ./AppDelegate.h interface AppDelegate : UIResponder UIApplicationDelegateproperty (strong, nonatomic) UIWindow *window;end # 11 main.m 2int main(int argc, char * argv[]) {autoreleasepool {return UIApplicationMain(argc, argv, ((void *)0), NSStringFromClass([AppDelegate class]));} }预处理会替进行头文件引入(递归操作)宏替换#define注释处理条件编译(#ifdef)#pargma处理等操作。比如#include stdio.h就是告诉预处理器将这一行替换成头文件stdio.h中的内容这个过程是递归的因为stdio.h也有可能包含其头文件。词法分析(lexical anaysis)预处理完成后就会进行词法分析这里会把代码切成一个个 Token比如大小括号等于号还有字符串等。clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m语法分析(semantic analysis)语法分析会校验语法的正确性然后将所有的节点组成抽象语法树AST。有了抽象语法树clang就可以对这个树进行分析找出代码中的错误。比如类型不匹配亦或Objective C中向target发送了一个未实现的消息。业内对Clang自定义插件或者开发静态检测插件都是基于AST语法树来分析。相关知识后续会学到。AST是开发者编写clang插件主要交互的数据结构clang也提供很多API去读取AST。更多细节Introduction to the Clang AST。clang -fmodules -fsyntax-only -Xclang -ast-dump main.m在输出里可以看到相关的AST结果如下图CodeGenCodeGen 会负责将语法树自顶向下遍历逐步翻译成 LLVM IRIR 是编译过程的前端的输出也是后端的输入。 Objective C代码也在这一步会进行runtime的桥接property合成ARC处理等。clang -S -fobjc-arc -emit-llvm main.m -o main.ll查看main.ll的内容如下... ; Function Attrs: noinline optnone ssp uwtable define i32 main(i32, i8**) #0 {%3 alloca i32, align 4%4 alloca i32, align 4%5 alloca i8**, align 8store i32 0, i32* %3, align 4store i32 %0, i32* %4, align 4store i8** %1, i8*** %5, align 8%6 call i8* llvm.objc.autoreleasePoolPush() #1%7 load i32, i32* %4, align 4%8 load i8**, i8*** %5, align 8%9 load %struct._class_t*, %struct._class_t** OBJC_CLASSLIST_REFERENCES_$_, align 8%10 bitcast %struct._class_t* %9 to i8*%11 call i8* objc_opt_class(i8* %10)%12 call %0* NSStringFromClass(i8* %11)%13 bitcast %0* %12 to i8*%14 notail call i8* llvm.objc.retainAutoreleasedReturnValue(i8* %13) #1%15 bitcast i8* %14 to %0*%16 call i32 UIApplicationMain(i32 %7, i8** %8, %0* null, %0* %15)store i32 %16, i32* %3, align 4%17 bitcast %0* %15 to i8*call void llvm.objc.release(i8* %17) #1, !clang.imprecise_release !10call void llvm.objc.autoreleasePoolPop(i8* %6)%18 load i32, i32* %3, align 4ret i32 %18 }; Function Attrs: nounwind ...如果在项目配置中开启了 bitcode 苹果还会做进一步的优化有新的后端架构还是可以用这份优化过的 bitcode 去生成。clang -emit-llvm -c main.m -o main.bc生成汇编代码clang -S -fobjc-arc main.m -o main.s生成目标文件汇编器以汇编代码作为输入将汇编代码转换为机器代码最后输出目标文件(object file)clang -fmodules -c main.m -o main.o接下来我们用nm命令查看下main.o中的符号➜ BuildTest nm -nm main.o(undefined) external _printf 0000000000000000 (__TEXT,__text) external _main这里可以看到_printf是一个是undefined external的。undefined表示在当前文件暂时找不到符号_printf而external表示这个符号是外部可以访问的对应表示文件私有的符号是non-external。生成可执行文件链接器可以把编译产生的.o文件和dylib,a,tbd文件生成一个mach-o文件clang main.o -o main接着在命令行执行./main可以看到输出了结果hello world。 最后我们用nm命令来分析下可执行文件的符号表➜ BuildTest nm -nm main(undefined) external _printf (from libSystem)(undefined) external dyld_stub_binder (from libSystem) 0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header 0000000100000f60 (__TEXT,__text) external _main 0000000100002008 (__DATA,__data) non-external __dyld_private可以看到_printf仍然是undefined但是后面多了一些信息from libSystem表示这个符号来自于libSystem会在运行时动态绑定。以上就是Clang编译源文件的完整流程了。Xcode中查看Clang编译.m文件信息如果你想在 Xcode 中查看可以通过 Show the report navigator 里对应 target 的 build 中查看每个 .m 文件的 clang 编译信息如下图随便找一个.m文件编译信息可以看到Xcode会首先对任务进行描述CompileC /Users/chenaibin/Library/Developer/Xcode/DerivedData/PodIntegrationDemo-achbuytjuwbatqbzvlwflifarxwa/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/podLibB.build/Objects-normal/x86_64/podClsB.o /Users/chenaibin/Work/DiDi/iOSDemo/BuildErrorDemo/podLibB/Classes/podClsB.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target podLibB from project Pods)接下来对会更新工作路径同时设置 PATHcd /Users/chenaibin/Work/DiDi/iOSDemo/BuildErrorDemo/PodIntegrationDemo/Pods export LANGen_US.US-ASCII export PATH/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin接下来就是实际的编译命令/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -target x86_64-apple-ios9.0-simulator -fmessage-length0 -fobjc-arc… -Wno-missing-field-initializers ... -DDEBUG1 ... -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk -iquote ... -I... -F...-c /.../podClsB.m -o /.../podClsB.oclang 用到的命令参数如下-x 编译语言比如objective-c -arch 编译的架构比如arm64 -f 以-f开头的。 -W 以-W开头的可以通过这些定制编译警告 -D 以-D开头的指的是预编译宏通过这些宏可以实现条件编译 -iPhoneSimulator13.0.sdk 编译采用的iOS SDK版本 -I 把编译信息写入指定的辅助文件 -F 需要的Framework -c 标识符指明需要运行预处理器语法分析类型检查LLVM生成优化以及汇编代码生成.o文件 -o 编译结果Xcode常见编译报错分析1. duplicate symbols报错第一个常见的编译报错原因就是duplicate symbols如下图就是因为我们链接后的可执行文件存在了重复的类导致的。注由于我们工程是由CocoaPods构建的在xcconfig中OTHER_LINK_FLAG都会被默认设置成$(inherited) -ObjC ......这会导致工程配置里Other Linker Flags会带上 -ObjC标记如果我们手动删除了-ObjC就会发现在编译时不会有duplicate symbols的错误了。但是运行的时候可能会出现unrecognized selector sent to class XXX的错误这是由于静态库中的分类并没被链接器链接进可执行文件中。-ObjC会把静态库中所有的类和分类都链接进可执行文件所以会出现duplicate symbols的错误。下面是官方描述This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes.2. symbol(s) not found for architecture x86_64/arm64第二个常见报错是在某个架构下找不到相关符号这是因为引用的某个静态库并没有包含当前工程制式下的架构类型解决方案是将静态库.a文件合并x86_64/arm64等架构为fat file再集成到工程里使用。报错原因如下图提示遇到这种情况时有时候多次pod update也不能解决报错原因。这是因为你本地缓存了有问题的静态库文件可在以下目录下找到相关类库并删除再执行pod install下载fix后的静态库文件。CocoaPods官方缓存目录~/Library/Caches/CocoaPods/Pods这个错误还有另外一种情况当同一个pod在多个不同的端集成时可能会遇到。报错信息大致如下问题原因在ProjectA中集成了podA和podBpodA使用了#if __has_include(podB中的cls.h)集成了podB中的类当切换到ProjectB时只会依赖podA一个库这个时候编译就会上图中的错误。解决方案在ProjectB中将podA以源码重新编译一遍即可。应用场景Clang Attributes在平时开发中我们经常会遇到头文件里有__attribute__的用法它是一个高级的的编译器指令它允许开发者指定更更多的编译检查和一些高级的编译期优化。__attribute__ 语法格式为__attribute__ ((attribute-list)) 放在声明分号“;”前面。比如在三方库中最常见的声明一个属性或者方法在当前版本弃用了property (strong,nonatomic)CLASSNAME * property __deprecated;下面是 iOS开发中常见的几个 __attribute__ 用法//弃用API用作API更新 #define __deprecated __attribute__((deprecated))//带描述信息的弃用 #define __deprecated_msg(_msg) __attribute__((deprecated(_msg)))//遇到__unavailable的变量/方法编译器直接抛出Error #define __unavailable __attribute__((unavailable))//告诉编译器即使这个变量/方法 没被使用也不要抛出警告 #define __unused __attribute__((unused))//和__unused相反 #define __used __attribute__((used))//如果不使用方法的返回值进行警告 #define __result_use_check __attribute__((__warn_unused_result__))//OC方法在Swift中不可用 #define __swift_unavailable(_msg) __attribute__((__availability__(swift, unavailable, message_msg)))Clang警告处理当我们在XCode中屏蔽部分Warning信息时可以使用下面的内容来解决。通过clang diagnostic push/pop来控制代码块的编译选项。#pragma clang diagnostic push #pragma clang diagnostic ignored -Wundeclared-selector ///代码 #pragma clang diagnostic pop预处理预处理可以让我们让我们自定义编译器变量实现条件编译。 比如我们常用的DEBUG宏#ifdef DEBUG //... #else //... #endif我们可以在XCode的Target中选中Build Setting选项搜索proprecess即可看到定义好的预处理宏。 目前iOS基本都是用CocoaPods来管理工程我们也可以在每个Pod的podspec文件中配置预编译宏CocoaPods会在构建工程时将这些信息写到Pod的xcconfig文件里。# Pod.podspec示例 s.subspec YourSubSpec do | ss |ss.source_files Pod/Classes/**/*ss.pod_target_xcconfig { GCC_PREPROCESSOR_DEFINITIONS $(inherited) YOUR_CUSTOM_DEFINE1 } end注意podA定义的GCC_PREPROCESSOR_DEFINITIONS内容在podB中是不生效的 如果想解决这个问题推荐podB中单独定义一个subspec来配置预编译宏的值在外层工程里通过区分是否引入podB的subspec来实现该预编译宏值的控制。Clang插件开发上面介绍到语法分析之后我们可以拿到抽象语法树AST接着就可以对这个树进行分析做静态代码分析或者无用代码分析都可以网上也有很多资料介绍这块的研究。感兴趣的可以搜索下或者看下 Introduction to the Clang AST总结以上内容主要介绍了下iOS编译相关的知识如有内容错误欢迎指正。推荐 作为一个开发者有一个学习的氛围跟一个交流圈子特别重要这是一个我的iOS交流群789143298 不管你是小白还是大牛欢迎入驻 分享BAT,阿里面试题、面试经验讨论技术 大家一起交流学习成长——点击加入iOS开发交流群BAT大厂面试题、独家面试工具包,资料免费领取包括 数据结构、底层进阶、图形视觉、音视频、架构设计、逆向安防、RxSwift、flutter原文作者陈爱彬
http://www.pierceye.com/news/938824/

相关文章:

  • 网站批量查询工具做影视外包的网站
  • 营销型网站建设试题html5网站网址
  • 网站建设策划书(建设前的市场分析)环球资源网的定位
  • 上海企业都用什么网站网站公司建站
  • 华为云速建站可以做英文网站高端服装产品网站建设
  • 网站建设中html 下载哪个平台做网站比较好
  • 成都网站设计哪家比较好邯郸市空船网络科技有限公司
  • 网站制作类软件推荐南昌网站建设推广专家
  • 做英文兼职的网站四川路桥建设股份有限公司网站
  • 电商网站开发的意义传统营销
  • 怎么自己创建网站或者app足球世界排名
  • 营站快车代理平台跑腿网站开发
  • 免费自助建站系统下载html5手机网站制作
  • 工信部网站怎么查网址邹平县建设局网站
  • 郑州有学网站制作网站背景修改
  • 免费建建网站域名没过期 网站打不开怎么办
  • 单页企业网站模板WordPress社团展示
  • 网站建设需要具备什么条件网站首页新世纪建设集团有限公司
  • 网站怎样做超链接si设计公司
  • 婚恋网站排名前三wordpress首页设置成文章还是页面
  • 制作网站 优帮云一键提交各大收录
  • 网站要怎么做才专业2022电商平台用户排行榜
  • 男男做暧网站免费网站建设期末论文
  • 电子政务门户网站建设wordpress 导入
  • 江苏建设监理协会网站网站建设siteserver
  • 家庭做网站做网站服务器可以挂到外地么
  • 做相册的网站 网易wordpress云服务器
  • 国内网站没备案自己做外贸购物网站
  • 国外h5网站模板下载长沙快速建站模板
  • 湛江网站建设方案找工程项目