mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
With the move to Avalonia the app runs on Linux and macOS, so the distribution tooling grows beyond Windows: publish.ps1 gains a -Platform parameter (the default keeps the Windows behavior unchanged), and new BuildTools scripts package the self-contained publish outputs into a zip, deb, and rpm on Linux and a zipped ILSpy.app on macOS. Nothing is signed at package time; signing happens offline on the release manager machine. Info-ZIP zip is used instead of Compress-Archive because the latter drops unix mode bits. deb/rpm are built with dpkg-deb/rpmbuild directly (both preinstalled on GitHub ubuntu runners) following sourcegit-scm/sourcegit's proven model, including the libicu OR-chain in the deb control file and disabled auto-requires for the self-contained rpm payload. Pre-release versions map '-' to '~' so both package managers sort them before the release. The macOS bundle's Info.plist now carries placeholders stamped at package time; on Windows the spec/control/desktop files are kept LF via .gitattributes because Linux tools consume them verbatim. Assisted-by: Claude:claude-fable-5:Claude Codepull/3404/head
9 changed files with 286 additions and 17 deletions
@ -0,0 +1,119 @@ |
|||||||
|
#!/usr/bin/env pwsh |
||||||
|
# Package the linux-x64 self-contained publish output (created by `./publish.ps1 -Platform linux`) |
||||||
|
# into the Linux distribution artifacts: |
||||||
|
# ILSpy_linux-x64_<version>.zip Info-ZIP archive (preserves the execute flag, unlike |
||||||
|
# Compress-Archive/7z, which drop unix mode bits) |
||||||
|
# ilspy_<version>-1_amd64.deb built with dpkg-deb |
||||||
|
# ilspy-<version>-1.x86_64.rpm built with rpmbuild |
||||||
|
# Must run on Linux. zip and dpkg-deb are preinstalled on GitHub's ubuntu runners; |
||||||
|
# locally: sudo apt-get install -y zip dpkg rpm |
||||||
|
param( |
||||||
|
[ValidateSet('Debug', 'Release')] |
||||||
|
[string]$Configuration = 'Release', |
||||||
|
# Defaults to the CI-computed version (env var, then the ILSPY_VERSION file written by |
||||||
|
# BuildTools/ghactions-install.ps1), falling back to the committed VERSION file for |
||||||
|
# local runs. |
||||||
|
[string]$Version, |
||||||
|
[string]$StagingDirectory = 'buildartifacts' |
||||||
|
) |
||||||
|
$ErrorActionPreference = 'Stop' |
||||||
|
$PSNativeCommandUseErrorActionPreference = $true |
||||||
|
|
||||||
|
$repoRoot = Split-Path -Parent $PSScriptRoot |
||||||
|
$resources = Join-Path $PSScriptRoot 'packaging/linux' |
||||||
|
|
||||||
|
foreach ($tool in 'zip', 'dpkg-deb', 'rpmbuild') { |
||||||
|
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) { |
||||||
|
throw "'$tool' not found. This script must run on Linux; install the tools with: sudo apt-get install -y zip dpkg rpm" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (-not $Version) { |
||||||
|
if ($env:ILSPY_VERSION_NUMBER) { |
||||||
|
$Version = $env:ILSPY_VERSION_NUMBER |
||||||
|
} |
||||||
|
elseif (Test-Path (Join-Path $repoRoot 'ILSPY_VERSION')) { |
||||||
|
$Version = (Get-Content (Join-Path $repoRoot 'ILSPY_VERSION') -Raw).Trim() |
||||||
|
} |
||||||
|
else { |
||||||
|
$Version = (Get-Content (Join-Path $repoRoot 'VERSION') -Raw).Trim() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$publishDir = Join-Path $repoRoot "ILSpy/bin/$Configuration/net10.0/linux-x64/publish/selfcontained" |
||||||
|
if (-not (Test-Path (Join-Path $publishDir 'ILSpy'))) { |
||||||
|
throw "Publish output not found at $publishDir. Run ./publish.ps1 -Configuration $Configuration -Platform linux first." |
||||||
|
} |
||||||
|
|
||||||
|
$staging = New-Item -ItemType Directory -Force (Join-Path $repoRoot $StagingDirectory) |
||||||
|
|
||||||
|
# ----- zip ----- |
||||||
|
$zipPath = Join-Path $staging "ILSpy_linux-x64_$Version.zip" |
||||||
|
Remove-Item $zipPath -ErrorAction Ignore |
||||||
|
Push-Location $publishDir |
||||||
|
try { |
||||||
|
zip -r -q $zipPath . -x '*.pdb' |
||||||
|
} |
||||||
|
finally { |
||||||
|
Pop-Location |
||||||
|
} |
||||||
|
Write-Host "created $zipPath" |
||||||
|
|
||||||
|
# Both dpkg and rpm reject '-' inside a version (it separates the package revision in deb |
||||||
|
# and is illegal in the rpm Version tag). '~' is legal in both and sorts *before* the |
||||||
|
# plain version, which is the correct semantic for pre-release suffixes like '-preview1'. |
||||||
|
$pkgVersion = $Version -replace '-', '~' |
||||||
|
|
||||||
|
# Shared payload layout for both package formats: the app in /opt/ilspy, a launcher |
||||||
|
# symlink on PATH, and desktop integration files. |
||||||
|
function Copy-PackagePayload([string]$root) { |
||||||
|
New-Item -ItemType Directory -Force (Join-Path $root 'opt/ilspy'), (Join-Path $root 'usr/bin'), |
||||||
|
(Join-Path $root 'usr/share/applications'), (Join-Path $root 'usr/share/icons/hicolor/256x256/apps') | Out-Null |
||||||
|
Copy-Item "$publishDir/*" (Join-Path $root 'opt/ilspy') -Recurse |
||||||
|
Get-ChildItem (Join-Path $root 'opt/ilspy') -Filter '*.pdb' -Recurse | Remove-Item |
||||||
|
chmod 755 (Join-Path $root 'opt/ilspy/ILSpy') |
||||||
|
ln -s /opt/ilspy/ILSpy (Join-Path $root 'usr/bin/ilspy') |
||||||
|
Copy-Item (Join-Path $resources 'ilspy.desktop') (Join-Path $root 'usr/share/applications') |
||||||
|
Copy-Item (Join-Path $resources 'ilspy.png') (Join-Path $root 'usr/share/icons/hicolor/256x256/apps') |
||||||
|
chmod 644 (Join-Path $root 'usr/share/applications/ilspy.desktop') (Join-Path $root 'usr/share/icons/hicolor/256x256/apps/ilspy.png') |
||||||
|
} |
||||||
|
|
||||||
|
# ----- deb ----- |
||||||
|
$debRoot = Join-Path ([IO.Path]::GetTempPath()) 'ilspy-deb' |
||||||
|
Remove-Item -Recurse -Force $debRoot -ErrorAction Ignore |
||||||
|
New-Item -ItemType Directory -Force (Join-Path $debRoot 'DEBIAN') | Out-Null |
||||||
|
Copy-PackagePayload $debRoot |
||||||
|
|
||||||
|
# Debian has no unversioned libicu package and the soname-versioned name differs per |
||||||
|
# release, so depend on an OR-chain covering the releases we care about (the leading |
||||||
|
# plain 'libicu' catches derivatives that do ship a virtual package). |
||||||
|
$icuVersions = 78, 77, 76, 74, 72, 71, 70, 69, 68, 67, 66, 65, 63 |
||||||
|
$icuDeps = (@('libicu') + ($icuVersions | ForEach-Object { "libicu$_" })) -join ' | ' |
||||||
|
$installedSize = [int]((Get-ChildItem $debRoot -Recurse -File | Measure-Object Length -Sum).Sum / 1024) |
||||||
|
|
||||||
|
$control = (Get-Content (Join-Path $resources 'deb/control.template') -Raw). |
||||||
|
Replace('@VERSION@', "$pkgVersion-1"). |
||||||
|
Replace('@ARCH@', 'amd64'). |
||||||
|
Replace('@INSTALLED_SIZE@', "$installedSize"). |
||||||
|
Replace('@ICU_DEPS@', $icuDeps) |
||||||
|
Set-Content (Join-Path $debRoot 'DEBIAN/control') $control |
||||||
|
|
||||||
|
$debPath = Join-Path $staging "ilspy_${pkgVersion}-1_amd64.deb" |
||||||
|
# gzip instead of dpkg's zstd default so the package installs on older dpkg versions |
||||||
|
dpkg-deb -Zgzip --root-owner-group --build $debRoot $debPath |
||||||
|
Write-Host "created $debPath" |
||||||
|
|
||||||
|
# ----- rpm ----- |
||||||
|
$rpmTop = Join-Path ([IO.Path]::GetTempPath()) 'ilspy-rpm' |
||||||
|
Remove-Item -Recurse -Force $rpmTop -ErrorAction Ignore |
||||||
|
$rpmRoot = Join-Path $rpmTop 'payload' |
||||||
|
New-Item -ItemType Directory -Force $rpmRoot | Out-Null |
||||||
|
Copy-PackagePayload $rpmRoot |
||||||
|
|
||||||
|
rpmbuild -bb (Join-Path $resources 'rpm/ilspy.spec') --target x86_64 ` |
||||||
|
--define "_topdir $rpmTop" ` |
||||||
|
--define "_version $pkgVersion" ` |
||||||
|
--define "_payload_dir $rpmRoot" |
||||||
|
$rpm = Get-ChildItem (Join-Path $rpmTop 'RPMS') -Filter '*.rpm' -Recurse |
||||||
|
Move-Item $rpm.FullName $staging -Force |
||||||
|
Write-Host "created $(Join-Path $staging $rpm.Name)" |
||||||
@ -0,0 +1,63 @@ |
|||||||
|
#!/usr/bin/env pwsh |
||||||
|
# Package the osx-arm64 ILSpy.app bundle (created by `./publish.ps1 -Platform macos` via the |
||||||
|
# BuildMacAppBundle target in ILSpy.csproj) into ILSpy_macos-arm64_<version>.zip. |
||||||
|
# Stamps the version placeholders in the bundle's Info.plist first. |
||||||
|
# Must run on macOS/Linux: Info-ZIP's zip preserves the execute flag and (-y) symlinks, |
||||||
|
# which Compress-Archive does not. |
||||||
|
param( |
||||||
|
[ValidateSet('Debug', 'Release')] |
||||||
|
[string]$Configuration = 'Release', |
||||||
|
# Defaults to the CI-computed version (env var, then the ILSPY_VERSION file written by |
||||||
|
# BuildTools/ghactions-install.ps1), falling back to the committed VERSION file for |
||||||
|
# local runs. |
||||||
|
[string]$Version, |
||||||
|
[string]$StagingDirectory = 'buildartifacts' |
||||||
|
) |
||||||
|
$ErrorActionPreference = 'Stop' |
||||||
|
$PSNativeCommandUseErrorActionPreference = $true |
||||||
|
|
||||||
|
$repoRoot = Split-Path -Parent $PSScriptRoot |
||||||
|
|
||||||
|
if (-not (Get-Command zip -ErrorAction SilentlyContinue)) { |
||||||
|
throw "'zip' not found. This script needs Info-ZIP, available on macOS and Linux." |
||||||
|
} |
||||||
|
|
||||||
|
if (-not $Version) { |
||||||
|
if ($env:ILSPY_VERSION_NUMBER) { |
||||||
|
$Version = $env:ILSPY_VERSION_NUMBER |
||||||
|
} |
||||||
|
elseif (Test-Path (Join-Path $repoRoot 'ILSPY_VERSION')) { |
||||||
|
$Version = (Get-Content (Join-Path $repoRoot 'ILSPY_VERSION') -Raw).Trim() |
||||||
|
} |
||||||
|
else { |
||||||
|
$Version = (Get-Content (Join-Path $repoRoot 'VERSION') -Raw).Trim() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$publishDir = Join-Path $repoRoot "ILSpy/bin/$Configuration/net10.0/osx-arm64/publish" |
||||||
|
$appDir = Join-Path $publishDir 'ILSpy.app' |
||||||
|
if (-not (Test-Path $appDir)) { |
||||||
|
throw "ILSpy.app not found at $appDir. Run ./publish.ps1 -Configuration $Configuration -Platform macos first." |
||||||
|
} |
||||||
|
|
||||||
|
# CFBundleVersion / CFBundleShortVersionString must be dotted numerics; strip the |
||||||
|
# pre-release suffix (11.0.0.8948-preview1 -> 11.0.0.8948) and shorten to three parts. |
||||||
|
$numericVersion = ($Version -split '-')[0] |
||||||
|
$shortVersion = ($numericVersion -split '\.')[0..2] -join '.' |
||||||
|
$plistPath = Join-Path $appDir 'Contents/Info.plist' |
||||||
|
$plist = (Get-Content $plistPath -Raw). |
||||||
|
Replace('ILSPY_SHORT_VERSION', $shortVersion). |
||||||
|
Replace('ILSPY_VERSION', $numericVersion) |
||||||
|
Set-Content $plistPath $plist |
||||||
|
|
||||||
|
$staging = New-Item -ItemType Directory -Force (Join-Path $repoRoot $StagingDirectory) |
||||||
|
$zipPath = Join-Path $staging "ILSpy_macos-arm64_$Version.zip" |
||||||
|
Remove-Item $zipPath -ErrorAction Ignore |
||||||
|
Push-Location $publishDir |
||||||
|
try { |
||||||
|
zip -r -y -q $zipPath ILSpy.app -x '*.pdb' |
||||||
|
} |
||||||
|
finally { |
||||||
|
Pop-Location |
||||||
|
} |
||||||
|
Write-Host "created $zipPath" |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
Package: ilspy |
||||||
|
Version: @VERSION@ |
||||||
|
Priority: optional |
||||||
|
Section: devel |
||||||
|
Architecture: @ARCH@ |
||||||
|
Installed-Size: @INSTALLED_SIZE@ |
||||||
|
Depends: libx11-6, libice6, libsm6, libfontconfig1, @ICU_DEPS@, xdg-utils |
||||||
|
Maintainer: ICSharpCode Team <https://github.com/icsharpcode> |
||||||
|
Homepage: https://github.com/icsharpcode/ILSpy |
||||||
|
Description: .NET assembly browser and decompiler |
||||||
|
ILSpy is the open-source .NET assembly browser and decompiler, |
||||||
|
built on Avalonia and the ICSharpCode.Decompiler engine. |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
[Desktop Entry] |
||||||
|
Name=ILSpy |
||||||
|
Comment=.NET assembly browser and decompiler |
||||||
|
Exec=/opt/ilspy/ILSpy %F |
||||||
|
Icon=ilspy |
||||||
|
Terminal=false |
||||||
|
Type=Application |
||||||
|
Categories=Development; |
||||||
|
MimeType=application/x-msdownload;application/vnd.microsoft.portable-executable; |
||||||
|
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,36 @@ |
|||||||
|
# Built by BuildTools/package-linux.ps1, which stages the complete payload tree |
||||||
|
# (/opt/ilspy + launcher symlink + desktop integration) and passes it in via |
||||||
|
# rpmbuild -bb ilspy.spec --target x86_64 |
||||||
|
# --define "_topdir <tmp>" --define "_version <version>" --define "_payload_dir <staged tree>" |
||||||
|
|
||||||
|
# The payload is a prebuilt self-contained .NET publish; skip post-install processing |
||||||
|
# (stripping the bundled native libraries breaks them) and debuginfo extraction. |
||||||
|
%global __os_install_post %{nil} |
||||||
|
%global debug_package %{nil} |
||||||
|
%global _build_id_links none |
||||||
|
|
||||||
|
Name: ilspy |
||||||
|
Version: %{_version} |
||||||
|
Release: 1 |
||||||
|
Summary: .NET assembly browser and decompiler |
||||||
|
License: MIT |
||||||
|
URL: https://github.com/icsharpcode/ILSpy |
||||||
|
# The self-contained payload bundles its own .NET runtime; automatic dependency scanning |
||||||
|
# would generate requires for every bundled shared object, so dependencies are listed |
||||||
|
# manually instead. |
||||||
|
AutoReqProv: no |
||||||
|
Requires: libX11, libSM, libICE, fontconfig, libicu |
||||||
|
|
||||||
|
%description |
||||||
|
ILSpy is the open-source .NET assembly browser and decompiler, |
||||||
|
built on Avalonia and the ICSharpCode.Decompiler engine. |
||||||
|
|
||||||
|
%install |
||||||
|
mkdir -p %{buildroot} |
||||||
|
cp -a %{_payload_dir}/. %{buildroot}/ |
||||||
|
|
||||||
|
%files |
||||||
|
/opt/ilspy |
||||||
|
/usr/bin/ilspy |
||||||
|
/usr/share/applications/ilspy.desktop |
||||||
|
/usr/share/icons/hicolor/256x256/apps/ilspy.png |
||||||
Loading…
Reference in new issue