Swift 入门:编译 Swift 源码(1)

2021-02-11 18:02:03 浏览数 (1)

本教程希望能提供一份面向新人编译 Swift 源码及相关组件的教程。

什么是 Swift

Swift 是一门快速、高效、安全的编译型语言。

它具有很多高级简洁的特性:

  • 泛型强大且易用
  • 协议扩展使得泛型代码编写变得更为容易
  • 头等函数和轻量级闭包语法
  • 对范围或集合进行快速、简洁的迭代
  • 元组和多值返回
  • 支持方法、扩展和协议的结构
  • 枚举能执行有效负载并支持模式匹配
  • 函数式编程模式,例如映射和过滤
  • 使用 try/catch/throw 处理原生错误

编程语言的很多特性都是依赖于编译器的。比如,与 C 语言的枚举相比,Swift 的枚举就依赖编译器实现了关联值等高级特性。

为了方便了解高级特性的实现原理,掌握 Swift 及相关库的源码编译是开发者必须掌握的技能。

目标

以 Swift 官方入门文档 为基础,增加 Xcode 对 Swift、LLVM、lldb 进行编译调试的内容。

环境

本文写作时间是 2020年11月07日。

随着 Swift 的持续迭代,环境依赖可能会随时更新。请参考官方入门文档的变更进行编译。

根据 https://ci.swift.org/ 网站的提示:

当前官方推荐使用的正常编译的环境是:

  • Host OS: 10.15.6
  • Xcode: 12.2 Beta 3 (12B5035g)

安装依赖包

安装 Xcode 和 HomeBrew

安装 Brew

如果安装 brew 时,存在网络问题,请使用手机热点或者参考以下方案进行解决

代码语言:txt复制
# 首次安装 Homebrew
# 下载 https://github.com/Homebrew/install/blob/master/install.sh 并编辑其中的:
BREW_REPO="https://github.com/Homebrew/brew"
# 变成:
BREW_REPO="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git"
# 接着,运行 install.sh 以安装 Homebrew:

HOMEBREW_CORE_GIT_REMOTE=https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git bash install.sh

#替换现有上游
# brew 程序本身
git -C "$(brew --repo)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git

# 以下针对 mac OS 系统上的 Homebrew
git -C "$(brew --repo homebrew/core)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git
git -C "$(brew --repo homebrew/cask)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask.git
git -C "$(brew --repo homebrew/cask-fonts)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask-fonts.git
git -C "$(brew --repo homebrew/cask-drivers)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask-drivers.git

# 以下针对 Linux 系统上的 Linuxbrew
git -C "$(brew --repo homebrew/core)" remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/linuxbrew-core.git

# 更换后测试工作是否正常
brew update

安装 CMake Ninja Sccache

推荐使用 Brew 工具安装:

代码语言:txt复制
brew install cmake ninja sccache

验证是否安装成功

代码语言:txt复制
#  3.18.1 或者更高版本
cmake --version
python3 --version
ninja --version
sccache --version

克隆代码

1、准备项目目录

代码语言:txt复制
mkdir -p ~/swift-source/swift

~/swift-source/swift 包含 Swift 主仓库的源码

2、克隆 Swift 源码

代码语言:txt复制
cd ~/swift-source/swift
git clone https://github.com/apple/swift.git .

3、克隆依赖仓库的源码

代码语言:txt复制
cd ~/swift-source/swift
utils/update-checkout --clone

> 执行该命令后,~/swift-source 会包含多个子文件夹:llvm-project 等等。

编译

请读者根据需要自行选择需要的脚本。

> 定制版本支持 Xcode 直接调试 lldb ,并且占用的磁盘空间会更低

> 通常情况下,Swift 全量编译需要 40G-60G 的磁盘空间才能完成。

> 对 Xcode 构建原理熟悉的同学,可以定制编译脚本,并将空间占用压缩到 20G 以内

官方版本

编译 llvm 和 Swift

代码语言:txt复制
cd ~/swift-source/swift
utils/build-script --skip-build-benchmarks 
  --skip-ios --skip-watchos --skip-tvos --swift-darwin-supported-archs "x86_64" 
  --sccache --release-debuginfo --test 
  --xcode

编译 lldb

根据 Swift 官方文档,lldb 必须使用 ninja 编译

代码语言:txt复制
cd ~/swift-source/swift
utils/build-script --skip-build-benchmarks 
  --skip-ios --skip-watchos --skip-tvos --swift-darwin-supported-archs "x86_64" 
  --sccache --release-debuginfo --test 
  --xcode

定制版本

代码语言:txt复制
set -ex

## 注意1:本脚本的编译产物路径是 ~/swift-source/build/Xcode-1107,读者可以根据需要进行变更
## 注意2:如果希望全量编译,可以手动移除 -S 参数
## 注意3: 如果不需要编译lldb,可以手动移除 extra-cmake-options 参数
./utils/build-script -x -S 
    --build-subdir Xcode-1107 
    --sccache 
    --release-debuginfo 
    --extra-cmake-options=" 
        -DLLDB_ENABLE:BOOL=TRUE, 
        -DLLDB_BUILD_DIR:STRING=~/swift-source/build/Xcode-1107/lldb-macosx-x86_64 
        "


