Repository navigation
提议引入“编译时数据注入”机制,分离镜像源数据与业务代码,降低维护门槛 #377
Description
Activity
- changed the title
[-][Feature Request] 提议引入“编译时数据注入”机制,分离镜像源数据与业务代码,降低维护门槛[/-][+]提议引入“编译时数据注入”机制,分离镜像源数据与业务代码,降低维护门槛[/+]on Aug 14, 2026 Hi, @victorclover
很开心听到你认为
chsrc好用以及对chsrc项目及代码本身的兴趣与关注!你的建议非常详细,并且能看出你已经阅读了许多我们撰写的文档,这为我们的沟通打下了一个顺利的基础。
回应
对于完全没碰过 C 的人来说,确实有点心理门槛
是这样的,为此我们写了一个较清晰的文档 doc/11-如何设置换源链接与测速链接.md
来帮助用户如何填写换源列表。
所以我琢磨了一个折中方案:在仓库里维护一份纯数据文件(比如 data/ruby.json),里面只放镜像源的名字和 URL。然后在编译的时候,通过 Makefile 或者一个简单的小脚本,自动把这些 JSON 转成 C 代码(比如生成静态字符串数组),再和业务逻辑一起编译进最终二进制。
你提出的这个方案很好,其背后的思想正合我们开发并应用的 rawstr4c 这个工具。
rawstr4c是一个使用 Raku 编写的命令行脚本。在chsrc的许多 recipe 中都需要大量调用外部程序,比如sed,grep等,在C语言里书写这些程序的正则是十分困难的,尤其是涉及到大量转义、换行的时候。rawstr4c帮助我们解决了这个痛点(还有高亮等其他好处),使我们可以在C语言文件外维护这些内容。你可以看到我们项目中有许多rawstr4c.md以及对应生成的rawstr4c.h,最终会和chsrc本身的代码#include,最终编译为一个文件,它大大简化了我们在C中调用各种命令所需的字符串的维护量。
理由
所以你提的这个方案的思想,我们是完全欢迎的。但是使用JSON或者其他形式来存储换源链接,本身并不能像上述
rawstr4c这样明显降低维护复杂度。我有如下理由:- 首先,由于
def_sources_begin宏的存在,现有的 "源链接"们 组成了一个规矩的方阵,已经具有形式上的高辨认度,在现有的 recipe 中一眼可以确认。所以如果用 JSON 或者其他格式转写,无非也是类似的形式。
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} def_sources_end()
-
参考上述代码中第一列的镜像站,放到外部非C语言文件中去维护,将失去静态分析能力和跳转能力,还是需要用户安装一个编译器进行编译后才能知道是否存在误写
-
实际上换源链接和测速链接的维护,并不仅仅是写一个静态的URL,大部分时候需要通过编程的方式改写URL。比如说上述代码的第三列是测速链接,之所以上面都写的是 FeedByPrepare,是以为需要在后续调用一个API来统一填充,否则,就会出现大量的重复前缀。无论是放在C语言本身中,还是放到外部文件中,都是不可取的,只有通过编程的方式减少前缀的书写,可参考 npm.c 这还只是简单的情况,每个镜像站并不是统一的,有的时候会出现某一个镜像站就是和其他人不同,修改了中间的路径,所以还需要单独修改。可参考 uv-python-build.c。所以无论如何都是避免不了在C语言中继续对链接进行修改的,所以再放到外部文件去维护这些链接意义已经不大。
-
所有贡献者,包括只修改了一个链接的贡献者,都需要在代码里注册自己的信息,以便在
chsrc ls <dish>的时候展示它的贡献所以他/她依然需要触及代码 -
chef.c这个文件本来就叫做 chef DSL,它已经是高度 DSL 化的API,可以看到在_prepare()函数里,几乎所有API都是声明式的了,包括定义源的这部分,再加上AI的帮助,即使不会C语言的贡献者,如果懂得任何其他一门编程语言,就足以维护镜像源数据。
- 首先,由于
事实上,我们已经有不少贡献者在完全不懂C语言的情况下做出了贡献。
尤其是 @Mikachu2333 在积极参与
chsrc贡献的过程中逐渐学习C语言,进步十分突出,成为本项目的协作者。发现有几个镜像站好像已经挂了
@victorclover 欢迎给我们提PR,参与我们的项目!❤️
有几个可能的原因,我可以提前说一下:
- 清华、北京外国语 等镜像站现在封禁IP十分严格,稍微重复请求就会被封禁
- 有新闻最近清华删除了几个源,对此我并没有做出代码上的修改,因为这是一个合适的机会留给新贡献者!
另外,其实对于C完全不怎么熟悉的人,也可以通过调用 .github/copilot-instructions.md 作为 AGENTS.md 使用,比如说我在维护
uv模块的时候就是这么做的。在我看来,哪怕纯AI的代码,只要风格与项目要求一致、完全遵守项目规范、代码测试覆盖全面,想改一些东西还是比较简单的。当然,如果是完全不懂代码的人,对 AI 的 prompt 太过空泛,也难以达到目的。prompt 需要比较精细,比如:
当前的UV模块存在以下问题,尝试修复: 1. UV无法对python-install-mirror进行换源,参考链接:<https://docs.astral.sh/uv/reference/settings/#python-install-mirror> 2. UV模块对chsrc的项目级别响应效果不佳(含pip和python mirror),当前仅实现了uv.toml,未对pyproject.toml适配,参考:<https://docs.astral.sh/uv/concepts/configuration-files> 与 <https://docs.astral.sh/uv/reference/settings/#index> 3. 需要同时支持uv.toml与pyproject.toml的语法适配与简单的错误处理 4. 难点:双源语义,`chsrc set uv XXX`需要同时考虑XXX在pip镜像源列表中是否存在、在python mirror镜像列表中是否存在 5. 注意事项:将具体的toml操作抽象成一个小型模块,尽量保持其通用性,uv模块内仅保留封装好的函数以供后期维护继续调用,使逻辑清晰 6. 注意事项:需针对toml允许的多种语法进行适配,例如 `[[tool.uv.index]]` 的等价形式 7. 其他:当前可用的镜像列表(pip、python mirror)见xxx文件,无需搜索,镜像列表的测速链接亦在文件内 对上述需要完成的事项汇总并按照功能类别进行分类,并在修复前进行汇总,汇报难易程度、复杂度、可行性
Hi,RubyMetric
最近开始重度用 chsrc,换源确实方便,省了不少事。不过用着用着发现有几个镜像站好像已经挂了,就想着能不能顺手更新一下。
然后我去看了下 recipe 的代码,发现虽然官方文档说“不熟悉 C 也能写”,但实际要改一个 URL,还是得在 .c 文件里找半天,而且得小心别碰坏逻辑。对于完全没碰过 C 的人来说,确实有点心理门槛。
于是我就冒出一个想法:能不能把每个 target 的镜像源列表(就是那些 URL 们)从 C 代码里剥离出来,单独放到一个 JSON(或者 YAML/TOML)文件里? 这样以后谁发现源失效了,直接改 JSON 里的 URL,提交 PR 就行,连编译器都不用装。
之后我又翻了一下项目的设计文档,看到你说“主程序不提供配置文件,干净无污染”,这个理念很赞。所以我琢磨了一个折中方案:
在仓库里维护一份纯数据文件(比如 data/ruby.json),里面只放镜像源的名字和 URL。然后在编译的时候,通过 Makefile 或者一个简单的小脚本,自动把这些 JSON 转成 C 代码(比如生成静态字符串数组),再和业务逻辑一起编译进最终二进制。
这样用户拿到的还是那个干净的单文件,没有任何外部依赖,但源列表的维护门槛直接降到了零——会改 JSON 就行。
我觉得这个方案挺香的,既保留了设计初心,又让社区贡献变得超简单。我自己对 C 还算熟悉,也经常折腾构建脚本,如果你觉得这个方向可行,我可以帮忙把这一整套东西搭出来,包括:
设计 JSON 的数据结构
写转换脚本(用 shell + jq 或者干脆用 C 写个 codegen 都行)
修改 Makefile/CMake,集成到构建流程里
顺手把现有的 recipe 数据迁移到 JSON
当然,如果你有更好的思路,或者觉得这个改动太大、不值得,也完全没关系,我就当提个脑洞交流一下。毕竟工具本身已经很好用了,我这属于锦上添花 😄
想听听你的看法,如果方向 OK,我可以先开个 draft PR 看看效果。