Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Script to create Chrome Installer archive. | 6 """Script to create Chrome Installer archive. |
| 7 | 7 |
| 8 This script is used to create an archive of all the files required for a | 8 This script is used to create an archive of all the files required for a |
| 9 Chrome install in appropriate directory structure. It reads chrome.release | 9 Chrome install in appropriate directory structure. It reads chrome.release |
| 10 file as input, creates chrome.7z archive, compresses setup.exe and | 10 file as input, creates chrome.7z archive, compresses setup.exe and |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 305 'archive_file': archive_file, | 305 'archive_file': archive_file, |
| 306 'archive_file_path': | 306 'archive_file_path': |
| 307 os.path.join(output_dir, archive_file).replace("\\","/"), | 307 os.path.join(output_dir, archive_file).replace("\\","/"), |
| 308 } | 308 } |
| 309 resource_file = _RESOURCE_FILE_TEMPLATE % args | 309 resource_file = _RESOURCE_FILE_TEMPLATE % args |
| 310 | 310 |
| 311 with open(resource_file_path, 'w') as f: | 311 with open(resource_file_path, 'w') as f: |
| 312 f.write(resource_file) | 312 f.write(resource_file) |
| 313 | 313 |
| 314 | 314 |
| 315 # Reads |manifest_name| from |build_dir| and writes |manifest_name| to | |
| 316 # |output_dir| with the same content plus |inserted_string| added just before | |
| 317 # |insert_before|. | |
| 318 def CopyAndAugmentManifest(build_dir, output_dir, manifest_name, | |
| 319 inserted_string, insert_before): | |
| 320 manifest_file = open( | |
| 321 os.path.join(build_dir, manifest_name), 'r') | |
| 322 manifest_lines = manifest_file.readlines() | |
| 323 manifest_file.close() | |
| 324 | |
| 325 insert_index = next((i for i, s in enumerate(manifest_lines) | |
| 326 if s.find(insert_before) != -1), -1) | |
|
gab
2012/05/16 21:50:22
I now use a python generator to get the first inde
| |
| 327 if insert_index == -1: | |
| 328 raise ValueError('could not find {0} in the manifest:\n{1}'.format( | |
| 329 insert_before, ''.join(manifest_lines))) | |
| 330 manifest_lines.insert(insert_index, inserted_string) | |
| 331 | |
| 332 modified_manifest_file = open( | |
| 333 os.path.join(output_dir, manifest_name), 'w') | |
| 334 modified_manifest_file.write(''.join(manifest_lines)) | |
| 335 modified_manifest_file.close() | |
| 336 | |
| 337 | |
| 338 # Copies component build DLLs and generates required config files and manifests | |
| 339 # in order for chrome.exe and setup.exe to be able to find those DLLs at | |
| 340 # run-time. | |
| 341 # This is meant for developer builds only and should never be used to package | |
| 342 # an official build. | |
| 343 def DoComponentBuildTasks(staging_dir, build_dir, current_version): | |
| 344 # Get the required directories for the upcoming operations. | |
| 345 chrome_dir = os.path.join(staging_dir, CHROME_DIR) | |
| 346 version_dir = os.path.join(chrome_dir, current_version) | |
| 347 installer_dir = os.path.join(version_dir, 'Installer') | |
| 348 # |installer_dir| is technically only created post-install, but we need it | |
| 349 # now to add setup.exe's config and manifest to the archive. | |
| 350 if not os.path.exists(installer_dir): | |
| 351 os.mkdir(installer_dir) | |
| 352 | |
| 353 # Copy all the DLLs in |build_dir| to the version directory. Simultaneously | |
| 354 # build a list of their names to mark them as dependencies of chrome.exe and | |
| 355 # setup.exe later. | |
| 356 dlls = glob.glob(os.path.join(build_dir, '*.dll')) | |
| 357 dll_names = [] | |
| 358 for dll in dlls: | |
| 359 shutil.copy(dll, version_dir) | |
| 360 dll_names.append(os.path.splitext(os.path.basename(dll))[0]) | |
| 361 | |
| 362 exe_config = ( | |
| 363 "<configuration>\n" | |
| 364 " <windows>\n" | |
| 365 " <assemblyBinding xmlns='urn:schemas-microsoft-com:asm.v1'>\n" | |
| 366 " <probing privatePath='{rel_path}'/>\n" | |
| 367 " </assemblyBinding>\n" | |
| 368 " </windows>\n" | |
| 369 "</configuration>") | |
| 370 | |
| 371 # Write chrome.exe.config to point to the version directory. | |
| 372 chrome_exe_config_file = open( | |
| 373 os.path.join(chrome_dir, 'chrome.exe.config'), 'w') | |
| 374 chrome_exe_config_file.write(exe_config.format(rel_path=current_version)) | |
| 375 chrome_exe_config_file.close() | |
| 376 | |
| 377 # Write setup.exe.config to point to the version directory (which is one | |
| 378 # level up from setup.exe post-install). | |
| 379 setup_exe_config_file = open( | |
| 380 os.path.join(installer_dir, 'setup.exe.config'), 'w') | |
| 381 setup_exe_config_file.write(exe_config.format(rel_path='..')) | |
| 382 setup_exe_config_file.close() | |
| 383 | |
| 384 # Add a dependency for each DLL in |dlls| to the existing manifests for | |
| 385 # chrome.exe and setup.exe. Some of these DLLs are not actually used by | |
| 386 # either process, but listing them all as dependencies doesn't hurt as it | |
| 387 # only makes them visible to the exes, just like they already are in the | |
| 388 # build output directory. | |
| 389 exe_manifest_dependencies_list = [] | |
| 390 for name in dll_names: | |
| 391 exe_manifest_dependencies_list.append( | |
| 392 " <dependency>\n" | |
| 393 " <dependentAssembly>\n" | |
| 394 " <assemblyIdentity type='win32' name='chrome.{dll_name}'\n" | |
| 395 " version='0.0.0.0' processorArchitecture='x86'\n" | |
| 396 " language='*'/>\n" | |
| 397 " </dependentAssembly>\n" | |
| 398 " </dependency>\n".format(dll_name=name)) | |
| 399 | |
| 400 exe_manifest_dependencies = ''.join(exe_manifest_dependencies_list) | |
| 401 | |
| 402 # Write a modified chrome.exe.manifest beside chrome.exe. | |
| 403 CopyAndAugmentManifest(build_dir, chrome_dir, 'chrome.exe.manifest', | |
| 404 exe_manifest_dependencies, '</assembly>') | |
| 405 | |
| 406 # Write a modified setup.exe.manifest beside setup.exe in | |
| 407 # |version_dir|/Installer. | |
| 408 CopyAndAugmentManifest(build_dir, installer_dir, 'setup.exe.manifest', | |
| 409 exe_manifest_dependencies, '</assembly>') | |
| 410 | |
| 411 # Generate assembly manifests for each DLL in |dlls|. These do not interfere | |
| 412 # with the private manifests potentially embedded in each DLL. They simply | |
| 413 # allow chrome.exe and setup.exe to see those DLLs although they are in a | |
| 414 # separate directory post-install. | |
| 415 for name in dll_names: | |
| 416 dll_manifest = ( | |
| 417 "<assembly\n" | |
| 418 " xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>\n" | |
| 419 " <assemblyIdentity name='chrome.{dll_name}' version='0.0.0.0'\n" | |
| 420 " type='win32' processorArchitecture='x86'/>\n" | |
| 421 " <file name='{dll_name}.dll'/>\n" | |
| 422 "</assembly>".format(dll_name=name)) | |
| 423 | |
| 424 dll_manifest_file = open(os.path.join( | |
| 425 version_dir, "chrome.{dll_name}.manifest".format(dll_name=name)), 'w') | |
| 426 dll_manifest_file.write(dll_manifest) | |
| 427 dll_manifest_file.close() | |
| 428 | |
| 429 | |
| 315 def main(options): | 430 def main(options): |
| 316 """Main method that reads input file, creates archive file and write | 431 """Main method that reads input file, creates archive file and write |
| 317 resource input file. | 432 resource input file. |
| 318 """ | 433 """ |
| 319 current_version = BuildVersion(options.build_dir) | 434 current_version = BuildVersion(options.build_dir) |
| 320 | 435 |
| 321 config = Readconfig(options.build_dir, options.input_file, current_version) | 436 config = Readconfig(options.build_dir, options.input_file, current_version) |
| 322 | 437 |
| 323 (staging_dir, temp_dir) = MakeStagingDirectories(options.staging_dir) | 438 (staging_dir, temp_dir) = MakeStagingDirectories(options.staging_dir) |
| 324 | 439 |
| 325 prev_version = GetPrevVersion(options.build_dir, temp_dir, | 440 prev_version = GetPrevVersion(options.build_dir, temp_dir, |
| 326 options.last_chrome_installer) | 441 options.last_chrome_installer) |
| 327 | 442 |
| 328 # Preferentially copy the files we can find from the output_dir, as | 443 # Preferentially copy the files we can find from the output_dir, as |
| 329 # this is where we'll find the Syzygy-optimized executables when | 444 # this is where we'll find the Syzygy-optimized executables when |
| 330 # building the optimized mini_installer. | 445 # building the optimized mini_installer. |
| 331 if options.build_dir != options.output_dir: | 446 if options.build_dir != options.output_dir: |
| 332 CopyAllFilesToStagingDir(config, options.distribution, | 447 CopyAllFilesToStagingDir(config, options.distribution, |
| 333 staging_dir, options.output_dir, | 448 staging_dir, options.output_dir, |
| 334 options.enable_hidpi, options.enable_metro) | 449 options.enable_hidpi, options.enable_metro) |
| 335 | 450 |
| 336 # Now copy the remainder of the files from the build dir. | 451 # Now copy the remainder of the files from the build dir. |
| 337 CopyAllFilesToStagingDir(config, options.distribution, | 452 CopyAllFilesToStagingDir(config, options.distribution, |
| 338 staging_dir, options.build_dir, | 453 staging_dir, options.build_dir, |
| 339 options.enable_hidpi, options.enable_metro) | 454 options.enable_hidpi, options.enable_metro) |
| 340 | 455 |
| 456 if options.component_build == '1': | |
| 457 DoComponentBuildTasks(staging_dir, options.build_dir, current_version) | |
| 458 | |
| 341 version_numbers = current_version.split('.') | 459 version_numbers = current_version.split('.') |
| 342 current_build_number = version_numbers[2] + '.' + version_numbers[3] | 460 current_build_number = version_numbers[2] + '.' + version_numbers[3] |
| 343 prev_build_number = '' | 461 prev_build_number = '' |
| 344 if prev_version: | 462 if prev_version: |
| 345 version_numbers = prev_version.split('.') | 463 version_numbers = prev_version.split('.') |
| 346 prev_build_number = version_numbers[2] + '.' + version_numbers[3] | 464 prev_build_number = version_numbers[2] + '.' + version_numbers[3] |
| 347 | 465 |
| 348 # Name of the archive file built (for example - chrome.7z or | 466 # Name of the archive file built (for example - chrome.7z or |
| 349 # patch-<old_version>-<new_version>.7z or patch-<new_version>.7z | 467 # patch-<old_version>-<new_version>.7z or patch-<new_version>.7z |
| 350 archive_file = CreateArchiveFile(options, staging_dir, | 468 archive_file = CreateArchiveFile(options, staging_dir, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 parser.add_option('-a', '--diff_algorithm', default='BSDIFF', | 504 parser.add_option('-a', '--diff_algorithm', default='BSDIFF', |
| 387 help='Diff algorithm to use when generating differential patches ' | 505 help='Diff algorithm to use when generating differential patches ' |
| 388 '{BSDIFF|COURGETTE}.') | 506 '{BSDIFF|COURGETTE}.') |
| 389 parser.add_option('-n', '--output_name', default='chrome', | 507 parser.add_option('-n', '--output_name', default='chrome', |
| 390 help='Name used to prefix names of generated archives.') | 508 help='Name used to prefix names of generated archives.') |
| 391 parser.add_option('--enable_hidpi', default='0', | 509 parser.add_option('--enable_hidpi', default='0', |
| 392 help='Whether to include HiDPI resource files.') | 510 help='Whether to include HiDPI resource files.') |
| 393 parser.add_option('--enable_metro', default='0', | 511 parser.add_option('--enable_metro', default='0', |
| 394 help='Whether to include resource files from the "METRO" section of the ' | 512 help='Whether to include resource files from the "METRO" section of the ' |
| 395 'input file.') | 513 'input file.') |
| 514 parser.add_option('--component_build', default='0', | |
| 515 help='Whether this archive is packaging a component build.') | |
| 396 | 516 |
| 397 options, args = parser.parse_args() | 517 options, args = parser.parse_args() |
| 398 if not options.build_dir: | 518 if not options.build_dir: |
| 399 parser.error('You must provide a build dir.') | 519 parser.error('You must provide a build dir.') |
| 400 | 520 |
| 401 if not options.staging_dir: | 521 if not options.staging_dir: |
| 402 parser.error('You must provide a staging dir.') | 522 parser.error('You must provide a staging dir.') |
| 403 | 523 |
| 524 if not options.input_file: | |
| 525 parser.error('You must provide an input file') | |
| 526 | |
| 404 if not options.output_dir: | 527 if not options.output_dir: |
| 405 options.output_dir = options.build_dir | 528 options.output_dir = options.build_dir |
| 406 | 529 |
| 407 if not options.resource_file_path: | 530 if not options.resource_file_path: |
| 408 options.options.resource_file_path = os.path.join(options.build_dir, | 531 options.resource_file_path = os.path.join(options.build_dir, |
| 409 MINI_INSTALLER_INPUT_FILE) | 532 MINI_INSTALLER_INPUT_FILE) |
| 410 | 533 |
| 411 return options | 534 return options |
| 412 | 535 |
| 413 | 536 |
| 414 if '__main__' == __name__: | 537 if '__main__' == __name__: |
| 415 print sys.argv | 538 print sys.argv |
| 416 sys.exit(main(_ParseOptions())) | 539 sys.exit(main(_ParseOptions())) |
| OLD | NEW |