手动计算Git Commit ID(Git Hash)

关于 Git Commit ID的计算过程讨论,可参考 How is git commit sha1 formed 计算过程 # 获取元数据字符串 info=`git cat-file commit HEAD` # 计算元数据的字符串长度 infoLen=`echo $info | wc -c` infoLen=${infoLen// /} # 拼接字符串 str=`printf "commit %s\0" $infoLen` str=$str$info # 计算SHA1 echo $str | shasum 其他 使用 git cat-file -p hash 命令查看git hash代表的具体内容 git cat-file -p 哈希字符串

May 4, 2023 · 1 min · holdsky

file system sandbox blocked mmap()

不允许从沙盒目录加载动态库(代码),尤其是在生产环境上。 在iOS9中,还没有这么严格的管控要求,在iOS10+后要求更加严格了。 https://developer.apple.com/forums/thread/711730

May 4, 2023 · 1 min · holdsky

iOS运行时解析embedded.mobileprovison

embedded.mobileprovison是由二进制的加密数据和普通文本字符串组成,我们使用NSPropertyListSerialization类解析普通文本字符串 首先将普通文本字符串提前出来,这里用到了NSScanner NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]; NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSISOLatin1StringEncoding error:nil]; NSScanner *scanner = [[NSScanner alloc] initWithString:embeddedProvisioning]; if (![scanner scanUpToString:@"<plist" intoString:nil]) { NSLog(@"parse embedded.mobilerovision error, no plist markup"); return nil; } NSString *extractedPlist = nil; //接收普通文本字符串 if (![scanner scanUpToString:@"</plist>" intoString:&extractedPlist]) { NSLog(@"parse embedded.mobilerovision error, no plist markup"); return nil; } extractedPlist = [extractedPlist stringByAppendingString:@"</plist>"]; //添加xml标签结束标记 然后就可以使用NSPropertyListSerialization解析了 NSError *error; NSDictionary *plist = [NSPropertyListSerialization propertyListWithData:[extractedPlist dataUsingEncoding:NSISOLatin1StringEncoding] options:NSPropertyListImmutable format:nil error:&error]; if (error || ![plist isKindOfClass:[NSDictionary class]]) { NSLog(@"parse embedded.mobilerovision error, %@",error); return nil; } return plist; //返回结果 参考 https://www.process-one.net/blog/reading-ios-provisioning-profile-in-swift/

April 11, 2023 · 1 min · holdsky

iOS构建动态库时忽略undefined symbols导致的missing symbol called

iOS开发环境下,构建动态库时可能会出现undefined symbols,某些情况下我们选择让链接器(ld)忽略这些错误 # 传给 ld特定 Wl参数,来忽略undefined symbols -Wl,-U ,符号A, -U ,符号B, -U, 符号C ... #或者使用 Xlinker -Xlinker -U -Xlinker 符号A,-Xlinker -U -Xlinker 符号B,-Xlinker -U -Xlinker 符号C... 上面的参数告诉链接器(ld),未定义的符号在其他地方实现了。 然后,当我们在hostApp环境中加载这个动态库时,可以正常加载,但是运行到某些场景时,会因为missing symbol called崩溃。 崩溃的原因是上面忽略的undefined symbols没有被加载。 而undefined symbols没有被加载的原因是链接器(ld)会只想Dead Code Strips这个动作,因为我们在构建动态库时选择了忽略undefined symbols,就有可能(不是一定)导致这些undefined symbols变成Dead Code而被移除掉。 为解决这个问题,我们还需要像链接器(ld)传递一些参数,强制这些在其他地方实现的undefined symbols被链接到hostApp环境中 # 注意和上面提到的参数区别,-u和-U,小写的u表示强制加载,大小的U表示忽略 # 传给 ld特定 Wl参数,来强制链接undefined symbols -Wl,-u ,符号A, -u, 符号B, -u, 符号C ... #或者使用 Xlinker -Xlinker -u -Xlinker 符号A,-Xlinker -u -Xlinker 符号B,-Xlinker -u -Xlinker 符号C... 另外,需要注意的是,上面提到的参数,忽略undefined symbols参数是在构建动态库过程中使用;强制链接undefined symbols参数是在构建hostApp时使用。

