Baulk

Stella981
• 阅读 241

前言

相对于其他操作系统,我更习惯使用 Windows,但一直以来 Windows 缺乏官方的包管理器,而第三方无论是 Scoop 还是 Chocolatey 都无法满足我独特的需求,我的要求很简单,所有的软件包都应该使用绿色解压模式,这包括了 MSI 安装包,另外安装软件时不应该修改系统和用户环境变量。包管理工具应该足够快,还要支持创建启动器等等。

从毕业工作以来,我开发了 clangbuilder,一个简化在 Windows 上使用 Visual Studio 构建 LLVM/Clang 的工具(含 GUI 工具),为了解决安装构建 LLVM 时所需工具依赖的问题,后来多次开坑编写各种软件,多年的失败经验与认知不断积累,于是在今年这个环球同此凉热的年份,我开始了新坑 ➡ baulk,baulk 花费了我半年的下班时间,现在基本可用,ReadMe 也写好了,应该可以给大家分享一下了。

安装和使用 Baulk

这个步骤只有四五步,下载 baulk 二进制包,解压 baulk 二进制包,点击 baulkterminal,更新元数据,安装你需要的软件,🆗,你可以使用 baulk 安装的软件了。

baulk update
# i 是 install 的别名
# baulk i cmake curl 7z ...
baulk install cmake curl 7z
cmake --version

baulk 升级命令可以使用如下命令:

baulk update
baulk upgrade

也可以使用别名:

# u 是特殊的别名,包含 update 和 upgrade 两个步骤
# baulk update and upgrade
baulk u

升级 baulk 自身可以使用帮助程序 baulk-update

baulk-update

卸载软件也很容易:

# r 是 uninstall 的别名
baulk uninstall 7z

在开发 baulk 时,我就决定只支持 Windows 10 1903 或更新的版本,好处显而易见,可以使用 Windows Terminal,利用 ANSI 转义输出颜色,体验非常不错:

Baulk

baulk 提供了 baulk-exec 在命令行中执行 baulk-exec 可以初始化 baulk 环境,还提供了 ssh-askpass-baulk,ssh-askpass-baulk 用于 TunnelSSH 某些 ssh 无法打开标准输入时请求输入密码,截图如下:

Baulk

在 baulk 中我引入了 VirtualEnv 机制,这种机制能够使得用户并行安装多个软件版本,在 baulk-exec,baulkterminal 中通过指定参数支持启动任意的 VENV,baulk 还提供了 baulk-dock 能够选择按照特定的 VENV 启动环境:

Baulk

在 Baulk 元数据存储库 bucket,收录了 OpenJDK8(Java),OpenJDK9(Java),GraalVM8(Java),Zulu14(Java),Go(golang),DMD(dlang) 等支持 VENV 的包,如果有人想把 Ruby 收录一下,在 Windows 上实现类似 rbenv 功能也不是什么难事。

Baulk 的内幕

入门说完,可以稍稍讲一下 Baulk 的实现细节,baulk 的包管理类似于 Scoop,即将包的元数据存储在 Github 上,官方源为 baulk/bucket,baulk 还可以通过编写 $BAULK_ROOT/config/baulk.json 添加新的源,或者删除某个源,如果不同的源中存在相同名字的包,baulk 还能根据 bucket 的权重去选择使用哪个源,但目前为止,只有 baulk/bucket 一个源。

{
    "bucket": [
        {
            "description": "Baulk default bucket",
            "name": "Baulk",
            "url": "https://github.com/baulk/bucket",
            "weights": 100
        }
    ]
}

baulk update 命令更新 bucket,这里我们使用了 Github Atom RSS 机制,以官方源为例,通过 HTTP 请求项目的 commits/master.atom 获得当前的最新的 commitID,如果本地不存在或者与其不同,则说明 bucket 有更新,于是 baulk 下载对应的 bucket 的压缩包,解压完成元数据的更新。然后检测本地已安装的包是否存在更新版本,存在就输出提示。

GET https://github.com/baulk/bucket/commits/master.atom

当人们运行 baulk upgrade 时,就会真正的升级已安装的包,更新元数据和升级分开这种机制类似于 apt-get,为了简化操作,baulk 提供了 baulk u 别名将 update/upgrade 合并在一起简化升级。

在 Baulk 中,安装软件大的步骤只有解压和生成启动器(创建符号链接),不存在什么执行初始化脚本,修改注册表,关联文件打开方式等等等等等。我的想法是最好做到隔离互不影响,因此,在开发 baulk 的过程中,我一直时朝这个方向去设计。在 baulk 中的 package 中,存在 extension 的关键字,extension 用于描述 package 压缩包(安装包)如何被 baulk 解压缩, extension 支持 zip, msi, 7z, exetar,baulk 按照 extension 的类型执行相应的解压缩程序。扩展的解压程序如下:

扩展

解压程序

限制

exe

-

-

zip

内置,基于 minizip

