From cbd55566caaf321009b1254bbf45588eeac38e10 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sun, 14 Apr 2024 20:00:46 +0000 Subject: [PATCH] Fix #894: Upgrade WiX from v3.14 to v4.0.5 This commit upgrades WiX, which we rely on to build Mozc's installer from WiX v3.14 to WiX v4.0.5 [1]. Unlike WiX v3.14, which we checked out as an xcopy deployment under src/third_party/wix with our in-house script update_deps.py, WiX v4 and later will be installed from NuGet repository with 'dotnet' command [2]. On top of that we use local installation mode so that a specified version of WiX can be used in our repository in a side-by-side manner rather than asking developers to install WiX globally. The WiX version is pined in dotnet-tools.json in the repository root [3]. You can run the following command dotnet tool restore from any directory in the repository so that the specified version of WiX can become available, no matter what version of WiX is globally installed in the system. To actually run locally installed version of WiX, you can run dotnet tool run wix from any directory in the repository. .wxs file were also converted as follows [4] dotnet tool run wix convert then manually cleaned up a bit. There must be no user observable behavior change in Mozc64.msi. I have actually confirmed it by manually checking InstallExecuteSequence table in Mozc64.msi by using Orca [5]. #codehealth [1]: https://github.com/wixtoolset/wix/releases/tag/v4.0.5 [2]: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet [3]: https://learn.microsoft.com/en-us/dotnet/core/tools/local-tools-how-to-use [4]: https://wixtoolset.org/docs/fourthree/ [5]: https://learn.microsoft.com/en-us/windows/win32/msi/orca-exe PiperOrigin-RevId: 624751431 --- docs/build_mozc_in_windows.md | 3 +- dotnet-tools.json | 12 + src/build_mozc.py | 15 +- src/build_tools/update_deps.py | 94 ++--- src/win32/installer/installer.gyp | 77 ++--- src/win32/installer/installer_64bit.wxs | 365 ++++++++++---------- src/win32/installer/installer_oss_64bit.wxs | 317 +++++++++-------- 7 files changed, 408 insertions(+), 475 deletions(-) create mode 100644 dotnet-tools.json diff --git a/docs/build_mozc_in_windows.md b/docs/build_mozc_in_windows.md index c7cd5d7d3..e8f791cc7 100644 --- a/docs/build_mozc_in_windows.md +++ b/docs/build_mozc_in_windows.md @@ -42,6 +42,7 @@ Building Mozc on Windows requires the following software. * Python 3.9 or later with the following pip modules. * `six` * `requests` + * `.NET 6` or later (for `dotnet` command). ### Install pip modules @@ -68,7 +69,7 @@ In this step, additional build dependencies will be downloaded. * [Ninja 1.11.0](https://github.com/ninja-build/ninja/releases/download/v1.11.0/ninja-win.zip) * [Qt 6.7.0](https://download.qt.io/archive/qt/6.7/6.7.0/submodules/qtbase-everywhere-src-6.7.0.tar.xz) - * [WiX 3.14](https://github.com/wixtoolset/wix3/releases/download/wix314rtm/wix314-binaries.zip) + * [.NET tools](../dotnet-tools.json) * [git submodules](../.gitmodules) You can skip this step if you would like to manually download these libraries. diff --git a/dotnet-tools.json b/dotnet-tools.json new file mode 100644 index 000000000..591ec9989 --- /dev/null +++ b/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "wix": { + "version": "4.0.5", + "commands": [ + "wix" + ] + } + } +} diff --git a/src/build_mozc.py b/src/build_mozc.py index 85fc5298e..743940851 100755 --- a/src/build_mozc.py +++ b/src/build_mozc.py @@ -194,15 +194,6 @@ def AddTargetPlatformOption(parser): 'should be done.')) -def GetDefaultWixPath(): - """Returns the default Wix directory..""" - possible_wix_path = pathlib.Path(ABS_SCRIPT_DIR).joinpath( - 'third_party', 'wix') - if possible_wix_path.exists(): - return possible_wix_path - return '' - - def GetDefaultQtPath(): """Returns the default Qt directory..""" qtdir_env = os.getenv('QTDIR', None) @@ -261,9 +252,6 @@ def ParseGypOptions(args): parser.add_option('--msvs_version', dest='msvs_version', default='2022', help='Version of the Visual Studio.') - parser.add_option('--wix_dir', dest='wix_dir', - default=GetDefaultWixPath(), - help='A path to the binary directory of wix.') if IsWindows() or IsMac(): parser.add_option('--qtdir', dest='qtdir', @@ -497,9 +485,8 @@ def GypMain(options, unused_args): gyp_options.extend(['-D', 'qt_dir=' + (qt_dir or '')]) gyp_options.extend(['-D', 'qt_ver=' + str(qt_ver or '')]) - if target_platform == 'Windows' and options.wix_dir: + if target_platform == 'Windows': gyp_options.extend(['-D', 'use_wix=YES']) - gyp_options.extend(['-D', 'wix_dir="%s"' % options.wix_dir]) else: gyp_options.extend(['-D', 'use_wix=NO']) diff --git a/src/build_tools/update_deps.py b/src/build_tools/update_deps.py index 1e7d7906f..db93e3181 100644 --- a/src/build_tools/update_deps.py +++ b/src/build_tools/update_deps.py @@ -86,12 +86,6 @@ def __hash__(self): sha256='11b2e29e2e52fb0e3b453ea13bbe51a10fdff36e1c192d8868c5a40233b8b254', ) -WIX = ArchiveInfo( - url='https://github.com/wixtoolset/wix3/releases/download/wix314rtm/wix314-binaries.zip', - size=41282726, - sha256='13f067f38969faf163d93a804b48ea0576790a202c8f10291f2000f0e356e934', -) - NINJA_MAC = ArchiveInfo( url='https://github.com/ninja-build/ninja/releases/download/v1.11.0/ninja-mac.zip', size=277298, @@ -232,59 +226,6 @@ def __exit__(self, *exc): self.cleaner.cleanup() -def wix_extract_filter( - members: Iterator[zipfile.ZipInfo], -) -> Iterator[zipfile.ZipInfo]: - """Custom extract filter for the WiX Zip archive. - - This custom filter can be used to adjust directory structure and drop - unnecessary files/directories to save disk space. - - Args: - members: an iterator of ZipInfo from the Zip archive. - - Yields: - an iterator of ZipInfo to be extracted. - """ - with ProgressPrinter() as printer: - for info in members: - paths = info.filename.split('/') - if '..' in paths: - continue - if len(paths) >= 2: - printer.print_line('skipping ' + info.filename) - continue - else: - printer.print_line('extracting ' + info.filename) - yield info - - -def extract_wix(dryrun: bool = False) -> None: - """Extract WiX archive. - - Args: - dryrun: True if this is a dry-run. - """ - dest = ABS_THIRD_PARTY_DIR.joinpath('wix').absolute() - src = CACHE_DIR.joinpath(WIX.filename) - - if dryrun: - if dest.exists(): - print(f"dryrun: shutil.rmtree(r'{dest}')") - print(f'dryrun: Extracting {src}') - return - - def filename(members: Iterator[zipfile.ZipInfo]): - if dest.exists(): - shutil.rmtree(dest) - for info in members: - yield info.filename - with zipfile.ZipFile(src) as z: - z.extractall( - path=dest, members=filename(wix_extract_filter(z.infolist())) - ) - - def extract_ninja(dryrun: bool = False) -> None: """Extract ninja-win archive. @@ -339,6 +280,35 @@ def update_submodules(dryrun: bool = False) -> None: subprocess.run(command, shell=True, check=True) +def exec_command(args: list[str], cwd: os.PathLike) -> None: + """Runs the given command then returns the output. + + Args: + args: The command to be executed. + + Raises: + ChildProcessError: When the given command cannot be executed. + """ + process = subprocess.Popen(args, stdout=subprocess.PIPE, shell=False, cwd=cwd) + _, _ = process.communicate() + exitcode = process.wait() + if exitcode != 0: + raise ChildProcessError(f'Failed to execute {args}') + + +def restore_dotnet_tools(dryrun: bool = False) -> None: + """Run 'dotnet tool restore'. + + Args: + dryrun: true to perform dryrun. + """ + args = ['dotnet', 'tool', 'restore'] + if dryrun: + print(f'dryrun: exec_command({args}, cwd={ABS_MOZC_SRC_DIR})') + else: + exec_command(args, cwd=ABS_MOZC_SRC_DIR) + + def main(): parser = argparse.ArgumentParser() parser.add_argument('--dryrun', action='store_true', default=False) @@ -358,8 +328,6 @@ def main(): archives.append(NINJA_MAC) elif is_windows(): archives.append(NINJA_WIN) - if (not args.nowix) and is_windows(): - archives.append(WIX) for archive in archives: download(archive, args.dryrun) @@ -367,8 +335,8 @@ def main(): if args.cache_only: return - if WIX in archives: - extract_wix(args.dryrun) + if (not args.nowix) and is_windows(): + restore_dotnet_tools(args.dryrun) if (NINJA_WIN in archives) or (NINJA_MAC in archives): extract_ninja(args.dryrun) diff --git a/src/win32/installer/installer.gyp b/src/win32/installer/installer.gyp index 137a26adf..612c6888c 100644 --- a/src/win32/installer/installer.gyp +++ b/src/win32/installer/installer.gyp @@ -110,12 +110,11 @@ 'type': 'none', 'variables': { 'wxs_file': '<(wxs_64bit_file)', - 'wixobj_file': '<(mozc_64bit_wixobj)', 'msi_file': '<(mozc_64bit_msi)', }, 'actions': [ { - 'action_name': 'candle', + 'action_name': 'generate_msi', 'conditions': [ ['channel_dev==1', { 'variables': { @@ -131,65 +130,47 @@ 'icon_path': '<(mozc_content_dir)/images/win/product_icon.ico', 'document_dir': '<(mozc_content_dir)/installer', }, - 'inputs': [ - '<(wxs_file)', - ], - 'outputs': [ - '<(wixobj_file)', - ], - 'action': [ - '<(wix_dir)/candle.exe', - '-nologo', - '-dMozcVersion=<(version)', - '-dUpgradeCode=<(upgrade_code)', - '-dOmahaGuid=<(omaha_guid)', - '-dOmahaClientKey=<(omaha_client_key)', - '-dOmahaClientStateKey=<(omaha_clientstate_key)', - '-dOmahaChannelType=<(omaha_channel_type)', - '-dVSConfigurationName=<(CONFIGURATION_NAME)', - '-dReleaseRedistCrt32Dir=<(release_redist_32bit_crt_dir)', - '-dReleaseRedistCrt64Dir=<(release_redist_64bit_crt_dir)', - '-dAddRemoveProgramIconPath=<(icon_path)', - '-dMozcTIP32Path=<(mozc_tip32_path)', - '-dMozcTIP64Path=<(mozc_tip64_path)', - '-dMozcBroker64Path=<(mozc_broker64_path)', - '-dMozcServer64Path=<(mozc_server64_path)', - '-dMozcCacheService64Path=<(mozc_cache_service64_path)', - '-dMozcRenderer64Path=<(mozc_renderer64_path)', - '-dMozcToolPath=<(mozc_tool_path)', - '-dCustomActions64Path=<(mozc_ca64_path)', - '-dDocumentsDir=<(document_dir)', - '-dQtDir=<(qt_dir)', - '-dQtVer=<(qt_ver)', - '-o', '<@(_outputs)', - # We do not use '<@(_inputs)' here because it contains some - # input files just for peoper rebiuld condition. - '<(wxs_file)', - ], - 'message': 'candle is generating <@(_outputs)', - }, - { - 'action_name': 'generate_msi', 'inputs': [ # ninja.exe will invoke this action if any file listed here is # newer than files in 'outputs'. - '<(wixobj_file)', + '<(wxs_file)', '<@(mozc_64bit_installer_inputs)', ], 'outputs': [ '<(msi_file)', ], 'action': [ - '<(wix_dir)/light.exe', + 'dotnet', 'tool', 'run', 'wix', + 'build', '-nologo', - # Suppress the validation to address the LGHT0217 error. - '-sval', - '-o', '<@(_outputs)', + '-arch', 'x64', + '-define', 'MozcVersion=<(version)', + '-define', 'UpgradeCode=<(upgrade_code)', + '-define', 'OmahaGuid=<(omaha_guid)', + '-define', 'OmahaClientKey=<(omaha_client_key)', + '-define', 'OmahaClientStateKey=<(omaha_clientstate_key)', + '-define', 'OmahaChannelType=<(omaha_channel_type)', + '-define', 'VSConfigurationName=<(CONFIGURATION_NAME)', + '-define', 'ReleaseRedistCrt32Dir=<(release_redist_32bit_crt_dir)', + '-define', 'ReleaseRedistCrt64Dir=<(release_redist_64bit_crt_dir)', + '-define', 'AddRemoveProgramIconPath=<(icon_path)', + '-define', 'MozcTIP32Path=<(mozc_tip32_path)', + '-define', 'MozcTIP64Path=<(mozc_tip64_path)', + '-define', 'MozcBroker64Path=<(mozc_broker64_path)', + '-define', 'MozcServer64Path=<(mozc_server64_path)', + '-define', 'MozcCacheService64Path=<(mozc_cache_service64_path)', + '-define', 'MozcRenderer64Path=<(mozc_renderer64_path)', + '-define', 'MozcToolPath=<(mozc_tool_path)', + '-define', 'CustomActions64Path=<(mozc_ca64_path)', + '-define', 'DocumentsDir=<(document_dir)', + '-define', 'QtDir=<(qt_dir)', + '-define', 'QtVer=<(qt_ver)', + '-out', '<@(_outputs)', # We do not use '<@(_inputs)' here because it contains some # input files just for peoper rebiuld condition. - '<(wixobj_file)', + '-src', '<(wxs_file)', ], - 'message': 'light is generating <@(_outputs)', + 'message': 'WiX is generating <@(_outputs)', }, ], }, diff --git a/src/win32/installer/installer_64bit.wxs b/src/win32/installer/installer_64bit.wxs index 9d396657b..ee9969839 100644 --- a/src/win32/installer/installer_64bit.wxs +++ b/src/win32/installer/installer_64bit.wxs @@ -1,4 +1,3 @@ - - - - + + - VersionNT >= 603 + - Privileged + - - - @@ -87,10 +82,10 @@ - + - (PREVIOUSCHANNELNAME="external-dev64") OR (PREVIOUSCHANNELNAME="internal-dev64") OR (PREVIOUSCHANNELNAME="external-dev-universal") OR (PREVIOUSCHANNELNAME="internal-dev-universal") OR (REMOVE="ALL") + - (REMOVE="ALL") AND UPGRADINGPRODUCTCODE AND (VersionNT64) - (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (VersionNT64) - (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (UILevel >= 3) + + + - (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) - NEWERVERSIONDETECTED + + - (NOT (REMOVE="ALL")) - (NOT (REMOVE="ALL")) + + - (NOT (REMOVE="ALL")) AND (VersionNT64) AND (NOT UPGRADING) - (NOT (REMOVE="ALL")) AND (VersionNT64) - (NOT (REMOVE="ALL")) - (NOT (REMOVE="ALL")) AND (NOT UPGRADING) - (NOT (REMOVE="ALL")) AND (NOT UPGRADING) + + + + + - (REMOVE="ALL") + - - - - - - - - - - - - - + The servie name specified in "Name" needs to be the same to + |mozc::kMozcCacheServiceName| defined in base/const.h. + TODO(yukawa): Share these parameters. http://b/2357270 + --> + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - + + - - + + - - + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - (NOT UPGRADING) - - + + + + + - - - - - + + + - + + + + + diff --git a/src/win32/installer/installer_oss_64bit.wxs b/src/win32/installer/installer_oss_64bit.wxs index a24ec0034..fd36905b2 100644 --- a/src/win32/installer/installer_oss_64bit.wxs +++ b/src/win32/installer/installer_oss_64bit.wxs @@ -38,7 +38,7 @@ - + - - - + + - VersionNT >= 603 + - Privileged + - - - @@ -86,7 +82,7 @@ - 新しいバージョンの Mozc が既にインストールされています。 + @@ -120,40 +116,40 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - (NOT (REMOVE="ALL")) AND (NOT UPGRADING) + - (NOT (REMOVE="ALL")) + - (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) + - (REMOVE="ALL") AND UPGRADINGPRODUCTCODE AND (VersionNT64) - (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) AND (VersionNT64) + + - (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE) - NEWERVERSIONDETECTED + + - (NOT (REMOVE="ALL")) - (NOT (REMOVE="ALL")) + + - (NOT (REMOVE="ALL")) AND (VersionNT64) AND (NOT UPGRADING) - (NOT (REMOVE="ALL")) AND (VersionNT64) - (NOT (REMOVE="ALL")) - (NOT (REMOVE="ALL")) AND (NOT UPGRADING) - (NOT (REMOVE="ALL")) AND (NOT UPGRADING) + + + + + - (REMOVE="ALL") + - - - - - - - - - - - - + The servie name specified in "Name" needs to be the same to + |mozc::kMozcCacheServiceName| defined in base/const.h. + TODO(yukawa): Share these parameters. http://b/2357270 + --> + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - + + - - + + - - + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + - - - - - - - + + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - + + + + + - + + + + +