Skip to content

Commit 75762e7

Browse files
committed
Use WiX for creating msi
1 parent 0eaa95c commit 75762e7

2 files changed

Lines changed: 73 additions & 26 deletions

File tree

.github/workflows/build.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,27 @@ jobs:
3535
python-version: '3.13'
3636

3737
- name: Set up Ruby
38+
if: ${{ matrix.platform != 'windows-latest' }}
3839
uses: ruby/setup-ruby@v1
3940
with:
4041
ruby-version: 3.2 # or any version you need
4142

4243
- name: Install fpm
44+
if: ${{ matrix.platform != 'windows-latest' }}
4345
run: |
4446
gem install --no-document fpm
4547
fpm --version
4648
49+
- name: Add msbuild to PATH
50+
if: ${{ matrix.platform == 'windows-latest' }}
51+
uses: microsoft/setup-msbuild@v2
52+
- name: Install WiX
53+
if: ${{ matrix.platform == 'windows-latest' }}
54+
run: |
55+
dotnet tool install --global wix --version 6.0.2
56+
echo "$env:USERPROFILE\.dotnet\tools" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
57+
wix --version
58+
4759
- name: ccache
4860
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 # v1.2
4961
if: ${{ matrix.platform != 'windows-latest' }}

script/package.py

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import shutil
44
import subprocess
55
import sys
6+
import uuid
7+
import xml.etree.ElementTree as ET
68
from pathlib import Path
79

810
from dfetch import __version__
@@ -95,33 +97,66 @@ def package_macos() -> None:
9597
run_command(cmd)
9698

9799

100+
def check_wix_installed():
101+
"""Check if WiX Toolset v4 is installed (candle.exe & light.exe)."""
102+
wix = shutil.which("wix.exe")
103+
if not wix:
104+
print(
105+
"Error: WiX Toolset v4 is required but not found.\n"
106+
"Please install it from https://wixtoolset.org/releases/\n"
107+
"and ensure 'wig.exe' is in your PATH."
108+
)
109+
sys.exit(1)
110+
111+
112+
def generate_wix_xml(build_dir: Path, output_wxs: Path) -> None:
113+
"""Generate a minimal WiX v4 XML including all files in build_dir."""
114+
wix = ET.Element("Wix", xmlns="http://wixtoolset.org/schemas/v4/wxs")
115+
package = ET.SubElement(
116+
wix,
117+
"Package",
118+
Name=PACKAGE_NAME,
119+
Manufacturer=MAINTAINER,
120+
Version=__version__,
121+
UpgradeCode=str(uuid.uuid4()),
122+
)
123+
124+
ET.SubElement(package, "Files", Include=str(build_dir / "**"))
125+
126+
ET.SubElement(package, "Property", Id="ARPCOMMENTS", Value=DESCRIPTION)
127+
128+
tree = ET.ElementTree(wix)
129+
tree.write(output_wxs, encoding="utf-8", xml_declaration=True)
130+
131+
132+
def generate_wix_proj(output_proj: Path, wix_file: Path) -> None:
133+
"""Generate a minimal WiX SDK project referencing the .wxs file."""
134+
project = ET.Element("Project", Sdk="WixToolset.Sdk/6.0.2")
135+
136+
item_group = ET.SubElement(project, "ItemGroup")
137+
ET.SubElement(item_group, "Wix", Include=str(wix_file))
138+
139+
tree = ET.ElementTree(project)
140+
tree.write(output_proj, encoding="utf-8", xml_declaration=True)
141+
142+
98143
def package_windows() -> None:
99-
"""Package the build directory into a .msi installer for Windows."""
100-
cmd = [
101-
"fpm",
102-
"-s",
103-
"dir",
104-
"-t",
105-
"msi",
106-
"-n",
107-
PACKAGE_NAME,
108-
"-v",
109-
__version__,
110-
"-C",
111-
str(BUILD_DIR),
112-
"--description",
113-
DESCRIPTION,
114-
"--maintainer",
115-
MAINTAINER,
116-
"--url",
117-
URL,
118-
"--license",
119-
LICENSE,
120-
"-p",
121-
f"{OUTPUT_DIR}/{PACKAGE_NAME}_{__version__}.msi",
122-
".",
123-
]
124-
run_command(cmd)
144+
"""Package the build directory into a .msi installer for Windows using WiX v4."""
145+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
146+
wix_file = OUTPUT_DIR / f"{PACKAGE_NAME}.wxs"
147+
wix_proj = OUTPUT_DIR / f"{PACKAGE_NAME}.wixproj"
148+
msi_file = OUTPUT_DIR / f"{PACKAGE_NAME}_{__version__}.msi"
149+
150+
generate_wix_xml(BUILD_DIR, wix_file)
151+
generate_wix_proj(wix_proj, wix_file)
152+
153+
check_wix_installed()
154+
155+
run_command(
156+
["dotnet", "build", str(wix_proj), "-c", "Release", "-o", str(OUTPUT_DIR)]
157+
)
158+
159+
print(f"MSI generated at {msi_file}")
125160

126161

127162
def main() -> None:

0 commit comments

Comments
 (0)