April 10, 2023 · 1 min · holdsky

不使用cocoapods-art插件情况下与jfrog协作

目前,cocoapods-art还不能很好的适配苹果M系列芯片的macOS系统,故而探索出这条兜底的协作路径,可以不用使用cocoapods-art插件。 本文涉及相关命令 curl、 tar、 git、 pod(cocoapods) 原理 cocoapods-art的原理是先从jfrog下载全量的podspec索引,然后在本地创建git仓库存储这些索引,供cocoapods使用。 cocoapods-art插件操作的git仓库路径在 ~/.cocoapods/repos 和 ~/.cocoapods/repos-art 里面。 同理,我们可以按照cocoapods-art这个流程来实现我们自己的索引管理方案。 下载索引 这里使用artifactory提供rest api,将索引下载到 /AAAA(绝对路径,且不和操作系统用户绑定) 路径 # -u 用户名密码鉴权 # -A 自定义http的User-Agent curl -u artifactory用户名:密码 -f -L -o /AAAA/file.tgz http://artifactory域名/artifactory/api/pods/jfrog仓库名/index/fetchIndex --create-dirs --netrc-optional --retry 2 -A 'CocoaPods/1.11.3 cocoapods-downloader/1.6.3' --ssl-no-revoke 创建git仓库或者更新git仓库 第一次下载索引文件时的操作(创建添加) 索引文件下载到 /AAAA/file.tgz,使用 tar 命令解压 tar xf /AAAA/file.tgz -C /AAAA # 解压后删除压缩包 rm /AAAA/file.tgz 将 /AAAA 目录初始化为git仓库,再次下载索引时只要更新git仓库就可以了 # 第一次下载索引文件后,初始化git仓库 cd /AAAA git init git branch -M main #设置main为默认目录 # 添加索引文件到git仓库 git add . git commit -m "add message" # 再次下载所以文件后,直接讲索引添加到git仓库 再次下载索引文件时的操作(更新) 索引文件下载到 /AAAA/file.tgz,先删除旧索引(specs),再使用 tar 命令解压压缩包 ...

March 16, 2023 · 1 min · holdsky

Objective-C 调用 Swift : dyld missing symbol called

一个可能的原因:多个静态库(或动态库)的Minimum Deployments不一致,通常相差比较大。 例如 A库是Objective-C开放,最小依赖iOS 11; B库是swift开放,最小依赖iOS 16 而HostApp是iOS 11,这在运行时很可能触发 missing symbol called 猜测是iOS 11和iOS16的swift运行时库有较大差异。

February 13, 2023 · 1 min · holdsky

将iOS静态库转为动态库

本文指的转换为无源码时的转换(有源码那叫编译构建) 涉及工具 libtool 用于静态库转为动态库 lipo 用于查看库信息,将fat库拆分为thin库,将thin库合并为fat库 ar 用于将thin库解压为object文件 基本过程,将fat静态库拆分为thin静态库,再将thin静态库解压为object文件,然后将object文件压缩为thin动态库,最后将thin动态库合并为fat动态库 拆分fat静态库 先查看fat库基本信息,重点是看由哪些指令架构的thin库组成 lipo -info libfat.a # 输出信息中重点看指令架构 Architectures in the fat file: libfat.a are: x86_64 arm64 按照指令架构拆分fat库 lipo libfat.a -extract x86_64 -output libfoo.a 解压thin静态库 会输出一组 .o 文件 ar -x libfoo.a 压缩为thin动态库 注意下,需要手动添加依赖库, -framework 依赖库 -l依赖库 libtool -dynamic *.o -o libfoo_dynamic-x86_64.dylib -framework CoreFoundation -lSystem 将thin动态库合并为fat动态库 lipo -create libfoo_dynamic-x86_64.dylib libfoo_dynamic-arm64.dylib -output ./libfoo_dynamic.dylib 参考 https://pewpewthespells.com/blog/convert_static_to_dynamic.html

February 8, 2023 · 1 min · holdsky

iOS NSHTTPCookie 设置NSHTTPCookieExpires失败

