Builds a PowerShell module by merging source files into a distributable package.
Build-PSModule compiles a structured PowerShell module project into a single distributable
package. It reads source files from the four canonical subdirectories (Enums, Classes,
Private, Public), merges them in the correct load order into one .psm1 file, copies and
updates the module manifest (.psd1) with the detected exported functions and aliases, and writes
all output to the specified distribution directory.
The function validates the module project structure before doing any work, so a clear error is
produced if required files are missing. All progress steps are reported through Write-Verbose.
The function supports -WhatIf and -Confirm through SupportsShouldProcess.
Merging is done with #region / #endregion markers so that the built .psm1 remains readable
and navigable in an editor. Dot-source lines from the dev .psm1 are stripped automatically so
the built file does not attempt to load individual source files at runtime.
Build-PSModule
[[-Path] <String>]
[-OutputPath <String>]
[-Clean]
[-WhatIf]
[-Confirm]
[<CommonParameters>]
The root directory of the PowerShell module project to build. Must be an existing directory and
must contain a .psd1 manifest file. The module name is derived from the manifest file name.
- Type:
String - Position: 0 (positional)
- Default: Current working directory (
Get-Location) - Required: No
- Accepts pipeline input: No
The directory where the built module will be written. If the directory does not exist it is
created. If not specified, the output path defaults to ../dist/<ModuleName> relative to
-Path (i.e., a dist folder one level above the module root, then a subfolder named after
the module).
- Type:
String - Position: Named
- Default:
<parent of Path>/dist/<ModuleName> - Required: No
- Accepts pipeline input: No
When specified, removes the existing output directory before building. A confirmation prompt is
shown unless -Confirm:$false is also passed. Useful in CI pipelines to ensure no stale files
remain from a previous build.
- Type:
Switch - Position: Named
- Default: Not set
- Required: No
- Accepts pipeline input: No
[PSCustomObject] with PSTypeName YFridelance.PS.ModuleFactory.BuildResult
| Property | Type | Description |
|---|---|---|
ModuleName |
String |
Name of the built module |
SourcePath |
String |
Absolute path of the module source root |
OutputPath |
String |
Directory where the built module was written |
ManifestPath |
String |
Full path to the output .psd1 file |
RootModulePath |
String |
Full path to the output .psm1 file |
FunctionsExported |
String[] |
Function names written to FunctionsToExport |
AliasesExported |
String[] |
Alias names written to AliasesToExport |
FilesMerged |
Int32 |
Total number of source files merged |
Success |
Boolean |
Always $true on a successful build |
Set-Location 'C:\Projects\MyModule'
Build-PSModuleBuilds the module in the current directory. Output is written to C:\Projects\dist\MyModule\.
Build-PSModule -Path 'C:\Projects\MyModule'Equivalent to Example 1 but using an explicit path rather than relying on the current directory.
Build-PSModule -Path 'C:\Projects\MyModule' -OutputPath 'C:\CI\Artifacts\MyModule' -VerboseWrites the built module to C:\CI\Artifacts\MyModule. Prints one VERBOSE: line per operation
so progress is visible in a CI log.
Build-PSModule -Path 'C:\Projects\MyModule' -Clean -Confirm:$falseRemoves the existing output directory without prompting, then rebuilds. Useful in automated pipelines where interactive prompts would block execution.
-
Structure validation —
Test-ModuleProjectStructurechecks that the module root contains exactly one.psd1and a matching.psm1. A terminating error is thrown if validation fails. -
Output path resolution — If
-OutputPathwas not supplied, the default path<parent>/dist/<ModuleName>is computed. -
Clean — If
-Cleanwas specified and the output directory exists, it is removed. -
Output directory creation — The output directory is created if it does not exist.
-
Source path resolution —
Resolve-ModuleSourcePathsdiscovers all source files in the four sections, applying the correct sort order:Enums/*.Enum.ps1— numerically prefixed files first (01_,02_, ...), then alphabeticalClasses/*.Class.ps1— same numeric-then-alpha orderingPrivate/*.ps1— strict alphabeticalPublic/*.ps1— strict alphabetical
-
Function and alias extraction —
Get-FunctionNamesFromFileandGet-AliasesFromFileuse the PowerShell AST to extract the names of all top-level functions andSet-Aliascalls from eachPublicfile. -
Merge —
Merge-SourceFilesconcatenates all source files into a single string, wrapping each section and each file in#region/#endregionmarkers and stripping dot-source lines. -
Write
.psm1— The merged content is written to<OutputPath>/<ModuleName>.psm1using UTF-8 with BOM encoding. -
Copy
.psd1— The source manifest is copied to the output directory. -
Update manifest —
FunctionsToExportandAliasesToExportfields in the copied manifest are replaced with the lists collected in step 6. -
Return result — A
BuildResultobject is returned summarizing the operation.
-
Encoding: All output files are written as UTF-8 with BOM (
utf8BOM). This matches the encoding expected by Windows PowerShell 5.1 and is safe for PowerShell 7+. -
Line endings: The merged
.psm1uses CRLF line endings throughout, regardless of the host OS. This ensures consistent behavior when the built module is distributed to Windows systems. -
Dot-source stripping: Any line matching
^\s*\.\s+.*\.ps1in a source file is removed during merge. This means the dev.psm1dot-source loader is automatically excluded from the built output without manual intervention. -
WhatIf support: When
-WhatIfis passed, no files are written or deleted. The function reports what it would do via standardWhatIf:output.