-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add python script with templates for creating msi installer with WIX
- Loading branch information
Showing
11 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
import argparse | ||
import glob | ||
import subprocess | ||
import json | ||
import shutil | ||
import os | ||
from pathlib import Path | ||
from string import Template | ||
|
||
# Dirs and Paths | ||
SCRIPT_DIR = Path(__file__).resolve().parent | ||
CFG_PATH = SCRIPT_DIR / f'installer_config.json' | ||
RESOURCE_DIR = SCRIPT_DIR / f'resources' | ||
|
||
VERSION_PATH = SCRIPT_DIR / f'../version.txt' | ||
|
||
DEFAULT_BUILD_DIR = SCRIPT_DIR / f'../build/build_msi' | ||
|
||
TEMPLATE_DIR = SCRIPT_DIR / f'templates' | ||
DEPLOYMENT_PROPERTIES_TEMPLATE_PATH = TEMPLATE_DIR / 'deployment.properties.in' | ||
|
||
WIX_TEMPLATE_PATH = TEMPLATE_DIR / f'palladio.wxs.in' | ||
WIX_REG_SEARCH_TEMPLATE_PATH = TEMPLATE_DIR / f'palladio_registry_search.in' | ||
WIX_DIRECTORY_TEMPLATE_PATH = TEMPLATE_DIR / f'palladio_directory.in' | ||
WIX_FEATURE_TEMPLATE_PATH = TEMPLATE_DIR / f'palladio_feature.in' | ||
|
||
PROJECT_NAME = 'Palladio' | ||
PLATFORM = 'win64' | ||
PACKAGE_VENDOR_ESCAPED = 'Esri R&D Center Zurich' | ||
|
||
|
||
def get_palladio_version_string(includePre=False, build_version=''): | ||
version_map = {} | ||
delimiter = '.' | ||
with open(VERSION_PATH, 'r') as version_file: | ||
version_text = version_file.read() | ||
lines = version_text.splitlines() | ||
for line in lines: | ||
key_value = line.split(' ') | ||
if len(key_value) == 2: | ||
version_map[key_value[0]] = key_value[1] | ||
version_string = version_map['PLD_VERSION_MAJOR'] + delimiter + \ | ||
version_map['PLD_VERSION_MINOR'] + \ | ||
delimiter + version_map['PLD_VERSION_PATCH'] | ||
if includePre: | ||
version_string += version_map['PLD_VERSION_PRE'] | ||
if len(build_version) > 0: | ||
version_string += '+b' + build_version | ||
return version_string | ||
|
||
|
||
def gen_installer_filename(build_version): | ||
return PROJECT_NAME + '-installer-' + get_palladio_version_string(True, build_version) + '.msi' | ||
|
||
|
||
def rel_to_os_dir(path): | ||
return Path(path).absolute() | ||
|
||
|
||
def clear_folder(path): | ||
if path.exists(): | ||
shutil.rmtree(path) | ||
os.makedirs(path) | ||
|
||
|
||
def run_wix_command(cmd, build_dir): | ||
process = subprocess.run(args=[str(i) for i in cmd], cwd=build_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, | ||
universal_newlines=True) | ||
print(process.args) | ||
print(process.stdout) | ||
print(process.stderr) | ||
|
||
|
||
def wix_harvest(houdini_version, binaries_install_dir, build_dir): | ||
output_path = build_dir / f'houdini{houdini_version}.wxs' | ||
wxs_file = output_path | ||
wxs_var = f'-dPalladioInstallComponentDir{houdini_version}={binaries_install_dir}' | ||
heat_cmd = ['heat', 'dir', binaries_install_dir, '-dr', f'PalladioInstallComponentDir{houdini_version}', '-ag', | ||
'-cg', f'PalladioInstallComponent{houdini_version}', '-sfrag', '-template fragment', '-var', f'wix.PalladioInstallComponentDir{houdini_version}', '-srd', '-sreg', '-o', output_path] | ||
|
||
run_wix_command(heat_cmd, build_dir) | ||
|
||
return wxs_file, wxs_var | ||
|
||
|
||
def wix_compile(sources, vars, build_dir): | ||
candle_cmd = ['candle', '-arch', 'x64', | ||
build_dir / 'palladio.wxs'] + sources + vars | ||
run_wix_command(candle_cmd, build_dir) | ||
|
||
objects = glob.glob(str(build_dir / '*.wixobj')) | ||
return objects | ||
|
||
|
||
def wix_link(objects, vars, build_dir, installer_filename): | ||
light_cmd = ['light', f'-dWixUILicenseRtf={SCRIPT_DIR}\\resources\\license.rtf', f'-dInstallDir=', '-ext', 'WixUIExtension', | ||
'-cultures:en-us', '-ext', 'WixUtilExtension', '-o', f'{build_dir}\\' + installer_filename] | ||
light_cmd.extend(objects) | ||
light_cmd.extend(vars) | ||
run_wix_command(light_cmd, build_dir) | ||
|
||
|
||
def create_installer(houdini_versions, binary_folders, build_dir, installer_filename): | ||
wxs_files = [] | ||
wxs_vars = [] | ||
for houdini_version_key in binary_folders: | ||
rel_path_string = binary_folders[houdini_version_key] | ||
major = houdini_versions[houdini_version_key]['major'] | ||
minor = houdini_versions[houdini_version_key]['minor'] | ||
|
||
binary_path = rel_to_os_dir(rel_path_string) | ||
|
||
print(binary_path, " ", houdini_version_key) | ||
wxs_file, wxs_var = wix_harvest( | ||
str(major) + str(minor), binary_path, build_dir) | ||
wxs_files.append(wxs_file) | ||
wxs_vars.append(wxs_var) | ||
|
||
wix_objects = wix_compile(wxs_files, wxs_vars, build_dir) | ||
wix_link(wix_objects, wxs_vars, build_dir, installer_filename) | ||
|
||
|
||
def copy_binaries(binary_folders, build_dir): | ||
clear_folder(build_dir) | ||
|
||
valid_binaries = {} | ||
for binary_folder in binary_folders: | ||
src_path = binary_folders[binary_folder] | ||
if len(src_path) == 0: | ||
continue | ||
os_src_path = rel_to_os_dir(src_path) | ||
if os_src_path.exists(): | ||
binary_path = build_dir / f'install' / Path(binary_folder) | ||
print("copy ", os_src_path, " to ", binary_path) | ||
shutil.copytree(os_src_path, binary_path) | ||
valid_binaries[binary_folder] = binary_path | ||
return valid_binaries | ||
|
||
|
||
def fill_template(src_path, token_value_dict): | ||
result = '' | ||
with open(src_path, 'r') as file: | ||
src = Template(file.read()) | ||
result = src.substitute(token_value_dict) | ||
return result | ||
|
||
|
||
def fill_template_to_file(src_path, dest_path, token_value_dict): | ||
result = fill_template(src_path, token_value_dict) | ||
with open(dest_path, 'w') as outfile: | ||
outfile.write(result) | ||
|
||
|
||
def fill_wix_template(houdini_versions, copied_binaries, build_dir): | ||
wix_reg_search = '' | ||
wix_directories = '' | ||
wix_features = '' | ||
|
||
for version in copied_binaries: | ||
version_dict = { | ||
'HOU_MAJOR': houdini_versions[version]['major'], | ||
'HOU_MINOR': houdini_versions[version]['minor'], | ||
'HOU_PATCH': houdini_versions[version]['patch'] | ||
} | ||
newline = '' | ||
if len(wix_reg_search) > 0: | ||
newline = '\n' | ||
wix_reg_search += newline + \ | ||
fill_template(WIX_REG_SEARCH_TEMPLATE_PATH, version_dict) | ||
wix_directories += newline + \ | ||
fill_template(WIX_DIRECTORY_TEMPLATE_PATH, version_dict) | ||
wix_features += newline + \ | ||
fill_template(WIX_FEATURE_TEMPLATE_PATH, version_dict) | ||
|
||
wix_properties = { | ||
'PROJECT_NAME': PROJECT_NAME, | ||
'PLD_VERSION_MMP': get_palladio_version_string(), | ||
'PACKAGE_VENDOR_ESCAPED': PACKAGE_VENDOR_ESCAPED, | ||
'RESOURCE_FOLDER': RESOURCE_DIR, | ||
'HOUDINI_REGISTRY_SEARCH': wix_reg_search, | ||
'HOUDINI_DIRECTORY': wix_directories, | ||
'PALLADIO_FOR_HOUDINI_FEATURE': wix_features | ||
} | ||
fill_template_to_file(WIX_TEMPLATE_PATH, build_dir / | ||
f'palladio.wxs', wix_properties) | ||
|
||
|
||
def fill_deployment_properties_templates(installer_filename, build_dir, build_version): | ||
deployment_properties = { | ||
'PACKAGE_NAME': PROJECT_NAME, | ||
'PLD_VERSION_BASE': get_palladio_version_string(), | ||
'PLD_VERSION': get_palladio_version_string(True, build_version), | ||
'PACKAGE_FILE_NAME': installer_filename, | ||
'PLD_PKG_OS': PLATFORM | ||
} | ||
fill_template_to_file(DEPLOYMENT_PROPERTIES_TEMPLATE_PATH, build_dir / | ||
f'deployment.properties', deployment_properties) | ||
|
||
|
||
def parse_arguments(houdini_versions): | ||
parser = argparse.ArgumentParser( | ||
description='Build unified MSI installer for the Palladio Plugin') | ||
for houdini_version in houdini_versions: | ||
h_major = houdini_versions[houdini_version]['major'] | ||
h_minor = houdini_versions[houdini_version]['minor'] | ||
parser.add_argument('-h' + h_major + h_minor, '--' + houdini_version, default='', | ||
help='path to binary location of Palladio build for ' + houdini_version) | ||
|
||
parser.add_argument('-bv', '--build_version', default='', | ||
help='build version for current Palladio build') | ||
|
||
parser.add_argument('-bd', '--build_dir', default=str(DEFAULT_BUILD_DIR), | ||
help='build directory where installer files are generated') | ||
|
||
parsed_args = vars(parser.parse_args()) | ||
binary_folders = {} | ||
for item in parsed_args: | ||
if item.__contains__('houdini'): | ||
binary_folders[item] = parsed_args[item] | ||
return binary_folders, parsed_args['build_version'], Path(parsed_args['build_dir']).resolve() | ||
|
||
|
||
def main(): | ||
with open(CFG_PATH, 'r') as config_file: | ||
installer_config = json.load(config_file) | ||
|
||
houdini_versions = installer_config['houdini_versions'] | ||
|
||
binary_folders, build_version, build_dir = parse_arguments(houdini_versions) | ||
|
||
copied_binaries = copy_binaries(binary_folders, build_dir) | ||
installer_filename = gen_installer_filename(build_version) | ||
|
||
if len(copied_binaries) == 0: | ||
print('Please provide at least one palladio binary folder, see "build.py --help" for help') | ||
return | ||
|
||
fill_deployment_properties_templates( | ||
installer_filename, build_dir, build_version) | ||
fill_wix_template(houdini_versions, copied_binaries, build_dir) | ||
|
||
create_installer(houdini_versions, copied_binaries, | ||
build_dir, installer_filename) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"houdini_versions":{ | ||
"houdini18.5": { | ||
"major": "18", | ||
"minor": "5", | ||
"patch": "759" | ||
}, | ||
"houdini19.0": { | ||
"major": "19", | ||
"minor": "0", | ||
"patch": "720" | ||
}, | ||
"houdini19.5": { | ||
"major": "19", | ||
"minor": "5", | ||
"patch": "303" | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package_name = ${PACKAGE_NAME} | ||
package_version_base = ${PLD_VERSION_BASE} | ||
package_version = ${PLD_VERSION} | ||
package_file = ${PACKAGE_FILE_NAME} | ||
package_classifier = ${PLD_PKG_OS} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?xml version="1.0"?> | ||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> | ||
<Product Name="${PROJECT_NAME}" Manufacturer="${PACKAGE_VENDOR_ESCAPED}" Version="${PLD_VERSION_MMP}" | ||
Id="*" UpgradeCode="D5336B62-F851-4D34-B6CA-0A9A3B685910" Language="1033" Codepage='1252'> | ||
|
||
<Package Platform='x64' Id='*' Keywords='Installer' Description="${PROJECT_NAME}" | ||
Manufacturer='${PACKAGE_VENDOR_ESCAPED}' InstallerVersion='200' | ||
Languages='1033' Compressed='yes' SummaryCodepage='1252' /> | ||
|
||
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" /> | ||
<Property Id='DiskPrompt' Value="${PROJECT_NAME} Installation [1]" /> | ||
|
||
${HOUDINI_REGISTRY_SEARCH} | ||
|
||
<MajorUpgrade Schedule="afterInstallInitialize" AllowSameVersionUpgrades="yes" | ||
DowngradeErrorMessage="A later version of [ProductName] is already installed.
 | ||
Please uninstall [ProductName] first if you want to downgrade to version [ProductVersion].
 | ||
Setup will now exit."/> | ||
|
||
<Property Id="ARPPRODUCTICON">ProductIcon.ico</Property> | ||
<Icon Id="ProductIcon.ico" SourceFile="${RESOURCE_FOLDER}\palladio.ico"/> | ||
<WixVariable Id="WixUIBannerBmp" Value="${RESOURCE_FOLDER}\banner.png"/> | ||
<WixVariable Id="WixUIDialogBmp" Value="${RESOURCE_FOLDER}\dialog.png"/> | ||
<PropertyRef Id="WIX_DIR_PERSONAL"/> | ||
|
||
<Directory Id='TARGETDIR' Name='SourceDir' ComponentGuidGenerationSeed="D676EF3E-B710-444A-BCCC-F11F888CD928"> | ||
<Directory Id='WIX_DIR_PERSONAL'> | ||
${HOUDINI_DIRECTORY} | ||
</Directory> | ||
</Directory> | ||
|
||
${PALLADIO_FOR_HOUDINI_FEATURE} | ||
|
||
<Property Id="WIXUI_INSTALLDIR" Value="WIX_DIR_PERSONAL" /> | ||
<UIRef Id="WixUI_FeatureTree" /> | ||
</Product> | ||
</Wix> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<Directory Id='PalladioInstallComponentDir${HOU_MAJOR}${HOU_MINOR}' Name='houdini${HOU_MAJOR}.${HOU_MINOR}' /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<Feature Id='PalladioForHoudini${HOU_MAJOR}${HOU_MINOR}' Level='0' Title="Palladio for Houdini ${HOU_MAJOR}.${HOU_MINOR}.${HOU_PATCH}" Description="Installs the Palladio Plugin for Houdini ${HOU_MAJOR}.${HOU_MINOR}.${HOU_PATCH}"> | ||
<ComponentGroupRef Id='PalladioInstallComponent${HOU_MAJOR}${HOU_MINOR}' /> | ||
<Condition Level="1">HOUDINI${HOU_MAJOR}${HOU_MINOR}INSTALLDIR</Condition> | ||
</Feature> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<Property Id="HOUDINI${HOU_MAJOR}${HOU_MINOR}INSTALLDIR"> | ||
<RegistrySearch Id="Houdini${HOU_MAJOR}${HOU_MINOR}InstallSearch" Root="HKLM" Key="SOFTWARE\Side Effects Software\Houdini" Name="${HOU_MAJOR}.${HOU_MINOR}.0.${HOU_PATCH}" Type="raw" /> | ||
</Property> |