PowerShell 7 源码仓库全解析:从 README 导读到跨平台构建、测试与版本生成的源码级实践
2026/9/6 21:21:24 网站建设 项目流程

PowerShell 7 源码仓库全解析:从 README 导读到跨平台构建、测试与版本生成的源码级实践

【免费下载链接】PowerShellPowerShell for every system!项目地址: https://gitcode.com/GitHub_Trending/po/PowerShell

本文以 PowerShell 仓库根目录的 README.md 为骨架,系统梳理 PowerShell(7.x 及更高版本)这一跨平台(Windows、Linux、macOS)自动化与配置框架的定位、与 Windows PowerShell 5.1 的边界关系、源码仓库结构、基于build.psm1模块的构建与测试流程,以及版本号的生成机制。读完本文,你将能够独立克隆并编译该仓库、定位三大平台各自的顶层构建项目,理解pwsh可执行文件的产出路径、测试入口,以及发布版本号是如何从 Git tag 推导出来的。

一、PowerShell 是什么:跨平台自动化与配置框架

README 对 PowerShell 的定义是:一个跨平台(Windows、Linux 和 macOS)的自动化与配置工具/框架,能与现有工具良好协作,并针对处理结构化数据(JSON、CSV、XML 等)、REST API 和对象模型做了优化。它由三部分组成:

  • 一个命令行 Shell;
  • 一门配套的脚本语言;
  • 一套用于处理 cmdlet 的框架。

从源码结构看,这三部分在仓库中都有明确落点:src/System.Management.Automation/(引擎、解释器、解析器、宿主接口、远程处理等核心实现)、src/Microsoft.PowerShell.Commands.*(各命令模块,如 Utility、Security、Diagnostics、Management)、src/Microsoft.PowerShell.ConsoleHost/(控制台宿主)。仓库定位也由此清晰:这不是一个单纯的脚本集合,而是一个完整的 .NET 宿主 + 语言引擎 + 命令框架的代码库。

需要强调的是运行入口。跨平台宿主项目的 .NET CLI 入口是 src/powershell/Program.cs,其中ManagedPSEntry.Main在 UNIX 平台会先执行AttemptExecPwshLogin(处理 pwsh 作为登录 Shell 启动时的 login 逻辑),随后委托给UnmanagedPSEntry.Start进入原生宿主。该入口文件被两个顶层项目共享引用(见下文构建章节)。

二、Windows PowerShell vs. PowerShell 7+:版本边界

README 中一段容易被忽略但极其重要的说明:

虽然本仓库最初是 Windows PowerShell 代码库的分支,但在此仓库中所做的更改不会移植回 Windows PowerShell 5.1。也就是说,仓库中跟踪的 issue 只针对 PowerShell 7.x 及更高版本。Windows PowerShell 特有的问题应通过 Feedback Hub(分类选择 "Apps > PowerShell")上报。

这带来两条实操结论:

  1. 你在本仓库看到的任何行为、任何修复,都只影响 PowerShell 7+;5.1 的问题与本仓库无关;
  2. 仓库内的代码(例如引擎、cmdlet、格式数据)只描述 7.x 的行为,不能拿它反推 5.1 的表现。

三、获取与升级 PowerShell

README 给出的安装与升级建议:

  • 支持平台:Windows、macOS 以及多种 Linux 发行版,官方安装文档见 Microsoft Learn 的 Installing PowerShell 主题(本仓库不重复给出外部链接);
  • 升级原则:为了获得最佳结果,升级时应使用与首次安装时相同的安装方式;每种平台和每种安装方式的更新途径都不同。

这一原则在仓库的构建/打包工具链中也有对应:tools/目录下维护了各平台的安装脚本,如 tools/install-powershell.sh、tools/install-powershell.ps1 以及面向各发行版的脚本(installpsh-debian.shinstallpsh-redhat.shinstallpsh-osx.shinstallpsh-suse.shinstallpsh-amazonlinux.sh等)。"安装方式与升级方式一致"的实质,就是避免包管理器安装的版本被 tarball 覆盖、或反向冲突。

四、克隆源码仓库

README 给出的仓库获取方式是git clone。对于开发者而言,配合 docs/git/README.md 中的仓库工作指南(分支、PR 流程等)使用。克隆完成后应进入仓库根目录,后文所有构建步骤均假设你在该目录执行。

五、仓库结构速览:从 README 链接到真实目录

README 通过链接串联了多个子文档,把它们展开后就是本仓库的核心地图:

