前言
为什么会想要调试源码?
苹果开源了部分源码, 但相似内容太多, 基本找不到代码见的对应关系, 如果能像自己工程一样进行跳转那多好哇~~
苹果源码开源地址: https://opensource.apple.com/
本文将以macOS 11.2/objc4-818.2的源码进行配置
源码配置
首先选中运行target: objc > My Mac
然后⌘+b进行编译
翻一下爆红的点看看都有哪些错误, 然后找到下面对应的解决方案~
编译报错 'sys/reason.h' file not found
解决方案: 谷歌中输入reason.h site:opensource.apple.com定向检索
点进去搜索结果里面, 进行"文件另存为"下载
下载后, 在objc源码根目录中创建一个文件夹"ZKLib",
然后因为reason.h文件是在sys目录下的, 所以我们在"ZKLib"目录下创建"sys"文件夹, 并把reason.h放到该目录里面(如下图)
接下来我们在源码工程 target > objc > Build Settings中搜索"Header Search Paths", 给Debug和Release都加上$(SRCROOT)/ZKLib即可
(不需要把ZKLib拉进源码Xcode工程里哦! )\
然后继续⌘+b编译
其它文件缺失
我们会发现相同的报错还有\
'mach-o/dyld_priv.h' file not found
'os/lock_private.h' file not found
'os/base_private.h' file not found
'pthread/tsd_private.h' file not found
'System/machine/cpu_capabilities.h' file not found
'os/tsd.h' file not found
'pthread/spinlock_private.h' file not found
'System/pthread_machdep.h' file not found
'CrashReporterClient.h' file not found
'objc-shared-cache.h' file not found
'_simple.h' file not found
'Block_private.h' file not found
这些报错的解决方案都跟上面的一样处理
objc源码文件代码修改
CrashReporterClient明明放进去了还是"file not found"
打开CrashReporterClient.h文件,
在#ifdef前面加上以下代码:
#define LIBC_NO_LIBCRASHREPORTERCLIENT
注释掉一些妨碍编译的代码
总的来说一共有这么多:
具体都有:
objc-cache.mm
87行:
#if TARGET_OS_OSX
//#include <cambria traps.h>
//#include <cambria cambria.h>
#endif
1120行:
//#if TARGET_OS_OSX
// if (oah_is_current_process_translated()) {
// kern_return_t ret = objc_thread_get_rip(threads[count], (uint64_t*)&pc);
// if (ret != KERN_SUCCESS) {
// pc = PC_SENTINEL;
// }
// } else {
// pc = _get_pc_for_thread (threads[count]);
// }
//#else
pc = _get_pc_for_thread (threads[count]);
//#endif
</cambria></cambria>
NSObject.mm
42行:
//#include <os feature_private.h>
extern "C" {
//#include <os reason_private.h>
//#include <os variant_private.h>
}
1185行:
// if (DebugPoolAllocation || sdkIsAtLeast(10_12, 10_0, 10_0, 3_0, 2_0)) {
// // OBJC_DEBUG_POOL_ALLOCATION or new SDK. Bad pop is fatal.
// _objc_fatal
// ("Invalid or prematurely-freed autorelease pool %p.", token);
// }
</os></os></os>
objc-runtime.mm
36行:
//#include <os feature_private.h> // os_feature_enabled_simple()
379行:
// if (!dyld_program_sdk_at_least(dyld_fall_2020_os_versions))
// DisableAutoreleaseCoalescingLRU = true;
444行:
// if (!os_feature_enabled_simple(objc4, preoptimizedCaches, true)) {
// DisablePreoptCaches = true;
// }
</os>
objc-class.mm
896行:
// LINKER_SET_FOREACH(_dupi, const objc_duplicate_class **, "__objc_dupclass") {
// const objc_duplicate_class *dupi = *_dupi;
//
// if (strcmp(dupi->name, name) == 0) {
// return;
// }
// }
objc-os.mm
31行:
//#include "objc-bp-assist.h"
\
567行:
// if (!dyld_program_sdk_at_least(dyld_platform_version_macOS_10_13)) {
// DisableInitializeForkSafety = true;
// if (PrintInitializing) {
// _objc_inform("INITIALIZE: disabling +initialize fork "
// "safety enforcement because the app is "
// "too old.)");
// }
// }
objc-runtime-new.mm
3547行:
// if (!dyld_program_sdk_at_least(dyld_platform_version_macOS_10_11)) {
// DisableNonpointerIsa = true;
// if (PrintRawIsa) {
// _objc_inform("RAW ISA: disabling non-pointer isa because "
// "the app is too old.");
// }
// }
8328行:
if (!DisableTaggedPointerObfuscation /**&& dyld_program_sdk_at_least(dyld_fall_2018_os_versions)*/) {
编译报错 Can't open order file: libobjc.order
具体来说是这么一个报错:
解决方案:
在源码工程 target > objc > Build Settings中搜索"Order File", 把Debug和Release的内容都改成$(SRCROOT)/libobjc.order即可
编译报错 Library not found for -lCrashReporterClient
在源码工程 target > objc > Build Settings中搜索"Other Linker Flags", 把Debug和Release中的-lCrashReporterClient都删掉
编译报错 SDK "macosx.internal" cannot be located.
具体来说是这么一个报错:
解决方案:
在源码工程 target > objc > Build Phases中找到Run Script(markgc)里面, 把脚本中的macosx.internal改成macosx即可
编译报错 library not found for -loah
具体来说是这么一个报错:
解决方案:
在源码工程 target > objc > Build Settings中搜索"Other Linker Flags", 把Debug和Release里的-loah删掉
编译报错 '_static_assert' declared as an array with a negative size
具体来说是这么一个报错:
解决方案:
把报错的这两行注释掉~~
编译成功!
诶嘿嘿~
是不是突然间看到"Build Successed"就很兴奋了, 反正我是兴奋了
编译调试
新建一个target
选择macOS里面的Command Line Tool (我们这里不需要界面)
将target命名为ZKBuild (如下图)
绑定依赖关系
在源码工程 target > ZKBuild > Build Phases中
在Dependencies 添加objc
打断点进行调试
切换运行target: ZKBuild > My Mac
在main.m代码中打断点, 并按⌘+r运行
此时按
(step into)进入这一行代码里面
来到objc源码里面, 则表示已经能成功调试objc源码
Original: https://www.cnblogs.com/mysweetAngleBaby/p/16747152.html
Author: 一眼万年的星空
Title: 使用objc4V818.2源码编译,没有什么比苹果底层源码更有说服力去证明底层原理真假
相关阅读
Title: python爬虫之抓取小说(逆天邪神)
2022-03-06 23:05:11
申明:自我娱乐,对自我学习过程的总结。
环境:
项目目标:
最终效果:都已实现。可以判断小说更新了没;更新了就下载下来;通过调整小说的已看章节数(就是你上次浏览小说章节位置记录)可以达到直接保存整本小说。
项目实现流程:
我这里只写了一个main.py,就一个主函数解决了。
import requestsimport refrom bs4 import BeautifulSoupimport osif __name__ == '__main__': novel_url = "https://www.bige3.com/book/1030/" return_value = is_update(novel_url) if return_value == 0: print("小说尚未更新!") else: print("小说已更新" + str(return_value) +"章!") print("正在下载已更新的小说......") download_novel(return_value)
def is_update(url): heards = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36" } try: resp = requests.get(url, headers=heards) resp.raise_for_status() resp.encoding = 'utf-8' except: print("爬取失败") resp = re.findall(r'(.*?)', resp.text) with open("小说更新记录.txt", "r", encoding='utf-8') as f: data = f.read() if data == str(resp[-1]): return 0 else: data_num = re.findall(r'\d+', data) data_num = ''.join(data_num) resp_num = re.findall(r'\d+', resp[-1]) resp_num = ''.join(resp_num) gap_num = int(resp_num)-int(data_num) with open("小说更新记录.txt", "w", encoding='utf-8') as f: f.write(str(resp[-1])) print("writing is ok!") return gap_num
def download_novel(return_value): if return_value >= 1: for i in range(1, return_value+1, 1): print(i) with open("小说更新记录.txt", "r", encoding='utf-8') as f: data = f.read() data_num = re.findall(r'\d+', data) data_num = ''.join(data_num) download_num = int(data_num)+1-(i-1) print(novel_url+str(download_num)+'.html') resp = requests.get(novel_url+str(download_num)+'.html') soup = BeautifulSoup(resp.text, 'lxml') soup.select('#chaptercontent') mytxt = soup.text[soup.text.find('下一章'):soup.text.rfind('『点此报错')] mytxt = mytxt[3:] mytxt = mytxt.strip() mytxt = mytxt.replace(' ', '\n') novel_save_location = "./novel_downloads/逆天邪神第"+str(download_num-1)+"章.txt" with open(novel_save_location, "w", encoding='utf-8') as f: f.write(mytxt) print("下载完毕!") else: print("invalid parameter!")
注意:
import requestsfrom lxml import etreeimport refrom bs4 import BeautifulSoupimport osdef is_update(url): heards = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36" } try: resp = requests.get(url, headers=heards) resp.raise_for_status() resp.encoding = 'utf-8' except: print("爬取失败") resp = re.findall(r'(.*?)', resp.text) with open("小说更新记录.txt", "r", encoding='utf-8') as f: data = f.read() if data == str(resp[-1]): return 0 else: data_num = re.findall(r'\d+', data) data_num = ''.join(data_num) resp_num = re.findall(r'\d+', resp[-1]) resp_num = ''.join(resp_num) gap_num = int(resp_num)-int(data_num) with open("小说更新记录.txt", "w", encoding='utf-8') as f: f.write(str(resp[-1])) print("writing is ok!") return gap_numdef download_novel(return_value): if return_value >= 1: for i in range(1, return_value+1, 1): print(i) with open("小说更新记录.txt", "r", encoding='utf-8') as f: data = f.read() data_num = re.findall(r'\d+', data) data_num = ''.join(data_num) download_num = int(data_num)+1-(i-1) print(novel_url+str(download_num)+'.html') resp = requests.get(novel_url+str(download_num)+'.html') soup = BeautifulSoup(resp.text, 'lxml') soup.select('#chaptercontent') mytxt = soup.text[soup.text.find('下一章'):soup.text.rfind('『点此报错')] mytxt = mytxt[3:] mytxt = mytxt.strip() mytxt = mytxt.replace(' ', '\n') novel_save_location = "./novel_downloads/逆天邪神第"+str(download_num-1)+"章.txt" with open(novel_save_location, "w", encoding='utf-8') as f: f.write(mytxt) print("下载完毕!") else: print("invalid parameter!")if __name__ == '__main__': novel_url = "https://www.bige3.com/book/1030/" return_value = is_update(novel_url) if return_value == 0: print("小说尚未更新!") else: print("小说已更新" + str(return_value) +"章!") print("正在下载已更新的小说......") download_novel(return_value) os.system("pause")
缺点:单线程,没有用到异步协程,也没有用线程池实现对小说下载章节数较多时的快速下载优势。之后有空再优化代码,并实现相应的功能。
实现效果:
例如章节是目前是
最新章节为:1936章 灾厄奏鸣 ,我改个数字演示。
不改话,就没有新章节更新:
改后跑起来,应该是
对应的文件夹里是:
打开后内容是:
Over!!!!!
步骤:
结果是:
项目中用到的知识点:
这里面可以有些在优化程序时被我给去掉了,嘿嘿
resp = requests.get(url, headers=heards)
data_num = re.findall(r'\d+', data) data_num = ''.join(data_num)
resp = re.findall(r'(.*?)', resp.text)
encoding='utf-8' 是有必要的,不然会报错。
with open("小说更新记录.txt", "r", encoding='utf-8') as f: data = f.read()
with open("小说更新记录.txt", "w", encoding='utf-8') as f: f.write(str(resp[-1]))
表示识别标签
soup = BeautifulSoup(resp.text, 'lxml')soup.select('#chaptercontent')
resp[-1]
data_num = re.findall(r'\d+', data)
soup.text str型find('下一章') 左边开始第一个索引rfind('『点此报错') 右边开始第一个索引
mytxt = soup.text[soup.text.find('下一章'):soup.text.rfind('『点此报错')]
novel_save_location = "./novel_downloads/逆天邪神第"+str(download_num-1)+"章.txt"
1.里面 有空白,直接用
mytxt = mytxt.strip()
时没有去掉,不知道啥原因。我记得听网课说是:去掉空格,空白,换行符,其他好像都去了,最后还剩小说之间一些空白。
解决方式:因为没有发现是啥符号(notepad++),于是之间将空白拿过来用(copy)。
mytxt=mytxt.replace(' ', '\n')
感谢观看!!!第一次写,好慢,好菜,回去写作业去了。呜呜呜
Original: https://www.cnblogs.com/bluemapleleaf/p/15974104.html
Author: bulemaple
Title: python爬虫之抓取小说(逆天邪神)