一、hmap
工程产物headermap等于 hmap
配置 header.json (学习工程化,确实很枯燥,但是坚持就是胜利!!!)
{
"Dog.h": [
"/user/module/include/",
"Dog.h"
]
}
//根据命令编译,生成 .hmap
hmapfile writer --json-path=./header.json
1、OC&Swift
我们用Realmswift框架了分析:
为什么已经用module * {export *} 还要声明 Private 呢?
因为特定的头文件并没有放入umbrella散头文件里。
xcode中配置
MODULEMAP_PRIVATE_FILE 文件路径跟module 文件配置私有库目录是一样的。
SwiftLibrary 的二进制库
swift.a 库的生成:先看下编译产物:
SwiftLibrary.swiftmodule 就是提供swift.a库的信息。
Product文件夹存储刚刚生成的3个产物- 然后创建
SwiftLibrary.modulemap文件 - 在通过命令生成对应
SwiftLibrary.modulemap:
module SwiftLibrary {
}
// -Swift.h系统自动生成 framework(子带module)
module SwiftLibrary.Swift {
header "SwiftLibrary-Swift.h"
//编译的语
requires objc
}
然后在项目中配置对SwiftLibrary.modulemap 的使用。
OTHER_CFLAGS = -fmodules -fmodule-map-file="${SRCROOT}/../Product/SwiftLibrary.modulemap"
// SwiftC --> SwiftLibrary-Swift.h 头文件 (module)
SWIFT_INCLUDE_PATHS = "${SRCROOT}/../Product"
OTHER_SWIFT_FLAGS = -Xclang -fmodule-map-file="${SRCROOT}/zoo.modulemap"
编译通过!
SwiftLibrary.a库在当前的cocoapods可以使用module header 来配置二进制库.a 需要配置modulemap文件
2、hmap
传统的目录搜索,依赖目录。如果当前.h和.m不在同一个目录的话,第二次循环才能找到相关的头文件
- hmap[key]-> 对应完整的头文件路径-module定义
- hmap改变头文件的引入方式 (完整路径/module)
- hmap也是二进制文件 (exec格式:mach-o ELF) header+二进制存储key和value
- process-->exec 依赖了什么第三方库,代码存在什么地方,需要配置文件
- 这个配置文件就是macho header
通过 file 命令查看DumpHeaderMap exec格式文件信息:
//查看objdump 命令
man objdump
objdump --macho --private-header /xxxx/你的exec文件
--private-headers 加s打印更加详细的信息
struct HMapHeader {
uint32_t Magic; // Magic word, also indicatession;
uint16_t Version; // Version number -- currently 1.
uint16_t Reserved; // Reserved for future use - zero for now.
uint32_t StringsOffset; // Offset to start of string pool.
uint32_t NumEntries; // Number of entries in the string table.
uint32_t NumBuckets; // Number of buckets (always a power of 2).
uint32_t MaxValueLength; // Length of longest result path (excluding nul).
// An array of 'NumBuckets' HMapBucket objects follows this header.
// Strings follow the buckets, at StringsOffset.
};
// hmap = header + [NumBuckets buckets] + [StringsOffset]string table hmap位置
// bucket --> 具体的key Prefix suffix。在string table什么位置
struct HMapBucket {
uint32_t Key; // Offset (into strings) of key.
uint32_t Prefix; // Offset (into strings) of value prefix.
uint32_t Suffix; // Offset (into strings) of value suffix.
};
所以hmap 等于header加一堆buckets在加上StringsOffset table hmap位置(偏移量) ,主要用到StringsOffset,NumEntries,NumBuckets 三个参数。
小结:
- hmap 优化的点,会进行模块映射需要自己编写modulemap文件
- hmap xcode 生成耗时是可以加快的(cocoapods-hmap)
二、vfs
vfs是虚拟文件系统,作用于framework(APP)。编译.m文件会先去当前所在的目录找.h文件。但是xcode编译生成产物的时候会生成一个Headers的文件来存放public级别的.h文件。如果是私有就会生成PrivateHeaders文件夹存放私有.h文件。
如果设置完:#import "/app包目录//PrivateHeaders/xx.h" 后在配置:
HEADER_SEARCH_PATHS = "/Users/ws/Library/Developer/Xcode/DerivedData/LGApp-dflcoivumjxanrbflpqkkzqfbmpz/Build/Products/Debug-iphonesimulator/LGApp.app/PrivateHeaders"
编译生成查看产物:发现all-product-headers.yaml是一个json文件,
{
"case-sensitive": "false",
"roots": [
{
"contents": [
{
"external-contents": "LGApp/Zoo/LGCat.h",
"name": "LGCat.h",
"type": "file"
}
],
"name": "/Debug-iphoneos/LGApp.app/Headers",
"type": "directory"
},
{
"contents": [
{
"external-contents": "/LGApp/Zoo/LGDog.h",
"name": "LGDog.h",
"type": "file"
}
],
"name": "/LGApp.app/PrivateHeaders",
"type": "directory"
}
],
"version": 0
}
把包里面的文件和源码里的文件进行一一映射。
vfs相关命令:
`vfs yamlwriter` lets you create clang opt "-ivfsoverlay" ymal file, map virtual path to real path.
# write the VFS YAML file to --output-path=<path>
$ vfs yamlwriter --framework-path=<path> --real-headers-dir=<path> --real-modules-dir=<path> --output-path=<path>
# write the VFS YAML file to .
$ vfs yamlwriter --framework-path=<path> --real-headers-dir=<path> --real-modules-dir=<path>