可能的一个原因是设置了NSHTTPCookieDiscard这个key NSMutableDictionary<NSString *, id> *properties = [NSMutableDictionary dictionary]; properties[NSHTTPCookieName] = @"aaa"; properties[NSHTTPCookieValue] = @"bbb"; // properties[NSHTTPCookieDiscard] = @"FALSE"; 该选项不生效,设置后会影响NSHTTPCookieExpires properties[NSHTTPCookiePath] = @"/ccc/ddd"; properties[NSHTTPCookieExpires] = [[NSDate new] dateByAddingTimeInterval:3*3600*24]; properties[NSHTTPCookieDomain] = @"xxx.yyy.zzz"; NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:properties]; NSLog(@"%@",cookie); // cookide 的过期时间应该设置成功了

January 31, 2023 · 1 min · holdsky

xcode构建动态库忽略undefined symbol

默认情况下,构建动态库时遇到undefinded symbol会构建失败。但有时候,这些undefinded symbol在运行时是存在的(如host app中、其他动态库中),这时可以添加链接参数,让xcode忽略undefinded symbol。 忽略所有undefinded symbol 省事,但不推荐。 在 other link flags 中添加下面参数即可 -undefined dynamic_lookup 忽略指定undefined symbol 可以精确控制 在 other link flags 中添加下面参数 # 有几个需要忽略的符号,就添加几行 -Wl,-U,symbol_nameA -Wl,-U,symbol_nameB -Wl,-U,symbol_nameC ... 其他注意事项 通过上述方法忽略的undefinded symbol,在运行时会在 flat namespace中查找对应的符号

January 15, 2023 · 1 min · holdsky

iOS 重签名知识点

介绍 1、IPA是ZIP压缩文件,可以直接用zip命令压缩解压 2、IPA 重签名需要准备p12证书、mobileprovision描述文件 3、IPA里面可能包含动态库(.framework , .dylib),也需要重签名 4、IPA里面的扩展(.appex)也有自己的mobileprovision,不复用主App。 5、扩展(.appex)的mobileprovision的id要和App的mobileprovision里面的id保持一致。例如主App是 A.B.C,那么扩展的必须是A.B.C.xxxx 。 6、重签名时,应要重新设置Info.plist里EXTENSION_GROUP值,修改为 group.主App的bundle_id,例如 group.A.B.C 命令 压缩解压缩 unzip 老包.ipa zip -r 新包.ipa Payload/ SwiftSupport/ # 如果没SwiftSupport可以不添加 查看本地的签名证书列表 security find-identity -v -p codesigning # 会输出证书的HASH值和证书名 打印mobileprovision的基本信息 主要获取application-identifier,为后面修改InfoPlist里面的bundle做准备 /usr/libexec/PlistBuddy -c \"Print Entitlements:application-identifier\" /dev/stdin <<< $(/usr/bin/security cms -D -i mobileprovision文件路径 ) 修改InfoPlist的bundle id /usr/libexec/PlistBuddy -c "Set:CFBundleIdentifier 新id" "/需要修改的bundle路径如framework/Info.plist" 读取InfoPlist的bundle id 使用defaults,比较简单 defaults read /需要读取的bundle路径如framework/Info CFBundleIdentifier # 注意,不添加.plist后缀 生成entitlements # 先获取全部信息 security cms -D -i "embedded.mobileprovision路径" > 输出的plist文件路径" # 提取entitlements信息 /usr/libexec/PlistBuddy -x -c 'Print:Entitlements' 全部信息的plist文件路径 > 输出entitlements信息的plist文件路径 重新签名 /usr/bin/codesign --continue -f -s "证书HASH或者名字" --entitlements "entitlements信息的plist文件路径" "需要签名的bundle如framework、appex、app" 流程 1、准备好证书和mobileprovision文件 2、解压缩ipa 3、复制对应mobileprovision到app目录、appex目录,并重命名为embedded.mobileprovision 4、修改app、appex的Info.plist文件里的bundle id和EXTENSION_GROUP值 5、生成entitlements信息文件 6、用codesign对app、appex重新签名 7、使用app的证书文件对动态库重新签名 8、把重新签名后的文件压缩为ipa

December 9, 2022 · 1 min · holdsky