目录/文件作用
src/全部源码。核心引擎 src/System.Management.Automation/(engine/parser/help/namespace 等子目录),命令模块 src/Microsoft.PowerShell.Commands.Utility/、src/Microsoft.PowerShell.Security/ 等,宿主 src/Microsoft.PowerShell.ConsoleHost/,入口 src/powershell/Program.cs,SDK 聚合项目 src/Microsoft.PowerShell.SDK/
src/powershell-unix/、src/powershell-win-core/Linux/macOS 与 Windows 两个顶层构建项目(详见第七节)
src/Modules/随构建输出的模块(按 Shared/Unix/Windows 分层)
tools/构建辅助、打包(packaging/releaseTools相关)、安装脚本、性能与 CI 工具
test/Pester 测试(test/powershell/)、xUnit 测试(test/xUnit/)、宿主测试(test/hosting/)、打包测试(test/packaging/)等
docs/building/三大平台构建指南 + 构建过程内部机制 docs/building/internals.md
docs/FAQ.md开发者 FAQ,构建遇到问题时的第一站
docs/community/governance.md项目治理政策
build.psm1构建模块,Start-PSBuild等函数的真实定义处(CI 上执行的就是它)
PowerShell.slnVisual Studio 解决方案文件
LICENSE.txtMIT 许可声明

另外两个根目录配置文件值得注意:

  • global.json:固定 .NET SDK 版本,当前为11.0.100-preview.6.26359.118。docs/building/windows-core.md 也明确指引"当前使用的版本见仓库根目录 global.json 第 3 行";
  • DotnetRuntimeMetadata.json:描述 SDK 渠道(channel/quality/qualityFallback)与 SDK 镜像版本,供Start-PSBootstrap等引导函数下载安装 SDK 时使用。

六、构建 PowerShell:build.psm1 模块全流程

README 的 "Building PowerShell" 小节以一张三列表格给出三大平台指南:Linux 见 docs/building/linux.md、Windows 见 docs/building/windows-core.md、macOS 见 docs/building/macos.md,并提示构建问题先查开发者 FAQ。下面把这三份指南的共同主线串成一条可复制的操作路径。

6.1 引导环境:Start-PSBootstrap

构建脚本本身是 PowerShell 代码,因此需要先装一份自宿主 PowerShell。Linux 上最简单的做法(docs/building/linux.md):

./tools/install-powershell.sh pwsh

然后在 PowerShell 中导入仓库根目录的构建模块 build.psm1 并引导:

Import-Module ./build.psm1 Start-PSBootstrap -Scenario Both

从源码结构看,Start-PSBootstrap定义于 build.psm1 第 2848 行附近,其文档化行为如下:

  • Linux:通过apt-get(或等效包管理器)安装构建依赖与打包工具,并下载安装 .NET SDK 到~/.dotnet
  • macOS:使用brewport安装 OpenSSL 与 GNU WGet,卸载旧版 .NET CLI,再安装 .NET Core SDK 到~/.dotnet(docs/building/macos.md);
  • Windows:Start-PSBootstrap -Scenario Dotnet或等效的Install-Dotnet会移除旧版 .NET CLI 并安装本仓库依赖的版本(docs/building/windows-core.md)。

如果要在使用Start-PSBuild之外直接调用dotnet,需把~/.dotnet加入PATH

6.2 执行构建:Start-PSBuild

三个平台指南给出的构建命令高度一致(均带-UseNuGetOrg):

# Linux / macOS Import-Module ./build.psm1 Start-PSBuild -UseNuGetOrg # Windows(建议附加清理与模块还原) Start-PSBuild -Clean -PSModuleRestore -UseNuGetOrg

README 与三份平台指南均带有一条重要提示:PowerShell 项目默认引用私有 Azure Artifacts 源,需要认证;-UseNuGetOrg参数会把构建重新配置为使用公共 NuGet.org 源。外部贡献者基本都需要带上该参数。

Start-PSBuild定义于 build.psm1 第 336 行附近。构建完成后,它会打印可执行文件位置。按 docs/building/linux.md 的当前说明,Linux 上的产物是:

./src/powershell-unix/bin/Debug/net11.0/linux-x64/publish/pwsh

