环境
macOS 10.12.1
Xcode 8.1
代码
可编译 & 运行的工程 objc-706
流程
源代码下载
编译 -> 失败 -> 编译 -> 失败… 编译 -> 成功
✘ ‘sys/reason.h’ file not found (objc-os.h)
Q1: 为什么
<sys/param.h>
可以找到?
按住⌘ 点击进入<sys/param.h>
实际路径
1 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/param.h |
Q2: 为什么会去找这个路径?
A2 : 决定于Build Settings中的Use Standard System Header Directory Searching字段
Controls whether the standard system directories are searched for header files. When disabled, only the directories you have specified with -I options (and the directory of the current file, if appropriate) are searched.
实际目录下确实没有 <sys/reason.h>
A1: 实际目录下确实没有
<sys/reason.h>
原来的头文件查找目录在/tmp*下,为了方便,添加路径$(SRCROOT)/include*
在objc-706工程目录中创建一个include目录,将相关的头文件放在这里
Q3: 如何找到对应的头文件
A3: Google ⏎ xxx.h site:opensource.apple.com
比如 reason.h site:opensource.apple.com
结果如下:
看上去应该在xnu这个目录下
根据有sys目录,最后找到 [reason.h](https://opensource.apple.com/source/xnu/xnu-3789.21.4/bsd/sys/reason.h)
更好的方法是将整个目录下载下来通过 find/grep 指令去查找
1 | $ find ~/Downloads/objc-res/xnu-3789.21.4/* -name "reason.h" |
- 在include下创建sys目录
- 将reason.h拷贝到sys目录下
- ⌘ + B*
✘ mach-o/dyld_priv.h file not found (objc-os.h)
⌘ + B
✘ os/lock_private.h file not found (objc-os.h)
没找到
换个思路,改搜github
比较过,两个都是一样的,选择一个即可
lock_private.h
lock_private.h
⌘ + B
✘ ‘System/pthread_machdep.h’ file not found (objc-os.h)
应该在Libc中
但macOS10.12.1的Libc-1158.20.4并没有pthreads目录,找以前的版本,在Libc-825.40.1找到了pthread目录
在include目录下新建System目录,拷贝pthread_machdep.h到该目录下
⌘ + B
✘ System/machine/cpu_capabilities.h file not found (pthread_machdep.h)
在System目录下新建machine目录,拷贝cpu_capabilities.h到该目录下
⌘ + B
✘ CrashReporterClient.h file not found (objc-os.h)
在Libc-825.40.1中存在
CrashReporterClient.h
将其拷贝到include目录下
⌘ + B
✘ CrashReporterClient.h file not found (CrashReporterClient.h)
#include_next 包含指定文件所在的路径的后面路径的那个文件
例如有个搜索路径链,在#include中,它们的搜索顺序依次是A,B,C,D和E。在B目录中有个头文件叫a.h,在D目录中也有个头文件叫a.h,如果在我们的源代码中这样写#include <a.h>,那么我们就会包含的是B目录中的a.h头文件,如果我们这样写#include_next <a.h>那么我们就会包含的是D目录中的a.h头文件
代码有如下注释
1 | /* Include the real CrashReporterClient.h */ |
但我们没有真正的CrashReporterClient.h
Build Settings->Preprocessor Macros(Debug & Release)加入:
LIBC_NO_LIBCRASHREPORTERCLIENT
⌘ + B
错误就有些多了
参考 objc - 编译Runtime源码
将需要的压缩包先下载下来
先解决.h没有的问题
✘ phread/workqueue_private.h file not found (objc-os.h)
✔︎ ./libpthread-218.20.1/private/workqueue_private.h
在include目录下新建pthread目录,拷贝workqueue_private.h到pthread目录中
⌘ + B
✘ pthread/qos_private.h file not found (objc-os.h)
./libpthread-218.20.1/private/qos_private.h
✔︎ ./libpthread-218.20.1/sys/qos_private.h
⌘ + B
✘ sys/qos_private.h file not found (objc-os.h)
./libpthread-218.20.1/private/qos_private.h
✔︎ ./libpthread-218.20.1/sys/qos_private.h
⌘ + B
✘ objc-shared-cache.h file not found (objc-os.h)
✔︎ ./dyld-421.2/include/objc-shared-cache.h
⌘ + B
终于不报xxx.h not found的错误了
继续,解决变量未定义的问题
用grep的方式去找出来
1 | $ grep -rne "#define.*_PTHREAD_TSD_SLOT_MACH_THREAD_SELF" . |
✔︎ /libpthread-218.20.1/private/tsd_private.h
workqueue_private.h*也是来自于/libpthread-218.20.1/private,拷贝到了pthread目录下,将tsd_private.h也拷贝至pthread*目录下
还是报错,仔细检查objc-os.h 发现并未引入tsd_private.h头文件
在第34行上下加一句
1 | #include <pthread/tsd_private.h> |
⌘ + B
✘ ‘os/tsd.h’ file not found (tsd_private.h)
./libdispatch-703.20.1/src/shims/tsd.h
✔︎ ./xnu-3789.21.4/libsyscall/os/tsd.h
⌘ + B
✘ ‘pthread/spinlock_private.h’ file not found (tsd_private.h)
✔︎./libpthread-218.20.1/private/spinlock_private.h
⌘ + B
错误”变多了”,看警告,发现重复定义了,参考上面的blog
重复定义了pthread_lock_t,切换到Terminal,⌘+T打开新的一个Tab,cd到objc4-680/include/那grep一下就好了:
cd ../objc4-680/include/
grep -rne “typedef.*pthread_lock_t” .
结果:
./pthread/spinlock_private.h:59:typedef volatile OSSpinLock pthread_lock_t;
./System/pthread_machdep.h:214:typedef int pthread_lock_t;
从结果发现我们之前引入的pthread_machdep.h已经typedef过了。注释掉其中一个就好。但我这里选择注释掉pthread_machdep.h的,在Line 214:
//typedef int pthread_lock_t;
为什么是它呢?因为它是我们从Libc拷过来的,而Libc我们下载了较旧的版本。…
因此注释掉pthread_machdep.h中重定义的部分
根据重定义pthread_lock_t的错误
1 | $ grep -rne "typedef.*pthread_lock_t" . |
./Libc-825.40.1/fbsdcompat/spinlock.h:65:typedef pthread_lock_t spinlock_t;./Libc-825.40.1/pthreads/pthread_machdep.h:214:typedef int pthread_lock_t;
✔︎ ./libpthread-218.20.1/private/spinlock_private.h:59:typedef volatile OSSpinLock pthread_lock_t __deprecated_msg(“Use <os/lock.h> instead”);./libpthread-218.20.1/tests/cond_hang3.c:14:typedef long pthread_lock_t;
⌘ + B
✘ Unknown type name ‘pthread_priority_t’ (objc-os.h)
1 | $ grep -rne "pthread_priority_t;" . |
./libdispatch-703.20.1/src/shims.h:42:typedef unsigned long pthread_priority_t;./libdispatch-703.20.1/src/shims.h:80:typedef unsigned long pthread_priority_t;
✔︎ ./libpthread-218.20.1/private/qos_private.h:38:typedef unsigned long pthread_priority_t;
1 | #include <pthread/qos_private.h> |
⌘ + B
1 | $ grep -rne "os_unfair_lock" . |
./libpthread-218.20.1/src/internal.h:105:typedef os_unfair_lock _pthread_lock;
./libpthread-218.20.1/src/internal.h:108:#define _PTHREAD_LOCK(lock) os_unfair_lock_lock_with_options_inline(&(lock), OS_UNFAIR_LOCK_DATA_SYNCHRONIZATION)
./libpthread-218.20.1/src/internal.h:109:#define _PTHREAD_LOCK_FROM_MACH_THREAD(lock) os_unfair_lock_lock_inline_no_tsd_4libpthread(&(lock))
./libpthread-218.20.1/src/internal.h:110:#define _PTHREAD_UNLOCK(lock) os_unfair_lock_unlock_inline(&(lock))
./libpthread-218.20.1/src/internal.h:111:#define _PTHREAD_UNLOCK_FROM_MACH_THREAD(lock) os_unfair_lock_unlock_inline_no_tsd_4libpthread(&(lock))
这里路径是src,有点不一样,先不要引入internal.h,先Google一下,os_unfair_lock
OSSpinlock is depreciated
os_unfair_lock
是个结构体,在facebook/folly - macOS Sierra issues
中提到了warning: ‘OSSpinLockUnlock’ is deprecated: first deprecated in macOS 10.12 - Use os_unfair_lock_unlock() from <os/lock.h> instead [-Wdeprecated-declarations]
所以引入
1 | #include <os/lock.h> |
⌘ + B
grep后发现又在internal.h中,根据lock.h,修改一下lock() & unlock()方法
修改后
⌘ + B
✘ ‘_simple.h’ file not found (objc-errors.mm)
✔︎ ./Libc-825.40.1/gen/_simple.h
⌘ + B
✘ Use of undeclared identifier ‘os_unfair_lock_assert_owner’ (objc-lockdebug.mm)
1 | $ grep -rne "os_unfair_lock_assert_owner" . |
没有匹配项
Google了未发现,先将该函数的功能修改为输出日志
⌘ + B
✘ ‘Block_private.h’ file not found (objc-block-trampolines.mm)
✔︎ ./libclosure-67/Block_private.h
⌘ + B
链接动态库的时候不能打开libobjc.order,查看在对应路径下并没有libobjc.order文件,发现objc工程已经有libobjc.order,应该会有字段说明要引用的路径,想办法让工程引入本身的libobjc.order文件
最后找到Build Settings的Order File
将该字段统一修改为$(PROJECT_DIR)/libobjc.order
⌘ + B
因为工程中并没有CrashReporterClient的库
将Other Linker flags*中的-lCrashReporterClient参数去掉
*⌘ + B**
终于编译成功了☺,然后创建一个debug-objc的target,导入修改的libobjc.A.dylib
⌘ + R
正常运行并输出,lockdebug_mutex_assert_locked被调用了很多次,但不会影响,可注释掉它的输出
OK,已经可以进行调试了
续
可以调试,但是在debug-objc工程中还是无法访问objc_class
进行以下操作
- 添加代码
1 | objc_class *obj_1 = (objc_class *)[NSObject class]; |
- main.m 引入#import “objc-private.h” // 会报错
- main.m -> main.mm 因为 objc-private.h 是objetive-c++类型的
- CrashReporterClient.h 报错 -> 同 objc-706 工程类似处理,在 buildsetting ,设置LIBC_NO_LIBCRASHREPORTERCLIENT
- objc-probes.h file not found => 从网上找到文件放到工程的 include 目录,并在 debug-objc 添加 $(SRCROOT)/include
- maptable.h file not found(<objc/maptable.h>) => 从网上找到文件后放到工程的 include/objc(目录没有要创建)
- 编译成功
截图如下: