xcodebuild、xcrun和swift命令行工具之间有哪些区别?

11

除了使用 Xcode,我们还可以通过多个命令行命令构建和运行 Swift 代码/项目。我听说过 xcodebuildxcrunswift 这些命令用于 Xcode 开发。我使用 fastlane,但我并不真正理解它的底层工具。

作为一名使用 Mac 的 iOS 开发者,我通常使用 Xcode 进行开发,因此以前没有使用过这些命令行工具。

这些命令之间有什么区别?有哪些情况下我最好使用其中之一?

2个回答

10

简述

xcodebuildxcrun 可以在无头环境下构建 Xcode 项目,例如在 CI 设置中使用。 swift 是 Swift REPL,主要用于 Swift on Server 应用程序。因此,我们可以构建应用程序而不必了解或使用常规移动应用程序开发中的工具。尽管我们没有意识到它们,但我们在与 Xcode 交互时使用了 xcodebuildxcrun,因为它们包含在 Xcode 的命令行工具(文档存档,但仍然相关)中。

fastlane 是一个示例 CI 工具,它使用这些工具自动化构建过程、证书签名和与 App Store Connect 的接口。

xcodebuild

xcodebuild 是 Xcode 捆绑的命令行工具包的一部分。从 manpages 中可以看到:

构建Xcode项目和工作区

xcodebuild可以构建Xcode项目中包含的一个或多个目标,或者构建包含在Xcode工作区或Xcode项目中的方案。

xcodebuild有很多选项和用例。这些选项相当于Xcode IDE中的某些用户操作。例如用法:

xcodebuild -workspace MyWorkspace.xcworkspace -scheme MyScheme

在Xcode工作区MyWorkspace.xcworkspace中构建方案MyScheme。在上述命令中,我们使用Xcode内部用于编译的方式,在没有Xcode的情况下构建工作区。Xcode只能安装在macOS上,并且我们在使用其命令行工具(包括xcodebuild和xcrun)时有相同的限制。
xcrun是另一个Xcode命令行工具,是Xcode CLI工具的一部分。根据manpages所述:
运行或定位开发工具 xcrun提供了一种查找或调用与平台相关的开发工具的方法,而无需用户修改makefile或采取其他不便的措施来支持多个Xcode工具链。
xcrun [-sdk SDK] -find <tool_name>

xcrun通常与Xcode-select一起使用,以在同一台机器上管理多个Xcode版本。每个Xcode版本都捆绑了自己的开发工具,我们可以使用xcrun获取当前路径:

xcrun xcode-select --print-path

Swift

Swift是Swift REPL。 Swift是一个命令行工具,包括Swift工具链,但也可以安装在Xcode捆绑工具之外。与xcodebuildxcrun不同,swift是编译的Swift而不是C。 Swift在MacOS manpages文档中并没有很好的记录,但是苹果在其blog上记录了这些工具:

Xcode 6.1引入了一种使用Swift进行实验的交互式读取评估打印循环(REPL)的另一种方式。

REPL指的是交互式编译环境或shell。首先,REPL会读取代码,然后评估它,打印输出,并重复此过程。可以想象,与IDE相比,我们可以使用REPL开发的内容要少得多。但是,Swift还有其他用途,不仅限于iOS、watchOS和macOS开发。

swift包括标准库,但不包括FoundationUIKit等库。这些Swift库几乎肯定需要用于iOS或macOS开发,因此我们不能仅使用swift REPL开发应用程序。但是,Swift on Server项目经常使用swift在Linux甚至Windows机器上运行Swift代码。

为了更广泛的使用,苹果公司使 swift 在没有 Xcode 的不同操作系统上可用。现在,Swift 还支持 Docker 和 Windows。Docker 让我们可以在任何机器上运行 swift,而不受底层操作系统的限制。在这些应用程序中,swift 作为一种脚本语言发挥作用。

SoS 的奖励说明

Swift被广泛用于服务器上的Swift。Swift在服务器应用方面具有出色的性能,具有更低的内存占用、快速启动时间和确定性能力。虽然在某些任务上它不像.NET Core那样快速,但这是因为Swift具有严格的类型系统、ARC垃圾回收和针对服务器特定应用的较少优化,因此更加安全。许多早期采用者赞扬了改进的语言类型系统、内存效率和算法性能。实际上,在JSON序列化任务的效率方面,Swift Vapor与Python和Ruby相当高效。Swift在非常少数的任务上与Java相当,但随着语言和生态系统的发展,这很可能会改变。