该路径遵循统一形式:./[project]/bin/[configuration]/[framework]/[rid]/publish/[binary name]。以 Windows 为例(docs/building/windows-core.md),默认 Debug 配置、win-x64RID 下为./src/powershell-win-core/bin/.../publish/pwsh.exe;build.psm1 中的Get-PSOutput(第 1428 行附近)返回可执行文件路径,因此可以直接& (Get-PSOutput)运行你刚构建的 pwsh 副本。

6.3 顶层项目与"哑依赖"

为什么dotnet build一个目录就能构建整个 PowerShell?答案在 docs/building/internals.md:

  • 构建命令实际执行于$Top目录:Windows 为src/powershell-win-core,Linux/macOS 为src/powershell-unix
  • 顶层项目通过**哑依赖(dummy dependencies)**串联所有程序集:例如src/powershell-win-core/powershell-win-core.csproj声明了对Microsoft.PowerShell.Commands.Diagnostics.csproj的引用,但实际并无真实构建依赖,目的是"只构建 $Top 一个文件夹"即可传递拉起全部组件;
  • 规则:凡是属于 CoreCLR 构建的程序集,都应列为$Top项目的依赖。

对照两个顶层工程文件可以印证这一结构:

  • src/powershell-unix/powershell-unix.csproj:AssemblyNamepwshRuntimeIdentifierslinux-x64;osx-x64;,编译包含..\powershell\Program.cs(共享入口),并将..\Modules\Unix\**..\Modules\Shared\**、PSMaml 帮助 Schema、LICENSE.txtThirdPartyNotices.txt、默认帮助assets/default.help.txtdsc/资源一并拷贝到发布输出;
  • src/powershell-win-core/powershell-win-core.csproj:同样的pwsh命名与共享Program.csRuntimeIdentifierswin-x86;win-x64,额外引用了 Diagnostics、CimCmdlets、WSMan.Management 等 Windows 专属模块,并拷贝assets/GroupPolicy/下的策略模板(PowerShellCoreExecutionPolicy.admx/adml)等内容。

两个工程都启用了 TieredCompilation 及 QuickJit 优化(TieredCompilationQuickJit等开关),以加速启动期的 JIT。

6.4 构建前置步骤:ResGen 与 Type Catalog

internals 文档 还揭示了两个不需要 PowerShell、可用dotnet手动执行的预构建步骤(Start-PSBuild会自动通过Start-ResGenStart-TypeGen调用它们,二者定义于 build.psm1 第 3292、3254 行附近):

ResGen(src/ResGen/Program.cs):为每个项目的resources目录中的*.resx文件生成强类型 C# 资源访问类,写入对应的gen目录。这些文件不会每次构建自动更新(否则破坏增量重编译);拉取新提交后若报"缺少字符串",通常需要删除gen目录重跑:

cd src/ResGen dotnet restore dotnet run

Type Catalog(src/TypeCatalogGen/):生成用于辅助类型解析的 C# 类型目录源文件CorePsTypeCatalog.cs(写入System.Management.Automation项目)。若构建时出现The name 'InitializeTypeCatalog' does not exist in the current context错误,即说明该源文件缺失,需按 docs/building/internals.md 中的步骤手动生成powershell.inc并运行 TypeCatalogGen。

6.5 原生组件的 NuGet 化

docs/building/internals.md 解释了另一项关键设计:原生组件被包装成 NuGet 包,避免每次构建都重新编译——

  • Windows 的 WinRM 插件pwrshplugin.dll打包为psrp.windows,事件跟踪程序集打包为PowerShell.Core.Instrumentation(清单位于 src/PowerShell.Core.Instrumentation/);
  • Linux/macOS 依赖libpsl-native.so/libpsl-native.dylib(src/libpsl-native/),打包为libpsllinux-x64二进制需在 CentOS 7 上构建以保证 glibc 可移植性;
  • 使用Start-BuildNativeWindowsBinaries/Start-BuildNativeUnixBinaries构建,linux-arm需要先用Start-PSBootstrap -BuildLinuxArm安装前置依赖。

从源码结构看,这意味着日常Start-PSBuild只是消费这些二进制包;只有改动原生代码时才需要走上游的打包-发布流程。

6.6 版本号如何生成:git describe 驱动

