Skip to content

Commit 8fb7910

Browse files
committed
Use WiX for creating msi
1 parent 0eaa95c commit 8fb7910

2 files changed

Lines changed: 54 additions & 26 deletions

File tree

.github/workflows/build.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,21 @@ 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: Install WiX Toolset
50+
if: ${{ matrix.platform != 'windows-latest' }}
51+
uses: wix-toolset/action-wix@v2
52+
4753
- name: ccache
4854
uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 # v1.2
4955
if: ${{ matrix.platform != 'windows-latest' }}

script/package.py

Lines changed: 48 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,53 @@ 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+
candle = shutil.which("candle.exe")
103+
light = shutil.which("light.exe")
104+
if not candle or not light:
105+
print(
106+
"Error: WiX Toolset v4 is required but not found.\n"
107+
"Please install it from https://wixtoolset.org/releases/\n"
108+
"and ensure 'candle.exe' and 'light.exe' are in your PATH."
109+
)
110+
sys.exit(1)
111+
112+
113+
def generate_wix_xml(build_dir: Path, output_wxs: Path) -> None:
114+
"""Generate a minimal WiX v4 XML including all files in build_dir."""
115+
wix = ET.Element("Wix", xmlns="http://wixtoolset.org/schemas/v4/wxs")
116+
package = ET.SubElement(
117+
wix,
118+
"Package",
119+
Name=PACKAGE_NAME,
120+
Manufacturer=MAINTAINER,
121+
Version=__version__,
122+
UpgradeCode=str(uuid.uuid4()),
123+
Description=DESCRIPTION,
124+
)
125+
126+
ET.SubElement(package, "Files", Include=str(build_dir / "**"))
127+
128+
tree = ET.ElementTree(wix)
129+
tree.write(output_wxs, encoding="utf-8", xml_declaration=True)
130+
131+
98132
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)
133+
"""Package the build directory into a .msi installer for Windows using WiX v4."""
134+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
135+
wix_file = OUTPUT_DIR / f"{PACKAGE_NAME}.wxs"
136+
msi_file = OUTPUT_DIR / f"{PACKAGE_NAME}_{__version__}.msi"
137+
138+
generate_wix_xml(BUILD_DIR, wix_file)
139+
140+
check_wix_installed()
141+
142+
run_command(["candle.exe", str(wix_file)])
143+
wixobj_file = wix_file.with_suffix(".wixobj")
144+
run_command(["light.exe", str(wixobj_file), "-o", str(msi_file)])
145+
146+
print(f"MSI generated at {msi_file}")
125147

126148

127149
def main() -> None:

0 commit comments

Comments
 (0)