This isn’t my only questionable take. After I switched back to WSL1, because I disabled virtualization after I found out Windows does insane things when Hyper-V is enabled, I revisited Linux From Scratch since I don’t like any of the pre-packaged WSL1 distros. I asked myself “What scripting language should I write it in?”
I settled on PowerShell.
Yes, you read that right. I actually really like PowerShell. Its syntax isn’t pretty, but it’s effective. Because it’s backed by .NET, it’s very capable out of the box. It’s cross-platform. Building a Linux system with PowerShell feels like blasphemy, but hey, it works quite well.
So far I’ve gotten through the base cross-compiled development tools. My current hurdles are handling case-insensitivity that is causing glibc to choke and some path substitutions.
#Requires -Version 7.5
[CmdletBinding(DefaultParameterSetName="StagingPhase")]
param (
[string]$WorkingDirectory=(Join-Path -Path ${PSScriptRoot} -ChildPath "lfs"),
[string]$Jobs="1",
[string]$LFSVersion="12.4",
[string]$BinutilsVersion="2.45",
[string]$MPFRVersion="4.2.2",
[string]$GMPVersion="6.3.0",
[string]$MPCVersion="1.3.1",
[string]$GCCVersion="15.2.0",
[string]$GLIBCVersion="2.42",
[string]$LinuxVersion="6.16.1",
[Parameter(ParameterSetName="StagingPhase")]
[switch]$StagingPhase,
[switch]$Binutils,
[switch]$GCC,
[switch]$LinuxHeaders,
[switch]$GLIBC,
[switch]$LibStdCPP,
[switch]$All,
[Parameter(ParameterSetName="PopulationPhase")]
[switch]$PopulationPhase
)
#Set-PSDebug -Trace 1
# FIXME: fsutil.exe file setCaseSensitiveInfo D:\src\lfs enable
Get-Command -ErrorAction Stop -Type Application "gcc"
Get-Command -ErrorAction Stop -Type Application "bison"
$env:LFS=$WorkingDirectory
$SourcesDirectory=(Join-Path -Path $WorkingDirectory -ChildPath "sources")
New-Item -Path $WorkingDirectory -ItemType Directory -Force
New-Item -Path $SourcesDirectory -ItemType Directory -Force
$env:LC_ALL="POSIX"
$env:LFS_TGT="$(uname -m)-lfs-linux-gnu"
$env:PATH="${env:LFS}/tools/bin:/usr/bin"
$env:CONFIG_SITE="${env:LFS}/usr/share/config.site"
umask 022
function Stage {
Push-Location $WorkingDirectory
New-Item -ItemType Directory -Path "etc", "usr", "var" -Force
Push-Location (Join-Path -Path $WorkingDirectory -ChildPath "usr")
New-Item -ItemType Directory -Path "bin", "lib", "lib64", "sbin" -Force
Pop-Location
foreach ($installPath in @("bin", "lib", "sbin")) {
ln -sv (Join-Path -Path "usr" -ChildPath $installPath) (Join-Path -Path $WorkingDirectory -ChildPath $installPath)
}
# binutils
if ($Binutils -or $All) {
$BinutilsDirectory="binutils-${BinutilsVersion}"
$BinutilsPackageName="${BinutilsDirectory}.tar.xz"
$BinutilsURL="https://sourceware.org/pub/binutils/releases/${BinutilsPackageName}"
$BinutilsFilePath=(Join-Path -Path $SourcesDirectory -ChildPath $BinutilsPackageName)
if (-not (Test-Path -Path $BinutilsFilePath)) {
Invoke-WebRequest -Uri $BinutilsURL -OutFile $BinutilsFilePath
}
Push-Location $SourcesDirectory
if (-not (Test-Path -Path $BinutilsDirectory)) {
tar -xvf $BinutilsPackageName
}
Push-Location $BinutilsDirectory
$BuildDirectory="build"
New-Item -ItemType Directory -Path $BuildDirectory -Force
Push-Location $BuildDirectory
$Arguments=@(
"--prefix=${env:LFS}/tools",
"--with-sysroot=${env:LFS}",
"--target=${env:LFS_TGT}",
"--disable-nls",
"--enable-gprofng=no",
"--disable-werror",
"--enable-new-dtags",
"--enable-default-hash-style=gnu"
)
Start-Process -FilePath "../configure" -ArgumentList $Arguments -Wait -NoNewWindow
Start-Process -FilePath "make" -ArgumentList @("-j", $Jobs) -Wait -NoNewWindow
make install
Pop-Location
Pop-Location
Remove-Item -Path $BinutilsDirectory -Recurse -Force
Remove-Item -Path $BinutilsPackageName
Pop-Location
}
# gcc
if ($GCC -or $All) {
$GCCDirectory="gcc-${GCCVersion}"
$GCCPackageName="${GCCDirectory}.tar.xz"
$GCCURL="https://ftp.gnu.org/gnu/gcc/gcc-${GCCVersion}/${GCCPackageName}"
$GCCFilePath=(Join-Path -Path $SourcesDirectory -ChildPath $GCCPackageName)
if (-not (Test-Path -Path $GCCFilePath)) {
Invoke-WebRequest -Uri $GCCURL -OutFile $GCCFilePath
}
Push-Location $SourcesDirectory
if (-not (Test-Path -Path $GCCDirectory)) {
tar -xvf $GCCPackageName
}
Push-Location $GCCDirectory
$MPFRDirectory="mpfr-${MPFRVersion}"
$MPFRPackageName="${MPFRDirectory}.tar.xz"
$MPFRURL="https://ftp.gnu.org/gnu/mpfr/${MPFRPackageName}"
Invoke-WebRequest -Uri $MPFRURL -OutFile $MPFRPackageName
tar -xvf $MPFRPackageName
mv $MPFRDirectory mpfr
$GMPDirectory="gmp-${GMPVersion}"
$GMPPackageName="${GMPDirectory}.tar.xz"
$GMPURL="https://ftp.gnu.org/gnu/gmp/${GMPPackageName}"
Invoke-WebRequest -Uri $GMPURL -OutFile $GMPPackageName
tar -xvf $GMPPackageName
mv $GMPDirectory gmp
$MPCDirectory="mpc-${MPCVersion}"
$MPCPackageName="${MPCDirectory}.tar.gz"
$MPCURL="https://ftp.gnu.org/gnu/mpc/${MPCPackageName}"
Invoke-WebRequest -Uri $MPCURL -OutFile $MPCPackageName
tar -xvf $MPCPackageName
mv $MPCDirectory mpc
$BuildDirectory="build"
New-Item -ItemType Directory -Path $BuildDirectory -Force
Start-Process -FilePath "sed" -ArgumentList @("-e", "/m64=/s/lib64/lib/", "-i.orig", "gcc/config/i386/t-linux64") -Wait -NoNewWindow
Push-Location $BuildDirectory
$Arguments=@(
"--target=${env:LFS_TGT}",
"--prefix=${env:LFS}/tools",
"--with-glibc-version=${GLIBCVersion}"
"--with-sysroot=${env:LFS}",
"--with-newlib",
"--without-headers",
"--enable-default-pie",
"--enable-default-ssp",
"--disable-nls",
"--disable-shared",
"--disable-multilib",
"--disable-threads",
"--disable-libatomic",
"--disable-libgomp",
"--disable-libquadmath",
"--disable-libssp",
"--disable-libvtv",
"--disable-libstdcxx",
"--enable-languages=c,c++"
)
Start-Process -FilePath "../configure" -ArgumentList $Arguments -Wait -NoNewWindow
Start-Process -FilePath "make" -ArgumentList @("-j", $Jobs) -Wait -NoNewWindow
make install
Pop-Location
Push-Location gcc
$LibGCCFileName=&${env:LFS_TGT}-gcc -print-libgcc-file-name
$IncludeDirectory=(Split-Path -Path $LibGCCFileName -Parent)
foreach ($File in @("limitx.h", "glimits.h", "limity.h")) {
Get-Content -Path $File | Add-Content -Path "$IncludeDirectory/include/limits.h"
}
Pop-Location
Pop-Location
Remove-Item -Path $GCCDirectory -Recurse -Force
Remove-Item -Path $GCCPackageName
Pop-Location
}
# linux headers
if ($LinuxHeaders -or $All) {
$LinuxDirectory="linux-${LinuxVersion}"
$LinuxPackageName="${LinuxDirectory}.tar.xz"
$LinuxURL="https://www.kernel.org/pub/linux/kernel/v$(([version]$LinuxVersion).major).x/${LinuxPackageName}"
$LinuxFilePath=(Join-Path -Path $SourcesDirectory -ChildPath $LinuxPackageName)
if (-not (Test-Path -Path $LinuxFilePath)) {
Invoke-WebRequest -Uri $LinuxURL -OutFile $LinuxFilePath
}
Push-Location $SourcesDirectory
if (-not (Test-Path -Path $LinuxDirectory)) {
tar -xvf $LinuxPackageName
}
Push-Location $LinuxDirectory
make mrproper
make headers
&find usr/include -type f ! -name '*.h' -delete
&cp -rv usr/include ${env:LFS}/usr
Pop-Location
Remove-Item -Path $LinuxDirectory -Recurse -Force
Pop-Location
}
# glibc
if ($GLIBC -or $All) {
$GLIBCDirectory="glibc-${GLIBCVersion}"
$GLIBCPackageName="${GLIBCDirectory}.tar.xz"
$GLIBCURL="https://ftp.gnu.org/gnu/glibc/${GLIBCPackageName}"
$GLIBCFilePath=(Join-Path -Path $SourcesDirectory -ChildPath $GLIBCPackageName)
if (-not (Test-Path -Path $GLIBCFilePath)) {
Invoke-WebRequest -Uri $GLIBCURL -OutFile $GLIBCFilePath
}
Push-Location $SourcesDirectory
if (-not (Test-Path -Path $GLIBCDirectory)) {
tar -xvf $GLIBCPackageName
}
Push-Location $GLIBCDirectory
&ln -sfv ../lib/ld-linux-x86-64.so.2 ${env:LFS}/lib64
&ln -sfv ../lib/ld-linux-x86-64.so.2 ${env:LFS}/lib64/ld-lsb-x86-64.so.3
$FHSPatchFile="glibc-${GLIBCVersion}-fhs-1.patch"
Invoke-WebRequest -Uri "https://www.linuxfromscratch.org/patches/lfs/${LFSVersion}/${FHSPatchFile}" -OutFile ${FHSPatchFile}
&patch -Np1 -i glibc-2.42-fhs-1.patch
Add-Content -Path "configparms" -Value "rootsbindir=/usr/sbin"
$BuildDirectory="build"
New-Item -ItemType Directory -Path $BuildDirectory -Force
Push-Location $BuildDirectory
$Arguments=@(
"--prefix=/usr",
"--host=${env:LFS_TGT}",
"--build=$(../scripts/config.guess)",
"--disable-nscd",
"libc_cv_slibdir=/usr/lib",
"--enable-kernel=5.4"
)
Start-Process -FilePath "../configure" -ArgumentList $Arguments -Wait -NoNewWindow
Start-Process -FilePath "make" -ArgumentList @("-j", $Jobs) -Wait -NoNewWindow
&make DESTDIR=${env:LFS} install
Pop-Location
Pop-Location
Remove-Item -Path $GLIBCDirectory -Recurse -Force
Remove-Item -Path $GLIBCPackageName -Recurse
Pop-Location
}
if ($LibStdCPP -or $All) {
$GCCDirectory="gcc-${GCCVersion}"
$GCCPackageName="${GCCDirectory}.tar.xz"
$GCCURL="https://ftp.gnu.org/gnu/gcc/gcc-${GCCVersion}/${GCCPackageName}"
$GCCFilePath=(Join-Path -Path $SourcesDirectory -ChildPath $GCCPackageName)
if (-not (Test-Path -Path $GCCFilePath)) {
Invoke-WebRequest -Uri $GCCURL -OutFile $GCCFilePath
}
Push-Location $SourcesDirectory
if (-not (Test-Path -Path $GCCDirectory)) {
tar -xvf $GCCPackageName
}
Push-Location $GCCDirectory
$BuildDirectory="build"
New-Item -ItemType Directory -Path $BuildDirectory -Force
Push-Location $BuildDirectory
$Arguments=@(
"--host=${env:LFS_TGT}",
"--build=$(../config.guess)",
"--prefix=/usr",
"--disable-multilib",
"--disable-nls",
"--disable-libstdcxx-pch",
"--with-gxx-include-dir=/tools/${env:LFS_TGT}/include/c++/${GCCVersion}"
)
Start-Process -FilePath "../libstdc++-v3/configure" -ArgumentList $Arguments -Wait -NoNewWindow
Start-Process -FilePath "make" -ArgumentList @("-j", $Jobs) -Wait -NoNewWindow
&make DESTDIR=${env:LFS} install
Start-Process -FilePath "rm" -ArgumentList @("-v", "${env:LFS}/usr/lib/lib{stdc++{,exp,fs},supc++}.la") -Wait -NoNewWindow # FIXME: this is not being interpreted as bash
Pop-Location
Pop-Location
Pop-Location
}
Pop-Location
}
function Populate {
}
switch ($PsCmdlet.ParameterSetName) {
"StagingPhase" {
Stage
}
"PopulationPhase" {
Populate
}
}
Code language: PowerShell (powershell)
Leave a Reply