| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python2.4 | |
| 2 # | |
| 3 # Copyright 2009-2010 Google Inc. | |
| 4 # | |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); | |
| 6 # you may not use this file except in compliance with the License. | |
| 7 # You may obtain a copy of the License at | |
| 8 # | |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 # | |
| 11 # Unless required by applicable law or agreed to in writing, software | |
| 12 # distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 # See the License for the specific language governing permissions and | |
| 15 # limitations under the License. | |
| 16 # ======================================================================== | |
| 17 | |
| 18 """Build an installer for use in enterprise situations. | |
| 19 | |
| 20 This module contains the functionality required to build enterprise | |
| 21 installers (MSIs) for Omaha's various customers. | |
| 22 | |
| 23 The supplied wxs templates need to have an XML extension because SCons | |
| 24 tries to apply WiX building rules to any input file with the .wxs suffix. | |
| 25 | |
| 26 BuildGoogleUpdateFragment(): Build an update fragment into a .wixobj. | |
| 27 GenerateNameBasedGUID(): Generate a GUID based on the names supplied. | |
| 28 BuildEnterpriseInstaller(): Build an MSI installer for use in enterprises. | |
| 29 """ | |
| 30 | |
| 31 import binascii | |
| 32 import md5 | |
| 33 | |
| 34 _GOOGLE_UPDATE_NAMESPACE_GUID = 'BE19B3E4502845af8B3E67A99FCDCFB1' | |
| 35 | |
| 36 | |
| 37 def BuildGoogleUpdateFragment(env, | |
| 38 metainstaller_path, | |
| 39 product_name, | |
| 40 product_version, | |
| 41 product_guid, | |
| 42 product_custom_params, | |
| 43 wixobj_base_name, | |
| 44 google_update_wxs_template_path): | |
| 45 """Build an update fragment into a WiX object. | |
| 46 | |
| 47 Takes a supplied wix fragment, and turns it into a .wixobj object for later | |
| 48 inclusion into an MSI. | |
| 49 | |
| 50 Args: | |
| 51 env: environment to build with | |
| 52 metainstaller_path: path to the Omaha metainstaller to include | |
| 53 product_name: name of the product the fragment is being built for | |
| 54 product_version: product version to be installed | |
| 55 product_guid: Omaha application ID of the product the fragment is being | |
| 56 built for | |
| 57 product_custom_params: custom values to be appended to the Omaha tag | |
| 58 wixobj_base_name: root of name for the wixobj | |
| 59 google_update_wxs_template_path: path to the fragment source | |
| 60 | |
| 61 Returns: | |
| 62 Output object for the built wixobj. | |
| 63 | |
| 64 Raises: | |
| 65 Nothing. | |
| 66 """ | |
| 67 | |
| 68 product_name_legal_identifier = product_name.replace(' ', '') | |
| 69 | |
| 70 intermediate_base_name = wixobj_base_name + '_google_update_fragment' | |
| 71 | |
| 72 copy_target = env.Command( | |
| 73 target=intermediate_base_name + '.wxs', | |
| 74 source=google_update_wxs_template_path, | |
| 75 action='@copy /y $SOURCE $TARGET', | |
| 76 ) | |
| 77 | |
| 78 wix_defines = [ | |
| 79 '-dProductName="%s"' % product_name, | |
| 80 '-dProductNameLegalIdentifier="%s"' % product_name_legal_identifier, | |
| 81 '-dProductVersion=' + product_version, | |
| 82 '-dProductGuid="%s"' % product_guid, | |
| 83 '-dProductCustomParams="%s"' % product_custom_params, | |
| 84 '-dGoogleUpdateMetainstallerPath="%s"' % ( | |
| 85 env.File(metainstaller_path).abspath), | |
| 86 ] | |
| 87 | |
| 88 wixobj_output = env.Command( | |
| 89 target=intermediate_base_name + '.wixobj', | |
| 90 source=copy_target, | |
| 91 action='@candle.exe -nologo -out $TARGET $SOURCE ' + ' '.join(wix_defines) | |
| 92 ) | |
| 93 | |
| 94 # Force a rebuild of the .wixobj file when the metainstaller changes. | |
| 95 # Does not necessarily force rebuild of the MSI because hash does not change. | |
| 96 env.Depends(wixobj_output, metainstaller_path) | |
| 97 | |
| 98 return wixobj_output | |
| 99 | |
| 100 | |
| 101 def _BuildMsiForExe(env, | |
| 102 product_name, | |
| 103 product_version, | |
| 104 product_guid, | |
| 105 product_installer_path, | |
| 106 product_installer_install_command, | |
| 107 product_installer_disable_update_registration_arg, | |
| 108 product_uninstaller_additional_args, | |
| 109 msi_base_name, | |
| 110 google_update_wixobj_output, | |
| 111 enterprise_installer_dir, | |
| 112 show_error_action_dll_path, | |
| 113 metainstaller_path, | |
| 114 output_dir): | |
| 115 """Build an MSI installer for use in enterprise situations. | |
| 116 | |
| 117 Builds an MSI for the executable installer at product_installer_path using | |
| 118 the supplied details. Requires an existing Google Update installer fragment | |
| 119 as well as a path to a custom action DLL containing the logic to launch the | |
| 120 product's uninstaller. | |
| 121 | |
| 122 This is intended to enable enterprise installation scenarios. | |
| 123 | |
| 124 Args: | |
| 125 env: environment to build with | |
| 126 product_name: name of the product being built | |
| 127 product_version: product version to be installed | |
| 128 product_guid: product's Omaha application ID | |
| 129 product_installer_path: path to specific product installer | |
| 130 product_installer_install_command: command line args used to run product | |
| 131 installer in 'install' mode | |
| 132 product_installer_disable_update_registration_arg: command line args used | |
| 133 to run product installer in 'do not register' mode | |
| 134 product_uninstaller_additional_args: extra command line parameters that the | |
| 135 custom action dll will pass on to the product uninstaller, typically | |
| 136 you'll want to pass any extra arguments that will force the uninstaller | |
| 137 to run silently here. | |
| 138 msi_base_name: root of name for the MSI | |
| 139 google_update_wixobj_output: the MSI fragment containing the Omaha | |
| 140 installer. | |
| 141 enterprise_installer_dir: path to dir which contains | |
| 142 enterprise_installer.wxs.xml | |
| 143 show_error_action_dll_path: path to the error display custom action dll that | |
| 144 exports a ShowInstallerResultUIString method. This CA method will read | |
| 145 the LastInstallerResultUIString from the product's ClientState key in | |
| 146 the registry and display the string via MsiProcessMessage. | |
| 147 metainstaller_path: path to the Omaha metainstaller. Should be same file | |
| 148 used for google_update_wixobj_output. Used only to force rebuilds. | |
| 149 output_dir: path to the directory that will contain the resulting MSI | |
| 150 | |
| 151 Returns: | |
| 152 Nothing. | |
| 153 | |
| 154 Raises: | |
| 155 Nothing. | |
| 156 """ | |
| 157 | |
| 158 product_name_legal_identifier = product_name.replace(' ', '') | |
| 159 msi_name = msi_base_name + '.msi' | |
| 160 | |
| 161 omaha_installer_namespace = binascii.a2b_hex(_GOOGLE_UPDATE_NAMESPACE_GUID) | |
| 162 | |
| 163 # Include the .msi filename in the Product Code generation because "the | |
| 164 # product code must be changed if... the name of the .msi file has been | |
| 165 # changed" according to http://msdn.microsoft.com/en-us/library/aa367850.aspx. | |
| 166 msi_product_id = GenerateNameBasedGUID( | |
| 167 omaha_installer_namespace, | |
| 168 'Product %s %s' % (product_name, msi_base_name) | |
| 169 ) | |
| 170 msi_upgradecode_guid = GenerateNameBasedGUID( | |
| 171 omaha_installer_namespace, | |
| 172 'Upgrade ' + product_name | |
| 173 ) | |
| 174 | |
| 175 copy_target = env.Command( | |
| 176 target=msi_base_name + '.wxs', | |
| 177 source=enterprise_installer_dir + '/enterprise_installer.wxs.xml', | |
| 178 action='@copy /y $SOURCE $TARGET', | |
| 179 ) | |
| 180 | |
| 181 # Disable warning LGHT1076 and internal check ICE61 on light.exe. Details: | |
| 182 # http://blogs.msdn.com/astebner/archive/2007/02/13/building-an-msi-using-wix-
v3-0-that-includes-the-vc-8-0-runtime-merge-modules.aspx | |
| 183 # http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/ICE61-Upgrade-
VersionMax-format-is-wrong-td4396813.html # pylint: disable-msg=C6310 | |
| 184 wix_env = env.Clone() | |
| 185 wix_env.Append( | |
| 186 WIXCANDLEFLAGS=[ | |
| 187 '-dProductName=' + product_name, | |
| 188 '-dProductNameLegalIdentifier=' + product_name_legal_identifier, | |
| 189 '-dProductVersion=' + product_version, | |
| 190 '-dProductGuid=' + product_guid, | |
| 191 '-dProductInstallerPath=' + env.File(product_installer_path).abspath, | |
| 192 '-dProductInstallerInstallCommand=' + ( | |
| 193 product_installer_install_command), | |
| 194 '-dProductInstallerDisableUpdateRegistrationArg=' + ( | |
| 195 product_installer_disable_update_registration_arg), | |
| 196 '-dShowErrorCADll=' + env.File(show_error_action_dll_path).abspath, | |
| 197 '-dProductUninstallerAdditionalArgs=' + ( | |
| 198 product_uninstaller_additional_args), | |
| 199 '-dMsiProductId=' + msi_product_id, | |
| 200 '-dMsiUpgradeCode=' + msi_upgradecode_guid, | |
| 201 ], | |
| 202 WIXLIGHTFLAGS=[ | |
| 203 '-sw1076', | |
| 204 '-sice:ICE61', | |
| 205 ], | |
| 206 ) | |
| 207 | |
| 208 wix_output = wix_env.WiX( | |
| 209 target='unsigned_' + msi_name, | |
| 210 source=[copy_target, google_update_wixobj_output], | |
| 211 ) | |
| 212 | |
| 213 # Force a rebuild when the installer or metainstaller changes. | |
| 214 # The metainstaller change does not get passed through even though the .wixobj | |
| 215 # file is rebuilt because the hash of the .wixobj does not change. | |
| 216 # Also force a dependency on the CA DLL. Otherwise, it might not be built | |
| 217 # before the MSI. | |
| 218 wix_env.Depends(wix_output, [product_installer_path, | |
| 219 metainstaller_path, | |
| 220 show_error_action_dll_path]) | |
| 221 | |
| 222 sign_output = wix_env.SignedBinary( | |
| 223 target=msi_name, | |
| 224 source=wix_output, | |
| 225 ) | |
| 226 | |
| 227 env.Replicate(output_dir, sign_output) | |
| 228 | |
| 229 | |
| 230 def GenerateNameBasedGUID(namespace, name): | |
| 231 """Generate a GUID based on the names supplied. | |
| 232 | |
| 233 Follows a methodology recommended in Section 4.3 of RFC 4122 to generate | |
| 234 a "name-based UUID," which basically means that you want to control the | |
| 235 inputs to the GUID so that you can generate the same valid GUID each time | |
| 236 given the same inputs. | |
| 237 | |
| 238 Args: | |
| 239 namespace: First part of identifier used to generate GUID | |
| 240 name: Second part of identifier used to generate GUID | |
| 241 | |
| 242 Returns: | |
| 243 String representation of the generated GUID. | |
| 244 | |
| 245 Raises: | |
| 246 Nothing. | |
| 247 """ | |
| 248 | |
| 249 # Generate 128 unique bits. | |
| 250 mymd5 = md5.new() | |
| 251 mymd5.update(namespace + name) | |
| 252 md5_hash = mymd5.digest() | |
| 253 | |
| 254 # Set various reserved bits to make this a valid GUID. | |
| 255 | |
| 256 # "Set the four most significant bits (bits 12 through 15) of the | |
| 257 # time_hi_and_version field to the appropriate 4-bit version number | |
| 258 # from Section 4.1.3." | |
| 259 version = ord(md5_hash[6]) | |
| 260 version = 0x30 | (version & 0x0f) | |
| 261 | |
| 262 # "Set the two most significant bits (bits 6 and 7) of the | |
| 263 # clock_seq_hi_and_reserved to zero and one, respectively." | |
| 264 clock_seq_hi_and_reserved = ord(md5_hash[8]) | |
| 265 clock_seq_hi_and_reserved = 0x80 | (clock_seq_hi_and_reserved & 0x3f) | |
| 266 | |
| 267 return ( | |
| 268 '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % ( | |
| 269 ord(md5_hash[0]), ord(md5_hash[1]), ord(md5_hash[2]), | |
| 270 ord(md5_hash[3]), | |
| 271 ord(md5_hash[4]), ord(md5_hash[5]), | |
| 272 version, ord(md5_hash[7]), | |
| 273 clock_seq_hi_and_reserved, ord(md5_hash[9]), | |
| 274 ord(md5_hash[10]), ord(md5_hash[11]), ord(md5_hash[12]), | |
| 275 ord(md5_hash[13]), ord(md5_hash[14]), ord(md5_hash[15]))) | |
| 276 | |
| 277 | |
| 278 def ConvertToMSIVersionNumberIfNeeded(product_version): | |
| 279 """Change product_version to fit in an MSI version number if needed. | |
| 280 | |
| 281 Some products use a 4-field version numbering scheme whereas MSI looks only | |
| 282 at the first three fields when considering version numbers. Furthermore, MSI | |
| 283 version fields have documented width restrictions of 8bits.8bits.16bits as | |
| 284 per http://msdn.microsoft.com/en-us/library/aa370859(VS.85).aspx | |
| 285 | |
| 286 As such, the following scheme is used: | |
| 287 | |
| 288 Product a.b.c.d -> a.(c>>8).(((c & 0xFF) << 8) + d) | |
| 289 | |
| 290 So eg. 6.1.420.8 would become 6.1.41992. | |
| 291 | |
| 292 This assumes: | |
| 293 1) we don't care about the product minor number, e.g. we will never reset | |
| 294 the 'c' number after an increase in 'b'. | |
| 295 2) 'd' will always be <= 255 | |
| 296 3) 'c' is <= 65535 | |
| 297 | |
| 298 As a final note, if product_version is not of the format a.b.c.d then | |
| 299 this function returns the original product_version value. | |
| 300 """ | |
| 301 | |
| 302 try: | |
| 303 version_field_strings = product_version.split('.') | |
| 304 (major, minor, build, patch) = [int(x) for x in version_field_strings] | |
| 305 except: | |
| 306 # Couldn't parse the version number as a 4-term period-separated number, | |
| 307 # just return the original string. | |
| 308 return product_version | |
| 309 | |
| 310 # Input version number was out of range. Return the original string. | |
| 311 if patch > 255 or build > 65535: | |
| 312 return product_string | |
| 313 | |
| 314 msi_major = major | |
| 315 msi_minor = build >> 8 | |
| 316 msi_build = ((build & 0xff) << 8) + patch | |
| 317 | |
| 318 return str(msi_major) + '.' + str(msi_minor) + '.' + str(msi_build) | |
| 319 | |
| 320 | |
| 321 def BuildEnterpriseInstaller(env, | |
| 322 product_name, | |
| 323 product_version, | |
| 324 product_guid, | |
| 325 product_custom_params, | |
| 326 product_installer_path, | |
| 327 product_installer_install_command, | |
| 328 product_installer_disable_update_registration_arg, | |
| 329 product_uninstaller_additional_args, | |
| 330 msi_base_name, | |
| 331 enterprise_installer_dir, | |
| 332 show_error_action_dll_path, | |
| 333 metainstaller_path, | |
| 334 output_dir='$STAGING_DIR'): | |
| 335 """Build an installer for use in enterprise situations. | |
| 336 | |
| 337 Builds an MSI using the supplied details and binaries. This MSI is | |
| 338 intended to enable enterprise installation scenarios. | |
| 339 | |
| 340 Args: | |
| 341 env: environment to build with | |
| 342 product_name: name of the product being built | |
| 343 product_version: product version to be installed | |
| 344 product_guid: product's Omaha application ID | |
| 345 product_custom_params: custom values to be appended to the Omaha tag | |
| 346 product_installer_path: path to specific product installer | |
| 347 product_installer_install_command: command line args used to run product | |
| 348 installer in 'install' mode | |
| 349 product_installer_disable_update_registration_arg: command line args used | |
| 350 to run product installer in 'do not register' mode | |
| 351 product_uninstaller_additional_args: extra command line parameters that the | |
| 352 custom action dll will pass on to the product uninstaller, typically | |
| 353 you'll want to pass any extra arguments that will force the uninstaller | |
| 354 to run silently here. | |
| 355 msi_base_name: root of name for the MSI | |
| 356 enterprise_installer_dir: path to dir which contains | |
| 357 enterprise_installer.wxs.xml | |
| 358 show_error_action_dll_path: path to the error display custom action dll that | |
| 359 exports a ShowInstallerResultUIString method. This CA method will read | |
| 360 the LastInstallerResultUIString from the product's ClientState key in | |
| 361 the registry and display the string via MsiProcessMessage. | |
| 362 metainstaller_path: path to the Omaha metainstaller to include | |
| 363 output_dir: path to the directory that will contain the resulting MSI | |
| 364 | |
| 365 Returns: | |
| 366 Nothing. | |
| 367 | |
| 368 Raises: | |
| 369 Nothing. | |
| 370 """ | |
| 371 product_version = ConvertToMSIVersionNumberIfNeeded(product_version) | |
| 372 | |
| 373 google_update_wixobj_output = BuildGoogleUpdateFragment( | |
| 374 env, | |
| 375 metainstaller_path, | |
| 376 product_name, | |
| 377 product_version, | |
| 378 product_guid, | |
| 379 product_custom_params, | |
| 380 msi_base_name, | |
| 381 enterprise_installer_dir + '/google_update_installer_fragment.wxs.xml') | |
| 382 | |
| 383 _BuildMsiForExe( | |
| 384 env, | |
| 385 product_name, | |
| 386 product_version, | |
| 387 product_guid, | |
| 388 product_installer_path, | |
| 389 product_installer_install_command, | |
| 390 product_installer_disable_update_registration_arg, | |
| 391 product_uninstaller_additional_args, | |
| 392 msi_base_name, | |
| 393 google_update_wixobj_output, | |
| 394 enterprise_installer_dir, | |
| 395 show_error_action_dll_path, | |
| 396 metainstaller_path, | |
| 397 output_dir) | |
| 398 | |
| 399 | |
| 400 def BuildEnterpriseInstallerFromStandaloneInstaller( | |
| 401 env, | |
| 402 product_name, | |
| 403 product_version, | |
| 404 product_guid, | |
| 405 product_custom_params, | |
| 406 product_uninstaller_additional_args, | |
| 407 product_installer_data, | |
| 408 standalone_installer_path, | |
| 409 show_error_action_dll_path, | |
| 410 msi_base_name, | |
| 411 enterprise_installer_dir, | |
| 412 output_dir='$STAGING_DIR'): | |
| 413 """Build an installer for use in enterprise situations. | |
| 414 | |
| 415 Builds an MSI around the supplied standalone installer. This MSI is | |
| 416 intended to enable enterprise installation scenarios while being as close | |
| 417 to a normal install as possible. It does not suffer from the separation of | |
| 418 Omaha and application install like the other methods do. | |
| 419 | |
| 420 This method only works for installers that do not use an MSI. | |
| 421 | |
| 422 Args: | |
| 423 env: environment to build with | |
| 424 product_name: name of the product being built | |
| 425 product_version: product version to be installed | |
| 426 product_guid: product's Omaha application ID | |
| 427 product_custom_params: custom values to be appended to the Omaha tag | |
| 428 product_uninstaller_additional_args: extra command line parameters that the | |
| 429 custom action dll will pass on to the product uninstaller, typically | |
| 430 you'll want to pass any extra arguments that will force the uninstaller | |
| 431 to run silently here. | |
| 432 product_installer_data: installer data to be passed to the | |
| 433 product installer at run time. This is useful as an alternative to | |
| 434 the product_installer_install_command parameter accepted by | |
| 435 BuildEnterpriseInstaller() since command line parameters can't be | |
| 436 passed to the product installer when it is wrapped in a standalone | |
| 437 installer. | |
| 438 standalone_installer_path: path to product's standalone installer | |
| 439 show_error_action_dll_path: path to the error display custom action dll that | |
| 440 exports a ShowInstallerResultUIString method. This CA method will read | |
| 441 the LastInstallerResultUIString from the product's ClientState key in | |
| 442 the registry and display the string via MsiProcessMessage. | |
| 443 msi_base_name: root of name for the MSI | |
| 444 enterprise_installer_dir: path to dir which contains | |
| 445 enterprise_standalone_installer.wxs.xml | |
| 446 output_dir: path to the directory that will contain the resulting MSI | |
| 447 | |
| 448 Returns: | |
| 449 Target nodes. | |
| 450 | |
| 451 Raises: | |
| 452 Nothing. | |
| 453 """ | |
| 454 product_name_legal_identifier = product_name.replace(' ', '') | |
| 455 msi_name = msi_base_name + '.msi' | |
| 456 product_version = ConvertToMSIVersionNumberIfNeeded(product_version) | |
| 457 | |
| 458 omaha_installer_namespace = binascii.a2b_hex(_GOOGLE_UPDATE_NAMESPACE_GUID) | |
| 459 | |
| 460 # Include the .msi filename in the Product Code generation because "the | |
| 461 # product code must be changed if... the name of the .msi file has been | |
| 462 # changed" according to http://msdn.microsoft.com/en-us/library/aa367850.aspx. | |
| 463 msi_product_id = GenerateNameBasedGUID( | |
| 464 omaha_installer_namespace, | |
| 465 'Product %s %s' % (product_name, msi_base_name) | |
| 466 ) | |
| 467 msi_upgradecode_guid = GenerateNameBasedGUID( | |
| 468 omaha_installer_namespace, | |
| 469 'Upgrade ' + product_name | |
| 470 ) | |
| 471 | |
| 472 # To allow for multiple versions of the same product to be generated, | |
| 473 # stick output in a subdirectory. | |
| 474 output_directory_name = product_guid + '.' + product_version | |
| 475 | |
| 476 copy_target = env.Command( | |
| 477 target=output_directory_name + msi_base_name + '.wxs', | |
| 478 source=(enterprise_installer_dir + | |
| 479 '/enterprise_standalone_installer.wxs.xml'), | |
| 480 action='@copy /y $SOURCE $TARGET', | |
| 481 ) | |
| 482 | |
| 483 wix_env = env.Clone() | |
| 484 wix_candle_flags = [ | |
| 485 '-dProductName=' + product_name, | |
| 486 '-dProductNameLegalIdentifier=' + product_name_legal_identifier, | |
| 487 '-dProductVersion=' + product_version, | |
| 488 '-dProductGuid="%s"' % product_guid, | |
| 489 '-dProductCustomParams="%s"' % product_custom_params, | |
| 490 '-dStandaloneInstallerPath=' + ( | |
| 491 env.File(standalone_installer_path).abspath), | |
| 492 '-dShowErrorCADll=' + env.File(show_error_action_dll_path).abspath, | |
| 493 '-dProductUninstallerAdditionalArgs=' + ( | |
| 494 product_uninstaller_additional_args), | |
| 495 '-dMsiProductId=' + msi_product_id, | |
| 496 '-dMsiUpgradeCode=' + msi_upgradecode_guid, | |
| 497 ] | |
| 498 | |
| 499 if product_installer_data: | |
| 500 wix_candle_flags.append('-dProductInstallerData=' + product_installer_data) | |
| 501 | |
| 502 wix_light_flags = [ | |
| 503 '-sw1076', | |
| 504 '-sice:ICE61', | |
| 505 ] | |
| 506 | |
| 507 wix_env.Append( | |
| 508 WIXCANDLEFLAGS=wix_candle_flags, | |
| 509 WIXLIGHTFLAGS=wix_light_flags | |
| 510 ) | |
| 511 | |
| 512 wix_output = wix_env.WiX( | |
| 513 target = output_directory_name + '/' + 'unsigned_' + msi_name, | |
| 514 source = [copy_target], | |
| 515 ) | |
| 516 | |
| 517 # Force a rebuild when the standalone installer changes. | |
| 518 # The metainstaller change does not get passed through even though the .wixobj | |
| 519 # file is rebuilt because the hash of the .wixobj does not change. | |
| 520 # Also force a dependency on the CA DLL. Otherwise, it might not be built | |
| 521 # before the MSI. | |
| 522 wix_env.Depends(wix_output, [standalone_installer_path, | |
| 523 show_error_action_dll_path]) | |
| 524 | |
| 525 sign_output = wix_env.SignedBinary( | |
| 526 target=output_directory_name + '/' + msi_name, | |
| 527 source=wix_output, | |
| 528 ) | |
| 529 | |
| 530 return env.Replicate(output_dir + '/' + output_directory_name, sign_output) | |
| OLD | NEW |