PSBuildModule.psm1
New-Alias -Name Build-ModuleProject -Value Export-PSModuleProject New-Alias -Name Initialize-ModuleProjectDirectory -Value Initialize-PSModuleProject function _ensureProjectDirectory{ param( [string]$ProjectPath, [string]$ModuleName, [string]$ModuleAuthor, [guid]$ModuleGuid = [guid]::NewGuid() ) "Building project directory at '{0}'..." -f $ProjectPath | Write-Debug $directoryStructure = @{ type='directory' children = @{ 'build.settings' = @{ type = 'directory' children = @{ 'manifest' = @{ type = 'directory' src = "$PSScriptRoot\.assets\defaultManifest" children = @{ author = @{ type = 'file' content = $ModuleAuthor } guid = @{ type = 'file' content = $ModuleGuid } } } 'modulename' = @{ type='file' content=$ModuleName } } } 'source' = @{ type='directory' } } } $buildDirectory = { param($path, $itemSpec, $prefixLength=0) switch ($prefixLength) { 0 { $itemPrefix = "" $infoPrefix = "" } 3 { $itemPrefix = "|- " $infoPrefix = " " } default { $itemPrefix = "|- ".PadLeft($prefixLength + 3, " ") $infoPrefix = " ".PadLeft($prefixLength + 3, " ") } } $exists = switch ($itemSpec.type) { file { Test-Path $path -PathType Leaf } directory { Test-Path -Path $path -PathType Container } } $leaf = Split-Path $path -Leaf if ($exists) { "{0}{2} '{1}': Found!" -f $itemPrefix, $leaf, $itemSpec.type.ToUpper() | Write-Debug } else { "{0}{2} '{1}': Missing!" -f $itemPrefix, $leaf, $itemSpec.type.ToUpper() | Write-Debug } if (!$exists) { switch($itemSpec.type) { file { if ($itemSpec.src) { Copy-Item -Path $itemSpec.src -Destination $path "{0}Copying from '{1}'" -f $infoPrefix, $itemSpec.src | Write-Debug } else { "{0}Creating blank file" -f $infoPrefix | Write-Debug New-Item -Path $path -ItemType File | Out-Null } if ($itemSpec.content) { "{0}Setting content to '{1}'" -f $infoPrefix, $itemSpec.content | Write-Debug Set-Content -Path $path -Value $itemSpec.content } } directory { if ($itemSpec.src) { "{0}Copying from '{1}'" -f $infoPrefix, $itemSpec.src | Write-Debug Copy-Item -Path $itemSpec.src -Destination $path -Recurse } else { "{0}Creating empty directory" -f $infoPrefix | Write-Debug New-Item -Path $path -ItemType Directory | Out-Null } } } } if ($children = $itemSpec.children) { foreach ($childName in $children.Keys) { $childPath = "{0}\{1}" -f $path, $childName & $buildDirectory $childPath $children[$childName] ($prefixLength + 3) } } } & $buildDirectory $ProjectPath $directoryStructure } # Build.ps1 - ps-build-module - https://github.com/Adicitus/ps-build-module <# Build script used to compile PS Modules arranged as: [ProjectRoot Dir] |- "source" folder | |- 0-1 ".assets" folder. | |- 0-* .ps1 files. | |- 0-* additional nested source folders (can contain 1 .assets folder and any number of .ps1 files). |- "build.settings" folder |- modulename.ps1 |- "manifest" folder |- Manifest setting file(s) The script will take all of the .ps1 under the "source" folder and flatten them into a single .psm1 file under "$OutRoot\$modulename\" directory. All assets in the .assets folders will similarly be combined in a ".assets" folder under "$OutRoot\$modulename\". The .ps1 files i a directory will be processed in lexicographical order. Subdirectories will also be processed in this order. #> function Export-PSModuleProject { [CmdletBinding()] param( [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$false, Position=1)] [string]$ProjectRoot=".", [ValidateNotNullOrEmpty()] [Parameter(Mandatory=$false, Position=2)] [string]$OutRoot = "$ProjectRoot\out" ) # Build manifest $manifestArgs = @{} $buildArgs = @{} Get-ChildItem "$ProjectRoot\build.settings" -File | ForEach-Object { $name = $_.Name.split(".")[0] if ($_.name -like "*.ps1") { $buildArgs.$name = & $_.FullName } else { $buildArgs.$name = Get-Content $_.FullName } } Get-ChildItem "$ProjectRoot\build.settings\manifest" -File | ForEach-Object { $name = $_.Name.split(".")[0] if ($_.name -like "*.ps1") { $manifestArgs.$name = & $_.FullName } else { $manifestArgs.$name = (Get-Content $_.FullName) -join "`n" } } $moduleName = $buildArgs.modulename if (-not $moduleName) { throw "No module name set ('-not `$modulename' evaluates to `$false)!" } $SrcDir = "$ProjectRoot\source" $outDir = "$OutRoot\$moduleName" $assetsOutDir = "$outDir\.assets" $moduleFile = "{0}\{1}.psm1" -f $outDir, $moduleName $manifestFile = "{0}\{1}.psd1" -f $outDir, $moduleName if (Test-Path $outDir -PathType Container) { Remove-Item $outDir -Force -Recurse } $null = New-Item $outDir -ItemType Directory # Build Script module $addFolder = { param( [System.IO.DirectoryInfo]$item, [String]$subname ) if ($subname) { "# {0}.{1}" -f $moduleName, $subname >> $moduleFile } if ($assetsDir = Get-ChildItem $item.FullName -Filter ".assets" -Directory) { if ( !(Test-Path $assetsOutDir) ) { mkdir $assetsOutDir } $assetsDir | Get-ChildItem | ForEach-Object { Copy-Item $_.FullName -Destination "$assetsOutDir\" -Recurse } } Get-ChildItem $item.FullName -Filter *.ps1 | Sort-Object -Property Name | ForEach-Object { Get-Content $_.FullName >> $moduleFile } } # Start with the root dir . $addFolder (Get-Item $srcDir) # Then include subfolders Get-ChildItem $srcDir -Directory -Exclude .assets | Sort-Object -Property Name | ForEach-Object { $item = $_ . $addFolder $item $item.Name } $manifestArgs | Out-String | Write-Host # Generate the manifest New-ModuleManifest -Path $manifestFile @manifestArgs } function Initialize-PSModuleProject{ [CmdletBinding()] param( [Parameter(Mandatory=$true, Position=1)] [ValidateNotNullOrEmpty()] [string]$ProjectDirectoryPath, [Parameter(Mandatory=$true, Position=2)] [ValidateNotNullOrEmpty()] [string]$ModuleName, [Parameter(Mandatory=$true, Position=3)] [ValidateNotNullOrEmpty()] [string]$Author ) _ensureProjectDirectory $ProjectDirectoryPath $ModuleName $Author } |