Swift CLI - LinkMap(1)

背景

在统计分析iOS包体积时,总有一必要的步骤: 分析Linkmap文件。通过LinkMap文件我们可以分析出ipa包中可执行文件的大小明细。最近本人在工作中也遇到这样的需求,提供一个CLI的工具给到CI,让CI可以执行我们提供的命令行工具从而得到包体积组成信息。

在这里本人便不对linkmap文件进行太多的赘述,直接进入主题:怎样利用Swift制作一个分析linkmap文件的命令行工具。

1.搭建项目

shell 复制代码
$ cd /User/xxx/Desktop
$ mkdir CLI
$ cd CLI

$ swift package init --type executable

这样我们便创建好了我们的Swift CLI项目工程,用Xcode打开工程可以看到如下目录:

2. 添加依赖

在package.json中添加依赖

  • Swift Argument Parser
  • Files
Swift 复制代码
import PackageDescription
let package = Package(

    name: "CLI",
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMajor(from: "1.0.0")),
        .package(url: "https://github.com/JohnSundell/Files", .upToNextMajor(from: "4.0.0")),
    ],

    targets: [
        .executableTarget(
            name: "CLI",
            dependencies: [
                .product(name: "ArgumentParser",package: "swift-argument-parser"),
                .product(name: "Files",package: "Files"),
            ]),

        .testTarget(
            name: "CLITests",
            dependencies: ["CLI"]),
    ]
)

"Swift Argument Parser"(Swift 参数解析器),用于简化命令行工具的参数解析和处理。它提供了一个方便的方式来定义和解析命令行参数,使开发者能够轻松地创建强大的命令行工具,而无需手动处理繁琐的参数解析逻辑。

"Files" 是一个第三方库,用于简化文件系统操作。这个库提供了一些便捷的方法,使得文件和目录的创建、读取、写入等操作更加容易。

3. 编写命令

编辑CLI文件如下:

Swift 复制代码
import ArgumentParser

@main
struct CLI: ParsableCommand {

     static var configuration = CommandConfiguration(commandName: "这是一个CLI命令")
     
     func run() throws {
        print("这是一个CLI命令")
    }
}

可见CLI 遵循了ParsableCommand协议,并实现了run函数,这便是命令的入口。这时候我们运行项目,会发现CLITests报错是因为我们删除了原先的代码,将其中的代码注释,再次运行可见控制台会输出:"这是一个CLI命令"。

回到主题,我们的目标是为了构建一个分析Linkmap的CLI工具,我期望的是在控制台输入如下命令从而得到一个解析过后的json文件

shell 复制代码
$ CLI linkmap /User/xxxx/Desktop/linkmap.txt

这时候我们需要构建一个子命令linkmap

并且需要有输入的参数:

linkmap.txt的文件目录: linkmappath

指定输出json文件的文件目录: outputpath

是否需要进行分组: needgroup

是否需要分组后的各个库文件明细: needgrouplist

这时需要新建一个linkmap.swift的文件并编写如下代码

swift 复制代码
import ArgumentParser
struct Linkmap: ParsableCommand {
    static var configuration: CommandConfiguration = CommandConfiguration(
        abstract: "分析linkmap文件,并输出json"
    )

    @Argument(help: "linkMap文件目录")
    var linkmappath: String = ""

    @Option(name: .shortAndLong,help: "linkmap.json输出目录")
    var outputpath: String?

    @Flag(help: "是否需要以Group进行统计")
    va needgroup = false

    @Flag(help: "是否需要Group明细")
    var needgrouplist = false

    public func run() throws {

    }
}

可以看到上面的LinkMap文件同样遵循了ParsableCommand协议,并通过申明式的方式定义了4个输入参数,其中linkmappath是必要参数,如果有个必要参数,传参顺序需要与定义顺序保持一致。outputpath、needgroup和needgrouplist都是可选参数。若我们需要进行分组、要有分组明细列表,且需要指定输出路径就需要使用如下命令

shell 复制代码
$ CLI linkmap /User/xxxx/Desktop/linkmap.txt --outputpath /User/xxxx/Desktop/linkmap.json --needgroup --needgrouplist
$ CLI linkmap /User/xxxx/Desktop/linkmap.txt -o /User/xxxx/Desktop/linkmap.json --needgroup --needgrouplist

上面的2个命令都是一样的。区别只是在于 --outputpat 和 -o 长命令和短命令。 @Option(name: .shortAndLong,help: "linkmap.json输出目录")中的 .shortAndLong枚举值的作用就在于此。

在上面的代码中所有参数的命名都没有采取驼峰命名是因为如果采取驼峰命令我们的参数名会被系统截断,并以"-"进行连接。

这时我们在CLI文件中将我们的子命令添加到CommandConfiguration中。

Swift 复制代码
import ArgumentParser

@main
struct CLI: ParsableCommand {

     static var configuration = CommandConfiguration(commandName: "这是一个CLI命令",subcommands: [Linkmap.self])
     
     func run() throws {
        print("这是一个CLI命令")
    }
}

这时候我们通过xcode -> Edit Scheme -> Arguments Passed On Launch。 在其中添加 --help如下图:

再次运行项目可见终端输出: 可见我们的子命令linkmap已经添加完毕。这样我们的CLI工程也就搭建完成。后续只需要在linkmap文件中添加分析linkmap的swift代码即可。

4. 构建CLI

我们再次打开终端输入如下命令:

shell 复制代码
$ cd /User/xxx/Desktop/CLI
$ swift build -c release

执行完上面的命令后,会在CLI同级文件夹中生成.build文件夹。在/.build/release目录可见同名的CLI可执行文件。我们将此文件拷贝到/usr/local/bin目录下。在终端中输入

shell 复制代码
$ CLI linkmap -h

执行完后可见如下输出:

这样我们CLI命令行工具便制作完成。

下一篇:代码实现分析linkmap的CLI工具

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端