From 4eb068e9495bd875446a9d11f05899455308e924 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Sun, 23 Jun 2024 05:36:45 +0800 Subject: [PATCH] feat: add windows x64 installer build with NSIS (#175) --- SourceGit.sln | 2 + build/build.windows.installer.nsi | 89 ++++++++++++++++++++++++++++++ build/build.windows.ps1 | 9 +++ build/resources/app/App.ico | Bin 0 -> 13059 bytes 4 files changed, 100 insertions(+) create mode 100644 build/build.windows.installer.nsi create mode 100644 build/resources/app/App.ico diff --git a/SourceGit.sln b/SourceGit.sln index 80921840..871174a1 100644 --- a/SourceGit.sln +++ b/SourceGit.sln @@ -10,6 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{773082AC build\build.linux.sh = build\build.linux.sh build\build.osx.command = build\build.osx.command build\build.windows.ps1 = build\build.windows.ps1 + build\build.windows.installer.nsi = build\build.windows.installer.nsi EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "resources", "resources", "{FD384607-ED99-47B7-AF31-FB245841BC92}" @@ -38,6 +39,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{ABC98884-F02 ProjectSection(SolutionItems) = preProject build\resources\app\App.icns = build\resources\app\App.icns build\resources\app\App.plist = build\resources\app\App.plist + build\resources\app\App.ico = build\resources\app\App.ico EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_common", "_common", "{04FD74B1-FBDB-496E-A48F-3D59D71FF952}" diff --git a/build/build.windows.installer.nsi b/build/build.windows.installer.nsi new file mode 100644 index 00000000..e58910cf --- /dev/null +++ b/build/build.windows.installer.nsi @@ -0,0 +1,89 @@ +; Application properties +!define PRODUCT_NAME "SourceGit" +!define PRODUCT_VERSION ${VERSION} +!define PRODUCT_PUBLISHER "sourcegit-scm" +!define PRODUCT_WEB_SITE "https://github.com/sourcegit-scm/sourcegit" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\${PRODUCT_NAME}\SourceGit.exe" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKLM" + +; Set installation and uninstallation icons and name +!define MUI_ICON "resources\app\App.ico" +!define MUI_UNICON "resources\app\App.ico" + +; Language Selection Dialog Settings +!define MUI_LANGDLL_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" +!define MUI_LANGDLL_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" +!define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language" + +; Include language files +!include "MUI2.nsh" + +; Set pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +; Set language +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_LANGUAGE "SimpChinese" +!insertmacro MUI_LANGUAGE "TradChinese" + +; Component descriptions +LangString DESC_SecDesktopShortcut ${LANG_ENGLISH} "Create a desktop shortcut." +LangString DESC_SecStartMenuShortcut ${LANG_ENGLISH} "Create a start menu shortcut." + +; Define some basic properties +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" +Outfile "sourcegit_${VERSION}.win-x64.installer.exe" +InstallDir $PROGRAMFILES64\${PRODUCT_NAME} +InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" +ShowInstDetails show +ShowUnInstDetails show +RequestExecutionLevel admin + +Function .onInit + !insertmacro MUI_LANGDLL_DISPLAY +FunctionEnd + +; Start installation section +Section "Install" + + ; Set version + WriteRegStr HKLM "Software\${PRODUCT_NAME}" "Version" ${VERSION} + + ; Copy files to installation directory + SetOutPath $INSTDIR + File /r "SourceGit\*.*" + + CreateDirectory "$SMPROGRAMS\SourceGit" + CreateShortCut "$SMPROGRAMS\SourceGit\SourceGit.lnk" "$INSTDIR\SourceGit.exe" + CreateShortCut "$DESKTOP\SourceGit.lnk" "$INSTDIR\SourceGit.exe" + + WriteUninstaller "$INSTDIR\uninst.exe" + WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\SourceGit.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" '$\"$INSTDIR\uninst.exe$\"' + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" '$\"$INSTDIR\uninst.exe$\"' + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" +SectionEnd + +; Start uninstallation section +Section "Uninstall" + + ; Delete all files and directories + RMDir /r $INSTDIR + + Delete "$DESKTOP\SourceGit.lnk" + Delete "$SMPROGRAMS\SourceGit\SourceGit.lnk" + RMDir "$SMPROGRAMS\SourceGit" + + ; Delete uninstallation information + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" + +SectionEnd diff --git a/build/build.windows.ps1 b/build/build.windows.ps1 index a218d5cd..980b5aa2 100644 --- a/build/build.windows.ps1 +++ b/build/build.windows.ps1 @@ -21,3 +21,12 @@ dotnet publish ..\src\SourceGit.csproj -c Release -r win-x64 -o SourceGit -p:Pub Remove-Item SourceGit\*.pdb -Force Compress-Archive -Path SourceGit -DestinationPath "sourcegit_$version.win-x64.zip" + +# check nsis exist +$nsisPath = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "NSIS\makensis.exe" +if (-not (Test-Path $nsisPath)) { + Write-Host "NSIS not found, please install NSIS from https://nsis.sourceforge.io/Download or run 'choco install nsis -y'" + exit 1 +} + +& $nsisPath /DVERSION=$version .\build.windows.installer.nsi diff --git a/build/resources/app/App.ico b/build/resources/app/App.ico new file mode 100644 index 0000000000000000000000000000000000000000..9f4972e50b853fc1c2c121d1a152c67310e61e84 GIT binary patch literal 13059 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