这是一个文档未展开、但 PowerShell.Common.props 里写得非常完整的机制,直接影响每个构建产物的版本号:

  1. 目标GetPSCoreVersionFromGitRestore/Pack/Build之前执行,运行git describe --abbrev=60 --long,得到形如v7.x.x-N-g<sha>的字符串;
  2. 未打 ReleaseTag 的日常构建:版本号取最近 tag + "Commits: N" + SHA,生成InformationalVersion形如7.x.x Commits: 5 SHA: abc1234
  3. 指定ReleaseTag(如7.2.0-rc.1)时:按正则解析,7.2.0→ 文件版本7.2.0.500(GA 增量 500);7.2.0-preview.17.2.0.1;RC 的迭代号从 100 起递增(7.2.0-rc.17.2.0.101);AssemblyVersion的 Build 段固定为 0,使服务性发布不改变程序集版本;
  4. 应用图标也会随版本渠道切换:preview 版用Powershell_av_colors.ico,daily 版用Powershell_avatar.ico,正式版用Powershell_black.ico(图标源文件见 assets/ 目录)。

理解这一点后,你就能解释为什么 CI 日常构建的pwsh版本号带 "Commits: N" 后缀,而 RC 构建的 FileVersion 会出现 .101、.102 这样的迭代。

七、测试:Pester 与 xUnit 双轨

三份平台构建指南在构建成功后都给出了相同的测试入口:

Start-PSPester -UseNuGetOrg # 跨平台 Pester 测试 Start-PSxUnit # xUnit 测试
  • Start-PSPester定义于 build.psm1 第 1686 行附近,驱动的是 test/powershell/ 下的 Pester 用例,覆盖engine/Language/Modules/Provider/Host/等目录,是 PowerShell 功能测试的主战场;
  • Start-PSxUnit定义于第 2492 行附近,运行 test/xUnit/ 下的 .NET 单元测试(csharp/子目录),面向引擎层面的断言;
  • 另有 test/hosting/(宿主 API 测试)、test/packaging/(分平台打包测试)、test/perf/(性能基准)。

测试布局本身(test/powershell/engine等按引擎、语言、模块、提供程序分目录)也印证了 README 所描述的"Shell + 脚本语言 + cmdlet 框架"三大件的组织方式。

八、社区、治理与安全

README 的后半部分定义了参与本项目的规范与渠道,写作时应一并继承:

  • 贡献:从 CONTRIBUTING 指南 开始;为 .NET Core/C# 应用开发 PowerShell 集成时,可查 docs/FAQ.md 中关于 PowerShell SDK NuGet 包的章节;设计层面的提案见 PowerShell-RFC 仓库(外部仓库,本文不附链接);
  • 讨论与聊天:GitHub Discussions 用于与代码无关的开放讨论,issue 保持可执行;社区频道包括 Discord、Libera.Chat 的 IRC 与 Slack;
  • 治理:项目治理政策见 docs/community/governance.md;
  • 行为准则:CODE_OF_CONDUCT.md;
  • 安全策略:.github/SECURITY.md;
  • 许可:MIT 许可,见 LICENSE.txt。

两点与"使用本仓库产物"直接相关的补充:

  1. 容器镜像:README 特别注明,PowerShell 容器镜像已转交 .NET 团队维护,mcr.microsoft.com/powershell下的容器目前不再维护——用容器化方案前请先确认镜像来源;
  2. 遥测:PowerShell 会采集遥测数据,细节以官方about_Telemetry主题文档为准。

九、小结:按本文路径跑通一次构建

把全文要点压缩成一条最短路径:

  1. 克隆仓库并进入根目录(Git 工作流参考 docs/git/README.md);
  2. ./tools/install-powershell.sh(Linux)安装自宿主 pwsh,pwsh进入;
  3. Import-Module ./build.psm1Start-PSBootstrap -Scenario Both安装 .NET SDK(版本以 global.json 为准,当前 11.0.100-preview.6.26359.118);
  4. Start-PSBuild -UseNuGetOrg构建,产物位于./src/powershell-unix/bin/Debug/net11.0/linux-x64/publish/pwsh(Linux);Windows 对应src/powershell-win-core下的pwsh.exe
  5. & (Get-PSOutput)直接运行自构建副本;
  6. Start-PSPester/Start-PSxUnit跑测试;
  7. 遇到版本或类型目录报错,回到第六节 6.4/6.6 的 ResGen、Type Catalog 与 git describe 机制定位。

本文所有命令、路径与版本事实均以当前仓库内容为准:构建指南位于 docs/building/,构建模块为 build.psm1,版本生成逻辑见 PowerShell.Common.props,内部机制详见 docs/building/internals.md。

【免费下载链接】PowerShellPowerShell for every system!项目地址: https://gitcode.com/GitHub_Trending/po/PowerShell

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询