Technical Documentation: RubyMetric/chsrc
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
全平台通用换源工具与框架 chsrc,目标支持 Linux, Windows (native, MSYS2, Cygwin), macOS, BSD, Android 等尽可能多的操作系统环境,龙芯、飞腾、RISC-V 等尽可能多的 CPU。我们使用 C11 来完成上述目标,以保证最大的可用性。本软件为自由软件,SDPX 软件许可证为 GPL-3.0-or-later and MIT
❤️ 致所有的朋友们
2025年8月11日,我因通宵重构本项目代码而被送去抢救(#252,突发!换源工具 chsrc 作者在重构过程中被送去 120 抢救)。大家给予的关心和帮助让我非常非常感动!在此,我衷心感谢每一位朋友!无论是开源还是闭源,无论是否为职业程序员,我们其实都是一群使用软件、热心互助、充满友爱的人,这是一个温暖的大家庭。
我为 chsrc 采用 GPL 协议,怀着殷切的期望:希望能够营造像 Richard Stallman 在创建 GNU 项目之前,在 MIT 那样的氛围——写自己用得上的软件,与大家一起开发、维护,简单纯粹,无关商业利益。就像小区、校园自发组建的足球篮球队,从一次偶然的加入,逐渐成长为互相支持的伙伴。
这次经历让我更加深刻地体会到:开源,是一种把大家联系在一起的方式,它让互助和协作成为可能。最后,希望大家能够时刻关注自己的身体,你可以随时 chsrc chown chgrp chmod 无限次,但是无法 chbody!
🤝 协作与贡献
[!TIP]
chsrc不仅是一个命令行工具,同时也是一个体现了 Ruby on Rails 思想的 MVC 换源框架,它甚至使你能够在不了解C语言的情况下编写出新的换源方法 (recipe)。 配合使用 rawstr4c, 这将比写 shell 脚本更加轻松。 如何编写 recipe?
[!NOTE]
这也许是你可以参与的第一个现实世界中有用的C语言项目,用 VS Code 一分钟内上手编译、运行、测试 chsrc欢迎对 GitHub、Gitee 协作不熟悉的人以此为契机学习参与贡献, 欢迎任何编程初学者。从开发到提交PR,我们覆盖全流程文档
[!IMPORTANT]
chsrc可换源 65+ 菜品。每个人仅仅贡献和维护自己熟悉的部分,回报是得到其他所有领域专家的帮助。 欢迎成为 recipe 维护者
📌 示例
桌面端:
安卓:
🚀 安装
[!IMPORTANT]
若通过下述手动方式安装,则会下载到当前目录,可直接通过./chsrc运行
Windows
- 可通过
scoop安装,感谢 @rocascent 与 @niheaven
scoop install chsrc- 可通过
WinGet安装,感谢 @YU-7 与 @Dragon1573
winget install RubyMetric.chsrc可通过
PowerShell脚本一键下载最新版二进制文件,感谢 @wickdynex若下方链接无法访问,可使用
https://gitee.com/RubyMetric/chsrc/raw/main/tool/installer.ps1替代
# 使用 -Version 指定版本 (不指定时默认为 pre)
# 1. 安装 pre 版本; 这比从包管理器安装的总是更新一些
# 2. 安装旧版本; 有时新版本可能引入某些 Bug,临时使用旧版本解决燃眉之急
"& { $(iwr -useb https://chsrc.run/windows) } -Version pre" | iex- 或手动下载二进制文件,这是最新版,往往比
scoop提供的更新,适用于修复 Bug、添加新功能后及时使用,以及未安装scoop时
# x64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-x64-windows.exe -o chsrc.exe
# x86
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-x86-windows.exe -o chsrc.exe
# Arm64 (WoA, Windows on Arm)
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-arm64-windows.exe -o chsrc.exeLinux
- 可通过
apt/dpkg安装,感谢 @sanchuanhehe
# x64
$ curl -LO https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc_latest-1_amd64.deb
# 也可以使用 Wget
wget https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc_latest-1_amd64.deb
$ sudo apt install ./chsrc_latest-1_amd64.deb
# 或
$ sudo sudo dpkg -i chsrc_latest-1_amd64.deb- 支持
AUR,可通过yay安装,感谢 @Jerry-Terrasse
# AUR
$ yay -S chsrc-bin # Binary from GitHub Release
$ yay -S chsrc-git # Build from the latest main branch (stable)
$ yay -S chsrc # Build from GitHub Release可通过
shell脚本一键安装最新版,感谢 @Efterklang 与 @wickdynex若下方链接无法访问,可使用
https://gitee.com/RubyMetric/chsrc/raw/main/tool/installer.sh替代
# 非root用户默认安装至 ~/.local/bin
$ curl https://chsrc.run/posix | bash
# 也可以使用 Wget
$ wget -O - https://chsrc.run/posix | bash
# root用户默认安装至 /usr/local/bin
$ curl https://chsrc.run/posix | sudo bash
# 使用 -d 指定目录安装
$ curl https://chsrc.run/posix | bash -s -- -d ./
# 使用 -v 指定版本 (不指定时默认为 pre)
# 1. 安装 pre 版本; 这比从包管理器安装的总是更新一些
# 2. 安装旧版本; 有时新版本可能引入某些 Bug,临时使用旧版本解决燃眉之急
$ curl https://chsrc.run/posix | bash -s -- -v 0.2.1
# 使用 -l en 输出英文
$ curl https://chsrc.run/posix | bash -s -- -l en- 可手动下载二进制文件安装
# x64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-x64-linux -o chsrc; chmod +x ./chsrc
# aarch64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-aarch64-linux -o chsrc; chmod +x ./chsrc
# riscv64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-riscv64-linux -o chsrc; chmod +x ./chsrc
# armv7
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-armv7-linux -o chsrc; chmod +x ./chsrc如果你所在的处理器架构没有预编译版本,可以使用 chsrc-bootstrap
macOS
- 可通过
homebrew安装,感谢 @Aaron-212 与 @chenrui333
brew install chsrc可通过
shell脚本安装最新版,感谢 @Efterklang 与 @wickdynex若下方链接无法访问,可使用
https://gitee.com/RubyMetric/chsrc/raw/main/tool/installer.sh替代
# 非root用户默认安装至 ~/.local/bin
$ curl https://chsrc.run/posix | bash
# root用户默认安装至 /usr/local/bin
$ curl https://chsrc.run/posix | sudo bash
# 使用 -d 指定目录安装
$ curl https://chsrc.run/posix | bash -s -- -d ./
# 使用 -v 指定版本 (不指定时默认为 pre)
# 1. 安装 pre 版本; 这比从包管理器安装的总是更新一些
# 2. 安装旧版本; 有时新版本可能引入某些 Bug,临时使用旧版本解决燃眉之急
$ curl https://chsrc.run/posix | bash -s -- -v 0.2.1
# 使用 -l en 输出英文
$ curl https://chsrc.run/posix | bash -s -- -l en- 或手动下载二进制文件,这是最新版,往往比
homebrew提供的更新,适用于修复 Bug、添加新功能后及时使用
# arm64/aarch64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-aarch64-macos -o chsrc; chmod +x ./chsrc
# x64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-x64-macos -o chsrc; chmod +x ./chsrcBSD
如果已安装好了编译 chsrc 所需要的依赖,可直接运行:
git clone https://gitee.com/RubyMetric/chsrc.git; cd chsrc
clang -Iinclude -Ilib src/chsrc-main.c -o chsrc如果还不存在这些依赖,你将会被死锁住: 我还没有换源,我该如何安装这些依赖呢?
这就是 chsrc-bootstrap 起作用的时刻,你可使用BSD系统的原生脚本语言编写 bootstrapper,并向我们提交
注: chsrc 实现的 FreeBSD recipe 长期存在问题,因此一个新的 bootstrapper 是相当必要的,请帮助你自己和大家!
Android/Termux
Termux 中默认无 Wget,我们都用 cURL 来下载安装
# arm64/aarch64
curl -L https://gitee.com/RubyMetric/chsrc/releases/download/pre/chsrc-arm64-android -o chsrc; chmod +x ./chsrc如果你所在的处理器架构没有预编译版本,可以使用 chsrc-bootstrap:
curl -L https://gitee.com/RubyMetric/chsrc/raw/main/bootstrap/Termux.bash | bash其他平台
若你所在的平台不存在预编译好的 chsrc,你需要手动编译。如果已安装好了编译 chsrc 所需要的依赖,可直接运行:
git clone https://gitee.com/RubyMetric/chsrc.git; cd chsrc; make如果还不存在这些依赖,你将会被死锁住: 我还没有换源,我该如何安装这些依赖呢?
这就是 chsrc-bootstrap 起作用的时刻,你可使用该平台原生脚本语言编写 bootstrapper,并向我们提交
💡 使用
名称:
chsrc - Change Source - (GPLv3+)
使用:
chsrc <command> [options] [dish] [mirror]
命令:
help, h 打印此帮助,或 -h, --help
issue, i 查看相关issue
list, ls, l 列出可用镜像站和可换源菜品
list mirror|dish 列出支持的: 镜像站/换源菜品
list os|lang|ware 列出支持的: 操作系统/编程语言/软件
list <dish> 查看该菜品可用源与支持功能
measure, m, cesu <dish> 对该菜品所有源测速
get, g <dish> 查看该菜品当前源的使用情况
set, s <dish> 换源,自动测速后挑选最快源
set <dish> first 换源,使用维护团队测速第一的源
set <dish> <mirror> 换源,指定使用某镜像站 (通过list <dish>查看)
set <dish> <URL> 换源,用户自定义源URL
reset <dish> 重置,使用上游默认使用的源
选项:
-dry Dry Run,模拟换源过程,命令仅打印并不运行
-scope=project|user|system 仅对本项目换源 / 用户级换源 / 系统级换源 (通过ls <dish>查看)
-ipv6 使用IPv6测速
-en(glish) 使用英文输出
-no-color 无颜色输出自动测速,寻找最快者,换源
$ chsrc set ruby
不想自动测速的时候,可使用维护团队测试的最快镜像站
$ chsrc set ruby first
先列出可用的镜像站,然后选择其一,如使用 RubyChina 作为镜像站
$ chsrc ls ruby
$ chsrc set ruby rubychina
若有自己的镜像,可以使用自定义URL
$ chsrc set ruby https://gems.ruby-china.com/
对支持 *项目级* 换源的菜品,可以避免全局(*系统级* 或 *用户级*)换源
$ chsrc set -scope=project bundler
$ chsrc set -scope project pdm编程语言开发
chsrc set ruby|rb|gem|bundler|rubygems
chsrc set python | py | pypi # 同时换 pip, poetry, pdm, uv 这4个包管理器,也可以4个独立换源
chsrc set pip
chsrc set poetry
chsrc set pdm
chsrc set uv
chsrc set rye
chsrc set node | nodejs # 同时换 npm, yarn 和 pnpm 这3个包管理器,也可以3个独立换源
chsrc set npm
chsrc set yarn
chsrc set pnpm
chsrc set nvm
chsrc set bun
chsrc set perl | cpan
chsrc set php | composer
chsrc set lua | luarocks
chsrc set rust | cargo | crate
chsrc set rustup
chsrc set go
chsrc set java | maven | mvn | maven-daemon | mvnd | gradle
chsrc set clojure | clojars
chsrc set dart | pub
chsrc set flutter
chsrc set haskell | hackage | cabal | stack
chsrc set ocaml | opam
# 同时会为 bioconductor 换源
chsrc set r | cran
chsrc set julia操作系统
sudo chsrc set ubuntu
sudo chsrc set zorinos
sudo chsrc set linuxmint
sudo chsrc set debian
sudo chsrc set fedora
# 同时支持 Leap 和 Tumbleweed
sudo chsrc set opensuse
sudo chsrc set kali
sudo chsrc set arch
sudo chsrc set archlinuxcn
sudo chsrc set manjaro
sudo chsrc set gentoo
sudo chsrc set rocky | rockylinux
sudo chsrc set alma | almalinux
sudo chsrc set alpine
sudo chsrc set voidlinux
sudo chsrc set solus
sudo chsrc set ros | ros2
sudo chsrc set trisquel
sudo chsrc set linuxlite
sudo chsrc set raspi | raspberrypi
sudo chsrc set armbian
sudo chsrc set openwrt
sudo chsrc set openeuler
sudo chsrc set openanolis | anolis
sudo chsrc set openkylin
sudo chsrc set deepin
chsrc set msys2 | msys
# Android
chsrc set termux
# BSD
sudo chsrc set freebsd
sudo chsrc set openbsd
sudo chsrc set netbsd软件
chsrc set winget
chsrc set brew | homebrew
chsrc set cocoapods | cocoa | pod
chsrc set dockerhub | docker
chsrc set flathub | flatpak
chsrc set nix
chsrc set guix
chsrc set emacs | elpa
chsrc set tex | ctan | latex | texlive | miktex
chsrc set conda | anaconda📝 许可证
chsrc主程序采用GPL-3.0-or-later许可证,保证该软件的永久自由xy.h使用MIT许可证,保证该库可以在尽可能多的情况下复用
❤️ 致谢
感谢各个镜像站提供的优质免费镜像服务
- mirror.c 包含了通用的镜像站信息
- 各个recipe内部定义的专用镜像站
另外特别感谢以下组织或项目:
🚀 赞赏支持
你是否因为 chsrc 而受到启发、节省了时间精力 or whatever?
爱发电主页: https://afdian.com/a/ccmywish
Overview (`.vscode/README.md`)
Dev in VS Code
首先需要安装好 just,而不再硬性需要 make
Ctrl-Shift-B直接构建F5直接开始 Debug
Overview (`bootstrap/README.md`)
Bootstrap
begin
download_prebuilt_chsrc_binary_for_my_platform
rescue NoReadyMadeBinary => e
bootstrap! e.my_platform
end预编译产生的死锁问题
我们支持预编译的操作系统目前只有 Windows, Linux, macOS,支持的架构请参考项目 README
某些操作系统如 BSD 家族,甚至是更小众的操作系统, 或者上述操作系统的某些架构,无法享受直接下载二进制立即使用的便利性,这导致用户需要自己编译 chsrc.
然而用户自己编译则面临着一个问题: 需要提前安装项目依赖
- 把代码
git clone下来 或 下载zip包进行解压缩 - C语言编译器
GNU make或just(这二者非强制,但是有了更好)
可是如果用户还没有换源,他/她又如何获得上述这些程序呢?这是一把死锁,导致用户最终回到手动换源的原始农耕时代。
`chsrc-bootstrap` to the Rescue
chsrc-bootstrap 是一组使用原生脚本语言的脚本,每个脚本称为 bootstrapper,用来完成两件事情:
帮助用户进行最基本的换源,让用户能够立即开始使用该系统安装其他软件
用户自行决定是否需要安装
chsrc若不需要: 流程直接结束,用户已可以完成基本日常工作
若需要: 帮助用户安装好所需的最少依赖,并编译安装
chsrc
注意,最基本的换源,即不测速,由维护者暂时决定先切换到某一个具体的源,先让系统跑起来。
支持的语言
上述提到的原生脚本语言只能是这些:
Windows:
PowerShell,CMDLinux:
Bash,sh备选:
PerlmacOS:
Zsh,Bash,sh备选:
Ruby,PerlBSD:
sh备选: 待议
其他平台: 一切该平台支持的脚本语言,无需额外安装
`chsrc` 与 `chsrc-bootstrap`
chsrc 需要实现 chsrc-bootstrap 中支持的平台。这是因为,chsrc-bootstrap 只换到了某一个具体的源,只是临时性的,后续用户可能还想要换到其他源,此时 chsrc 就可以接管。
而事实上,chsrc-bootstrap 可以完成一些操作,使得系统已经满足一些前置条件,这样的话 chsrc 可以在这些前置条件存在时接着换源,从而大幅减轻 recipe 的实现难度。
帮助
FreeBSD 的换源 从项目一开始就是我们的目标之一,然而由于其:
- 换源所需的步骤太多
- 面临着特有的鸡蛋困境
- BSD 工具和 GNU 工具总是有不兼容之处
- 在C语言中实现困难重重
因此我们一直没有很好的办法去实现
任何你所在的平台,都可以添加到此
Overview (`doc/README.md`)
文档说明
E2E (End-to-End) 开发文档:
- 开发环境准备,如何编译和测试,请参考 01-开发与构建.md
- 直接推送还是提交 PR,请参考 02-提交与贡献.md
- 代码风格,请参考 03-为什么拒绝使用代码格式化工具.md
具体 recipe 相关:
如何编写一个具体的 recipe,请参考 10-如何编写recipe.md
如何修改换源链接、模糊/精准测速链接,请参考 11-如何设置换源链接与测速链接.md
关于维护者身份的说明,请参考 50-协作者与维护者.md
用户手册:
贡献指导
若有任何问题,可在 GitHub discussions 中询问和讨论
Overview (`pkg/README.md`)
Packages
分发情况
-
Homebrew -
Scoop -
WinGet -
AUR -
Flatpak -
snap - ...
$ brew install chsrc
$ scoop install chsrc
$ winget install RubyMetric.chsrc
yay -S chsrc-bin # Binary from GitHub Release
yay -S chsrc # Build from GitHub Release
yay -S chsrc-git # Build from the latest main branch (stable)Homebrew
https://github.com/Homebrew/homebrew-core/blob/master/Formula/c/chsrc.rb
Scoop
https://github.com/ScoopInstaller/Main/blob/master/bucket/chsrc.json
WinGet
https://github.com/microsoft/winget-pkgs/tree/master/manifests/r/RubyMetric/chsrc
AUR:
打包情况
-
deb
Overview (`tool/README.md`)
工具说明
installer.shBash 编写的一键安装工具
installer.ps1PowerShell 编写的一键安装工具
download-pre-on-GitHub.ps1从 GitHub
prerelease 上下载所有附件completion/目录Shell 自动补全文件
`rawstr4c`
C语言字符串生成工具,本身是为了本项目而开发,是放在本仓库下的一个完整子项目。但为了维护更方便,拆分到新的仓库: https://github.com/RubyMetric/rawstr4c
Overview (`pkg/AUR/README.md`)
AUR package
本文档说明了 chsrc 项目的 AUR 包的相关情况
相关文件
CI 维护者 @Jerry-Terrasse
- .github/workflows/pub-AUR-chsrc-git.yml
- [.github/workflows/pub-AUR-chsrc-and-chsrc-bin.yml`](../../.github/workflows/pub-AUR-chsrc-git.yml)
分发
位于 https://aur.archlinux.org/packages
Overview (`pkg/deb/README.md`)
deb package
本文档说明了 chsrc 项目的 deb 包的相关情况
相关文件
.github/workflows/pkg-deb.yml- CI 配置文件./CI.md- CI 情况说明
./debian/- deb 包构建配置目录./BUILD.md- 如何手动构建./Makefile- deb 包构建 Makefile./deb-installation-test.sh- deb 包 已正确安装 测试脚本
安装
如果你是普通用户,你应该从 GitHub Releases 下载合适的 deb 包,然后运行以下命令安装:
sudo dpkg -i chsrc_*.deb
sudo apt-get install -f # Fix any dependency issues如果你是高级用户,你可以自己阅读本目录下的 ./BUILD.md 来自己构建 deb 包并按照上述同样的方式安装。
`debian/` 目录结构
debian/
├── changelog # 版本更新日志
├── compat # debhelper 兼容性版本
├── control # 包控制信息和依赖
├── copyright # 版权信息
├── postinst # 安装后脚本
├── prerm # 卸载前脚本
└── rules # 构建规则其中,最后三个是 +x 的可执行文件。
Overview (`src/recipe/lang/Ruby/README.md`)
Ruby 换源问题
https://github.com/ustclug/discussions/issues/438
Ruby China: 于2026年7月21日暂停服务 (https://ruby-china.org/topics/44619)
清华、北京外国语: 不可用,原因是: 实现不足 https://github.com/tuna/issues/issues/374
腾讯: 不可用,原因是: 缺乏
versions文件阿里: 不可用,原因是: 缺乏
versions文件华为: 不可用,原因是:版本太过老旧,应该是没有同步
Overview (`src/recipe/ware/Docker/README.md`)
Docker
- USTC 与 SJTUG 于 2024-06-06 停止支持 DockerHub
- NJU 于 2024-06-07 停止支持 DockerHub
Overview (`src/recipe/lang/Python/uv/README.md`)
uv 换源实现说明
chsrc set uv 同时配置两类下载地址:
- Python 包索引,即
uv.toml的[[index]]或pyproject.toml的[[tool.uv.index]] - uv 管理的 CPython 下载地址,即
python-install-mirror
配置文件选择
项目作用域只修改当前目录,不向父目录查找并修改配置:
- 当前目录存在
uv.toml时修改uv.toml - 否则,当前目录存在
pyproject.toml时修改其中的[tool.uv] - 两者都不存在时创建
uv.toml
这个顺序与 uv 的行为一致:同一目录同时存在 uv.toml 与 pyproject.toml 的 [tool.uv] 时,uv 优先使用 uv.toml 中的对应字段。
用户作用域使用 uv 的用户配置目录:Windows 为 %APPDATA%\uv\uv.toml,Linux 和 macOS 优先使用 $XDG_CONFIG_HOME/uv/uv.toml,未设置时使用 ~/.config/uv/uv.toml。
Python 包索引
索引 URL 必须指向兼容 Python Simple Repository API 的地址,通常以 /simple 结尾;uv 不要求 URL 必须以 / 结尾。
default = true 表示该 index 替代 uv 内置的 PyPI,并且始终具有最低 index 优先级。它不表示“文本中的第一个”或“最高优先级”。配置中存在多个 index 时,chsrc 优先更新 default = true 的 index;没有 default index 时才更新第一个 index。
默认的 first-index 策略会在第一个包含目标包的 index 停止搜索。私有源与公共镜像并存时,不应把它理解成跨所有 index 选择全局最新版本。
Python 下载镜像
python-install-mirror 是 https://github.com/astral-sh/python-build-standalone/releases/download 的替换前缀。配置值必须是镜像侧对应的 releases/download 基址,不能是仓库主页、某个具体构建日期或某个归档文件。uv 会在其后追加构建日期和
归档文件名。
官方示例使用不带尾部 / 的基址,chsrc 内置源也遵循该形式。
reset 与备份
chsrc set uv 修改已有配置前会创建 .bak 备份。
chsrc reset uv 把 chsrc 管理的 index 与 python-install-mirror 写回默认上游:index 恢复为 https://pypi.org/simple,python-install-mirror 恢复为 https://github.com/astral-sh/python-build-standalone/releases/download。
其他用户配置原样保留,不依赖 .bak 恢复旧 URL。
指定镜像代码时,若该代码同时提供 PyPI 与 Python 下载镜像(例如 nju),两部分使用同一镜像代码;仅提供其中一类时,另一类自动测速。用户自定义 URL 只解释为 PyPI index URL,因为 Python 下载镜像要求完全不同的 releases 目录布局。
default = true 的 index(不存在时取第一个)被视为 PyPI 替代源,reset 只修改这一处;私有 index 不受影响。
实现边界
配置改写器只解析 chsrc 使用的 TOML 子集,但支持常见的行首缩进、CRLF、行尾注释、多个 index,以及位于 [tool.uv.sources] 等子表之后的 [[tool.uv.index]]。读取时换行统一为 LF 处理,写入时按系统平台输出行尾(Windows 为 CRLF,其余为 LF)。多行字符串和完整 TOML 转义语义不属于该轻量改写器的支持范围。
参考:
Doc 01 开发与构建 (`doc/01-开发与构建.md`)
开发 chsrc
依赖与开发环境
请安装好:
我推荐你使用 VS Code 开发,你可以在一分钟内成功编译、运行和 Debug chsrc
Ctrl-Shift-B直接构建F5直接开始 Debug
获取代码
请务必使用 dev 分支开发
git clone https://gitee.com/RubyMetric/chsrc.git -b dev关于分支的说明,可参考 ./03-CONTRIBUTING.md
编译运行
共有四种构建模式:
DEV modeDEBUG modeRELEASE modeCI-RELEASE mode
开发时只需要前两种模式;第四种模式只在 GitHub Actions 使用。
如果你使用 just,可以在 VS Code 中获得更好的体验,按 Ctrl-Shift-B 直接使用 DEV mode 构建
注意: DEBUG 模式下, 执行任意一个 recipe 的任意操作,会额外检查所有 _prepare() 是否能正常工作,如: ./chsrc-debug ls <recipe>
just (b) # 在Windows上默认使用 gcc 编译,在macOS上默认使用 clang 编译,在其他系统上默认使用 cc 编译
just CC=clang # 使用 clang 编译
just CC=gcc # 使用 gcc 编译
# 编译出 debug 版本: chsrc-debug
just bd
# 编译出 release 版本: chsrc-release
just brmake 用户:
make (b) # 在Windows上默认使用 cc 编译,在macOS上默认使用 clang 编译,在其他系统上默认使用 cc 编译
make CC=clang # 使用 clang 编译
make CC=gcc # 使用 gcc 编译
# 编译出 debug 版本: chsrc-debug
make bd
# 编译出 release 版本: chsrc-release
make brDebug
如果你使用 just,可以在 VS Code 中获得更好的体验,按 F5 即可立即开始 Debug
# 重新编译出 ./chsrc-debug,并启动 GDB 调试 (在macOS上启动 LLDB 调试)
$ just debug
# 重新编译出 ./chsrc-debug,并启动 LLDB 调试
$ just DEBUGGER=lldb debugmake 用户:
# 重新编译出 ./chsrc-debug,并启动 GDB 调试 (在macOS上启动 LLDB 调试)
$ make debug
# 重新编译出 ./chsrc-debug,并启动 LLDB 调试
$ make debug DEBUGGER=lldb测试
just 用户只需要替换下述 make 为 just
make test-xy # 测试 xy.h
make test-fw # 测试 framework
make test # 测试上述两个
make test-cli # 测试命令
make clean提交 PR
关于分支的说明以及如何提交代码,请参考 ./03-CONTRIBUTING.md
Doc 02 提交与贡献 (`doc/02-提交与贡献.md`)
贡献说明
分支
gh-build:仅仅在发布版本时由@ccmywish推送,触发编译到 GitHub Releases 中main: stable,代码一定是可以编译运行的,我们假设 end users 在其他条件都得不到二进制时,会自己编译这个分支来运行chsrcdev:开发分支,工作分支,在此分支上解决冲突
提交与审阅
当你提交 PR 的时候,一定要将 PR 指定 chsrc 原仓库的 dev 分支。
提交的代码分两种情况考虑。(1)recipe 相关的 (2)framework 相关的
(1)
需要先搜索你修改的部分涉及到的 recipe,然后提 issue @ 所有相关的 recipe chefs 来 review
(2)
如果涉及了所有 recipe,则需要 @ 项目创建者或者协作者,而无需把所有 recipe 的 chefs 都喊过来,但是如果觉得有必要,可以 @ 任意你觉得有能力 review 和能给出建议的人来 review
Doc 03 为什么拒绝使用代码格式化工具 (`doc/03-为什么拒绝使用代码格式化工具.md`)
chsrc 代码风格
Ruby 的语法优美性在编程行业中具有标杆地位。Matz(松本行弘)提出的 代码应该为人类而写,偶尔为机器执行 这一理念,已经成为现代编程语言设计的重要指导原则。chsrc 项目的第一作者深受 Ruby 语言哲学的影响。
本项目起源于 AI 编程尚未流行的时代,所有代码全部依赖人类的耐心来维护。现在,我们的代码以及这篇文章不仅会由人类阅读,也会由 AI 阅读。我们始终坚持:代码的可读性和维护性是项目长期发展的根本保障。
为什么我们坚持不使用代码格式化工具
代码格式化工具(code formatter)在多人协作的代码仓库中确实有其价值,参与的人越多,统一格式的需求越迫切。然而,chsrc 项目经过深思熟虑后,拒绝使用代码格式化工具。让我来说明这一决定背后的深层原因。
被强迫使用
像 Prettier 这样的工具表面上带来了统一性,但其代价是什么?它是极度专制的(opiniated),我们必须完全交出代码审美的自主权。今天我们大部分人使用 Prettier,并非出于真心的认同,而是因为整个前端生态圈的集体胁迫——不用就意味着被边缘化。
这种现象的本质令人深思:少数 Prettier 维护者的个人偏好,竟然决定了全球数百万开发者的代码美学标准。这显然是一种技术独裁,坚决拒绝向格式化工具的霸权低头。
一致性 ≠ 美观 ≠ 可读
格式化工具只保证了表面的一致性,就像一些校服,一致不一定代表美。同样,一致不一定代表代码就是最易读易懂的。
每一个有追求的程序员都应该保留对代码美学的最后决定权,格式化工具的便利性不应该以牺牲美观性和可维护性为代价。
满足不了我们的需求
C语言的格式化工具通常选择 clang-format,它的配置选项十分丰富,比 Prettier 要理性得多。然而,即便如此,其配置的复杂性和局限性仍然无法满足 chsrc 对代码格式的严苛要求。如果你是一位 clang-format 的配置专家,我们诚挚邀请您告诉我们如何优雅地处理以下代码场景,也许这能改变我的立场。
挑战案例
以下是我认为自动格式化工具很难完美处理的代码场景:
= 对齐:
char *name = va_arg (args, char*);
char *email = va_arg (args, char*);复杂逻辑的 = 对齐:
bool matched = iterate_menu (chsrc_pl_menu, input, &dish_tmp);
if (!matched) matched = iterate_menu (chsrc_os_menu, input, &dish_tmp);
if (!matched) matched = iterate_menu (chsrc_wr_menu, input, &dish_tmp);预处理指令的层次缩进:
#ifdef _WIN32
#define XY_Build_On_Windows 1
#define xy_on_windows true
#ifdef XY_DEBUG
#define xy_debug_mode 1
#endif
#endif...... 等等
C语言代码风格
整体上基于
GNU style,但我们坚持自己的美学原则,在细节上有所改进类型名:
PascalCase_t,即UpperCamelCase_t函数定义和调用时,函数名和
()之间始终保持一个空格,如果是在宏中,可紧凑一些,无硬性规定函数和函数定义之间一般保持2个空行
- 若函数之间有高度关联性,可用1个空行
- 若一系列函数和一系列函数存在主题性区别,可用3个空行
Markdown 写作风格
维护者很多时候不是从渲染好的界面来看 Markdown 文件的,而是阅读 Markdown 源文件,所以 Markdown 在源文件层面也要易读。
我们保持每个主题之间 1个`` + 3个空行 的简单风格。
拒绝使用 VS Code 的 markdownlint 插件,因为它总是用它狭隘的标准给我们增加了巨多的黄色下划线。
其他语言代码风格
我们秉承 入乡随俗、尊重传统 的原则,尊重每种语言社区的既定传统。比如,YAML 使用2个空格,JSON使用4个空格,Perl 使用 Larry Wall 钟爱的4个空格。
我们使用 .editorconfig 来确保这些格式的应用。
Doc 10 如何编写Recipe (`doc/10-如何编写recipe.md`)
Write A Recipe Even If You Don't Know C
介绍
chsrc 不仅是一个命令行工具,同时也是一个体现了 Ruby on Rails 思想的 MVC 换源框架,它甚至使你能够在不了解C语言的情况下编写出新的换源方法(recipe)。
我鼓励你为新的软件添加换源支持,因为通过 chsrc 框架,这将比写 shell 脚本更加轻松,你的贡献也将非常有价值。理论上每一个 recipe 都需要有专人长时间维护 (招募)。
- 本项目采用
GPLv3+协议,是真正的自由软件,而非仅仅是开源软件 - 代码规范灵活遵循
GNU标准(若标准干扰了可维护性,则并不采纳) - 高度模块化,目录结构清晰易懂
- 极小依赖,极易构建,只需要
GCC或Clang即可编译 (make和just可简化编译,但不是必需的) - 易于将
shell脚本转换为等价的recipe - 已有大量
recipe可提供参考,并提供了 recipe template 供直接使用 - 本仓库外的子项目 rawstr4c 帮助你在C语言中维护复杂的字符串
- chsrc-bootstrap 帮助你在没有预编译
chsrc的平台上 bootstrap 自己
成功案例:
基本概念
dish: 所要换源的菜品combo dish: 一个dish包含了多个子dish,比如Python包含了该语言的多个包管理器category: 是dish category的简写,即dish所属的类别,可以是 编程语言,操作系统,软件 三类之一- 在目录中,三者分别为
lang,os,ware - 在代码中,三者前缀分别为
pl,os,wr
- 在目录中,三者分别为
mirror: 是mirror site的简写,指镜像站,如清华大学开源软件镜像站source: 该dish所能换的具体的源,由mirror提供服务,往往一个mirror会提供许多sourcerecipe: 是为一个dish定义的具体换源方法,请参考src目录中的recipe目录chef DSL:是chef Domain Specific Language的简写,这是一组以chef_开头的函数,用来定义维护者信息、可用源等元信息换源链接: 指镜像站所提供的某一个具体的换源使用的URL
测速链接: 用来测速的URL,与 "换源链接" 不同,可分为 精准测速 和 模糊测速
在代码中,测速链接一般使用
smURL(即speed measure URL) 或speed_measure_url来指代在代码中,换源链接一般使用
repoURL(即repository URL) 或直接用url来指代- 为什么不用
regurl,因为使用术语repository的 dish 远多于使用术语registry的。 - 为什么莫名其妙使用了大小写混合的API? 因为
smurl和repourl的可读性太差
- 为什么不用
镜像源: 为了方便,偶尔我们将直接称
mirror和/或source为镜像源,这只是一种方便性的称呼,可以统称二者,也可以根据上下文指代二者之一
编写 `recipe` 步骤
确定你要编写的
dish的标准名称,创建Dish-Name.c文件大小写需严格按官方,若名称包含空格,需使用
-代替空格根据类别将上述文件放在
recipe/目录的某个子目录中复制 recipe template 的内容到上述文件中,并替换
<...>占位符参考现有
recipe的写法- 看一眼就能上手的参照物是 PHP recipe
- 最好的参照物是 Ruby recipe
- 组换源参照物是 JS combo recipe
在 Wiki 中记录的镜像站中寻找可用源;可以额外补充镜像站
使用 chef DSL 定义
_prepare()函数该函数将填充
dish所有的必要信息,包括维护信息、换源信息按需实现
_setsrc()_getsrc()_resetsrc(), 可以使用这些函数:framework/*.c中以chsrc_,chef_,hp_开头的所有函数或宏xy.h中以xy_开头的所有函数或宏
一个简单的方法是,在 VS Code 中按快捷键
Ctrl-T搜索上述三种前缀在
recipe/menu.c中登记此dish编译、运行、测试 (how?),若无问题可提交 Pull Request
开发准则
代码高度可移植
Convention over Configuration
NO UFO 原则: 不要乱丢文件到$HOME等目录,尤其是使用各种隐晦的文件名
chsrc主程序不提供配置文件,不提供数据文件,干净无污染。那么在实现recipe的时候,除了备份文件外,也不要污染用户环境。
其它
如果你借助 AI 进行开发,让 AI 阅读 copilot-instructions.md 并将它作为项目规范,该文件明确了很多在 AI 辅助开发时需要注意的问题。
Doc 11 如何设置换源链接与测速链接 (`doc/11-如何设置换源链接与测速链接.md`)
新增/修改 "换源链接"
在 _prepare() 函数中,在 def_sources_begin() 的位置的第二列,新增/修改你想要替换的链接。
注: 以下代码仅起解释作用,JavaScript换源的真正实现可能不同
def_sources_begin()
{&UpstreamProvider, "https://registry.npmjs.org/", FeedByPrepare},
{&NpmMirror, "https://registry.npmmirror.com", FeedByPrepare},
{&Huawei, "https://mirrors.huaweicloud.com/repository/npm/", FeedByPrepare},
{&Tencent, "https://mirrors.cloud.tencent.com/npm/", FeedByPrepare},
{&某新镜像站, "某镜像站提供的换源链接", FeedByPrepare}
def_sources_end()
//
// 调整上述某一个镜像站的所提供源的 "换源链接"
chef_set_repoURL (this, &UpstreamProvider, "新的换源链接");设置/修改 "测速链接"
在 _prepare() 函数中,在 def_sources_begin() 的位置的第三列,设置/修改你想要替换的链接。
在下面代码的第一行中,我们直接给了一个链接,这就是精准测速链接
在下面代码的第二行和第三行中,我们都设置了一个宏
DelegateToMirror,这意味着我们没有直接提供精准测速链接,而是让chsrc去测试其对应镜像站定义的测速链接NpmMirror是专用镜像站,所以其测速链接被设置为了ACCURATE,即精准测速Huawei是通用镜像站,所以其测速链接被设置为了ROUGH,即模糊测速
在下面代码的第四行中,我们设置了一个宏
FeedByPrepare,这意味着我们将在_prepare()函数的后续动态计算 URL
注: 以下代码仅起解释作用,JavaScript换源的真正实现可能不同
def_sources_begin()
{&UpstreamProvider, "https://registry.npmjs.org/", "https://registry.npmjs.org/BigFile.tar.gz"},
{&NpmMirror, "https://registry.npmmirror.com", DelegateToMirror},
{&Huawei, "https://mirrors.huaweicloud.com/repository/npm/", DelegateToMirror},
{&Tencent, "https://mirrors.cloud.tencent.com/npm/", FeedByPrepare},
def_sources_end()
//
// 调整/设置上述某一个镜像站的所提供源的 "精准测速链接"
chef_set_smURL (this, &UpstreamProvider, "新的测速链接");
// 设置上述某一个镜像站的所提供源的 "精准测速链接" 设置为 "换源链接" + postfix
chef_set_smURL_with_postfix (this, &UpstreamProvider, "/dir/BigFile.tar.gz");
// 基于 "换源链接" 做更自定义的操作
chef_set_smURL_with_func (this, &UpstreamProvider, func, data);
// 把所有上述源中还未设置 "精准测速链接" 的源进行设置
chef_set_rest_smURL_with_postfix (this, "/dir/BigFile.tar.gz");
chef_set_rest_smURL_with_func (this, func, data);
// 调整某一个镜像站(Provider)的 "测速链接"
chef_set_provider_smURL (&Tencent, "https://mirrors.cloud.tencent.com/npm/BigFile.tar.gz");
// 调整某一个镜像站(Provider)的 "测速精度"
chef_set_provider_sm_accuracy (&UpstreamProvider, ROUGH);Doc 50 协作者与维护者 (`doc/50-协作者与维护者.md`)
协作者与维护者
想要达到最理想的维护状态,每一个 recipe 都需要有专人长时间维护。我们的代码里使用了 recipe (某个菜的烹饪方法) 这个词,因而整个项目便和 "饮食" 有关,比如 menu: 汇集了所有的 dish 的菜单。因此,我们的维护者和贡献者身份依然使用了这个惯例:
Chef
主厨: 一个 recipe 的主要作者
Saucier
调味:一个 recipe 的次要贡献者
第一次贡献者
注册身份信息
在 src/chsrc-main.c 的 chsrc_register_contributors() 函数里,在最后(我们按参与本项目的时间顺序排列)添加一行:
chef_register_contributor ("@ID: 你的GitHub/Gitee用户名或任意不与其他贡献者冲突的名字",
"你的真实姓名",
"你的邮箱地址",
"若 chsrc ls <recipe> 的时候不想使用真实姓名,可以用这个参数的字符串来代替");更新 Recipe 信息
在你修改的 recipe 文件的 _prepare() 函数里,需要做以下更新:
更新 recipe 修改时间(每次修改 recipe 代码都要更新):
cchef_set_recipe_last_updated (this, "YYYY-MM-DD");更新镜像源信息时间(仅当你修改了镜像源列表时才更新):
cchef_set_sources_last_updated (this, "YYYY-MM-DD");将自己加入
sauciers(次要贡献者列表,将计数加一并添加自己的@ID):c// 原来是 0 个 saucier: chef_set_sauciers (this, 0); // 改为添加你自己: chef_set_sauciers (this, 1, "@你刚注册的ID"); // 原来已有 1 个 saucier: chef_set_sauciers (this, 1, "@Someone"); // 改为添加你自己: chef_set_sauciers (this, 2, "@Someone", "@你刚注册的ID");验证上述信息正确
sh# 应当能看到你的信息 ./chsrc ls <recipe>
--- METRICS ---
- Files Extracted: 17
- Estimated Token Budget: ~7922 tokens
- Canonical Reference: https://codewiki.google/github.com/RubyMetric/chsrc