{"id":19174042,"url":"https://github.com/onezens/wechatbot","last_synced_at":"2025-08-15T18:39:39.707Z","repository":{"id":166687745,"uuid":"178149459","full_name":"onezens/WeChatBot","owner":"onezens","description":"Tweak 工程创建、配置教程 \u0026 实现logos语法自动补全","archived":false,"fork":false,"pushed_at":"2021-09-24T03:17:07.000Z","size":45,"stargazers_count":44,"open_issues_count":0,"forks_count":16,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-07T18:29:21.391Z","etag":null,"topics":["ios","theos","theos-tweak","tweak","wechat"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onezens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-03-28T07:27:39.000Z","updated_at":"2025-02-19T13:42:56.000Z","dependencies_parsed_at":"2023-06-01T16:15:24.479Z","dependency_job_id":null,"html_url":"https://github.com/onezens/WeChatBot","commit_stats":null,"previous_names":["onezens/wechatbot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/onezens/WeChatBot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onezens%2FWeChatBot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onezens%2FWeChatBot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onezens%2FWeChatBot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onezens%2FWeChatBot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onezens","download_url":"https://codeload.github.com/onezens/WeChatBot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onezens%2FWeChatBot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270614556,"owners_count":24616730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","theos","theos-tweak","tweak","wechat"],"created_at":"2024-11-09T10:15:47.054Z","updated_at":"2025-08-15T18:39:39.686Z","avatar_url":"https://github.com/onezens.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"在创建一个逆向工程项目时，如何让工程使用起来更加便捷和易于扩展，以及编译器识别，能够大大提升我们日常的开发效率以及代码的质量。本文主要描述了，如果使用Theos的tweak工程，创建一个可以被Xcode编译器识别的项目工程，以及工程中常用的配置。\n\n## 搭建逆向环境\nhttps://www.onezen.cc/2017/09/16/iosrevert/revdevconfig.html\n\n搭建好环境之后，创建对应的tweak工程项目\n\n## 创建Xcode项目\n\n根据前面创建好的tweak项目名称，创建一个Xcode静态库项目，然后将tweak和创建的Xcode项目混合到一起\n\n![](https://src.onezen.cc/blog/1216462-d602af3788b41a13.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n\n在Xcode项目里面创建一个Config文件夹（New Group Without Folder），将Makefile、对应的plist文件、control配置文件，不要copy放到此目录下。 然后在Xcode里面，创建对应的文件夹，然后将生成的`.xm`文件的后缀名，全部替换为`.xmi` ，并且放到项目的最外层，作为唯一的入口类\n\n设置Tweak.xmi在Xcode编译器识别类型为`Objective-C++`\n\n![](https://src.onezen.cc/blog/1216462-e6a4fa8809716f16.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n![](https://src.onezen.cc/blog/1216462-6b7965fe33f1717f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n设置XcodeTheos头文件，让编译器识别logos语法，对应的头文件的地址：[https://github.com/onezens/Xcode-Theos](https://github.com/onezens/Xcode-Theos)，导入项目之后，创建一个全局头文件，并且到该头文件放到`tweak.xmi`里面，发现里面的代码是黑色的，没有被编译器识别，这时候，关闭项目重新打开后发现会被Xcode重新识别了\n\n接着设置`XcodeTheos`的宏，让Xcode识别logos宏\n![](https://src.onezen.cc/blog/1216462-e0e0023f295f139f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n一起设置好之后，开始写logos的hook代码，一切正常的话，你会发现Xcode写起logos代码超级顺畅，并且编译Xcode提示成功\n\n![](https://src.onezen.cc/blog/1216462-7fc24c32765286fa.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n\n## 将Xcode的配置和Makefile进行同步\n\n**首先修改Makefile的编译文件**\n在以后创建对应的logos语法的文件时，始终命名为xmi文件，并且写入Makefile里面\n\n```\nWeChatBot_FILES = Tweak.xm\n=\u003e 修改为：\nWeChatBot_FILES = Tweak.xmi\n```\n**在项目中头文件引用路径问题，导致编译失败**\n\n```\n➜  WeChatBot git:(master) ✗ make\n\u003e Making all for tweak WeChatBot…\n==\u003e Preprocessing Tweak.xmi…\nTweak.xmi:2:9: fatal error: 'wechatbot-prefix-header.h' file not found\n#import \"wechatbot-prefix-header.h\"\n        ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n1 error generated.\nmake[3]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/armv7/Tweak.mii] Error 1\nmake[2]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/armv7/WeChatBot.dylib] Error 2\nmake[1]: *** [internal-library-all_] Error 2\nmake: *** [WeChatBot.all.tweak.variables] Error 2\n```\n发现是头文件，引入的原因，Makefile里面设置头文件目录\n\n```\n#头文件\nWeChatBot_OBJCFLAGS += -I./WeChatBot/Headers/wechatHeaders/ \nWeChatBot_OBJCFLAGS += -I./WeChatBot/Headers/\n```\n**如果使用最新版的theos，我们会发现编译`.xmi` 文件会包下面的错误**\n\n```\n➜  WeChatBot git:(master) ✗ make\n\u003e Making all for tweak WeChatBot…\n==\u003e Preprocessing Tweak.xmi…\n==\u003e Compiling Tweak.xmi (arm64)…\nTweak.xmi:18:104: error: use of undeclared identifier 'MSHookMessageEx'\n{Class _logos_class$_ungrouped$MicroMessengerAppDelegate = objc_getClass(\"MicroMessengerAppDelegate\"); MSHookMessageEx(_logos_class$_ungro...\n                                                                                                       ^\n1 error generated.\nmake[3]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/Tweak.xmi.ca6fefe9.o] Error 1\nmake[2]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/WeChatBot.dylib] Error 2\nmake[1]: *** [internal-library-all_] Error 2\nmake: *** [WeChatBot.all.tweak.variables] Error 2\n```\n解决办法：\n1. 将所有的`.xmi`更改为`.xi`文件， 并且导入头文件 `#include \u003csubstrate.h\u003e`\n2. 使用老版本的theos: `https://github.com/onezens/theos.git` 替换原版进行编译\n\n\n**解决编译警告，导致报错的问题**\n\n```\n➜  WeChatBot git:(master) ✗ make\n\u003e Making all for tweak WeChatBot…\n==\u003e Preprocessing Tweak.xmi…\n==\u003e Compiling Tweak.xmi (arm64)…\nTweak.xmi:8:4: error: 'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated. Use UIAlertController with a preferredStyle\n      of UIAlertControllerStyleAlert instead [-Werror,-Wdeprecated-declarations]\n   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@\"Works for hook\" message:__null delegate:__null cancelButtonTitle:@\"cancel\" otherBu...\n   ^\n/opt/theos/sdks/iPhoneOS11.2.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAlertView.h:26:12: note: 'UIAlertView' has been explicitly marked\n      deprecated here\n@interface UIAlertView : UIView\n           ^\nTweak.xmi:8:27: error: 'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated. Use UIAlertController with a\n      preferredStyle of UIAlertControllerStyleAlert instead [-Werror,-Wdeprecated-declarations]\n   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@\"Works for hook\" message:__null delegate:__null cancelButtonTitle:@\"cancel\" otherBu...\n                          ^\n/opt/theos/sdks/iPhoneOS11.2.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAlertView.h:26:12: note: 'UIAlertView' has been explicitly marked\n      deprecated here\n@interface UIAlertView : UIView\n           ^\n2 errors generated.\nmake[3]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/Tweak.xmi.6c3ff448.o] Error 1\nmake[2]: *** [/Users/wz/Documents/GitHub/WeChatBot/.theos/obj/debug/arm64/WeChatBot.dylib] Error 2\nmake[1]: *** [internal-library-all_] Error 2\nmake: *** [WeChatBot.all.tweak.variables] Error 2\n```\n解决办法：\n1. 将Makefile里面的版本号降低：`TARGET = iphone:11.2:7.0`\n2. Makefile里面设置忽略方法过期警告：\n \n```\n#忽略OC警告\nWeChatBot_OBJCFLAGS +=  -Wno-deprecated-declarations\n```\n\n## 项目中动态和静态库的配置\n\n### 系统库\n\n```\n#导入系统的frameworks\nWeChatBot_FRAMEWORKS = Foundation UIKit\n\n#导入系统库\nWeChatBot_LIBRARIES = stdc++ c++\n```\n### 配置第三库\n\n```\n#导入第三方Frameworks, 动态库需特殊处理\nWeChatBot_LDFLAGS += -F./Libraries/dynamic -F./Libraries/static   # 识别的库实现\nWeChatBot_CFLAGS  += -F./Libraries/dynamic -F./Libraries/static   # 头文件识别\nWeChatBot_FRAMEWORKS += WCBFWStatic WCBFWDynamic\n\n#导入第三方lib\nWeChatBot_LDFLAGS += -L./Libraries/dynamic -L./Libraries/static \t# 识别的库实现\nWeChatBot_CFLAGS  += -I./Libraries/include  \t\t\t\t\t\t# 头文件识别\nWeChatBot_LIBRARIES += WCBStatic WCBDyLib \n```\n\n### 对应的本地文件夹说明\ninclude 放置所有的.a和.dylib库的头文件\ndynamic 放置所有的动态库的文件夹，动态库放一起，方便脚本处理\nstatic 防止所有的静态库的文件夹\n\n### 动态库问题\n当我们把，动态库加入的项目中，我们发现运行我们的tweak插件，在宿主APP中不起作用，通过log提示信息为：\n\n```\nApr 9 15:55:28 wz5 WeChat[5329] \u003cError\u003e: MS:Error: dlopen(/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib, 9): Library not loaded: @rpath/WCBFWDynamic.framework/WCBFWDynamic\n\t  Referenced from: /Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib\n\t  Reason: image not found\n```\n该日志信息中可以看出，宿主在自己的bundle里面，没有加载到我们的动态库，所以导致我们整个插件的功能不生效\n\n查看生成的动态库：\n\n```\n➜  WeChatBot git:(master) ✗ otool -L .theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib\n.theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib:\n\t/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib (compatibility version 0.0.0, current version 0.0.0)\n\t/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)\n\t/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1450.14.0)\n\t/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1450.14.0)\n\t/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3698.33.6)\n\t@rpath/WCBFWDynamic.framework/WCBFWDynamic (compatibility version 1.0.0, current version 1.0.0)\n\t/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)\n\t@rpath/libWCBDyLib.dylib (compatibility version 0.0.0, current version 0.0.0)\n\t/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)\n```\n我们发现tweak项目的动态库，依赖都是rpath，是宿主的bundle路径，所以我们要更改这个路径\n\n解决办法，通过脚本,更改动态库依赖路径：\n\n```\nTWEAK_NAME=WeChatBot\ncydiaLibPath=/Library/MobileSubstrate/DynamicLibraries/$TWEAK_NAME\ndylibPath=Libraries/dynamic\noriDylibPath=$dylibPath/ori\ntweakLayoutPath=layout$cydiaLibPath\necho $tweakLayoutPath\nif [[ ! -d $oriDylibPath ]]; then\n\tmkdir $oriDylibPath\nfi\n\nif [[ ! -d $tweakLayoutPath ]]; then\n\tmkdir $tweakLayoutPath\nfi\n\ncheckDylibID() {\n\tpath=$1\n\tlibFullPath=$2\n\tckLibId=$(otool -L $path | grep rpath)\n\tif [[ -n $ckLibId ]]; then\n\t\tcp -r $libFullPath $oriDylibPath\n\t\tckLibId=${ckLibId%' ('*}\n\t\tckLibId=${ckLibId#*/}\n\t\tinstall_name_tool -id $cydiaLibPath/$ckLibId $path\n\t\totool -L $path\n\tfi\n\tcp -r $libFullPath $tweakLayoutPath\n}\n\nfor file in $dylibPath/*; do\n\tif [[ $file =~ \".dylib\" ]]; then\n\t\tcheckDylibID $file $file\n\telif [[ $file =~ \".framework\" ]]; then\n\t\tname=${file##*/}\n\t\tname=${name%.*}\n\t\tcheckDylibID $file/$name $file\n\tfi\ndone\n```\n\n在每次package之前，运行此脚本，打包完成后查看信息：\n\n```\n➜  WeChatBot git:(master) ✗ otool -L .theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib\n.theos/_/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib:\n\t/Library/MobileSubstrate/DynamicLibraries/WeChatBot.dylib (compatibility version 0.0.0, current version 0.0.0)\n\t/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)\n\t/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1450.14.0)\n\t/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1450.14.0)\n\t/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3698.33.6)\n\t/Library/MobileSubstrate/DynamicLibraries/WeChatBot/WCBFWDynamic.framework/WCBFWDynamic (compatibility version 1.0.0, current version 1.0.0)\n\t/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.1)\n\t/Library/MobileSubstrate/DynamicLibraries/WeChatBot/libWCBDyLib.dylib (compatibility version 0.0.0, current version 0.0.0)\n\t/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)\n```\n\n\n\n## 常用的编译命令配置\n\n简化常用命令，提高日常开发效率\n\n```\nbefore-package::\n\tsh bin/check_dynamic_lib.sh  #动态库处理脚本\n\tcp ./bin/postinst .theos/_/DEBIAN/\n\tcp ./bin/postrm .theos/_/DEBIAN/\n\tchmod 755 .theos/_/DEBIAN/postinst\n\tchmod 755 .theos/_/DEBIAN/postrm\nafter-install::\n\tinstall.exec \"killall -9 SpringBoard\"\np::\n\tmake package\nc::\n\tmake clean\ni::\n\tmake\n\tmake p\n\tmake install\n```\n\n## 常用的脚本说明\n\npostinst 脚本是每次deb包安装之前执行的脚本\npostrm 脚本是每次deb包安装完成后执行的脚本\n\n注意：打包前需要修改这两个的执行权限\n\n```\nchmod 755 .theos/_/DEBIAN/postinst\nchmod 755 .theos/_/DEBIAN/postrm\n```\n相关的脚本描述：[http://iphonedevwiki.net/index.php/Packaging](http://iphonedevwiki.net/index.php/Packaging)\n\n**应用场景：在Cydia中安装插件，并且显示返回按钮**\npostrm脚本 \u0026 删除control的depend依赖：\n\n```\n#!/bin/bash\ndeclare -a cydia\ncydia=($CYDIA)\nif [[ ${CYDIA+@} ]]; then\n    eval \"echo 'finish:open' \u003e\u0026${cydia[0]}\"\nelse\n    echo \"uninstall wk completed!\"\n    echo \"\"\nfi\nkillall -9 WeChat\nexit 0\n```\n\n参数说明：\n\n```\nAcceptable parameters for finish\n# return - normal behaviour (return to cydia)\n# reopen - exit cydia\n# restart - reload springboard\n# reload - reload springboard\n# reboot - reboot device\n```\n\n## 资源文件的导入\n\n通过项目根目录中的layout目录，映射文件到手机设备当中，然后读取资源文件\n\n```\n#define kWCBImgSrcPath @\"/Library/AppSupport/WeChatBot/imgs\"\n\nUIImage *img = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@\"%@/wcb_icon.png\", kWCBImgSrcPath]];\nNSLog(@\"[WeChatBot] img: %@\", img);\nUIImageView *imgView = [[UIImageView alloc] initWithImage:img];\n[imgView sizeToFit];\nimgView.center = CGPointMake(46, 60);\n[self.window addSubview:imgView];\n```\n\n## 其他配置说明\n\n### Makefile\n\n```\n#用于编译的SDK和支持的ios最低版本\nTARGET = iphone:11.2:9.0\n\n#用于调试的设备地址\nTHEOS_DEVICE_IP = localhost\nTHEOS_DEVICE_PORT = 2222\n\n# 打包命名不一样，正式包不会输出log等\nDEBUG = 1\n\n# 采用ARC内存管理\nWeChatBot_CFLAGS = -fobjc-arc\n\n#忽略OC警告，避免警告导致编译不过\nWeChatBot_OBJCFLAGS +=  -Wno-deprecated-declarations -Wno-unused-variable\n```\n\n### control \n\n```\nPackage: cc.onezen.wechatbot  #包名\nName: WeChatBot\nDepends: mobilesubstrate   #依赖库和依赖插件，如果需要插件在cydia安装后不重启springboard可以删掉，否则每次重新\nVersion: 0.0.1\nArchitecture: iphoneos-arm\nDescription: An awesome MobileSubstrate tweak!\nMaintainer: wz\nAuthor: wz\nSection: Tweaks #cydia源中的分类\nIcon: file:///Library/AppSupport/WeChatBot/imgs/wcb_icon.png #icon\n```\n## 项目\ngit 地址: https://github.com/onezens/WeChatBot\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonezens%2Fwechatbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonezens%2Fwechatbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonezens%2Fwechatbot/lists"}