Skip to content

提议引入“编译时数据注入”机制,分离镜像源数据与业务代码,降低维护门槛 #377

Description

@victorclover

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 看看效果。

Activity

  1. added theissue type on Aug 14, 2026
  2. changed the title [-][Feature Request] 提议引入“编译时数据注入”机制,分离镜像源数据与业务代码,降低维护门槛[/-] [+]提议引入“编译时数据注入”机制,分离镜像源数据与业务代码,降低维护门槛[/+] on Aug 14, 2026
  3. ccmywish commented on Aug 14, 2026

    @ccmywish
    Contributor

    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 这样明显降低维护复杂度。我有如下理由:

    1. 首先,由于 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()
    1. 参考上述代码中第一列的镜像站,放到外部非C语言文件中去维护,将失去静态分析能力和跳转能力,还是需要用户安装一个编译器进行编译后才能知道是否存在误写

    2. 实际上换源链接和测速链接的维护,并不仅仅是写一个静态的URL,大部分时候需要通过编程的方式改写URL。比如说上述代码的第三列是测速链接,之所以上面都写的是 FeedByPrepare,是以为需要在后续调用一个API来统一填充,否则,就会出现大量的重复前缀。无论是放在C语言本身中,还是放到外部文件中,都是不可取的,只有通过编程的方式减少前缀的书写,可参考 npm.c 这还只是简单的情况,每个镜像站并不是统一的,有的时候会出现某一个镜像站就是和其他人不同,修改了中间的路径,所以还需要单独修改。可参考 uv-python-build.c。所以无论如何都是避免不了在C语言中继续对链接进行修改的,所以再放到外部文件去维护这些链接意义已经不大。

    3. 所有贡献者,包括只修改了一个链接的贡献者,都需要在代码里注册自己的信息,以便在 chsrc ls <dish> 的时候展示它的贡献所以他/她依然需要触及代码

    4. chef.c 这个文件本来就叫做 chef DSL,它已经是高度 DSL 化的API,可以看到在 _prepare() 函数里,几乎所有API都是声明式的了,包括定义源的这部分,再加上AI的帮助,即使不会C语言的贡献者,如果懂得任何其他一门编程语言,就足以维护镜像源数据。

  4. pinned and unpinned a comment on Aug 14, 2026
  5. ccmywish commented on Aug 14, 2026

    @ccmywish
    Contributor

    事实上,我们已经有不少贡献者在完全不懂C语言的情况下做出了贡献。

    尤其是 @Mikachu2333 在积极参与 chsrc 贡献的过程中逐渐学习C语言,进步十分突出,成为本项目的协作者。

  6. ccmywish commented on Aug 14, 2026

    @ccmywish
    Contributor

    发现有几个镜像站好像已经挂了

    @victorclover 欢迎给我们提PR,参与我们的项目!❤️

    有几个可能的原因,我可以提前说一下:

    1. 清华、北京外国语 等镜像站现在封禁IP十分严格,稍微重复请求就会被封禁
    2. 有新闻最近清华删除了几个源,对此我并没有做出代码上的修改,因为这是一个合适的机会留给新贡献者!
  7. Mikachu2333 commented on Aug 15, 2026

    @Mikachu2333
    Collaborator

    另外,其实对于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文件,无需搜索,镜像列表的测速链接亦在文件内
    
    对上述需要完成的事项汇总并按照功能类别进行分类,并在修复前进行汇总,汇报难易程度、复杂度、可行性
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    讨论讨论 Discussion

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions