编程语言镜像源
本文探索不同编程语言都是如何管理其依赖包的,如何做到快速安装使用?如何为其构建的源做贡献?以及,如果想自定义一个第三方包管理,怎么做?
python
自定义包上传官方源
自定义包上传到pypi的教程:Packaging Python Projects — Python Packaging User Guide
通过twine命令。
有两点需要注意:
1、需要设置2FA验证后才能生成token。
什么是2FA验证:类似一种动态口令,需要手机扫二维码,获得口令码,再输入验证。
腾讯小程序有一个比较好用的: Authentic
2、如果遇到上传失败,提示403的情况,检查包名是否跟其他人重复:
1 | ERROR HTTPError: 403 Forbidden from https://test.pypi.org/legacy/ |
上传成功后,就可以使用该命令安装:
1 | (venv) wutengda@wutengda:~/packaging_tutorial$ pip install example-package-wutengda |
场景思考:
对于pytorch,在arm上直接使用报没有和cuda联合编译,导致运行失败的情况。此时我们手动编译构建了一个可用的联合编译版本,如何提交到pypi?
方式1:理想的,推动pytorch社区合入发布联合编译版本
方式2:在pypi上开一个新账号,提交新包到该账号下。该方式弊端是,你没法用pytorch命名,而使用者想用的话,只能去适配你的名称
方式3:新建一个私有pypi,将联合编译版本提交到这里。该方式需考虑:
- 是否允许采用pytorch命名?
- 当联合编译版本依赖其他包时,是否允许跨仓库关联解决?
自定义私有源
参考:Setting up a Private PyPI Server
安装pypiserver
1 | pip install pypiserver |
拉起成功后,可登录:localhost:8080
-a . -P .
表示不需要登录就可以上传包,只要在上传时保持账号密码为空即可。
在没有指定目录时,上传的包会自动放到$HOME/packages目录下,如果该目录没有提前创建,上传会失败。
上传成功后,即可访问http://localhost:8080/simple查看已上传的包。
如果A包在自定义的仓库,B包在官方pypi源,此时pip install的行为是什么样的?示例:
1 | # requirements.txt |
安装前清理cache:
1 | pip cache purge |
此时执行:
1 | (venv) wutengda@wutengda:~/test$ pip install --index-url http://localhost:8080 --trusted-host=localhost:8080 -r requirements.txt |
可以正常安装, 不过会有一个DEPRECATION。
兼容性结论:
私有pypi源内如果有包依赖到官方源,则pip能够处理这种关系,pip将首先在当前配置的私有源中查找,如果未找到,则默认回退到官方源中查找。
java
自定义包上传maven源
参考:Maven – Maven Central Repository (apache.org)
为jar包生成gpgkey:Working with PGP Signatures - The Central Repository Documentation (sonatype.org)
提交jar包到中央仓库:
apache项目都提交到这里:Nexus Repository Manager (apache.org)
其他项目提交到OSSRH:OSSRH Guide - The Central Repository Documentation (sonatype.org)
对于自定义的包,一般往OSSRH提交。该提交必须首先要持有一个JIRA账号和项目ticket(也就是新建一个group id)
对于私人项目,groupid可基于github命名,比如:io.github.stavewu(其他命名方式参考:Choosing your Coordinates - The Central Repository Documentation (sonatype.org))。提交new project后,还必须在自己的github下创建一个名为OSSRH-xxxxxx的仓库,完成后在对应OSSRH申请单下评论知会工作人员,通常是由机器人秒批的。
这部分细节处理可参考:发布 Jar 包到 Maven 中央仓库 – LOFFER – 一个可以fork的博客 (gitee.io)
现在就可以通过jira账号登录OSSRH包管理网站:https://s01.oss.sonatype.org/
准备jar包,pom.xml文件按照以下两个指南编写:
- 最基本的包信息配置:Requirements - The Central Repository Documentation (sonatype.org)
- 用于一键上传到maven repository的配置:Apache Maven - The Central Repository Documentation (sonatype.org)
准备好后,使能编译:
1 | mvn clean deploy |
java17版本在deploy阶段存在编译错误:selenium webdriver - Unable to make field private final java.util.Comparator java.util.TreeMap.comparator accessible: java.base doesn’t “opens java.util” to unnamed module - Stack Overflow
可采用降版本为java8规避。
如成功,将在OOSRH包管理网站上查询到staging profile信息:
虽然官网写了:Upon release, your component will be published to Central: this typically occurs within 30 minutes, though updates to search can take up to four hours.
实际同步花个更长时间,可能大概两天,终于查到了我们要上传的包:
兼容性结论:
- maven central对group id有严格控制,必须要得到group id管理员许可才能够提交进去
- 如果想基于已有开源软件(如spark)合入问题修复的版本,如做了兼容性适配完善等,想提交到maven central的话,必定会收到group id权限限制,也即需要社区同意后才能合入,无法自行处理。
自定义maven源
自定义maven源可以使用sonatypes nexus:Nexus!最受欢迎的仓库管理软件 - 知乎 (zhihu.com)
从上一章节讨论:
- nexus是介于maven central和本地之间的中转仓库,所有提交的包都会先存在于nexus这里
- 有很多包管理网站基于nexus搭建,如OSSRH、apache基金会等
该软件提供了图形化界面来上传包,支持除java以外的各种包类型,如npm等,详细包类型支持见Uploading Components (sonatype.com)。
nexus本身是开源的:GitHub - sonatype/nexus-public: Sonatype Nexus Repository Manager; Open-source codebase mirror
go
参考:Using Go Modules - The Go Programming Language
类似maven这种包管理工具在go里面是go mod
go没有像maven一样有统一的中央仓库,go引入mod完全是靠各个包所在的网络链接来include
以k8s为例,k8s仓库中存在一份go.mod,打开可以看到其require方式为url:
1 | // This is a generated file. Do not edit directly. |
兼容性结论:
对于兼容性来说,因为go本身没有中央仓库管理,因此如有定制的patch等,在合入go mod官方仓库前是可以通过rpm等系统包管理机制来承载。go本身最终编译生成的文件也是一个标准系统二进制文件。
js
参考:
js的包发布通过npm即可完成,js的包也分两种,私人的和组织的,通过scope的表达方式进行(示例:@xxx/hello-world
),这里的scope其实等价于namespace,用于预防和其他同名包冲突。不是所有的包都需要声明scope,比如vue。私人也可以发一些不带scope的包,比如shanglv-utils。
因为在npm发布时要求必须要首先登录npm:npm login
,所以不会出现私人包覆盖官方包的情况。
兼容性结论:
npm发布包的机制和python基本一致,对于官方包,当官方包已经占位的情况下,我们无法去覆盖它,如有类型兼容性的patch需要合入,只有一种方式,就是通过包官方仓库接纳。
rust
rust是有中央仓库的:crates.io: Rust Package Registry
ruby
ruby也有中央仓库托管各种包:RubyGems.org