目录
快速开始
一、pch
1、include 和 import 的区别? import = include + #pragma once
2、头文件是如何找到的
完整路径 = header_search_path + viewcontroller.h
3、pch文件的原理
pch文件在编译阶段会生成ast产物,然后被复制到所有的.m文件中
节省了重复编译的时间,但重复copy的时间没有缩短还增加了
二、编译流程
编译器前端clang:词法分析(token) - 语法分析(ast) - 语义分析(ast) - 代码生成(中间产物llvm ir)
编译器后端llvm:clang传递过来的llvm ir - Opt(代码优化,优化后的ir) - asm printer(汇编代码) - Assembler(.o二进制文件) - linker(可执行文件)
三、Module
Module是pch的升级版,可以理解为管理了一组PCH,并解决了PCH的重复copy问题
Module是按需导入的
module Zoo {
// 一个头文件,映射多个头文件
umbrella header "Zoo.h"
export *
//相当于
//module Cat { export * }
//module Dog { export * }
module * { export * }
}
PCH文件
一、include 和 import
include 不会去重,
include “viewcontroller.h”
include “viewcontroller.h”
import对同一个路径下的头文件不会重复引入
如果有两个相同的头文件,位于不同的目录下,那么也不会去重
import = include + #pragma once
下面这种说法未理解
import 维护了一个字典
import "viewcontroller.h"
如果在字典里能找到路径的话就不会再引入
import "viewcontroller.h"
二、头文件是如何找到的
编译器:header_search_path
完整路径 = header_search_path + viewcontroller.h
三、pch
PCH文件叫预编译头文件,是为缩短编译时间而存在的
只编译一次:PCH文件在预编译阶段和编译的前期阶段,会替换其中的宏定义,生成ast产物
全局可见:ast产物会被拷贝到项目中的所有的.m文件内
所以pch文件节省的是重复编译的时间,但重复拷贝的时间并没有被节省甚至还增加了,因为有的.m文件不需要引入pch也给引入了
pch在config文件中的配置
GCC_PRECOMPILE_PREFIX_HEADER = YES
GCC_PREFIX_HEADER = LGApp/LGApp-prefix.pch
四、讲课中用到的一些指令
clang -x objective-c-header -c include/Zoo.pch -o include/Zoo.pch.gch
# llvm-bcanalyzer 来分析二进制位码(Bitcode)文件的内容
# --dump 标志表示要输出详细的信息
# 这个命令的目的是对 zoo.pch.gch 文件进行分析,并以人类可读的方式输出其内容
llvm-bcanalyzer --dump Zoo.pch.gch
llvm-bcanalyzer --dump Zoo.pch.gch > zoo.xml
llvm-bcanalyzer --dump Zoo.pch.gch --show-binary-blobs > zoo.xml
clang -x objective-c -include-pch include/Zoo.pch.gch -emit-llvm use.m -S
编译流程
module
一、module介绍
可以理解成,module管理的是一组pch文件
module.modulemap文件
module Zoo {
// 子module
module Cat {
header "Cat.h"
//引用了其他的module,将其它的module导出
//xy:一个头文件就是一个module,将其它的头文件作为module进行二次导出
export *
}
module Dog {
header "Dog.h"
}
}
二、module是按需求导入的
@Zoo.Cat 如果使用了Dog,不会导入,这时会报错
@Zoo
如果只使用了Cat,那么Dog的头文件不会导入
如果使用了Cat和Dog,那么Cat和Dog的头文件都会导入
三、在config文件内配置modulemap文件
Zoo.h文件
#import "Cat.h"
#import "Dog.h"
module Zoo {
// 一个头文件,映射多个头文件
umbrella header "Zoo.h"
export *
//相当于
//module Cat { export * }
//module Dog { export * }
module * { export * }
}
在配置文件内配置modulemap文件
OTHER_CFLAGS = -fmodules
-fmodule-map-file="${SRCROOT}/LGApp/Zoo/zoo.modulemap"
对工程编译,编译成功后,对.m文件选择预编译查看头文件采用的是copy的方式还是module得方式
行者常至,为者常成!