支持 deflate/bzip2/zstd,不支持加密和 deflate64(deflate64 可以使用 7z

msi

内置,基于 MSI API

此方式仅作解压,和在资源管理器点击安装不同

7z

优先级:
baulk7z - Baulk 发行版
7z - 使用 baulk install 安装的
7z - 环境变量中的

tar.* 之类格式解压不能一次完成,因此建议使用 tar 解压 tar.* 压缩包

tar

优先级:
baulktar - BaulkTar bsdtar 的现代重构
bsdtar - Baulk 构建版
MSYS2 tar - Git for Windows 携带的
Windows tar

Windows 内置的 tar 不支持 xz(基于 libarchive bsdtar),但 baulk 构建的 bsdtar 支持,解压 zip 时均不不支持 deflate64

baulk 的哲学是不要修改系统和用户环境变量,环境变量的生效应该是和终端关联或者启动器关联,因此,在 baulk 中,我编写了 baulkterminal 和 baulk-exec 以及 baulk-dock 程序,baulkterminal 主要用于用户通过创建桌面快捷方式或者将 baulkterminal 添加到桌面、文件夹右键菜单,通过用户点击快速打开初始化 Baulk 环境的 Windows Terminal(如果没有安装 Windows Terminal 则打开 Windows 控制台),而 baulk-exec 则是一个启动器,在运行 baulk-exec 时,根据输入的命令行参数 baulk-exec 初始化环境变量,然后启动相关的子命令,比如 Windows 操作系统中没有安装 cmake,而 baulk 安装了 cmake,以下命令就能够正常运行:

# 打印 cmake 版本信息
baulk-exec cmake --version

为了避免环境变量中 PATH 条目过多,降低 SearchPath 搜索相关命令的命中率,baulk 使用了 links 机制,对于一些不依赖自身目录下的 dll 的命令,我们使用创建符号链接的方式将其软连接到 baulk 根目录的 bin\links 目录,如果自身依赖发行携带的 dll,或者需要处理 GetModuleFileName 且没有正确处理符号链接行为的命令,我们使用 launchers 机制,根据命令的类型调用 MSVC 生成特定的启动器,启动器大小 5K 左右,体积能够接受。如果用户没有安装 Visual Studio,则使用 baulk-lnk 实现相关逻辑(baulk-lnk 需要解析 baulk.linkmeta.json,效率有一点点损失)。baulk 在环境变量和启动器这块做了很多事情,需要解析 PE 可执行文件的信息,还需要获得 PE 文件的版本信息,在之前使用 PowerShell 编写的 devi 中,同样是这样做的,但 PowerShell 脚本执行不太快,baulk 相比是一个巨大的效率提升。

baulk 使用 WinHTTP 实现 HTTP 下载功能,能够很好的处理代理的情况,另外,baulk 还会解析 HTTPS_PROXY 环境变量,还支持 --https-proxy 设置代理,但是,我们建议应该优先使用支持设置 Windows 系统代理的工具。

baulk 基于 minizip 内置了 zip 提取能力,支持使用 ZSTD 压缩算法的 ZIP 文件,这比市面上很多压缩软件要快一步。baulk 还内置了 bela::hash 支持 SHA2(SHA224, SHA256, SHA384, SHA512) SHA3(SHA3-224, SHA3-256, SHA3-384, SHA3-512),以及 BLAKE3。由于安全问题不支持 MD5 和 SHA1,因此在 bucket 存储包哈希时应该选择使用这里列出的哈希算法,哈希字符串使用前缀匹配,默认即无前缀时为 SHA256。

  constexpr HashPrefix hnmaps[] = {
      {L"BLAKE3", hash_t::BLAKE3},     // BLAKE3
      {L"SHA224", hash_t::SHA224},     // SHA224
      {L"SHA256", hash_t::SHA256},     // SHA256
      {L"SHA384", hash_t::SHA384},     // SHA384
      {L"SHA512", hash_t::SHA512},     // SHA512
      {L"SHA3", hash_t::SHA3},         // SHA3 alias for SHA3-256
      {L"SHA3-224", hash_t::SHA3_224}, // SHA3-224
      {L"SHA3-256", hash_t::SHA3_256}, // SHA3-256
      {L"SHA3-384", hash_t::SHA3_384}, // SHA3-384
      {L"SHA3-512", hash_t::SHA3_512}, // SHA3-512
  };

Baulk VirtualEnv 介绍

这里需要重点说的时 Baulk VirtualEnv,很多时候,开发者不得不并行安装一个软件的多个版本以适配不同的开发需求,但这些软件在处理环境变量的时候并没有做的那么好,因此有了 VirtualEnv 这样的工具,比如 rbenv 。baulk 目前能够很好的大多数编程语言开发工具的 VirtualEnv,以下截图是加载 Zulu14(Java JDK) 和 Go 的截图:

Baulk

目前 baulkterminal 和 baulk-exec 能够加载任意的 venv,baulk-dock 仅支持一个。

最后

baulk 花费了我很多的时间,我自己用还是很好用的,并且 baulk 沉淀了我这些年来在 Windows 系统上的技术积累,所以写一篇文章记录一下还是有一些必要的。

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
5个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
浅梦一笑 浅梦一笑
5个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
技术小男生 技术小男生
5个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi/etc/profile2:按字母键i进入编辑模式,在最底部添加内容:JAVAHOME/opt/jdk1.8.0152CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jarPATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
5个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
5个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
小森森 小森森
5个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
5个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
5个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
密钥管理系统-为你的天翼云资产上把“锁
本文关键词:数据安全,密码机,密钥管理一、你的云上资产真的安全么?1.2021年1月,巴西的一个数据库30TB数据被破坏,泄露的数据包含有1.04亿辆汽车和约4000万家公司的详细信息,受影响的人员数量可能有2.2亿;2.2021年2月,广受欢迎的音频聊天室应用Clubhouse的用户数据被恶意黑客或间谍窃取。据悉,一位身份不明的用户能够将Clubho
NVIDIA安培架构下MIG技术分析
关键词:NVIDIA、MIG、安培一什么是MIG2020年5月,NVIDIA发布了最新的GPU架构:安培,以及基于安培架构的最新的GPU:A100。安培提供了许多新的特性,MIG是其中一项非常重要的新特性。MIG的全名是MultiInstanceGPU。NVIDIA安培架构中的MIG模式可以在A100GPU上并行运行七个作业。多实
helloworld_28799839 helloworld_28799839
5个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue