mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-14 00:07:14 +03:00
Build: Enforce win32 only at top-level, and clean up how error is raised
* Repeating the same test is just un-necessary, bad past-Ath. * Use `raise AssertionError(...)`. I'd move some of this stuff into functions, but it wouldn't actually aid readability.
This commit is contained in:
parent
9347f12723
commit
26c2bd720f
@ -22,12 +22,12 @@ if sys.version_info[0:2] != (3, 10):
|
|||||||
raise AssertionError(f'Unexpected python version {sys.version}')
|
raise AssertionError(f'Unexpected python version {sys.version}')
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
assert platform.architecture()[0] == '32bit', 'Assumes a Python built for 32bit'
|
assert platform.architecture()[0] == '32bit', 'A Python 32bit build is required'
|
||||||
import py2exe # noqa: F401 # Yes, this *is* used
|
import py2exe # noqa: F401 # Yes, this *is* used
|
||||||
dist_dir = 'dist.win32'
|
dist_dir = 'dist.win32'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
assert False, f'Unsupported platform {sys.platform}'
|
raise AssertionError(f'Unsupported platform {sys.platform}')
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
@ -76,9 +76,7 @@ PLUGINS = [
|
|||||||
'plugins/inara.py',
|
'plugins/inara.py',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Ensure this fails on non-win32
|
OPTIONS = {
|
||||||
if sys.platform == 'win32':
|
|
||||||
OPTIONS = {
|
|
||||||
'py2exe': {
|
'py2exe': {
|
||||||
'dist_dir': dist_dir,
|
'dist_dir': dist_dir,
|
||||||
'optimize': 2,
|
'optimize': 2,
|
||||||
@ -103,9 +101,9 @@ if sys.platform == 'win32':
|
|||||||
'unittest'
|
'unittest'
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DATA_FILES = [
|
DATA_FILES = [
|
||||||
('', [
|
('', [
|
||||||
'.gitversion', # Contains git short hash
|
'.gitversion', # Contains git short hash
|
||||||
'WinSparkle.dll',
|
'WinSparkle.dll',
|
||||||
@ -128,10 +126,7 @@ if sys.platform == 'win32':
|
|||||||
join('FDevIDs', 'rare_commodity.csv'),
|
join('FDevIDs', 'rare_commodity.csv'),
|
||||||
]),
|
]),
|
||||||
('plugins', PLUGINS),
|
('plugins', PLUGINS),
|
||||||
]
|
]
|
||||||
|
|
||||||
else:
|
|
||||||
raise AssertionError('Unsupported platform')
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
@ -172,50 +167,48 @@ freeze(
|
|||||||
# Build installer(s)
|
# Build installer(s)
|
||||||
###########################################################################
|
###########################################################################
|
||||||
package_filename = None
|
package_filename = None
|
||||||
# Ensure this fails on non-win32
|
template_file = pathlib.Path('wix/template.wxs')
|
||||||
if sys.platform == 'win32':
|
components_file = pathlib.Path('wix/components.wxs')
|
||||||
template_file = pathlib.Path('wix/template.wxs')
|
final_wxs_file = pathlib.Path('EDMarketConnector.wxs')
|
||||||
components_file = pathlib.Path('wix/components.wxs')
|
|
||||||
final_wxs_file = pathlib.Path('EDMarketConnector.wxs')
|
|
||||||
|
|
||||||
# Use heat.exe to generate the Component for all files inside dist.win32
|
# Use heat.exe to generate the Component for all files inside dist.win32
|
||||||
os.system(rf'"{WIXPATH}\heat.exe" dir {dist_dir}\ -ag -sfrag -srid -suid -out {components_file}')
|
os.system(rf'"{WIXPATH}\heat.exe" dir {dist_dir}\ -ag -sfrag -srid -suid -out {components_file}')
|
||||||
|
|
||||||
component_tree = etree.parse(str(components_file))
|
component_tree = etree.parse(str(components_file))
|
||||||
# 1. Change the element:
|
# 1. Change the element:
|
||||||
#
|
#
|
||||||
# <Directory Id="dist.win32" Name="dist.win32">
|
# <Directory Id="dist.win32" Name="dist.win32">
|
||||||
#
|
#
|
||||||
# to:
|
# to:
|
||||||
#
|
#
|
||||||
# <Directory Id="INSTALLDIR" Name="$(var.PRODUCTNAME)">
|
# <Directory Id="INSTALLDIR" Name="$(var.PRODUCTNAME)">
|
||||||
directory_win32 = component_tree.find('.//{*}Directory[@Id="dist.win32"][@Name="dist.win32"]')
|
directory_win32 = component_tree.find('.//{*}Directory[@Id="dist.win32"][@Name="dist.win32"]')
|
||||||
if directory_win32 is None:
|
if directory_win32 is None:
|
||||||
raise ValueError(f'{components_file}: Expected Directory with Id="dist.win32"')
|
raise ValueError(f'{components_file}: Expected Directory with Id="dist.win32"')
|
||||||
|
|
||||||
directory_win32.set('Id', 'INSTALLDIR')
|
directory_win32.set('Id', 'INSTALLDIR')
|
||||||
directory_win32.set('Name', '$(var.PRODUCTNAME)')
|
directory_win32.set('Name', '$(var.PRODUCTNAME)')
|
||||||
# 2. Change:
|
# 2. Change:
|
||||||
#
|
#
|
||||||
# <Component Id="EDMarketConnector.exe" Guid="*">
|
# <Component Id="EDMarketConnector.exe" Guid="*">
|
||||||
# <File Id="EDMarketConnector.exe" KeyPath="yes" Source="SourceDir\EDMarketConnector.exe" />
|
# <File Id="EDMarketConnector.exe" KeyPath="yes" Source="SourceDir\EDMarketConnector.exe" />
|
||||||
# </Component>
|
# </Component>
|
||||||
#
|
#
|
||||||
# to:
|
# to:
|
||||||
#
|
#
|
||||||
# <Component Id="MainExecutable" Guid="{D33BB66E-9664-4AB6-A044-3004B50A09B0}">
|
# <Component Id="MainExecutable" Guid="{D33BB66E-9664-4AB6-A044-3004B50A09B0}">
|
||||||
# <File Id="EDMarketConnector.exe" KeyPath="yes" Source="SourceDir\EDMarketConnector.exe" />
|
# <File Id="EDMarketConnector.exe" KeyPath="yes" Source="SourceDir\EDMarketConnector.exe" />
|
||||||
# <Shortcut Id="MainExeShortcut" Directory="ProgramMenuFolder" Name="$(var.PRODUCTLONGNAME)"
|
# <Shortcut Id="MainExeShortcut" Directory="ProgramMenuFolder" Name="$(var.PRODUCTLONGNAME)"
|
||||||
# Description="Downloads station data from Elite: Dangerous" WorkingDirectory="INSTALLDIR"
|
# Description="Downloads station data from Elite: Dangerous" WorkingDirectory="INSTALLDIR"
|
||||||
# Icon="EDMarketConnector.exe" IconIndex="0" Advertise="yes" />
|
# Icon="EDMarketConnector.exe" IconIndex="0" Advertise="yes" />
|
||||||
# </Component>
|
# </Component>
|
||||||
main_executable = directory_win32.find('.//{*}Component[@Id="EDMarketConnector.exe"]')
|
main_executable = directory_win32.find('.//{*}Component[@Id="EDMarketConnector.exe"]')
|
||||||
if main_executable is None:
|
if main_executable is None:
|
||||||
raise ValueError(f'{components_file}: Expected Component with Id="EDMarketConnector.exe"')
|
raise ValueError(f'{components_file}: Expected Component with Id="EDMarketConnector.exe"')
|
||||||
|
|
||||||
main_executable.set('Id', 'MainExecutable')
|
main_executable.set('Id', 'MainExecutable')
|
||||||
main_executable.set('Guid', '{D33BB66E-9664-4AB6-A044-3004B50A09B0}')
|
main_executable.set('Guid', '{D33BB66E-9664-4AB6-A044-3004B50A09B0}')
|
||||||
shortcut = etree.SubElement(
|
shortcut = etree.SubElement(
|
||||||
main_executable,
|
main_executable,
|
||||||
'Shortcut',
|
'Shortcut',
|
||||||
nsmap=main_executable.nsmap,
|
nsmap=main_executable.nsmap,
|
||||||
@ -229,22 +222,22 @@ if sys.platform == 'win32':
|
|||||||
'IconIndex': '0',
|
'IconIndex': '0',
|
||||||
'Advertise': 'yes'
|
'Advertise': 'yes'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# Now insert the appropriate parts as a child of the ProgramFilesFolder part
|
# Now insert the appropriate parts as a child of the ProgramFilesFolder part
|
||||||
# of the template.
|
# of the template.
|
||||||
template_tree = etree.parse(str(template_file))
|
template_tree = etree.parse(str(template_file))
|
||||||
program_files_folder = template_tree.find('.//{*}Directory[@Id="ProgramFilesFolder"]')
|
program_files_folder = template_tree.find('.//{*}Directory[@Id="ProgramFilesFolder"]')
|
||||||
if program_files_folder is None:
|
if program_files_folder is None:
|
||||||
raise ValueError(f'{template_file}: Expected Directory with Id="ProgramFilesFolder"')
|
raise ValueError(f'{template_file}: Expected Directory with Id="ProgramFilesFolder"')
|
||||||
|
|
||||||
program_files_folder.insert(0, directory_win32)
|
program_files_folder.insert(0, directory_win32)
|
||||||
# Append the Feature/ComponentRef listing to match
|
# Append the Feature/ComponentRef listing to match
|
||||||
feature = template_tree.find('.//{*}Feature[@Id="Complete"][@Level="1"]')
|
feature = template_tree.find('.//{*}Feature[@Id="Complete"][@Level="1"]')
|
||||||
if feature is None:
|
if feature is None:
|
||||||
raise ValueError(f'{template_file}: Expected Feature element with Id="Complete" Level="1"')
|
raise ValueError(f'{template_file}: Expected Feature element with Id="Complete" Level="1"')
|
||||||
|
|
||||||
# This isn't part of the components
|
# This isn't part of the components
|
||||||
feature.append(
|
feature.append(
|
||||||
etree.Element(
|
etree.Element(
|
||||||
'ComponentRef',
|
'ComponentRef',
|
||||||
attrib={
|
attrib={
|
||||||
@ -252,8 +245,8 @@ if sys.platform == 'win32':
|
|||||||
},
|
},
|
||||||
nsmap=directory_win32.nsmap
|
nsmap=directory_win32.nsmap
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for c in directory_win32.findall('.//{*}Component'):
|
for c in directory_win32.findall('.//{*}Component'):
|
||||||
feature.append(
|
feature.append(
|
||||||
etree.Element(
|
etree.Element(
|
||||||
'ComponentRef',
|
'ComponentRef',
|
||||||
@ -264,35 +257,35 @@ if sys.platform == 'win32':
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Insert what we now have into the template and write it out
|
# Insert what we now have into the template and write it out
|
||||||
template_tree.write(
|
template_tree.write(
|
||||||
str(final_wxs_file), encoding='utf-8',
|
str(final_wxs_file), encoding='utf-8',
|
||||||
pretty_print=True,
|
pretty_print=True,
|
||||||
xml_declaration=True
|
xml_declaration=True
|
||||||
)
|
)
|
||||||
|
|
||||||
os.system(rf'"{WIXPATH}\candle.exe" {appname}.wxs')
|
os.system(rf'"{WIXPATH}\candle.exe" {appname}.wxs')
|
||||||
|
|
||||||
if not exists(f'{appname}.wixobj'):
|
if not exists(f'{appname}.wixobj'):
|
||||||
raise AssertionError(f'No {appname}.wixobj: candle.exe failed?')
|
raise AssertionError(f'No {appname}.wixobj: candle.exe failed?')
|
||||||
|
|
||||||
package_filename = f'{appname}_win_{appversion_nobuild()}.msi'
|
package_filename = f'{appname}_win_{appversion_nobuild()}.msi'
|
||||||
os.system(rf'"{WIXPATH}\light.exe" -b {dist_dir}\ -sacl -spdb -sw1076 {appname}.wixobj -out {package_filename}')
|
os.system(rf'"{WIXPATH}\light.exe" -b {dist_dir}\ -sacl -spdb -sw1076 {appname}.wixobj -out {package_filename}')
|
||||||
|
|
||||||
if not exists(package_filename):
|
if not exists(package_filename):
|
||||||
raise AssertionError(f'light.exe failed, no {package_filename}')
|
raise AssertionError(f'light.exe failed, no {package_filename}')
|
||||||
|
|
||||||
# Seriously, this is how you make Windows Installer use the user's display language for its dialogs. What a crock.
|
# Seriously, this is how you make Windows Installer use the user's display language for its dialogs. What a crock.
|
||||||
# http://www.geektieguy.com/2010/03/13/create-a-multi-lingual-multi-language-msi-using-wix-and-custom-build-scripts
|
# http://www.geektieguy.com/2010/03/13/create-a-multi-lingual-multi-language-msi-using-wix-and-custom-build-scripts
|
||||||
lcids = [
|
lcids = [
|
||||||
int(x) for x in re.search( # type: ignore
|
int(x) for x in re.search( # type: ignore
|
||||||
r'Languages\s*=\s*"(.+?)"',
|
r'Languages\s*=\s*"(.+?)"',
|
||||||
open(f'{appname}.wxs').read()
|
open(f'{appname}.wxs').read()
|
||||||
).group(1).split(',')
|
).group(1).split(',')
|
||||||
]
|
]
|
||||||
assert lcids[0] == 1033, f'Default language is {lcids[0]}, should be 1033 (en_US)'
|
assert lcids[0] == 1033, f'Default language is {lcids[0]}, should be 1033 (en_US)'
|
||||||
shutil.copyfile(package_filename, join(gettempdir(), f'{appname}_1033.msi'))
|
shutil.copyfile(package_filename, join(gettempdir(), f'{appname}_1033.msi'))
|
||||||
for lcid in lcids[1:]:
|
for lcid in lcids[1:]:
|
||||||
shutil.copyfile(
|
shutil.copyfile(
|
||||||
join(gettempdir(), f'{appname}_1033.msi'),
|
join(gettempdir(), f'{appname}_1033.msi'),
|
||||||
join(gettempdir(), f'{appname}_{lcid}.msi')
|
join(gettempdir(), f'{appname}_{lcid}.msi')
|
||||||
@ -301,7 +294,4 @@ if sys.platform == 'win32':
|
|||||||
os.system(rf'cscript /nologo "{SDKPATH}\WiLangId.vbs" {gettempdir()}\{appname}_{lcid}.msi Product {lcid}')
|
os.system(rf'cscript /nologo "{SDKPATH}\WiLangId.vbs" {gettempdir()}\{appname}_{lcid}.msi Product {lcid}')
|
||||||
os.system(rf'"{SDKPATH}\MsiTran.Exe" -g {gettempdir()}\{appname}_1033.msi {gettempdir()}\{appname}_{lcid}.msi {gettempdir()}\{lcid}.mst') # noqa: E501 # Not going to get shorter
|
os.system(rf'"{SDKPATH}\MsiTran.Exe" -g {gettempdir()}\{appname}_1033.msi {gettempdir()}\{appname}_{lcid}.msi {gettempdir()}\{lcid}.mst') # noqa: E501 # Not going to get shorter
|
||||||
os.system(rf'cscript /nologo "{SDKPATH}\WiSubStg.vbs" {package_filename} {gettempdir()}\{lcid}.mst {lcid}')
|
os.system(rf'cscript /nologo "{SDKPATH}\WiSubStg.vbs" {package_filename} {gettempdir()}\{lcid}.mst {lcid}')
|
||||||
|
|
||||||
else:
|
|
||||||
raise AssertionError('Unsupported platform')
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
Loading…
x
Reference in New Issue
Block a user