PublishAotCompressed.macOS
1.0.1-preview
dotnet add package PublishAotCompressed.macOS --version 1.0.1-preview
NuGet\Install-Package PublishAotCompressed.macOS -Version 1.0.1-preview
<PackageReference Include="PublishAotCompressed.macOS" Version="1.0.1-preview" />
<PackageVersion Include="PublishAotCompressed.macOS" Version="1.0.1-preview" />
<PackageReference Include="PublishAotCompressed.macOS" />
paket add PublishAotCompressed.macOS --version 1.0.1-preview
#r "nuget: PublishAotCompressed.macOS, 1.0.1-preview"
#:package PublishAotCompressed.macOS@1.0.1-preview
#addin nuget:?package=PublishAotCompressed.macOS&version=1.0.1-preview&prerelease
#tool nuget:?package=PublishAotCompressed.macOS&version=1.0.1-preview&prerelease
PublishAotCompressed.macOS
MSBuild targets to automatically compress Native AOT binaries with UPX on macOS. Designed to work seamlessly with cross-compilation from macOS to Windows and Linux.
English | 简体中文
🚀 Features
- ✅ Automatic UPX compression after Native AOT compilation
- ✅ Cross-compilation support - compress binaries for Windows and Linux from macOS
- ✅ macOS-only - streamlined for macOS development workflow
- ✅ 60%+ size reduction - typical compression rates
- ✅ Optional LZMA for even better compression
- ✅ Smart detection - automatically skips compression for macOS targets
📋 Table of Contents
- Quick Start
- Configuration
- Supported Targets
- How It Works
- Compression Results
- Troubleshooting
- Related Projects
Quick Start
Prerequisites
- macOS (Apple Silicon or Intel)
- .NET 9.0 SDK or later
- UPX installed via Homebrew:
brew install upx
For Windows Cross-compilation
This package works perfectly with PublishAotCross.macOS for cross-compiling to Windows.
Install cross-compilation tools:
# Install LLVM for lld-link brew install lld # Add to PATH (or add to ~/.zshrc for permanent) export PATH="$(brew --prefix lld)/bin:$PATH" # Install xwin for Windows SDK cargo install --locked xwin # Download Windows SDK (~1.5GB) mkdir -p $HOME/.local/share/xwin-sdk xwin --accept-license \ --cache-dir $HOME/.local/share/xwin-sdk \ --arch x86_64,aarch64 \ splat --preserve-ms-arch-notationAdd packages to your project:
<ItemGroup> <PackageReference Include="PublishAotCross.macOS" Version="1.0.3-preview" /> <PackageReference Include="PublishAotCompressed.macOS" Version="1.0.0-preview" /> </ItemGroup>Publish with compression:
# Ensure lld-link is in PATH export PATH="$(brew --prefix lld)/bin:$PATH" # Build for Windows (automatically compressed with UPX) dotnet publish -r win-x64 -c Release dotnet publish -r win-arm64 -c Release dotnet publish -r win-x86 -c Release
📖 Detailed Windows setup guide: See PublishAotCross.macOS QUICKSTART.md
For Linux Cross-compilation
Install Zig (via Homebrew):
brew install zigAdd packages to your project (same as above):
<ItemGroup> <PackageReference Include="PublishAotCross.macOS" Version="1.0.3-preview" /> <PackageReference Include="PublishAotCompressed.macOS" Version="1.0.0-preview" /> </ItemGroup>Publish with compression:
# glibc-based (Ubuntu, Debian, etc.) dotnet publish -r linux-x64 -c Release /p:StripSymbols=false dotnet publish -r linux-arm64 -c Release /p:StripSymbols=false # musl-based (Alpine Linux) dotnet publish -r linux-musl-x64 -c Release /p:StripSymbols=false dotnet publish -r linux-musl-arm64 -c Release /p:StripSymbols=false
📖 Detailed Linux setup guide: See PublishAotCross.macOS QUICKSTART-LINUX.md
For macOS (native)
Good news: macOS targets are built-in! Just publish normally:
dotnet publish -r osx-arm64 -c Release
dotnet publish -r osx-x64 -c Release
✅ Note: macOS targets automatically skip UPX compression. The package will display a message and produce uncompressed binaries that run normally. This is by design since UPX-compressed macOS binaries cannot run due to macOS security restrictions (System Integrity Protection, code signing, Gatekeeper).
Configuration
Compression Settings
You can use either the full property name or the short alias:
<PropertyGroup>
<Upx>true</Upx>
<PublishAotCompressed>true</PublishAotCompressed>
<CompressBest>true</CompressBest>
<PublishLzmaCompressed>true</PublishLzmaCompressed>
</PropertyGroup>
Command Line Usage
# Enable compression (short form) ✅ Recommended
dotnet publish -r win-x64 -c Release /p:Upx=true
# Disable compression (short form) ✅ Recommended
dotnet publish -r win-x64 -c Release /p:Upx=false
# Or use the full property name
dotnet publish -r win-x64 -c Release /p:PublishAotCompressed=false
Example Project Configuration
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<PublishAot>true</PublishAot>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PublishAotCross.macOS" Version="1.0.3-preview" />
<PackageReference Include="PublishAotCompressed.macOS" Version="1.0.0-preview" />
</ItemGroup>
</Project>
Supported Targets
Windows (via lld-link + xwin)
| Target | UPX Support | Cross-compilation Tool |
|---|---|---|
win-x64 |
✅ Compresses | PublishAotCross.macOS |
win-arm64 |
✅ Compresses | PublishAotCross.macOS |
win-x86 |
✅ Compresses | PublishAotCross.macOS |
Linux (via Zig)
| Target | UPX Support | Cross-compilation Tool |
|---|---|---|
linux-x64 |
✅ Compresses | PublishAotCross.macOS |
linux-arm64 |
✅ Compresses | PublishAotCross.macOS |
linux-musl-x64 |
✅ Compresses | PublishAotCross.macOS |
linux-musl-arm64 |
✅ Compresses | PublishAotCross.macOS |
macOS (native)
| Target | UPX Support | Notes |
|---|---|---|
osx-arm64 |
⏭️ Skipped | Auto-skipped due to macOS security |
osx-x64 |
⏭️ Skipped | Auto-skipped due to macOS security |
How It Works
This package hooks into the Native AOT build process and automatically compresses the compiled binary:
Build Flow:
.NET AOT Compiler (macOS) → Native Binary → UPX Compression → Compressed Executable
(.exe/.elf) (macOS tool) (for target OS)
Technical Details:
- MSBuild Target: Runs
AfterTargets="LinkNative"to compress the binary immediately after linking - Platform Detection: Identifies target OS from RuntimeIdentifier (win-/linux-/osx-*)
- Smart Compression:
- For Windows/Linux targets: runs UPX with
--bestflag - For macOS targets: skips compression and displays a message
- For Windows/Linux targets: runs UPX with
- Host Tool: Always uses macOS ARM64 UPX binary included in the package
UPX Compression:
- Algorithm: LZBA (default) or LZMA (optional)
- Level:
--best(level 9) by default - Decompression: Automatic at program launch, in-memory, typically unnoticeable
Compression Results
For a Hello World program with size optimizations enabled:
| Target | Uncompressed | With --best UPX |
Compression Ratio | Savings |
|---|---|---|---|---|
| Windows x64 | 1.05 MB | 483 KB | 44.9% | 55.1% |
| Windows ARM64 | 1.01 MB | 455 KB | 45.0% | 55.0% |
| Linux x64 | 1.30 MB | 520 KB | 40.0% | 60.0% |
| Linux ARM64 | 1.25 MB | 500 KB | 40.0% | 60.0% |
| macOS ARM64 | 1.20 MB | N/A (skipped) | - | - |
💡 Tip: Add
<PublishLzmaCompressed>true</PublishLzmaCompressed>for even better compression (typically 5-10% smaller, but adds ~50-100ms to startup time).
Deploying to Target Platforms
Linux Deployment
.NET Native AOT binaries require the ICU library on the target system:
# Ubuntu/Debian
sudo apt-get install -y libicu-dev
# CentOS/RHEL/Fedora
sudo yum install -y icu
# Alpine Linux
apk add --no-cache icu-libs
Docker Example:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y libicu-dev
COPY YourApp /app/
CMD ["/app/YourApp"]
Disable ICU (Optional):
<PropertyGroup>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
Windows Deployment
UPX-compressed Windows executables:
- ✅ Run on any Windows 10/11 system
- ✅ No additional runtime required (.NET Native AOT)
- ⚠️ May trigger false positives in some antivirus software (add to whitelist if needed)
If Windows shows "compressed file" dialog:
- This is a file association issue with WinRAR/7-Zip
- Solution: Right-click → Properties → Unblock (if shown)
- The
.exeis directly executable, not a compressed archive
Troubleshooting
upx: command not found
Install UPX via Homebrew:
brew install upx
Cross-compilation fails
Make sure you've installed the cross-compilation tools:
- For Windows: See PublishAotCross.macOS Windows setup
- For Linux: See PublishAotCross.macOS Linux setup
UPX compression fails
Check that the package is properly installed:
# Verify UPX is available
upx --version
# Check package installation
dotnet list package | grep PublishAotCompressed.macOS
"PublishAotCompressed.macOS can only be used on macOS"
This package only works on macOS. For other platforms:
- Original cross-platform version: PublishAotCompressed
Related Projects
Complete .NET Native AOT Cross-Compilation Ecosystem
| Project | Purpose | Platforms |
|---|---|---|
| PublishAotCross.macOS | Cross-compile from macOS | macOS → Windows/Linux |
| PublishAotCompressed.macOS (this) | UPX compression on macOS | Compresses Windows/Linux binaries |
| PublishAotCross | Cross-compile from Windows | Windows → Linux |
| PublishAotCrossXWin | Cross-compile from Linux | Linux → Windows |
| PublishAotCompressed | Original UPX package | Multi-platform |
Cross-Compilation + Compression Matrix
| Build Host | Target | Cross-compilation | UPX Compression |
|---|---|---|---|
| macOS | Windows | ✅ PublishAotCross.macOS | ✅ This package |
| macOS | Linux | ✅ PublishAotCross.macOS | ✅ This package |
| macOS | macOS | Native | ⏭️ Skipped (security) |
| Windows | Linux | ✅ PublishAotCross | ✅ PublishAotCompressed |
| Linux | Windows | ✅ PublishAotCrossXWin | ✅ PublishAotCompressed |
💡 macOS users get the best of both worlds - cross-compile to both Windows and Linux with automatic UPX compression from a single machine!
Requirements
Build Host
- macOS (Apple Silicon or Intel)
- .NET 9.0 SDK or later
- Homebrew (for installing tools)
For Windows Cross-compilation
- LLVM (
lld-linklinker) - viabrew install lld - Rust/Cargo (for installing xwin) - via
brew install rust - xwin - via
cargo install xwin - ~1.5GB disk space for Windows SDK
For Linux Cross-compilation
- Zig (~200MB, includes everything) - via
brew install zig
Example Project
See the test/ directory in this repository for a complete example.
License
MIT License - see LICENSE.TXT for details.
Credits
- Based on PublishAotCompressed by Michal Strehovsky
- UPX by UPX Team
- Designed to work with PublishAotCross.macOS
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
Made with ❤️ for the .NET Native AOT community on macOS
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.1-preview | 291 | 11/5/2025 |
| 1.0.0-preview | 290 | 11/5/2025 |