Skip to content

Commit 953c971

Browse files
feat(installer/windows): add wix installer
1 parent 22065bf commit 953c971

File tree

6 files changed

+167
-4
lines changed

6 files changed

+167
-4
lines changed

.github/workflows/ci-windows.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ jobs:
129129
# Clean up
130130
Remove-Item -Path doxygen-setup.exe
131131
132+
- name: Setup dotnet # needed for wix
133+
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
134+
with:
135+
dotnet-version: '10.x'
136+
132137
- name: Setup python
133138
id: setup-python
134139
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
@@ -176,12 +181,19 @@ jobs:
176181
177182
# package
178183
cpack -G NSIS
184+
cpack -G WIX
179185
cpack -G ZIP
180186
181187
# move
182188
mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe
189+
mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi
183190
mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip
184191
192+
- name: Debug wix
193+
if: always()
194+
shell: msys2 {0}
195+
run: cat ./build/cpack_artifacts/_CPack_Packages/win64/WIX/wix.log || true
196+
185197
- name: Run tests
186198
id: test
187199
shell: msys2 {0}

cmake/packaging/windows_wix.cmake

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,97 @@
11
# WIX Packaging
22
# see options at: https://cmake.org/cmake/help/latest/cpack_gen/wix.html
33

4-
# TODO: Replace nsis with wix
4+
# find dotnet
5+
find_program(DOTNET_EXECUTABLE dotnet HINTS "C:/Program Files/dotnet")
6+
7+
if(NOT DOTNET_EXECUTABLE)
8+
message(WARNING "Dotnet executable not found, skipping WiX packaging.")
9+
return()
10+
endif()
11+
12+
set(CPACK_WIX_VERSION 4)
13+
set(WIX_VERSION 4.0.4)
14+
set(WIX_UI_VERSION 4.0.4) # extension versioning is independent of the WiX version
15+
set(WIX_BUILD_PARENT_DIRECTORY "${CMAKE_BINARY_DIR}/wix_packaging")
16+
set(WIX_BUILD_DIRECTORY "${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/win64/WIX")
17+
18+
# Download and install WiX tools locally in the build directory
19+
set(WIX_TOOL_PATH "${CMAKE_BINARY_DIR}/.wix")
20+
file(MAKE_DIRECTORY ${WIX_TOOL_PATH})
21+
22+
# Install WiX locally using dotnet
23+
execute_process(
24+
COMMAND ${DOTNET_EXECUTABLE} tool install --tool-path ${WIX_TOOL_PATH} wix --version ${WIX_VERSION}
25+
ERROR_VARIABLE WIX_INSTALL_OUTPUT
26+
RESULT_VARIABLE WIX_INSTALL_RESULT
27+
)
28+
29+
if(NOT WIX_INSTALL_RESULT EQUAL 0)
30+
message(FATAL_ERROR "Failed to install WiX tools locally.
31+
WiX packaging may not work correctly, error: ${WIX_INSTALL_OUTPUT}")
32+
endif()
33+
34+
# Install WiX UI Extension
35+
execute_process(
36+
COMMAND "${WIX_TOOL_PATH}/wix" extension add WixToolset.UI.wixext/${WIX_UI_VERSION}
37+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
38+
ERROR_VARIABLE WIX_UI_INSTALL_OUTPUT
39+
RESULT_VARIABLE WIX_UI_INSTALL_RESULT
40+
)
41+
42+
if(NOT WIX_UI_INSTALL_RESULT EQUAL 0)
43+
message(FATAL_ERROR "Failed to install WiX UI extension, error: ${WIX_UI_INSTALL_OUTPUT}")
44+
endif()
45+
46+
# Install WiX Util Extension
47+
execute_process(
48+
COMMAND "${WIX_TOOL_PATH}/wix" extension add WixToolset.Util.wixext/${WIX_UI_VERSION}
49+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
50+
ERROR_VARIABLE WIX_UTIL_INSTALL_OUTPUT
51+
RESULT_VARIABLE WIX_UTIL_INSTALL_RESULT
52+
)
53+
54+
if(NOT WIX_UTIL_INSTALL_RESULT EQUAL 0)
55+
message(FATAL_ERROR "Failed to install WiX Util extension, error: ${WIX_UTIL_INSTALL_OUTPUT}")
56+
endif()
57+
58+
# Set WiX-specific variables
59+
set(CPACK_WIX_ROOT "${WIX_TOOL_PATH}")
60+
set(CPACK_WIX_UPGRADE_GUID "512A3D1B-BE16-401B-A0D1-59BBA3942FB8")
61+
62+
# Installer metadata
63+
set(CPACK_WIX_HELP_LINK "https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html")
64+
set(CPACK_WIX_PRODUCT_ICON "${SUNSHINE_ICON_PATH}")
65+
set(CPACK_WIX_PRODUCT_URL "${CMAKE_PROJECT_HOMEPAGE_URL}")
66+
set(CPACK_WIX_PROGRAM_MENU_FOLDER "LizardByte")
67+
68+
set(CPACK_WIX_EXTENSIONS
69+
"WixToolset.UI.wixext"
70+
"WixToolset.Util.wixext"
71+
)
72+
73+
message(STATUS "cpack package directory: ${CPACK_PACKAGE_DIRECTORY}")
74+
75+
# copy custom wxs files to the build directory
76+
file(COPY "${CMAKE_CURRENT_LIST_DIR}/wix_resources/"
77+
DESTINATION "${WIX_BUILD_PARENT_DIRECTORY}/")
78+
79+
set(CPACK_WIX_EXTRA_SOURCES
80+
"${WIX_BUILD_PARENT_DIRECTORY}/sunshine-installer.wxs"
81+
)
82+
set(CPACK_WIX_PATCH_FILE
83+
"${WIX_BUILD_PARENT_DIRECTORY}/patch.xml"
84+
)
85+
86+
# Copy root LICENSE and rename to have .txt extension
87+
file(COPY "${CMAKE_SOURCE_DIR}/LICENSE"
88+
DESTINATION "${CMAKE_BINARY_DIR}")
89+
file(RENAME "${CMAKE_BINARY_DIR}/LICENSE" "${CMAKE_BINARY_DIR}/LICENSE.txt")
90+
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/LICENSE.txt") # cpack will covert this to an RTF if it is txt
91+
92+
# https://cmake.org/cmake/help/latest/cpack_gen/wix.html#variable:CPACK_WIX_ARCHITECTURE
93+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
94+
set(CPACK_WIX_ARCHITECTURE "arm64")
95+
else()
96+
set(CPACK_WIX_ARCHITECTURE "x64")
97+
endif()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<CPackWiXPatch>
2+
<CPackWiXFragment Id="CM_G_Core">
3+
<FeatureRef Id="RunSunshineInstallScripts"/>
4+
</CPackWiXFragment>
5+
</CPackWiXPatch>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2+
<Fragment>
3+
<StandardDirectory Id="ProgramMenuFolder">
4+
<Directory Id="ProgramMenuSubfolder" Name="LizardByte">
5+
<Component Id="ApplicationShortcut" Guid="*">
6+
<Shortcut Id="ApplicationStartMenuShortcut"
7+
Name="Sunshine"
8+
Description="Sunshine Game Stream Host"
9+
Target="[INSTALL_ROOT]sunshine.exe"
10+
Arguments="--shortcut"
11+
WorkingDirectory="INSTALL_ROOT"/>
12+
<RemoveFolder Id="CleanUpShortCut" Directory="ProgramMenuSubfolder" On="uninstall"/>
13+
<RegistryValue Root="HKCU" Key="Software\LizardByte\Sunshine" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
14+
</Component>
15+
</Directory>
16+
</StandardDirectory>
17+
18+
<CustomAction Id="CA_ResetPermissions" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]icacls.exe&quot; &quot;.&quot; /reset" Execute="deferred" Return="ignore" Impersonate="no" />
19+
<CustomAction Id="CA_UpdatePathAdd" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\update-path.bat&quot; add" Execute="deferred" Return="ignore" Impersonate="no" />
20+
<CustomAction Id="CA_UpdatePathRemove" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\update-path.bat&quot; remove" Execute="deferred" Return="ignore" Impersonate="no" />
21+
<CustomAction Id="CA_MigrateConfig" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\migrate-config.bat&quot;" Execute="deferred" Return="ignore" Impersonate="no" />
22+
<CustomAction Id="CA_FirewallAdd" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\add-firewall-rule.bat&quot;" Execute="deferred" Return="ignore" Impersonate="no" />
23+
<CustomAction Id="CA_FirewallRemove" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\delete-firewall-rule.bat&quot;" Execute="deferred" Return="ignore" Impersonate="no" />
24+
<CustomAction Id="CA_ServiceInstall" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\install-service.bat&quot;" Execute="deferred" Return="ignore" Impersonate="no" />
25+
<CustomAction Id="CA_ServiceAutostart" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\autostart-service.bat&quot;" Execute="deferred" Return="ignore" Impersonate="no" />
26+
<CustomAction Id="CA_ServiceUninstall" Directory="INSTALL_ROOT" ExeCommand="&quot;[SystemFolder]cmd.exe&quot; /c &quot;[INSTALL_ROOT]scripts\uninstall-service.bat&quot;" Execute="deferred" Return="ignore" Impersonate="no" />
27+
<CustomAction Id="CA_RestoreNvPrefs" Directory="INSTALL_ROOT" ExeCommand="&quot;[INSTALL_ROOT]sunshine.exe&quot; --restore-nvprefs-undo" Execute="deferred" Return="ignore" Impersonate="no" />
28+
29+
<InstallExecuteSequence>
30+
<Custom Action="CA_ResetPermissions" After="InstallFiles" Condition="NOT Installed" />
31+
<Custom Action="CA_UpdatePathAdd" After="CA_ResetPermissions" Condition="NOT Installed" />
32+
<Custom Action="CA_MigrateConfig" After="CA_UpdatePathAdd" Condition="NOT Installed" />
33+
<Custom Action="CA_FirewallAdd" After="CA_MigrateConfig" Condition="NOT Installed" />
34+
<Custom Action="CA_ServiceInstall" After="CA_FirewallAdd" Condition="NOT Installed" />
35+
<Custom Action="CA_ServiceAutostart" After="CA_ServiceInstall" Condition="NOT Installed" />
36+
37+
<Custom Action="CA_FirewallRemove" Before="RemoveFiles" Condition="REMOVE=&quot;ALL&quot;" />
38+
<Custom Action="CA_ServiceUninstall" Before="CA_FirewallRemove" Condition="REMOVE=&quot;ALL&quot;" />
39+
<Custom Action="CA_RestoreNvPrefs" After="CA_ServiceUninstall" Condition="REMOVE=&quot;ALL&quot;" />
40+
<Custom Action="CA_UpdatePathRemove" After="CA_RestoreNvPrefs" Condition="REMOVE=&quot;ALL&quot;" />
41+
</InstallExecuteSequence>
42+
43+
<!-- We need this in order to actually run our custom actions, but let's hide it -->
44+
<Feature Id="RunSunshineInstallScripts" Title="Run Sunshine Installation Scripts" Level="1" Display="hidden">
45+
<ComponentRef Id="ApplicationShortcut" />
46+
</Feature>
47+
</Fragment>
48+
</Wix>