1
感谢您的精彩写作。只是关于您的SoS笔记:ARC不是垃圾回收。从您提供的SoS链接中,有这样一句话:“Swift使用ARC(而不是跟踪垃圾回收)…” - BigHeadCreations
不是的。ARC 是一种垃圾回收形式。追踪式垃圾回收是不同的。请参见:https://softwareengineering.stackexchange.com/questions/285333/how-does-garbage-collection-compare-to-reference-counting - Pranav Kasetti

3

xcrun

xcrun视为一种方便的前缀,以调用当前活动的Xcode工具链中的各种命令行工具。

同一台机器上可以安装多个Xcode工具链(例如最新版本、测试版和/或旧版本)。使用xcode-select设置要使用哪个Xcode工具链路径。或者,可以通过设置环境变量SDKROOTDEVELOPER_DIR来指定活动的开发人员工具链。

### open 'bin' directory for the currently active Xcode toolchain 
open `xcode-select --print-path`/usr/bin

可以使用 xcrun 命令调用的工具包括:

  • xcrun simctl <subcommand> ~ iOS 模拟器控制
  • xcrun xcodebuild … ~ 构建/测试 Xcode 项目和工作区
  • xcrun xctrack <commands> [options] ~ 记录、导入和导出 Instruments .trace 文件
xcrun not_a_tool  help

# xcrun: error: 
#   sh -c '/Applications/Xcode.app/…/bin/xcodebuild 
#         -sdk /Applications/Xcode.app/…/MacOSX.sdk 
#         -find not_a_tool 2> /dev/null' 
# failed with exit code 17664: (null) (errno=Invalid argument)

xcodebuild

xcodebuild 可以看作是一种专门用于调度多个其他工具,以管理整个项目构建过程的单一命令行工具。调用 xcodebuild 将执行许多任务,就像在创建和/或测试项目时 Xcode GUI 菜单中的 BuildTest 命令一样。

xcodebuild -help

注意:可以在不使用前置 xcrun 的情况下调用 xcodebuild
xcrun xcodebuild -version
# Xcode 13.2.1
# Build version 13C100

xcodebuild -version 
# Xcode 13.2.1
# Build version 13C100

Swift

swift(单独)视为 swiftc 编译器的解释性、交互式、可脚本化的“REPL”版本。

然后,将范围扩大,将 swift 视为一个扩展生态系统的基础,该生态系统不需要 Xcode 的存在(除非需要针对 Apple 硬件进行 AppleOS SDK 的目标定位)。

swift --help

# SUBCOMMANDS (swift <subcommand> [arguments]):
#   build:   SwiftPM - Build sources into binary products
#   package: SwiftPM - Perform operations on Swift packages
#   run:     SwiftPM - Build and run an executable product
#   test:    SwiftPM - Build and run tests

命令行示例

> swift
Welcome to Swift version 5.5.2-dev.
Type :help for assistance.
  1> 8 + 9 
$R0: Int = 17
  2> :quit

注意:Swift REPL与LLDB调试器配合使用,因此在REPL会话期间,前缀用于命令,如helpquit

Swift脚本示例

脚本example_script.swift文件:

#!/usr/bin/swift

// File: example_script.swift
// reminder: chmod to executable before invoking the script

import Foundation

func printHelp() {
    print("Please add an argument to the command line. Thanks.")
}

// --- main ---
if CommandLine.argc < 2 {
    printHelp()
} else {
    for i: Int in 1 ..< Int(CommandLine.argc) {
        print( CommandLine.arguments[i] )
    }
}

解释和编译脚本执行:

ls -l example_script.swift 
# -rwxr--r--@ 1 user staff  321 Dec 30 16:56 example_script.swift

./example_script.swift 
# Please add an argument to the command line. Thanks.

./example_script.swift a bcd
# a
# bcd

## Let's compile the script...
swiftc example_script.swift 

ls -l ex*
# -rwxr-xr-x  1 user staff  55136 Dec 30 16:57 example_script
# -rwxr--r--  1 user staff    321 Dec 30 16:56 example_script.swift

./example_script
# Please add an argument to the command line. Thanks.

./example_script xyx
# xyz  

REPL: 读取-评估-打印-循环


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接