0%

Objc4源码环境搭建

苹果在 OpenSource 官网 上开放了一部分源码,我们可以同过这个官网,下载我们所需要的东西,比如 objc 的源码,通过源码能够方便我们了解iOS的底层原理。想要快速的了解我们的 runtime,搭建一个可以编译调试的 runtime ,能够向我们的效率倍增。下面对针对最新的 objc4-781.2 进行编译

准备工作

  • mac OS 10.15
  • Xcode 11
  • objc4-781.2
  • dyld-733.8
  • Libc-1353.60.8
  • Libc-825.40.1 2
  • launchd-106.10
  • libauto-187
  • libclosure-74
  • libdispatch-1173.60.1
  • libplatform-220
  • libpthread-416.60.2
  • xnu-6153.81.5

以上资料都可以通过 Apple source 获取。

将文件解压到同一个目录中,这里用 OpenSource 来作为示例。

OpenSource目录结构

开始配置

直接编译 ojbc4-781.2 会出现如下报错

unable to find sdk ‘macosx.internal’

更改 Build Settings 里的 Base SDK 选项卡的内容

解决 i386 报错, 将 objc-trampolines 中的 Build Setting 选项 Architectures 中的值切换为 Standard Architectures(64-bit Intel)

重新编译

文件查漏补缺

这个时候会提示 'sys/reason.h' file not found 错误, 如下图:

reason-no-found

在项目目录下创建一个 include 文件夹,用于存放需要导入工程的文件,并且把它添加到项目 Header search Paths 中。操作步骤 objc->TARGETS->ojbc-> Build Settings 搜索 header search paths 添加 $(SRCROOT)/include

接下来,我们用命令 cdOpenSource 文件夹中 (PS: OpenSource 文件夹存放了准备工作中下载的文件). 通过 find . -name 'reason.h' 命令去查找 sys/reason.h 文件. 确认文件个数和名字是否正确,通过以下命令去移动工程所需的文件到 include 文件夹中

1
2
cd [OpenSource文件夹的路径]
finde . -name 'reason.h' | xargs -I '{}' mv {} [include的文件夹路径]

根据提示一次将下列文件按照上面的方法导入到 objc4-781.2 里的 include 文件夹中

  • <sys/reason.h>
  • <mach-o/dyld_priv.h>
  • <os/lock_private.h>
  • <os/base_private.h>
  • <pthread/tsd_private.h>
  • <System/machine/cpu_capabilities.h> 这个选择 ./xnu-6153.81.5/osfmk/machine/cpu_capabilities.h
  • <os/tsd.h> 这个选择 ./xnu-6153.81.5/libsyscall/os/tsd.h
  • <pthread/spinlock_private.h>
  • <System/pthread_machdep.h> 这个文件在 Libc-825.40.1 中可以找到,在最新的 Libc 中会找不到
  • <CrashReporterClient.h> 这个文件在 Libc-825.40.1 中可以周到,在最新的 Libc 中会找不到,导入后依旧异常,查看下面的 CrashReporterClient 异常处理
  • <objc-shared-cache.h>
  • <_simple.h> 这个文件夹在 Libc-825.40.1libplatform-220 文件夹中都存在,这里选择 libplatform-220 这个文件夹中的 _simple.h 文件
  • <restartable.h>
  • <Block_private.h>

CrashReporterClient 异常处理

CrashReporterClient.h 文件导入后,依旧会提示错误 file not found 错误, 需要再 Build Settings -> Preprocessor Macros 中加入: LIBC_NO_LIBCRASHREPORTERCLIENT

其他异常处理

编译时提示 typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int')), 在 include 文件夹下,使用 grep 命令,查找重复定义的文件

1
2
3
4
5
6
grep -rne "typedef.*pthread_lock_t" .
# . 表示查找当前文件
# 输出

./pthread/spinlock_private.h:59:typedef volatile OSSpinLock pthread_lock_t __deprecated_msg("Use <os/lock.h> instead");
./System/pthread_machdep.h:214:typedef int pthread_lock_t;

这里我们选择注释掉 pthread_machdep.h 文件中的定义即可.

同样 提示 Static declaration of '_pthread_has_direct_tsd' follows non-static declaration 我们也通过 grep 命令查重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

grep -re "_pthread_has_direct_tsd(void)" .
# 输出
./pthread/tsd_private.h:273:_pthread_has_direct_tsd(void)
./System/pthread_machdep.h:217:_pthread_has_direct_tsd(void)

grep -re "_pthread_getspecific_direct(unsigned long slot)" .
# 输出
./pthread/tsd_private.h:284:_pthread_getspecific_direct(unsigned long slot)
./System/pthread_machdep.h:244:_pthread_getspecific_direct(unsigned long slot)

grep -re "_pthread_setspecific_direct(unsigned long slot, void \* val)" # 这里注意 特殊符 * 需要加 \ 修饰
# 输出
./pthread/tsd_private.h:_pthread_setspecific_direct(unsigned long slot, void * val)
./System/pthread_machdep.h://_pthread_setspecific_direct(unsigned long slot, void * val)

这里我们都选择注释掉 pthread_machdep.h 文件中的重复定义

编译遇到 Expected ',' 错误的时候,注释掉本行,或者复制上一个值,代替本行代码. 错误如下图:
RuntimeError1
RuntimeError2
ps: 解决了半天,暂时还没有找到更好的办法,不影响编译

libobjc.order 路径问题

  • 选择 target -> objc -> Build Settings
  • 在工程目录的 Order File 选项中,添加搜索路径 $(SRCROOT)/libobjc.order

lCrashReporterClient 编译不到

Library not found for -lCrashReporterClient

  • 选择 target -> objc -> Build Settings
  • Other Linker Flags 中删除 -lCrashReporterClient ( DebugRelease 都删了)

_objc_opt_class 无法编译

Undefined symbol: _objc_opt_class
选择一个 macOSX 的早期版本

Xcode 脚本编译问题

/xcodebuild:1:1: SDK “macosx.internal” cannot be located.
/xcrun:1:1: sh -c ‘/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -sdk macosx.internal -find clang++ 2> /dev/null’ failed with exit code 16384: (null) (errno=No such file or directory)
/xcrun:1:1: unable to find utility “clang++”, not a developer tool or in PATH

  • 选择 target -> objc -> Build Phases -> Run Script(markgc)
  • 把脚本文本 macosx.internal 改成 macosx

ObjectiveC.apinotes 异常

  • 选择 target -> objc -> Build Settings
  • Text-Based InstallAPI Verification Model 中添加搜索路径 Errors Only
  • Other Text-Based InstallAPI Flags 清空所有内容

编译成功

经过重重难关,终于迎来了我们的编译成功
Build Success

调试编译

新建一个 Target , 然后添加依赖, 如下图:
Runtime new Target
Runtime dependency

Xcode 11 新特性

新建好我们的 Target, 这里需要注意,要进行一下设置

target -> objc -> Build Settings -> Enable Hardened Runtime -> NO`

https://developer.apple.com/documentation/security/hardened_runtime

开心玩转吧

-------------本文结束感谢您的阅读-------------