JHHK

欢迎来到我的个人网站
行者常至 为者常成

7.头文件和PCH

目录

快速开始

一、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得方式


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.