Building PowerShell from Source
Relevant source files
The following files were used as context for generating this wiki page:
PowerShell is a cross-platform automation and configuration framework built on .NET. Building the project from source allows developers to customize the runtime, target specific architectures (x64, ARM, ARM64), and include experimental features. The build system is designed to be portable across Windows, Linux, and macOS, utilizing PowerShell scripts and the .NET CLI as the primary engine for compilation and publishing.
The build process is divided into several logical phases: environment bootstrapping, build configuration, source code generation, and final publishing. The primary entry point for these operations is the Start-PSBuild function, which orchestrates the invocation of the .NET SDK and internal generator tools.
Sources: README.md:1-12, test/perf/benchmarks/assets/compiler.test.ps1:117-120
Build Orchestration and Workflow
The build lifecycle is managed through a set of specialized functions that detect the host environment and configure the .NET build properties accordingly.
Environment Detection
Before compilation begins, the system executes Get-EnvInformation to determine the operating system platform, CPU architecture, and specific Linux distribution details (e.g., Debian, Ubuntu, Alpine, RHEL). This information is critical for selecting the correct Runtime Identifier (RID) and package manager for dependency installation.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:5-115
The Build Execution Flow
The Start-PSBuild function handles the core logic of the build. It performs the following sequential steps:
- Pre-checks: Verifies the presence of
gitand the required version of the.NET SDK. - Bootstrap: Executes
Restore-PSPackageto fetch NuGet dependencies. - Generation: Runs
ResGento create C# bindings for resource files andTypeGento generate theCorePsTypeCatalog.cs. - Compilation: Invokes
dotnet publishwith specific arguments for configuration (Debug/Release), framework (net6.0), and runtime. - Post-Build: Finalizes the output by copying reference assemblies and creating symbolic links for shared libraries on Linux.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:117-434
Build Process Logic
The following diagram illustrates the high-level flow of the build orchestration logic defined in the project scripts.
The diagram shows the sequence from initial environment detection through compilation to final asset preparation. Sources: test/perf/benchmarks/assets/compiler.test.ps1:117-300
Build Configuration and Options
The build system uses a centralized options object generated by New-PSOptions to maintain consistency across the compilation and packaging stages.
Supported Runtimes and Configurations
Builds can be targeted at multiple platforms using the -Runtime parameter.
| Runtime Category | Supported Identifiers |
|---|---|
| Windows | win-arm, win-arm64, win7-x64, win7-x86 |
| Linux | linux-x64, linux-arm, linux-arm64, alpine-x64 |
| macOS | osx-x64, osx-arm64 |
| Agnostic | fxdependent, fxdependent-win-desktop |
Sources: test/perf/benchmarks/assets/compiler.test.ps1:165-178, test/perf/benchmarks/assets/compiler.test.ps1:436-465
Build Arguments and Properties
The build script translates PowerShell parameters into .NET MSBuild properties. For example:
- Configuration: Sets
--configuration(defaults toDebug). - Framework: Hardcoded to
net6.0. - Minimal Size: The
-ForMinimalSizeswitch disablesCrossGenand targets specific runtimes to reduce disk footprint. - SMA Only: The
-SMAOnlyswitch allows quick recompilation of only theSystem.Management.Automation.dllengine.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:240-275, test/perf/benchmarks/assets/compiler.test.ps1:467-478
Source Generation and Versioning
A unique aspect of the PowerShell build is the use of Roslyn Source Generators to inject build-time information into the assemblies.
PSVersionInfo Generator
The PSVersionInfoGenerator class is an IIncrementalGenerator that captures MSBuild properties like ProductVersion and ReleaseTag during the compilation. It generates a partial class PSVersionInfo.g.cs containing:
- ProductVersion: The full semantic version (e.g.,
7.3.0-preview.8). - GitCommitId: The specific SHA or describe string from the git repository.
- Version Components: Integer constants for Major, Minor, and Patch versions to avoid runtime parsing overhead.
Integration with build.psm1
The build script passes these properties to the compiler through /property:ReleaseTag and other MSBuild flags, ensuring that the final binary reports the correct version in the $PSVersionTable.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:284-288, test/powershell/Host/PSVersionTable.Tests.ps1:11-20
Performance Optimization: CrossGen
To improve startup time, the build system supports CrossGen (or NGEN-like optimization), which compiles Intermediate Language (IL) assemblies into native images.
CrossGen2 Logic
When the -CrossGen switch is used, the build invokes the crossgen2.exe tool. This process:
- Locates the
crossgen2binary within the restored NuGet packages. - Identifies a specific set of "high-JIT" assemblies (e.g.,
Microsoft.CodeAnalysis.dll,System.Linq.Expressions.dll). - Executes single-file compilation for these assemblies targeting the specified OS and architecture.
- Replaces the original IL assemblies with the optimized native images.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:842-990
Dependency Management and Bootstrapping
The project provides automation to prepare the development environment, specifically for Linux environments that lack necessary build tools.
Start-PSBootstrap
The bootstrap function automates the installation of:
- System Dependencies:
curl,g++,make,libunwind,libicu, andopenssl. - Distro-specific tools:
zypperfor SUSE,apt-getfor Ubuntu/Debian, andapkfor Alpine. - .NET SDK: Downloads and installs the exact version required by the build script if it is missing or outdated.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:712-840, tools/installpsh-suse.sh:85-98
The sequence shows the interaction between the build script and external installers to ensure a valid toolchain. Sources: test/perf/benchmarks/assets/compiler.test.ps1:630-710
Conclusion
Building PowerShell from source is a multi-stage process that leverages the .NET SDK while augmenting it with custom C# source generators and optimization tools like CrossGen2. By utilizing the Start-PSBuild framework, developers can ensure that the generated binaries are properly versioned, optimized for startup performance, and compatible with the target operating system's shared libraries.
Sources: test/perf/benchmarks/assets/compiler.test.ps1:117-125, src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.cs:13-15