从零写一个Cocoa库依赖管理工具(一):建立工程结构和添加依赖

工程结构

初步结构以下图git

屏幕快照 2020-01-10 下午6.41.29.png

暂时一共有7个Target,和SPM大体同样,随着项目进行会调整:github

  1. nabla:包含main.swift。
  2. Commands:全部的命令行。
  3. Build:提供编译功能,如将一个将依赖库编译成framework。
  4. PackageGraph:依赖管理。
  5. PageModel:包含所须要的一些基本Model。
  6. SourceControl:负责git下载和管理依赖库。
  7. Workspace:一个工程的全部操做的管理者。
  8. Xcodeproj:表示一个xocde的工程结构,提供修改xcodeproj,和生成xcworkspace的能力。

依赖的库

在写的时候一来为了减小依赖,二来确实苹果官方的库写的挺好,因此会尽可能用苹果官方库。写一个命令行工具通常须要有三个基础能力:swift

写好命令行:如今开源的有CommanderCommandant,这个是Carthage社区的,Guaka。然而这些咱们都不会用,苹果官方的swift-tools-support-coreArgumentParser提供这种能力,只不过上手要稍微难一些,SPM和llbuild都是使用swift-tools-support-core。xcode

路径搜索和文件管理: 如今开源的有PathKitPath.swiftPath.swift是Homebrew做者写的,用过挺不错的,不过咱们依然选择使用苹果官方的swift-tools-support-coreAbsolutePathbash

调用其余命令行工具:好比咱们须要调用git命令和xcodebuild命令,如今开源的有SwiftShellSwiftCLI,咱们依旧选着苹果官方的swift-tools-support-coreProcess😂,这个工具备一个缺点就是不能设置currentDirectoryPath,不过咱们也用不到。固然你也能够本身实现,简单版就以下所示:app

func exec(_ cmd: String, currentDirectory: String? = nil, env: [String: String]? = nil, _ args: [String]) -> (output: String, error: String, exitCode: Int32) {

    let task = Process()
    task.launchPath = cmd
    task.arguments = args
    if let currentDirectory = currentDirectory {
        task.currentDirectoryPath = currentDirectory
    }
    if let env = env {
        task.environment = mergeEnv(env)
    }

    let outpipe = Pipe()
    task.standardOutput = outpipe
    let errpipe = Pipe()
    task.standardError = errpipe

    task.launch()

    let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: outdata, encoding: .utf8)!.trimmingCharacters(in: .whitespacesAndNewlines)

    let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
    let error = String(data: errdata, encoding: .utf8)!.trimmingCharacters(in: .whitespacesAndNewlines)

    task.waitUntilExit()
    let status = task.terminationStatus

    return (output, error, status)
}

func mergeEnv(_ env: [String: String]) -> [String: String] {
    var e = ProcessInfo.processInfo.environment
    for (key, value) in env {
        e[key] = value
    }
    return e
}

复制代码

最后由于咱们暂时是经过.yml文件来配置项目和依赖,因此须要引入Yams工具

配置Package.swift

工程结构和依赖库都已经定好了,配置Package.swift就比较简单了,这里就不细讲了,能够直接拉下来工程看代码。ui

编写Makefile

咱们须要经过Makefile来编译咱们项目,而后将生成的可执行命令行工具nabla拷贝到/usr/local/bin来方便咱们在终端调试,暂时只先实现最简单功能。spa

usr_local ?= /usr/local

bindir = $(usr_local)/bin
libdir = $(usr_local)/lib

build:
	swift build -c release --disable-sandbox

install: build
	install ".build/release/nabla" "$(bindir)"

uninstall:
	rm -rf "$(bindir)/nabla"
    
clean:
	rm -rf .build

.PHONY: build install uninstall clean

复制代码

这里只有一个点须要注意,--disable-sandbox,这样才有用户home directory的读写权限。命令行

你们在调试的时候只须要执行如下操做在终端调试nabla了。

$ git clone https://github.com/woshiccm/Pecker.git
$ cd Pecker
$ make install
复制代码

项目地址

Nabla

最后

才写了第一篇就感受好花时间并且写的又乱又水😓。

相关文章
相关标签/搜索