cmake/prep/build_version.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ else()
5656
if(NOT GIT_DESCRIBE_ERROR_CODE)
5757
MESSAGE("Sunshine Branch: ${GIT_DESCRIBE_BRANCH}")
5858
if(NOT GIT_DESCRIBE_BRANCH STREQUAL "master")
59-
set(PROJECT_VERSION ${PROJECT_VERSION}.${GIT_DESCRIBE_VERSION})
59+
set(PROJECT_VERSION ${PROJECT_VERSION}-${GIT_DESCRIBE_VERSION})
6060
MESSAGE("Sunshine Version: ${GIT_DESCRIBE_VERSION}")
6161
endif()
6262
if(GIT_IS_DIRTY)
63-
set(PROJECT_VERSION ${PROJECT_VERSION}.dirty)
63+
set(PROJECT_VERSION ${PROJECT_VERSION}-dirty)
6464
MESSAGE("Git tree is dirty!")
6565
endif()
6666
else()

docs/building.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ dependencies=(
156156
pacman -S "${dependencies[@]}"
157157
```
158158

159+
To create a WiX installer, you also need to install [.NET](https://dotnet.microsoft.com/download).
160+
159161
### Clone
160162
Ensure [git](https://git-scm.com) is installed on your system, then clone the repository using the following command:
161163

@@ -198,9 +200,12 @@ ninja -C build
198200
```}
199201
}}
200202
@tab{Windows | @tabs{
201-
@tab{Installer | ```bash
203+
@tab{NSIS Installer | ```bash
202204
cpack -G NSIS --config ./build/CPackConfig.cmake
203205
```}
206+
@tab{WiX Installer | ```bash
207+
cpack -G WIX --config ./build/CPackConfig.cmake
208+
```}
204209
@tab{Portable | ```bash
205210
cpack -G ZIP --config ./build/CPackConfig.cmake
206211
```}

0 commit comments

Comments
 (0)