Installing PowerShell modules via Portage
Building PowerShell
As a part of my work of modernizing the way .NET SDK packages are distributed in Gentoo I delved into packaging a from-source build of PowerShell for Gentoo using the dotnet-pkg eclass.
Packaging pwsh
was a little tricky but I got a lot of help from reading the Alpine Linux’s APKBUILD. I had to generate special C# code bindings with ResGen
and repackage the PowerShell tarball. Other than this trick, restoring and building PowerShell was pretty straight forward with the NuGet package management support from the dotnet-pkg.eclass
.
Alternatively if you do not want to build PowerShell you can install the binary package, I have in plans to keep that package around even after we get the non-binary app-shells/pwsh into the official Gentoo ebuild repository.
Why install modules via Portage?
But why stop on PowerShell when we can also package multiple PS modules?
Installing modules via Portage has many benefits:
- better version control,
- more control over global install,
- no need to enable PS Gallery,
- sandboxed builds,
- using system .NET runtime.
Merging the modules
PowerShell’s method of finding modules is at follows: check paths from the PSModulePath
environment variable for directories containing valid .psd1
files which define the PS modules.
By default pwsh
tries to find modules in paths:
- user’s modules directory —
~/.local/share/powershell/Modules
- system modules directory in
/usr/local
—/usr/local/share/powershell/Modules
Modules
directory inside thepwsh
home — for example/usr/share/pwsh-7.3/Modules
Because we do not want to touch either /usr/local
nor pwsh
home, we embed a special environment variable inside the pwsh
launcher script to extend the path where pwsh
looks for PS modules. The new module directory is located at /usr/share/GentooPowerShell/Modules
.
1 2 |
dotnet-pkg-utils_append_launchervar \ 'PSModulePath="${PSModulePath}:/usr/share/GentooPowerShell/Modules:"' |
So every PowerShell module will install it’s files inside /usr/share/GentooPowerShell/Modules
.
To follow PS module location convention we add to that path a segment for the real module name and a segment for module version. This also enables us to have proper multi-slotting because most of the time the modules will not block installing other versions.
Take a look at this example from the app-pwsh/posh-dotnet–1.2.3 ebuild:
1 2 3 4 5 6 |
src_install() { insinto /usr/share/GentooPowerShell/Modules/${PN}/${PV} doins ${PN}.psd1 ${PN}.psm1 einstalldocs } |
And that is it. Some packages do not even need to be compiled, they just need files placed into specific location. But when compilation of C# code is needed we have dotnet-pkg
to help.