编译Objc源码
要诀:
能删则删, 不确定先注释,
需加须加, 能设置就设置.
准备工作
本次编译objc4-838
源码, 即对应macOS 12.2
, 高版本未尝试, 理论上大版本一致可行
以下相关源码均可在Apple Open Source中 macOS Monterey 12 -> macOS 12.2
分支看到
旧版源码下载
Libc-825.26 下载地址 在 OS X Mountain Lion 10.8 -> Mac OS X 10.8.4
分支下
libplatform-220.100.1 下载地址在 macOS Catalina 10.15 -> macOS 10.15.6
分支下
Project 相关
修改 Base SDK
在 Project -> Build Setting -> Base SDK
选择为macOS
选择编译 Targets 为 objc
Targets 配置相关
修改 Script
在 Targets -> objc -> Build Phases -> Run Script (markgc)
将 macosx.internal
改成 macosx
编译时 报错
文件缺失居多, xx file not found
在项目根目录新增一目录, 用来放缺失文件, (名字可以自定义, 比如/common
)
然后在项目 Targets -> Build Settings -> Header Search Paths
新增 /common
路径:$(SRCROOT)/common
'sys/reason.h' file not found
在xnu
源码的/bsd/sys/reason.h
目录下载文件reason.h
文件, 拷贝至/common
下, 对应/sys/reason.h
目录'os/feature_private.h' file not found
直接注释即可, 共三处, 其NSObject.mm
有两处'mach-o/dyld_priv.h' file not found
在dyld
源码的/include/mach-o/dyld_priv.h
目录下载文件dyld_priv.h
文件, 拷贝至/common
下, 对应/mach-o/dyld_priv.h
目录然后要此文件添加宏定义:
1
2
3
4#define DYLD_MACOSX_VERSION_10_11 0x000A0B00
#define DYLD_MACOSX_VERSION_10_12 0x000A0C00
#define DYLD_MACOSX_VERSION_10_13 0x000A0D00
#define DYLD_MACOSX_VERSION_10_14 0x000A0E00Expected ','
在/mach-o/dyld_priv.h
文件中
移除__API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0), bridgeos(3.0))
中bridgeos(3.0)
的条件即可'os/lock_private.h' file not found
在libplatform
源码的/private/os/lock_private.h
目录下载文件lock_private.h
文件, 拷贝至/common
下, 对应/os/lock_private.h
目录Expected ','
在/os/lock_private.h
文件中
移除__API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0), bridgeos(4.0))
中bridgeos(4.0)
的条件即可'os/base_private.h' file not found
在libplatform-220.100.1
源码的/private/os/base_private.h
目录下载文件base_private.h
文件, 拷贝至/common
下, 对应/os/base_private.h
目录'pthread/tsd_private.h' file not found
在libpthread
源码的/private/pthread/tsd_private.h
目录下载文件tsd_private.h
文件, 拷贝至/common
下, 对应/pthread/tsd_private.h
目录'System/machine/cpu_capabilities.h' file not found
在xnu
源码的/osfmk/machine/cpu_capabilities.h
目录下载文件cpu_capabilities.h
文件, 拷贝至/common
下, 对应/System/machine/cpu_capabilities.h
目录'os/tsd.h' file not found
在xnu
源码的libsyscall/os/tsd.h
目录下载文件tsd.h
文件, 拷贝至/common
下, 对应/os/tsd.h
目录'pthread/spinlock_private.h' file not found
在libpthread
源码的/private/pthread/spinlock_private.h
目录下载文件spinlock_private.h
文件, 拷贝至/common
下, 对应/pthread/spinlock_private.h
目录'System/pthread_machdep.h' file not found
在Libc-825.26
源码的/pthreads/pthread_machdep.h
目录下载文件pthread_machdep.h
文件, 拷贝至/common
下, 对应/System/pthread_machdep.h
目录'CrashReporterClient.h' file not found
在
Libc-825.26
源码的/include/CrashReporterClient.h
目录下载文件CrashReporterClient.h
文件, 拷贝至/common
下, 对应/CrashReporterClient.h
目录还未结束, 因为还缺少宏定义, 在
Targets -> objc -> Build Settings -> Preprocessor Macros
中,添加LIBC_NO_LIBCRASHREPORTERCLIENT
- 在
pthread_machdep.h
文件中一个typedef和三个函数, 这些全部注释即可
Typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int'))
Static declaration of '_pthread_has_direct_tsd' follows non-static declaration
Static declaration of '_pthread_getspecific_direct' follows non-static declaration
Static declaration of '_pthread_setspecific_direct' follows non-static declaration
Unknown type name 'uint32_t' 'uint64_t, Use of undeclared identifier 'INT64_C'
在/llvm-MathExtras.h
文件中
导入头文件#include <cstdint>
即可解决Use of undeclared identifier 'dyld_fall_2020_os_versions'
Use of undeclared identifier 'objc4' 'preoptimizedCaches'
'objc-shared-cache.h' file not found
在dyld
源码的/include/objc-shared-cache.h
目录下载文件objc-shared-cache.h
文件, 拷贝至/common
下, 对应/objc-shared-cache.h
目录Use of undeclared identifier 'dyld_platform_version_macOS_10_13'
Use of undeclared identifier 'dyld_platform_version_macOS_10_11'
Use of undeclared identifier 'dyld_fall_2018_os_versions'
注释部分判断条件'Block_private.h' file not found
在libclosure
源码的/Block_private.h
目录下载文件Block_private.h
文件, 拷贝至/common
下, 对应/Block_private.h
目录'Cambria/Traps.h' file not found
直接注释即可1
2// #include <Cambria/Traps.h>
// #include <Cambria/Cambria.h>'_simple.h' file not found
在libplatform
源码的/private/_simple.h
目录下载文件_simple.h
文件, 拷贝至/common
下, 对应/_simple.h
目录'os/linker_set.h' file not found
在xnu
源码的/bsd/sys/linker_set.h
目录下载文件linker_set.h
文件, 拷贝至/common
下, 对应/os/linker_set.h
目录'kern/restartable.h' file not found
在xnu
源码的/osfmk/kern/restartable.h
目录下载文件restartable.h
文件, 拷贝至/common
下, 对应/kern/restartable.h
目录Use of undeclared identifier 'oah_is_current_process_translated' 和 'objc_thread_get_rip'
注释此if
分支'os/reason_private.h' file not found
在xnu
源码的/libkern/os/reason_private.h
目录下载文件reason_private.h
文件, 拷贝至/common
下, 对应/os/reason_private.h
目录'os/variant_private.h' file not found
在Libc
源码的/os/variant_private.h
目录下载文件variant_private.h
文件, 拷贝至/common
下, 对应/os/variant_private.h
目录还要去掉文件里面的
bridgeos 、 bridgeos(4.0)
参数Use of undeclared identifier 'dyld_platform_version_bridgeOS_2_0' iOS_10_0 macOS_10_12 tvOS_10_0 watchOS_3_0
注释此if
判断'_static_assert' declared as an array with a negative size
链接时 报错
Library not found for -lCrashReporterClient
进入Targets -> objc -> Build Setting -> Other Linker Flags
中,删除-lCrashReporterClient
Library not found for -loah
进入Targets -> objc -> Build Setting -> Other Linker Flags
中,删除-loah
终于 Build Succeded
添加测试 Target
新增Target
点击在Target
左下角的+
, 然后选择macOS -> Command Line Tool
, 随便取名, 比如TestOC
链接
libobjc.A.dylib
选择Target -> TestOC -> General -> Frameworks and Libraries
的+
然后选择libobjc.A.dylib
点击Add
编译 TestOC Target
选择新 Target - TestOC
愉快的在main中写代码吧
此时可能会发现, 断点发虚, 无法触发
断点失败, 解决方法有二
- 第一种: 关闭LTO(
Link-Time Optimization
),
找到Targets -> Build Settings -> Link-Time Optimization
, 选择值为NO
即可
LTO 代码链接时候的一个优化选项, Apple官方解释:1
2
3
4
5
6
7Enabling this setting allows optimization across file boundaries during linking.
**No:*
Disabled. Do not use link-time optimization.
**Monolithic Link-Time Optimization:*
This mode performs monolithic link-time optimization of binaries, combining all executable code into a single unit and running aggressive compiler optimizations.
**Incremental Link-Time Optimization:*
This mode performs partitioned link-time optimization of binaries, inlining between compilation units and running aggressive compiler optimizations on each unit in parallel. This enables fast incremental builds and uses less memory than Monolithic LTO. - 第二种:
- 找到
Build Phases -> Compile Sources
中,确保main.m
在最最最前面 - 找到
Targets -> Build Settings -> Enable Hardened Runtime
,确保值为NO
- 找到
- 第一种: 关闭LTO(