add Windows build process to fix application icon until .NET bug is fixed

This commit is contained in:
Jesse Plamondon-Willard 2021-12-05 18:55:10 -05:00
parent c05fdf65cf
commit f4ca7dd228
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
13 changed files with 449 additions and 58 deletions

View File

@ -22,6 +22,9 @@ insert_final_newline = false
[README.txt] [README.txt]
end_of_line=crlf end_of_line=crlf
[*.{command,sh}]
end_of_line=lf
########## ##########
## C# formatting ## C# formatting
## documentation: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference ## documentation: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference

5
.gitattributes vendored
View File

@ -1,3 +1,6 @@
# normalize line endings # normalize line endings
* text=auto * text=auto
README.txt text=crlf README.txt text eol=crlf
*.command text eol=lf
*.sh text eol=lf

View File

@ -1,5 +1,13 @@
#!/bin/bash #!/bin/bash
#
#
# This is the Bash equivalent of ../windows/prepare-install-package.ps1.
# When making changes, both scripts should be updated.
#
#
########## ##########
## Constants ## Constants
########## ##########
@ -17,19 +25,18 @@ declare -A msBuildPlatformNames=(["linux"]="Unix" ["macOS"]="OSX" ["windows"]="W
########## ##########
## Move to SMAPI root ## Move to SMAPI root
########## ##########
cd "`dirname "$0"`/.." cd "`dirname "$0"`/../.."
########## ##########
## Clear old build files ## Clear old build files
########## ##########
echo "Clearing old builds..." echo "Clearing old builds..."
echo "-----------------------" echo "-------------------------------------------------"
for path in */**/bin */**/obj; do for path in bin */**/bin */**/obj; do
echo "$path" echo "$path"
rm -rf $path rm -rf $path
done done
rm -rf "bin"
echo "" echo ""
########## ##########
@ -40,20 +47,20 @@ for folder in ${folders[@]}; do
msbuildPlatformName=${msBuildPlatformNames[$folder]} msbuildPlatformName=${msBuildPlatformNames[$folder]}
echo "Compiling SMAPI for $folder..." echo "Compiling SMAPI for $folder..."
echo "------------------" echo "-------------------------------------------------"
dotnet publish src/SMAPI --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained true dotnet publish src/SMAPI --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained true
echo "" echo ""
echo "" echo ""
echo "Compiling installer for $folder..." echo "Compiling installer for $folder..."
echo "----------------------" echo "-------------------------------------------------"
dotnet publish src/SMAPI.Installer --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" -p:PublishTrimmed=True -p:TrimMode=Link --self-contained true dotnet publish src/SMAPI.Installer --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" -p:PublishTrimmed=True -p:TrimMode=Link --self-contained true
echo "" echo ""
echo "" echo ""
for modName in ${bundleModNames[@]}; do for modName in ${bundleModNames[@]}; do
echo "Compiling $modName for $folder..." echo "Compiling $modName for $folder..."
echo "----------------------------------" echo "-------------------------------------------------"
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false"
echo "" echo ""
echo "" echo ""
@ -65,7 +72,7 @@ done
## Prepare install package ## Prepare install package
########## ##########
echo "Preparing install package..." echo "Preparing install package..."
echo "----------------------------" echo "-------------------------------------------------"
# init paths # init paths
installAssets="src/SMAPI.Installer/assets" installAssets="src/SMAPI.Installer/assets"
@ -93,7 +100,6 @@ for folder in ${folders[@]}; do
# installer files # installer files
cp -r "src/SMAPI.Installer/bin/$buildConfig/$runtime/publish"/* "$internalPath" cp -r "src/SMAPI.Installer/bin/$buildConfig/$runtime/publish"/* "$internalPath"
rm -rf "$internalPath/ref"
rm -rf "$internalPath/assets" rm -rf "$internalPath/assets"
# runtime config for SMAPI # runtime config for SMAPI

View File

@ -1,5 +1,13 @@
#!/bin/bash #!/bin/bash
#
#
# This is the Bash equivalent of ../windows/set-smapi-version.ps1.
# When making changes, both scripts should be updated.
#
#
# get version number # get version number
version="$1" version="$1"
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
@ -8,7 +16,7 @@ if [ $# -eq 0 ]; then
fi fi
# move to SMAPI root # move to SMAPI root
cd "`dirname "$0"`/.." cd "`dirname "$0"`/../.."
# apply changes # apply changes
sed "s/<Version>.+<\/Version>/<Version>$version<\/Version>/" "build/common.targets" --in-place --regexp-extended sed "s/<Version>.+<\/Version>/<Version>$version<\/Version>/" "build/common.targets" --in-place --regexp-extended

View File

@ -0,0 +1,67 @@
#!/bin/bash
##########
## Read config
##########
# get SMAPI version
version="$1"
if [ $# -eq 0 ]; then
echo "SMAPI release version (like '4.0.0'):"
read version
fi
# get Windows bin path
windowsBinPath="$2"
if [ $# -le 1 ]; then
echo "Windows compiled bin path:"
read windowsBinPath
fi
# installer internal folders
buildFolders=("linux" "macOS" "windows")
##########
## Finalize release package
##########
for folderName in "SMAPI $version installer" "SMAPI $version installer for developers"; do
# move files to Linux filesystem
echo "Preparing $folderName.zip..."
echo "-------------------------------------------------"
echo "copying '$windowsBinPath/$folderName' to Linux filesystem..."
cp -r "$windowsBinPath/$folderName" .
# fix permissions
echo "fixing permissions..."
find "$folderName" -type d -exec chmod 755 {} \;
find "$folderName" -type f -exec chmod 644 {} \;
find "$folderName" -name "*.sh" -exec chmod 755 {} \;
find "$folderName" -name "*.command" -exec chmod 755 {} \;
find "$folderName" -name "SMAPI.Installer" -exec chmod 755 {} \;
find "$folderName" -name "StardewModdingAPI" -exec chmod 755 {} \;
# convert bundle folder into final 'install.dat' files
for build in ${buildFolders[@]}; do
echo "packaging $folderName/internal/$build/install.dat..."
pushd "$folderName/internal/$build/bundle" > /dev/null
zip "install.dat" * --recurse-paths --quiet
mv install.dat ../
popd > /dev/null
rm -rf "$folderName/internal/$build/bundle"
done
# zip installer
echo "packaging installer..."
zip -9 "$folderName.zip" "$folderName" --recurse-paths --quiet
# move zip back to Windows bin path
echo "moving release zip to $windowsBinPath/$folderName.zip..."
mv "$folderName.zip" "$windowsBinPath"
rm -rf "$folderName"
echo ""
echo ""
done
echo "Done!"

View File

@ -0,0 +1,11 @@
function In-Place-Regex {
param (
[Parameter(Mandatory)][string]$Path,
[Parameter(Mandatory)][string]$Search,
[Parameter(Mandatory)][string]$Replace
)
$content = (Get-Content "$Path" -Encoding UTF8)
$content = ($content -replace "$Search", "$Replace")
[System.IO.File]::WriteAllLines((Get-Item "$Path").FullName, $content)
}

View File

@ -0,0 +1,217 @@
#
#
# This is the PowerShell equivalent of ../unix/prepare-install-package.sh, *except* that it doesn't
# set Linux permissions, create the install.dat files, or create the final zip. Due to limitations
# in PowerShell, the final changes are handled by the windows/finalize-install-package.sh file in
# WSL.
#
# When making changes, make sure to update ../unix/prepare-install-package.ps1 too.
#
#
. "$PSScriptRoot\lib\in-place-regex.ps1"
##########
## Constants
##########
# paths
$gamePath = "C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley"
$bundleModNames = "ConsoleCommands", "ErrorHandler", "SaveBackup"
# build configuration
$buildConfig = "Release"
$folders = "linux", "macOS", "windows"
$runtimes = @{ linux = "linux-x64"; macOS = "osx-x64"; windows = "win-x64" }
$msBuildPlatformNames = @{ linux = "Unix"; macOS = "OSX"; windows = "Windows_NT" }
##########
## Move to SMAPI root
##########
cd "$PSScriptRoot/../.."
##########
## Clear old build files
##########
echo "Clearing old builds..."
echo "-------------------------------------------------"
foreach ($path in (dir -Recurse -Include ('bin', 'obj'))) {
echo "$path"
rm -Recurse -Force "$path"
}
echo ""
##########
## Compile files
##########
ForEach ($folder in $folders) {
$runtime = $runtimes[$folder]
$msbuildPlatformName = $msBuildPlatformNames[$folder]
echo "Compiling SMAPI for $folder..."
echo "-------------------------------------------------"
dotnet publish src/SMAPI --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" --self-contained true
echo ""
echo ""
echo "Compiling installer for $folder..."
echo "-------------------------------------------------"
dotnet publish src/SMAPI.Installer --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false" -p:PublishTrimmed=True -p:TrimMode=Link --self-contained true
echo ""
echo ""
foreach ($modName in $bundleModNames) {
echo "Compiling $modName for $folder..."
echo "-------------------------------------------------"
dotnet publish src/SMAPI.Mods.$modName --configuration $buildConfig -v minimal --runtime "$runtime" -p:OS="$msbuildPlatformName" -p:GamePath="$gamePath" -p:CopyToGameFolder="false"
echo ""
echo ""
}
}
##########
## Prepare install package
##########
echo "Preparing install package..."
echo "----------------------------"
# init paths
$installAssets = "src/SMAPI.Installer/assets"
$packagePath = "bin/SMAPI installer"
$packageDevPath = "bin/SMAPI installer for developers"
# init structure
foreach ($folder in $folders) {
mkdir "$packagePath/internal/$folder/bundle/smapi-internal" > $null
}
# copy base installer files
foreach ($name in @("install on Linux.sh", "install on macOS.command", "install on Windows.bat", "README.txt")) {
cp "$installAssets/$name" "$packagePath"
}
# copy per-platform files
foreach ($folder in $folders) {
$runtime = $runtimes[$folder]
# get paths
$smapiBin = "src/SMAPI/bin/$buildConfig/$runtime/publish"
$internalPath = "$packagePath/internal/$folder"
$bundlePath = "$internalPath/bundle"
# installer files
cp "src/SMAPI.Installer/bin/$buildConfig/$runtime/publish/*" "$internalPath" -Recurse
rm -Recurse -Force "$internalPath/assets"
# runtime config for SMAPI
# This is identical to the one generated by the build, except that the min runtime version is
# set to 5.0.0 (instead of whatever version it was built with) and rollForward is set to latestMinor instead of
# minor.
cp "$installAssets/runtimeconfig.json" "$bundlePath/StardewModdingAPI.runtimeconfig.json"
# installer DLL config
if ($folder -eq "windows") {
cp "$installAssets/windows-exe-config.xml" "$packagePath/internal/windows/install.exe.config"
}
# bundle root files
foreach ($name in @("StardewModdingAPI", "StardewModdingAPI.dll", "StardewModdingAPI.pdb", "StardewModdingAPI.xml", "steam_appid.txt")) {
if ($name -eq "StardewModdingAPI" -and $folder -eq "windows") {
$name = "$name.exe"
}
cp "$smapiBin/$name" "$bundlePath"
}
# bundle i18n
cp -Recurse "$smapiBin/i18n" "$bundlePath/smapi-internal"
# bundle smapi-internal
foreach ($name in @("0Harmony.dll", "0Harmony.xml", "Mono.Cecil.dll", "Mono.Cecil.Mdb.dll", "Mono.Cecil.Pdb.dll", "MonoMod.Common.dll", "Newtonsoft.Json.dll", "TMXTile.dll", "SMAPI.Toolkit.dll", "SMAPI.Toolkit.pdb", "SMAPI.Toolkit.xml", "SMAPI.Toolkit.CoreInterfaces.dll", "SMAPI.Toolkit.CoreInterfaces.pdb", "SMAPI.Toolkit.CoreInterfaces.xml")) {
cp "$smapiBin/$name" "$bundlePath/smapi-internal"
}
cp "$smapiBin/SMAPI.config.json" "$bundlePath/smapi-internal/config.json"
cp "$smapiBin/SMAPI.metadata.json" "$bundlePath/smapi-internal/metadata.json"
if ($folder -eq "linux" -or $folder -eq "macOS") {
cp "$installAssets/unix-launcher.sh" "$bundlePath"
cp "$smapiBin/System.Runtime.Caching.dll" "$bundlePath/smapi-internal"
}
else {
cp "$installAssets/windows-exe-config.xml" "$bundlePath/StardewModdingAPI.exe.config"
}
# copy .NET dependencies
cp "$smapiBin/System.Configuration.ConfigurationManager.dll" "$bundlePath/smapi-internal"
cp "$smapiBin/System.Runtime.Caching.dll" "$bundlePath/smapi-internal"
cp "$smapiBin/System.Security.Permissions.dll" "$bundlePath/smapi-internal"
if ($folder -eq "windows") {
cp "$smapiBin/System.Management.dll" "$bundlePath/smapi-internal"
}
# copy bundled mods
foreach ($modName in $bundleModNames) {
$fromPath = "src/SMAPI.Mods.$modName/bin/$buildConfig/$runtime/publish"
$targetPath = "$bundlePath/Mods/$modName"
mkdir "$targetPath" > $null
cp "$fromPath/$modName.dll" "$targetPath"
cp "$fromPath/$modName.pdb" "$targetPath"
cp "$fromPath/manifest.json" "$targetPath"
if (Test-Path "$fromPath/i18n" -PathType Container) {
cp -Recurse "$fromPath/i18n" "$targetPath"
}
}
}
# DISABLED: will be handled by Linux script
# mark scripts executable
#ForEach ($path in @("install on Linux.sh", "install on macOS.command", "bundle/unix-launcher.sh")) {
# if (Test-Path "$packagePath/$path" -PathType Leaf) {
# chmod 755 "$packagePath/$path"
# }
#}
# split into main + for-dev folders
cp -Recurse "$packagePath" "$packageDevPath"
foreach ($folder in $folders) {
# disable developer mode in main package
In-Place-Regex -Path "$packagePath/internal/$folder/bundle/smapi-internal/config.json" -Search "`"DeveloperMode`": true" -Replace "`"DeveloperMode`": false"
# DISABLED: will be handled by Linux script
# convert bundle folder into final 'install.dat' files
#foreach ($path in @("$packagePath/internal/$folder", "$packageDevPath/internal/$folder"))
#{
# Compress-Archive -Path "$path/bundle/*" -CompressionLevel Optimal -DestinationPath "$path/install.zip"
# mv "$path/install.zip" "$path/install.dat"
# rm -Recurse -Force "$path/bundle"
#}
}
###########
### Create release zips
###########
# get version number
$version = $args[0]
if (!$version) {
$version = Read-Host "SMAPI release version (like '4.0.0')"
}
# rename folders
mv "$packagePath" "bin/SMAPI $version installer"
mv "$packageDevPath" "bin/SMAPI $version installer for developers"
# DISABLED: will be handled by Linux script
## package files
#Compress-Archive -Path "bin/SMAPI $version installer" -DestinationPath "bin/SMAPI $version installer.zip" -CompressionLevel Optimal
#Compress-Archive -Path "bin/SMAPI $version installer for developers" -DestinationPath "bin/SMAPI $version installer for developers.zip" -CompressionLevel Optimal
echo ""
echo "Done! See docs/technical/smapi.md to create the release zips."

View File

@ -0,0 +1,25 @@
#
#
# This is the PowerShell equivalent of ../unix/set-smapi-version.sh.
# When making changes, both scripts should be updated.
#
#
. "$PSScriptRoot\lib\in-place-regex.ps1"
# get version number
$version=$args[0]
if (!$version) {
$version = Read-Host "SMAPI release version (like '4.0.0')"
}
# move to SMAPI root
cd "$PSScriptRoot/../.."
# apply changes
In-Place-Regex -Path "build/common.targets" -Search "<Version>.+</Version>" -Replace "<Version>$version</Version>"
In-Place-Regex -Path "src/SMAPI/Constants.cs" -Search "RawApiVersion = `".+?`";" -Replace "RawApiVersion = `"$version`";"
ForEach ($modName in "ConsoleCommands","ErrorHandler","SaveBackup") {
In-Place-Regex -Path "src/SMAPI.Mods.$modName/manifest.json" -Search "`"(Version|MinimumApiVersion)`": `".+?`"" -Replace "`"`$1`": `"$version`""
}

View File

@ -7,7 +7,6 @@
* The installer now detects when the game folder contains an incompatible legacy game version. * The installer now detects when the game folder contains an incompatible legacy game version.
* Updated for the latest Stardew Valley 1.5.5 hotfix. * Updated for the latest Stardew Valley 1.5.5 hotfix.
* Updated compatibility list. * Updated compatibility list.
* **Known issue:** SMAPI no longer has a pufferchick icon on Windows. That's [a known bug in .NET](https://github.com/dotnet/runtime/issues/3828) which affects the changes needed to run SMAPI without installing .NET manually.
* For the web UI: * For the web UI:
* Fixed the JSON validator marking `.fnt` files invalid in Content Patcher files. * Fixed the JSON validator marking `.fnt` files invalid in Content Patcher files.

View File

@ -11,11 +11,12 @@ This document is about SMAPI itself; see also [mod build package](mod-package.md
* [Configuration file](#configuration-file) * [Configuration file](#configuration-file)
* [Command-line arguments](#command-line-arguments) * [Command-line arguments](#command-line-arguments)
* [Compile flags](#compile-flags) * [Compile flags](#compile-flags)
* [For SMAPI developers](#for-smapi-developers) * [Compile from source code](#compile-from-source-code)
* [Compiling from source](#compiling-from-source) * [Main project](#main-project)
* [Debugging a local build](#debugging-a-local-build) * [Custom Harmony build](#custom-harmony-build)
* [Preparing a release](#preparing-a-release) * [Prepare a release](#prepare-a-release)
* [Using a custom Harmony build](#using-a-custom-harmony-build) * [On any platform](#on-any-platform)
* [On Windows](#on-windows)
* [Release notes](#release-notes) * [Release notes](#release-notes)
## Customisation ## Customisation
@ -58,36 +59,37 @@ flag | purpose
---- | ------- ---- | -------
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/macOS. Set automatically in `common.targets`. `SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/macOS. Set automatically in `common.targets`.
## For SMAPI developers ## Compile from source code
### Compiling from source ### Main project
Using an official SMAPI release is recommended for most users, but you can compile from source Using an official SMAPI release is recommended for most users, but you can compile from source
directly if needed. There are no special steps (just open the project and compile), but SMAPI often directly if needed. Just open the project in an IDE like [Visual
uses the latest C# syntax. You may need the latest version of your IDE to compile it. Studio](https://visualstudio.microsoft.com/vs/community/) or [Rider](https://www.jetbrains.com/rider/),
and build the `SMAPI` project. The project will automatically adjust the build settings for your
current OS and Stardew Valley install path.
SMAPI uses build configuration derived from the [crossplatform mod config](https://smapi.io/package/readme)
to detect your current OS automatically and load the correct references. Compile output will be
placed in a `bin` folder at the root of the Git repository.
### Debugging a local build
Rebuilding the solution in debug mode will copy the SMAPI files into your game folder. Starting Rebuilding the solution in debug mode will copy the SMAPI files into your game folder. Starting
the `SMAPI` project with debugging from Visual Studio (on macOS or Windows) will launch SMAPI with the `SMAPI` project with debugging from Visual Studio or Rider should launch SMAPI with the
the debugger attached, so you can intercept errors and step through the code being executed. That debugger attached, so you can intercept errors and step through the code being executed.
doesn't work in MonoDevelop on Linux, unfortunately.
### Preparing a release ### Custom Harmony build
To prepare a crossplatform SMAPI release, you'll need to run the build script on Linux or macOS. SMAPI uses [a custom build of Harmony](https://github.com/Pathoschild/Harmony#readme), which is
included in the `build` folder. To use a different build, just replace `0Harmony.dll` in that
folder before compiling.
#### Initial setup ## Prepare a release
First-time setup: ### On any platform
**⚠ Ideally we'd have one set of instructions for all platforms. The instructions in this section
will produce a fully functional release for all supported platfrms, _except_ that the application
icon for SMAPI on Windows will disappear due to [.NET runtime bug
3828](https://github.com/dotnet/runtime/issues/3828). Until that's fixed, see the _[on
Windows](#on-windows)_ section below to create a build that retains the icon.**
#### First-time setup
1. On Windows only: 1. On Windows only:
1. [Install Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install). 1. [Install Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install).
2. Run `sudo apt update` in WSL to update the package list. 2. Run `sudo apt update` in WSL to update the package list.
3. The rest of the instructions below should be run in WSL. 3. The rest of the instructions below should be run in WSL.
2. Install the required software: 2. Install the required software:
1. Install the [.NET 5 SDK](https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu). 1. Install the [.NET 5 SDK](https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu).
_For Ubuntu-based systems, you can run `lsb_release -a` to get the Ubuntu version number._ _For Ubuntu-based systems, you can run `lsb_release -a` to get the Ubuntu version number._
2. [Install Steam](https://linuxconfig.org/how-to-install-steam-on-ubuntu-20-04-focal-fossa-linux). 2. [Install Steam](https://linuxconfig.org/how-to-install-steam-on-ubuntu-20-04-focal-fossa-linux).
@ -100,14 +102,12 @@ First-time setup:
ln -s "/opt/JetBrains Rider-<version>/bin/rider.sh" ln -s "/opt/JetBrains Rider-<version>/bin/rider.sh"
./rider.sh ./rider.sh
``` ```
3. Clone the SMAPI repo: 3. Clone the SMAPI repo:
```sh ```sh
git clone https://github.com/Pathoschild/SMAPI.git git clone https://github.com/Pathoschild/SMAPI.git
``` ```
To launch the game: ### Launch the game
1. Run these commands to start Steam: 1. Run these commands to start Steam:
```sh ```sh
export TERM=xterm export TERM=xterm
@ -115,8 +115,8 @@ To launch the game:
``` ```
2. Launch the game through the Steam UI. 2. Launch the game through the Steam UI.
#### Prepare the release ### Prepare the release
1. Run `build/set-smapi-version.sh` to set the SMAPI version. Make sure you use a [semantic 1. Run `build/unix/set-smapi-version.sh` to set the SMAPI version. Make sure you use a [semantic
version](https://semver.org). Recommended format: version](https://semver.org). Recommended format:
build type | format | example build type | format | example
@ -124,12 +124,45 @@ To launch the game:
dev build | `<version>-alpha.<date>` | `4.0.0-alpha.20251230` dev build | `<version>-alpha.<date>` | `4.0.0-alpha.20251230`
prerelease | `<version>-beta.<date>` | `4.0.0-beta.20251230` prerelease | `<version>-beta.<date>` | `4.0.0-beta.20251230`
release | `<version>` | `4.0.0` release | `<version>` | `4.0.0`
2. Run `build/prepare-install-package.sh` to create the release package in the root `bin` folder.
### Custom Harmony build 2. Run `build/unix/prepare-install-package.sh` to create the release package in the root `bin`
SMAPI uses [a custom build of Harmony](https://github.com/Pathoschild/Harmony#readme), which is folder.
included in the `build` folder. To use a different build, just replace `0Harmony.dll` in that
folder before compiling. ### On Windows
#### First-time setup
1. Set up Windows Subsystem for Linux (WSL):
1. [Install WSL](https://docs.microsoft.com/en-us/windows/wsl/install).
2. Run `sudo apt update` in WSL to update the package list.
3. The rest of the instructions below should be run in WSL.
2. Install the required software:
1. Install the [.NET 5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0).
2. Install [Stardew Valley](https://www.stardewvalley.net/).
3. Clone the SMAPI repo:
```sh
git clone https://github.com/Pathoschild/SMAPI.git
```
### Prepare the release
1. Run `build/windows/set-smapi-version.ps1` in PowerShell to set the SMAPI version. Make sure you
use a [semantic version](https://semver.org). Recommended format:
build type | format | example
:--------- | :----------------------- | :------
dev build | `<version>-alpha.<date>` | `4.0.0-alpha.20251230`
prerelease | `<version>-beta.<date>` | `4.0.0-beta.20251230`
release | `<version>` | `4.0.0`
2. Run `build/windows/prepare-install-package.ps1` in PowerShell to create the release package
folders in the root `bin` folder.
3. Launch WSL and run this script:
```bash
# edit to match the build created in steps 1-2
# In WSL, `/mnt/c/example` accesses `C:\example` on the Windows filesystem.
version="4.0.0"
binFolder="/mnt/e/source/_Stardew/SMAPI/bin"
build/windows/finalize-install-package.sh "$version" "$binFolder"
```
## Release notes ## Release notes
See [release notes](../release-notes.md). See [release notes](../release-notes.md).

View File

@ -28,8 +28,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{09CF91E5
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
..\build\common.targets = ..\build\common.targets ..\build\common.targets = ..\build\common.targets
..\build\find-game-folder.targets = ..\build\find-game-folder.targets ..\build\find-game-folder.targets = ..\build\find-game-folder.targets
..\build\prepare-install-package.sh = ..\build\prepare-install-package.sh
..\build\set-smapi-version.sh = ..\build\set-smapi-version.sh
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{EB35A917-67B9-4EFA-8DFC-4FB49B3949BB}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{EB35A917-67B9-4EFA-8DFC-4FB49B3949BB}"
@ -85,6 +83,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Toolkit.CoreInterface
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Web", "SMAPI.Web\SMAPI.Web.csproj", "{80EFD92F-728F-41E0-8A5B-9F6F49A91899}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Web", "SMAPI.Web\SMAPI.Web.csproj", "{80EFD92F-728F-41E0-8A5B-9F6F49A91899}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "windows", "windows", "{4D661178-38FB-43E4-AA5F-9B0406919344}"
ProjectSection(SolutionItems) = preProject
..\build\windows\finalize-install-package.sh = ..\build\windows\finalize-install-package.sh
..\build\windows\prepare-install-package.ps1 = ..\build\windows\prepare-install-package.ps1
..\build\windows\set-smapi-version.ps1 = ..\build\windows\set-smapi-version.ps1
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unix", "unix", "{CAA1488E-842B-433D-994D-1D3D0B5DD125}"
ProjectSection(SolutionItems) = preProject
..\build\unix\prepare-install-package.sh = ..\build\unix\prepare-install-package.sh
..\build\unix\set-smapi-version.sh = ..\build\unix\set-smapi-version.sh
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{3B5BF14D-F612-4C83-9EF6-E3EBFCD08766}"
ProjectSection(SolutionItems) = preProject
..\build\windows\lib\in-place-regex.ps1 = ..\build\windows\lib\in-place-regex.ps1
EndProjectSection
EndProject
Global Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution GlobalSection(SharedMSBuildProjectFiles) = preSolution
SMAPI.Internal\SMAPI.Internal.projitems*{0634ea4c-3b8f-42db-aea6-ca9e4ef6e92f}*SharedItemsImports = 5 SMAPI.Internal\SMAPI.Internal.projitems*{0634ea4c-3b8f-42db-aea6-ca9e4ef6e92f}*SharedItemsImports = 5
@ -168,6 +184,9 @@ Global
{0634EA4C-3B8F-42DB-AEA6-CA9E4EF6E92F} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5} {0634EA4C-3B8F-42DB-AEA6-CA9E4EF6E92F} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5}
{491E775B-EAD0-44D4-B6CA-F1FC3E316D33} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5} {491E775B-EAD0-44D4-B6CA-F1FC3E316D33} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5}
{CD53AD6F-97F4-4872-A212-50C2A0FD3601} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5} {CD53AD6F-97F4-4872-A212-50C2A0FD3601} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5}
{4D661178-38FB-43E4-AA5F-9B0406919344} = {09CF91E5-5BAB-4650-A200-E5EA9A633046}
{CAA1488E-842B-433D-994D-1D3D0B5DD125} = {09CF91E5-5BAB-4650-A200-E5EA9A633046}
{3B5BF14D-F612-4C83-9EF6-E3EBFCD08766} = {4D661178-38FB-43E4-AA5F-9B0406919344}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {70143042-A862-47A8-A677-7C819DDC90DC} SolutionGuid = {70143042-A862-47A8-A677-7C819DDC90DC}