上一章讲了Xcode IDE是终端,是各种Shell,ruby,python等脚本的集合,runscript运行shell,pods 是如何关联target的。
一、pods工程产物
1、 Target产物
可以 Product --> Show Build Folder in Finder 打开Build产物路径,生成在 DerivedData 文件夹下
- workspace名称 / 第一个project名称-复杂字符串
- Build文件夹
Intermediates.noindex文件夹:存放中间产物Products文件夹:存放产物
如何创建相同Target呢?
改名为(NYTag-US):
可是NYTag-US Target并不是和NYTag同名啊,那我们在创建一个framework工程(NYTag-US)然后进行Target 修改成同名NYTag:
这时候需要一个workspace来管理两个Target(NYWorkspace.xcworkspace):
2、 修改Target产物
如何通过NYWorkspace.xcworkspace 修改配置产物路径呢?
我们把LGCatRun.m和LGMeow.m 这两个文件,分别拖动到
NYTag->Sources和NYTag-US->Sources 中
注意:Dependencies 的特点是在相同(project)作用域下才能添加引用。
核心问题:
如果我要在NYTag 中使用到NYTag-US中的(xx.m xx.h)怎么办呢?
那么我们在温习一下Scheme的特点:
scheme定义了要各个action使用的Target集合、以及要使用的配置以及环境变量等等。
所以一个Scheme可以定义使用多个Target了。就能解决我们在NYTag 中使用 NYTag-US 文件的问题。
创建一个Scheme - NYTag-Merge
这样NYTag-Merge 就控制了两个NYTag :但是目前编译是会报错的。
产物路径规则,这两个target产出路径会重名,因此我们可以通过修改产物路径,对其多加一层文件夹来做出差异.
那么如何修改产物路径呢?
当前Shell所有环境变量
- 要修改路径,需要用到很多环境变量,可以使用
% printenv拿到 - 写到脚本中就能获取Xcode的所有环境变量 :
(printenv > /dev/ttys000) - 可以 将环境变量的值 与已有project的路径进行比对,从而确定需要使用哪几个
环境变量名进行拼接
2个project 分别创建Config文件 修改CONFIGURATION_BUILD_DIR为不同路径(CocoaPods自动集成三方库也是增加了文件夹层级,只是因为是Pods所以 环境变量名前多个PODS_,可以作为参考)
将2个Config文件分别应用到对应的project中,再运行时即使2个project的target同名也不会报错了
(注意:PRODUCT 要换成 PROJEC)
编译运行:
小结:
1.产物路径是固定的
2.要使用同名target 需要配置shceme 对的target集合对应。
3.需要配置config 来生成文件夹别名区分产物路径。才能在一个workspace同时编译生成同名target产物。
3、 打印解析hmap,自定义命令
我们build 项目看到中间产物各种.hmap 文件,然后我们知道config文件可以编写编译命令:
VERBOSE_SCRIPT_LOGGING=-v
HMAP_PATH="${TEMP_FILES_DIR}/${PRODUCT_NAME}-all-non-framework-target-headers.hmap" "$(TARGET_TEMP_DIR)/${PRODUCT_NAME}-all-target-headers.hmap" "$(TARGET_TEMP_DIR)/${PRODUCT_NAME}-generated-files.hmap" "$(TARGET_TEMP_DIR)/${PRODUCT_NAME}-own-target-headers.hmap" "$(TARGET_TEMP_DIR)/${PRODUCT_NAME}-project-headers.hmap" "$(TARGET_TEMP_DIR)/${PRODUCT_NAME}.hmap"
// hmap路径?
// shell for
// DumpHeaderMap
// DumpHeaderMap ${HMAP_PATH}
CMD = source ~/.bashrc;for i in $HMAP_PATH;do DumpHeaderMap $i;done
//
TTY = /dev/ttys000
run script: printenv >/dev/ttys000 输出环境变量到终端。
在打开$SRCROOT/xcode_run_cmd.sh 运行【由于我的DumpHeaderMap(在github:作者cat1237可以下载)配置有点问题】
解决配置环境问题:
1.vim ~/.bashrc
2.export PATH=~/thirdpartyLib/custom:$PATH
3.source ~/.bashrc
4.cho $PATH
打印结果(在运行上面NYAPP01):
我们创建一个工程 NYDumpHeaderMap (模仿DumpHeaderMap-自定义命令工具):
lldb命令:parray 2 argv
运行结果:
**__XPC_DYLD_FRAMEWORK_PATH=/Users/ningye/Library/Developer/Xcode/DerivedData/NYDumpHeaderMap-ajcxszcdjzgzfcfoenqyammsktzd/Build/Products/Debug**
**TMPDIR=/var/folders/v9/ry9xdp0n3mb9mfz00s2ckzt80000gn/T/**
**FZ_YN_ENV=NY**
**XPC_FLAGS=0x0**
**SHELL=/bin/zsh**
**GPUProfilerEnabled=YES**
**XPC_SERVICE_NAME=application.com.apple.dt.Xcode.8734984961.8735719237**
**NSUnbufferedIO=YES**
拷贝-Swift.h文件到指定目录
1.创建staticlibrary工程=NYLibrary
2.添加NYL.swift 文件中定义一个继承于NSObject的类
3.创建Config文件CONFIGURATION_BUILD_DIR = ${SRCROOT}/build
4.Xcode会自动生成Target名-Swift.h文件,用于OC调用Swift文件内容(OC调用Swift文件内容需要导入该头文件)因为是编译过程中产生,因此 -Swift.h 文件会放到 中间产物目录
5.在OC文件中使用Swift内容,需要导入 -Swift.h头文件
#import "NYLibrary.h"
#import "NYLibrary-Swift.h
@implementation NYLibrary
- (instancetype)init {
self = [super init];
if (self) {
NYL *file = [NYL new];
}
return self;
}
@end
编写脚本将 -Swift.h文件 copy 到project同级文件夹下
SWIFT_H_PATH="${SRCROOT}/Swift Compatibility Header/${PRODUCT_NAME}-Swift.h"
ditto "$DERIVED_FILES_DIR/${PRODUCT_NAME}-Swift.h" "${SWIFT_H_PATH}"
二、pbxproj文件
1、pbxproj文件解析
1.我们先创建一个空project,再新建一个target,选择 macOS 类型的Command Line Tool(命令行工具)
2.然后在这个target下的 Build Phases 中我们能看到,Compile Sources中自动将main.m文件添加了进来
3.NYdpx.xcodeproj显示包内容打开project.pbxproj 查看:
由此可见:pbxproj文件是用来管理,项目文件的。
核心问题:
为什么Xcode能准确的将main.m添加到Compile Sources 中,而不是 Dependencies 或者 Link Binary 呢?
4.为了有对比添加文件后的参数变化,我们先删掉project的target留个空project,然后用VS打开 project.pbxproj文件(有个pbx插件辅助看文件)
能看到 pbxproj文件包含的几种Key:
| key | 描述 |
|---|---|
archiveVersion | 当前文件的生成版本 |
| classes | 无意义,占位 |
| objectVersion | 当前文件内objects的描述版本 |
objects | 字典,以每个object的UUID作为key,object的属性(Private、Public等)作为value |
| rootObject | 当前文件的根object的UUID(isa = PBXProject) |
rootObject表示 当前文件的根object的UUID,那么我们就搜一下它UUID
- 每个object都有一个key名为
isa,用来表明 当前是什么object - 每个object也有key名为
attributes,用来表明 当前object特性,以及包含的其他object的UUID,描述object的依赖与包含关系
object类型
pbxproj⽂件,已知的object:
• PBXBuildFile
• AbstractBuildPhase
• PBXBuildRule
• XCBuildConfiguration
• XCConfigurationList
• PBXContainerItemProxy:⽤来代指当前project包含的其他project
• PBXFileReference
• PBXGroup
• PBXProject
• PBXTargetDependency
• PBXReferenceProxy:当前project引⽤的,相同空间的其他project的⽂件
• AbstractTarget
还可以通过 xcodeproj --help 终端查看相应的命令。
5.创建一个NYObject,然后在看pbxproj⽂件变化了什么,发现:
注:sourceTree
| sourceTree的值 | 描述 |
|---|---|
| < absolute > | 绝对路径 |
| < group > | 相对于所在group路径 |
| SOURCE_ROOT | 相对于⼯程所在⽬录路径 |
| DEVELOPER_DIR | 相对于DEVELOPER_DIR⽬录路径 |
| BUILT_PRODUCTS_DIR | 相对于产物所在⽬录路径 |
| SDKROOT | 相对于SDK⽬录所在路径 |
已知的AbstractTarget:
-
PBXNativeTarget:正常
-
PBXAggregateTarget:代表一组文件,占位target
-
PBXLegacyTarget:使用外部构建工具的生成的target