ln -s -f ~/swift-source/build/Xcode-1107/llvm-macosx-x86_64/Debug/lib/clang/10.0.0/include 
    ~/swift-source/build/Xcode-1107/llvm-macosx-x86_64/lib/clang/10.0.0/include

/usr/local/bin/cmake --build ~/swift-source/build/Xcode-1107/llvm-macosx-x86_64 --target ZERO_CHECK --config RelWithDebInfo

## 准备 clang 头文件
/usr/local/bin/cmake 
      --build ~/swift-source/build/Xcode-1107/llvm-macosx-x86_64 --target clang-resource-headers  --config RelWithDebInfo


## 注意4:可以根据需要只编译部分 target
/usr/local/bin/cmake --build ~/swift-source/build/Xcode-1107/llvm-macosx-x86_64 --target ZERO_CHECK --config RelWithDebInfo 
    -- -parallelizeTargets -jobs 12 -target ALL_BUILD

## 编译 clang 和 lldb 依赖的目标
/usr/local/bin/cmake --build ~/swift-source/build/Xcode-1107/llvm-macosx-x86_64 --target clang --config RelWithDebInfo

## 编译 swiftFrontend 和 lldb 依赖的目标 
/usr/local/bin/cmake 
    --build ~/swift-source/build/Xcode-1107/swift-macosx-x86_64 
    --target swiftFrontend 
    --target swiftASTSectionImporter 
    --target swiftReflection 
    --target swiftRemoteAST 
    --config RelWithDebInfo


## 如果遇到无法解决的问题,可以根据需要删除 lldb 目录
# rm -rf ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64/

mkdir -p ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64
mkdir -p ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64/.cmake/api/v1/query

touch ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64/.cmake/api/v1/query/codemodel-v2 
    ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64/.cmake/api/v1/query/cache-v2

pushd ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64

## 生成 lldb.xcodeproj 工程
env /usr/local/bin/cmake -G Xcode 
    -DCMAKE_C_COMPILER_LAUNCHER:PATH=/usr/local/bin/sccache 
    -DCMAKE_CXX_COMPILER_LAUNCHER:PATH=/usr/local/bin/sccache 
    -DCMAKE_C_COMPILER:PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang 
    -DCMAKE_CXX_COMPILER:PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang   
    -DCMAKE_LIBTOOL:PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool 
    -DLLVM_VERSION_MAJOR:STRING=10 
    -DLLVM_VERSION_MINOR:STRING=0 
    -DLLVM_VERSION_PATCH:STRING=0 
    -DCMAKE_OSX_SYSROOT:PATH=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk 
    -DCMAKE_OSX_ARCHITECTURES=x86_64 
    -DLLVM_HOST_TRIPLE:STRING=x86_64-apple-macosx10.9 
    -C~/swift-source/llvm-project/lldb/cmake/caches/Apple-lldb-Xcode.cmake 
    '-DCMAKE_C_FLAGS= -Wno-unknown-warning-option -Werror=unguarded-availability-new -arch x86_64 -fno-stack-protector -g' 
    '-DCMAKE_CXX_FLAGS= -Wno-unknown-warning-option -Werror=unguarded-availability-new -arch x86_64 -fno-stack-protector -g' 
    -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo 
    -DLLDB_SWIFTC:PATH=~/swift-source/build/Xcode-1107/swift-macosx-x86_64/bin/swiftc 
    -DLLDB_SWIFT_LIBS:PATH=~/swift-source/build/Xcode-1107/swift-macosx-x86_64/lib/swift 
    -DCMAKE_INSTALL_PREFIX:PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/ 
    -DLLDB_FRAMEWORK_INSTALL_DIR=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/../System/Library/PrivateFrameworks 
    -DLLVM_DIR:PATH=~/swift-source/build/Xcode-1107/llvm-macosx-x86_64/lib/cmake/llvm 
    -DClang_DIR:PATH=~/swift-source/build/Xcode-1107/llvm-macosx-x86_64/lib/cmake/clang 
    -DSwift_DIR:PATH=~/swift-source/build/Xcode-1107/swift-macosx-x86_64/lib/cmake/swift 
    -DLLDB_ENABLE_CURSES=ON 
    -DLLDB_ENABLE_LIBEDIT=ON 
    -DLLDB_ENABLE_PYTHON=ON 
    -DLLDB_ENABLE_LZMA=OFF 
    -DLLDB_ENABLE_LUA=OFF 
    -DLLDB_INCLUDE_TESTS:BOOL=TRUE 
    '-DLLDB_TEST_USER_ARGS=--build-dir;~/swift-source/build/Xcode-1107/lldb-macosx-x86_64/lldb-test-build.noindex;--skip-category=watchpoint' 
    '-DCMAKE_IGNORE_PATH=/usr/lib;/usr/local/lib;/lib' 
    -DPKG_CONFIG_EXECUTABLE=/usr/bin/false 
    ~/swift-source/llvm-project/lldb

popd

## lldb 依赖这个路径
mkdir -p ~/swift-source/build/Xcode-1107/swift-macosx-x86_64/lib/swift

## 编译 lldb 目标
/usr/local/bin/cmake 
      --build ~/swift-source/build/Xcode-1107/lldb-macosx-x86_64 
      --target lldb  
      --config RelWithDebInfo

##参考链接

  1. https://www.cnswift.org/about-swift
  2. .Swift 枚举
  3. .homebrew 清华镜像帮助文档

0 人点赞