编译Objc4-838

编译Objc源码

要诀:
能删则删, 不确定先注释,
需加须加, 能设置就设置.

准备工作

本次编译objc4-838源码, 即对应macOS 12.2, 高版本未尝试, 理论上大版本一致可行
以下相关源码均可在Apple Open SourcemacOS Monterey 12 -> macOS 12.2 分支看到

objc4-838 下载地址

dyld-941.5 下载地址

Libc-1506.40.4 下载地址

libclosure-79 下载地址

libplatform-273.40.1 下载地址

libpthread-485.60.2 下载地址

xnu-8019.80.24 下载地址

旧版源码下载
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

  1. 'sys/reason.h' file not found
    xnu源码的/bsd/sys/reason.h目录下载文件reason.h文件, 拷贝至/common下, 对应/sys/reason.h目录

  2. 'os/feature_private.h' file not found
    直接注释即可, 共三处, 其NSObject.mm有两处

  3. '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 0x000A0E00
  4. Expected ','/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) 的条件即可

  5. 'os/lock_private.h' file not found
    libplatform源码的/private/os/lock_private.h目录下载文件lock_private.h文件, 拷贝至/common下, 对应/os/lock_private.h目录

  6. 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) 的条件即可

  7. 'os/base_private.h' file not found
    libplatform-220.100.1源码的/private/os/base_private.h目录下载文件base_private.h文件, 拷贝至/common下, 对应/os/base_private.h目录

  8. 'pthread/tsd_private.h' file not found
    libpthread源码的/private/pthread/tsd_private.h目录下载文件tsd_private.h文件, 拷贝至/common下, 对应/pthread/tsd_private.h目录

  9. 'System/machine/cpu_capabilities.h' file not found
    xnu源码的/osfmk/machine/cpu_capabilities.h目录下载文件cpu_capabilities.h文件, 拷贝至/common下, 对应/System/machine/cpu_capabilities.h目录

  10. 'os/tsd.h' file not found
    xnu源码的libsyscall/os/tsd.h目录下载文件tsd.h文件, 拷贝至/common下, 对应/os/tsd.h目录

  11. 'pthread/spinlock_private.h' file not found
    libpthread源码的/private/pthread/spinlock_private.h目录下载文件spinlock_private.h文件, 拷贝至/common下, 对应/pthread/spinlock_private.h目录

  12. 'System/pthread_machdep.h' file not found
    Libc-825.26源码的/pthreads/pthread_machdep.h目录下载文件pthread_machdep.h文件, 拷贝至/common下, 对应/System/pthread_machdep.h目录

  13. '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

  1. 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

  1. Unknown type name 'uint32_t' 'uint64_t, Use of undeclared identifier 'INT64_C'/llvm-MathExtras.h 文件中
    导入头文件 #include <cstdint> 即可解决

  2. Use of undeclared identifier 'dyld_fall_2020_os_versions'

  3. Use of undeclared identifier 'objc4' 'preoptimizedCaches'

  4. 'objc-shared-cache.h' file not found
    dyld源码的/include/objc-shared-cache.h目录下载文件objc-shared-cache.h文件, 拷贝至/common下, 对应/objc-shared-cache.h目录

  5. Use of undeclared identifier 'dyld_platform_version_macOS_10_13'

  6. Use of undeclared identifier 'dyld_platform_version_macOS_10_11'

  7. Use of undeclared identifier 'dyld_fall_2018_os_versions' 注释部分判断条件

  8. 'Block_private.h' file not found
    libclosure源码的/Block_private.h目录下载文件Block_private.h文件, 拷贝至/common下, 对应/Block_private.h目录

  9. 'Cambria/Traps.h' file not found
    直接注释即可

    1
    2
    // #include <Cambria/Traps.h>
    // #include <Cambria/Cambria.h>
  10. '_simple.h' file not found
    libplatform源码的/private/_simple.h目录下载文件_simple.h文件, 拷贝至/common下, 对应/_simple.h目录

  11. 'os/linker_set.h' file not found
    xnu源码的/bsd/sys/linker_set.h目录下载文件linker_set.h文件, 拷贝至/common下, 对应/os/linker_set.h目录

  12. 'kern/restartable.h' file not found
    xnu源码的/osfmk/kern/restartable.h目录下载文件restartable.h文件, 拷贝至/common下, 对应/kern/restartable.h目录

  13. Use of undeclared identifier 'oah_is_current_process_translated' 和 'objc_thread_get_rip' 注释此if分支

  14. 'os/reason_private.h' file not found
    xnu源码的/libkern/os/reason_private.h目录下载文件reason_private.h文件, 拷贝至/common下, 对应/os/reason_private.h目录

  15. 'os/variant_private.h' file not found
    Libc源码的/os/variant_private.h目录下载文件variant_private.h文件, 拷贝至/common下, 对应/os/variant_private.h目录

    还要去掉文件里面的 bridgeos 、 bridgeos(4.0) 参数

  16. Use of undeclared identifier 'dyld_platform_version_bridgeOS_2_0' iOS_10_0 macOS_10_12 tvOS_10_0 watchOS_3_0 注释此if判断

  17. '_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

  1. 新增Target
    点击在 Target 左下角的 +, 然后选择 macOS -> Command Line Tool, 随便取名, 比如TestOC

  2. 链接libobjc.A.dylib
    选择 Target -> TestOC -> General -> Frameworks and Libraries+ 然后选择 libobjc.A.dylib 点击 Add

编译 TestOC Target

  1. 选择新 Target - TestOC

  2. 愉快的在main中写代码吧

  3. 此时可能会发现, 断点发虚, 无法触发

    断点失败, 解决方法有二

    • 第一种: 关闭LTO(Link-Time Optimization),
      找到Targets -> Build Settings -> Link-Time Optimization, 选择值为 NO 即可
      LTO 代码链接时候的一个优化选项, Apple官方解释:
      1
      2
      3
      4
      5
      6
      7
      Enabling 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.
    • 第二种:
      1. 找到 Build Phases -> Compile Sources 中,确保 main.m 在最最最前面
      2. 找到 Targets -> Build Settings -> Enable Hardened Runtime ,确保值为 NO
文章目录
  1. 1. 编译Objc源码
  2. 2. 准备工作
  3. 3. Project 相关
    1. 3.1. 修改 Base SDK
    2. 3.2. 选择编译 Targets 为 objc
  4. 4. Targets 配置相关
    1. 4.1. 修改 Script
    2. 4.2. 编译时 报错
    3. 4.3. 链接时 报错
  5. 5. 终于 Build Succeded
  6. 6. 添加测试 Target
  7. 7. 编译 TestOC Target