15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Script to create Chrome Installer archive.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  This script is used to create an archive of all the files required for a
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Chrome install in appropriate directory structure. It reads chrome.release
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file as input, creates chrome.7z archive, compresses setup.exe and
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generates packed_files.txt for mini_installer project.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import ConfigParser
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import glob
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import shutil
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ARCHIVE_DIR = "installer_archive"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# suffix to uncompresed full archive file, appended to options.output_name
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ARCHIVE_SUFFIX = ".7z"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BSDIFF_EXEC = "bsdiff.exe"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CHROME_DIR = "Chrome-bin"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CHROME_PATCH_FILE_SUFFIX = "_patch"  # prefixed by options.output_name
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# compressed full archive suffix, will be prefixed by options.output_name
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPRESSED_ARCHIVE_SUFFIX = ".packed.7z"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPRESSED_FILE_EXT = ".packed.7z"     # extension of patch archive file
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COURGETTE_EXEC = "courgette.exe"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MINI_INSTALLER_INPUT_FILE = "packed_files.txt"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PATCH_FILE_EXT = '.diff'
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SETUP_EXEC = "setup.exe"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SETUP_PATCH_FILE_PREFIX = "setup_patch"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEMP_ARCHIVE_DIR = "temp_installer_archive"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VERSION_FILE = "VERSION"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def BuildVersion(build_dir):
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns the full build version string constructed from information in
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VERSION_FILE.  Any segment not found in that file will default to '0'.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  major = 0
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  minor = 0
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  build = 0
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  patch = 0
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for line in open(os.path.join(build_dir, '../../chrome', VERSION_FILE), 'r'):
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line = line.rstrip()
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if line.startswith('MAJOR='):
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      major = line[6:]
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif line.startswith('MINOR='):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      minor = line[6:]
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif line.startswith('BUILD='):
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      build = line[6:]
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif line.startswith('PATCH='):
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      patch = line[6:]
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return '%s.%s.%s.%s' % (major, minor, build, patch)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CompressUsingLZMA(build_dir, compressed_file, input_file):
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lzma_exec = GetLZMAExec(build_dir)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd = [lzma_exec,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         'a', '-t7z',
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # pre-filter). This results in a ~2.3MB decrease in installer size on
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # a 24MB installer.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # Additionally, these settings reflect a 7zip 4.42 and up change in
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # the definition of -mx9, increasting the dicionary size moving to
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # 26bit = 64MB. This results in an additional ~3.5MB decrease.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # Older 7zip versions can support these settings, as these changes
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # rely on existing functionality in the lzma format.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-m0=BCJ2',
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-m1=LZMA:d27:fb128',
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-m2=LZMA:d22:fb128:mf=bt2',
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-m3=LZMA:d22:fb128:mf=bt2',
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-mb0:1',
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-mb0s1:2',
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '-mb0s2:3',
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          compressed_file,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          input_file,]
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if os.path.exists(compressed_file):
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os.remove(compressed_file)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunSystemCommand(cmd)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CopyAllFilesToStagingDir(config, distribution, staging_dir, build_dir,
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             enable_hidpi):
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Copies the files required for installer archive.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Copies all common files required for various distributions of Chromium and
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  also files for the specific Chromium build specified by distribution.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if distribution:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if len(distribution) > 1 and distribution[0] == '_':
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      distribution = distribution[1:]
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopySectionFilesToStagingDir(config, distribution.upper(),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 staging_dir, build_dir)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if enable_hidpi == '1':
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopySectionFilesToStagingDir(config, 'HIDPI', staging_dir, build_dir)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CopySectionFilesToStagingDir(config, section, staging_dir, src_dir):
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Copies installer archive files specified in section from src_dir to
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  staging_dir. This method reads section from config and copies all the
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  files specified from src_dir to staging dir.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for option in config.options(section):
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if option.endswith('dir'):
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dst_dir = os.path.join(staging_dir, config.get(section, option))
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src_paths = glob.glob(os.path.join(src_dir, option))
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if src_paths and not os.path.exists(dst_dir):
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      os.makedirs(dst_dir)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for src_path in src_paths:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dst_path = os.path.join(dst_dir, os.path.basename(src_path))
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not os.path.exists(dst_path):
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shutil.copy(src_path, dst_dir)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GenerateDiffPatch(options, orig_file, new_file, patch_file):
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options.diff_algorithm == "COURGETTE"):
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exe_file = os.path.join(options.last_chrome_installer, COURGETTE_EXEC)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd = '%s -gen "%s" "%s" "%s"' % (exe_file, orig_file, new_file, patch_file)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exe_file = os.path.join(options.build_dir, BSDIFF_EXEC)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd = [exe_file, orig_file, new_file, patch_file,]
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunSystemCommand(cmd)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetLZMAExec(build_dir):
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lzma_exec = os.path.join(build_dir, "..", "..", "third_party",
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "lzma_sdk", "Executable", "7za.exe")
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lzma_exec
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetPrevVersion(build_dir, temp_dir, last_chrome_installer, output_name):
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not last_chrome_installer:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ''
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lzma_exec = GetLZMAExec(build_dir)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_archive_file = os.path.join(last_chrome_installer,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   output_name + ARCHIVE_SUFFIX)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd = [lzma_exec,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         'x',
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         '-o"%s"' % temp_dir,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         prev_archive_file,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         'Chrome-bin/*/chrome.dll',]
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunSystemCommand(cmd)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dll_path = glob.glob(os.path.join(temp_dir, 'Chrome-bin', '*', 'chrome.dll'))
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os.path.split(os.path.split(dll_path[0])[0])[1]
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def MakeStagingDirectories(staging_dir):
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Creates a staging path for installer archive. If directory exists already,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deletes the existing directory.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if os.path.exists(file_path):
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shutil.rmtree(file_path)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os.makedirs(file_path)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  temp_file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if os.path.exists(temp_file_path):
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shutil.rmtree(temp_file_path)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os.makedirs(temp_file_path)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (file_path, temp_file_path)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Readconfig(input_file, current_version):
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Reads config information from input file after setting default value of
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  global variabes.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  variables = {}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  variables['ChromeDir'] = CHROME_DIR
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  variables['VersionDir'] = os.path.join(variables['ChromeDir'],
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          current_version)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config = ConfigParser.SafeConfigParser(variables)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config.read(input_file)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def RunSystemCommand(cmd, **kw):
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print 'Running', cmd
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  exit_code = subprocess.call(cmd, **kw)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code != 0):
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise Exception("Error while running cmd: %s, exit_code: %s" %
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    (cmd, exit_code))
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CreateArchiveFile(options, staging_dir, current_version, prev_version):
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Creates a new installer archive file after deleting any existing old file.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # First create an uncompressed archive file for the current build (chrome.7z)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lzma_exec = GetLZMAExec(options.build_dir)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  archive_file = os.path.join(options.output_dir,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              options.output_name + ARCHIVE_SUFFIX)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd = [lzma_exec,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         'a',
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         '-t7z',
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         archive_file,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         os.path.join(staging_dir, CHROME_DIR),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         '-mx0',]
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # There doesnt seem to be any way in 7za.exe to override existing file so
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # we always delete before creating a new one.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not os.path.exists(archive_file):
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunSystemCommand(cmd)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elif options.skip_rebuild_archive != "true":
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os.remove(archive_file)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunSystemCommand(cmd)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Do not compress the archive in developer (component) builds.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if options.component_build == '1':
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compressed_file = os.path.join(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        options.output_dir, options.output_name + COMPRESSED_ARCHIVE_SUFFIX)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if os.path.exists(compressed_file):
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      os.remove(compressed_file)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return os.path.basename(archive_file)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # If we are generating a patch, run bsdiff against previous build and
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # compress the resulting patch file. If this is not a patch just compress the
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # uncompressed archive file.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  patch_name_prefix = options.output_name + CHROME_PATCH_FILE_SUFFIX
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if options.last_chrome_installer:
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_archive_file = os.path.join(options.last_chrome_installer,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     options.output_name + ARCHIVE_SUFFIX)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    patch_file = os.path.join(options.build_dir, patch_name_prefix +
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  PATCH_FILE_EXT)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateDiffPatch(options, prev_archive_file, archive_file, patch_file)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compressed_archive_file = patch_name_prefix + '_' + \
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              current_version + '_from_' + prev_version + \
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              COMPRESSED_FILE_EXT
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    orig_file = patch_file
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    orig_file = archive_file
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  compressed_archive_file_path = os.path.join(options.output_dir,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              compressed_archive_file)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompressUsingLZMA(options.build_dir, compressed_archive_file_path, orig_file)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return compressed_archive_file
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PrepareSetupExec(options, current_version, prev_version):
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Prepares setup.exe for bundling in mini_installer based on options."""
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if options.setup_exe_format == "FULL":
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setup_file = SETUP_EXEC
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elif options.setup_exe_format == "DIFF":
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not options.last_chrome_installer:
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise Exception(
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "To use DIFF for setup.exe, --last_chrome_installer is needed.")
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_setup_file = os.path.join(options.last_chrome_installer, SETUP_EXEC)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_setup_file = os.path.join(options.build_dir, SETUP_EXEC)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    patch_file = os.path.join(options.build_dir, SETUP_PATCH_FILE_PREFIX +
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  PATCH_FILE_EXT)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateDiffPatch(options, prev_setup_file, new_setup_file, patch_file)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setup_file = SETUP_PATCH_FILE_PREFIX + '_' + current_version + \
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '_from_' + prev_version + COMPRESSED_FILE_EXT
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setup_file_path = os.path.join(options.build_dir, setup_file)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompressUsingLZMA(options.build_dir, setup_file_path, patch_file)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd = ['makecab.exe',
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           '/D', 'CompressionType=LZX',
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           '/V1',
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           '/L', options.output_dir,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           os.path.join(options.build_dir, SETUP_EXEC),]
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Send useless makecab progress on stdout to the bitbucket.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunSystemCommand(cmd, stdout=open(os.devnull, "w"))
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setup_file = SETUP_EXEC[:-1] + "_"
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return setup_file
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_RESOURCE_FILE_TEMPLATE = """\
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is automatically generated by create_installer_archive.py.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It contains the resource entries that are going to be linked inside
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mini_installer.exe. For each file to be linked there should be two
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lines:
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The first line contains the output filename (without path) and the
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// type of the resource ('BN' - not compressed , 'BL' - LZ compressed,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'B7' - LZMA compressed)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The second line contains the path to the input file. Uses '/' to
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// separate path components.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)%(setup_file)s  %(setup_file_resource_type)s
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "%(setup_file_path)s"
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)%(archive_file)s  B7
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "%(archive_file_path)s"
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CreateResourceInputFile(
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output_dir, setup_format, archive_file, setup_file, resource_file_path):
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Creates resource input file (packed_files.txt) for mini_installer project.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  This method checks the format of setup.exe being used and according sets
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  its resource type.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  setup_resource_type = "BL"
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (setup_format == "FULL"):
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setup_resource_type = "BN"
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  elif (setup_format == "DIFF"):
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setup_resource_type = "B7"
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Expand the resource file template.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args = {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'setup_file': setup_file,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'setup_file_resource_type': setup_resource_type,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'setup_file_path':
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os.path.join(output_dir, setup_file).replace("\\","/"),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'archive_file': archive_file,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'archive_file_path':
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          os.path.join(output_dir, archive_file).replace("\\","/"),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource_file = _RESOURCE_FILE_TEMPLATE % args
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  with open(resource_file_path, 'w') as f:
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f.write(resource_file)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Reads |manifest_name| from |build_dir| and writes |manifest_name| to
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# |output_dir| with the same content plus |inserted_string| added just before
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# |insert_before|.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CopyAndAugmentManifest(build_dir, output_dir, manifest_name,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           inserted_string, insert_before):
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  with open(os.path.join(build_dir, manifest_name), 'r') as f:
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    manifest_lines = f.readlines()
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  insert_line = -1
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  insert_pos = -1
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for i in xrange(len(manifest_lines)):
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    insert_pos = manifest_lines[i].find(insert_before)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if insert_pos != -1:
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      insert_line = i
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if insert_line == -1:
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise ValueError('Could not find {0} in the manifest:\n{1}'.format(
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        insert_before, ''.join(manifest_lines)))
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old = manifest_lines[insert_line]
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  manifest_lines[insert_line] = (old[:insert_pos] + '\n' + inserted_string +
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 '\n' + old[insert_pos:])
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  with open(os.path.join(output_dir, manifest_name), 'w') as f :
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    f.write(''.join(manifest_lines))
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def CopyIfChanged(src, target_dir):
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  """Copy specified |src| file to |target_dir|, but only write to target if
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  the file has changed. This avoids a problem during packaging where parts of
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  the build have not completed and have the runtime DLL locked when we try to
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  copy over it. See http://crbug.com/305877 for details."""
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  assert os.path.isdir(target_dir)
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  dest = os.path.join(target_dir, os.path.basename(src))
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if os.path.exists(dest):
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    # We assume the files are OK to buffer fully into memory since we know
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    # they're only 1-2M.
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    with open(src, 'rb') as fsrc:
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      src_data = fsrc.read()
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    with open(dest, 'rb') as fdest:
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      dest_data = fdest.read()
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if src_data != dest_data:
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # This may still raise if we get here, but this really should almost
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # never happen (it would mean that the contents of e.g. msvcr100d.dll
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      # had been changed).
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      shutil.copyfile(src, dest)
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  else:
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    shutil.copyfile(src, dest)
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copy the relevant CRT DLLs to |build_dir|. We copy DLLs from all versions
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# of VS installed to make sure we have the correct CRT version, unused DLLs
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# should not conflict with the others anyways.
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def CopyVisualStudioRuntimeDLLs(target_arch, build_dir):
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_debug = os.path.basename(build_dir).startswith('Debug')
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if not is_debug and not os.path.basename(build_dir).startswith('Release'):
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print ("Warning: could not determine build configuration from "
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           "output directory, assuming Release build.")
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crt_dlls = []
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sys_dll_dir = None
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if is_debug:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crt_dlls = glob.glob(
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "C:/Program Files (x86)/Microsoft Visual Studio */VC/redist/"
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "Debug_NonRedist/" + target_arch + "/Microsoft.*.DebugCRT/*.dll")
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crt_dlls = glob.glob(
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "C:/Program Files (x86)/Microsoft Visual Studio */VC/redist/" +
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        target_arch + "/Microsoft.*.CRT/*.dll")
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Also handle the case where someone is building using only winsdk and
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # doesn't have Visual Studio installed.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not crt_dlls:
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if target_arch == 'x64':
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # check we are are on a 64bit system by existence of WOW64 dir
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if os.access("C:/Windows/SysWOW64", os.F_OK):
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sys_dll_dir = "C:/Windows/System32"
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # only support packaging of 64bit installer on 64bit system
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # but this just as bad as not finding DLLs at all so we
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # don't abort here to mirror behavior below
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        print ("Warning: could not find x64 CRT DLLs on x86 system.")
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # On a 64-bit system, 32-bit dlls are in SysWOW64 (don't ask).
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if os.access("C:/Windows/SysWOW64", os.F_OK):
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sys_dll_dir = "C:/Windows/SysWOW64"
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sys_dll_dir = "C:/Windows/System32"
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if sys_dll_dir is not None:
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_debug:
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        crt_dlls = glob.glob(os.path.join(sys_dll_dir, "msvc*0d.dll"))
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        crt_dlls = glob.glob(os.path.join(sys_dll_dir, "msvc*0.dll"))
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not crt_dlls:
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print ("Warning: could not find CRT DLLs to copy to build dir - target "
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           "may not run on a system that doesn't have those DLLs.")
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for dll in crt_dlls:
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CopyIfChanged(dll, build_dir)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copies component build DLLs and generates required config files and manifests
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# in order for chrome.exe and setup.exe to be able to find those DLLs at
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# run-time.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This is meant for developer builds only and should never be used to package
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# an official build.
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def DoComponentBuildTasks(staging_dir, build_dir, target_arch, current_version):
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Get the required directories for the upcoming operations.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_dir = os.path.join(staging_dir, CHROME_DIR)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_dir = os.path.join(chrome_dir, current_version)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  installer_dir = os.path.join(version_dir, 'Installer')
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # |installer_dir| is technically only created post-install, but we need it
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # now to add setup.exe's config and manifest to the archive.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not os.path.exists(installer_dir):
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os.mkdir(installer_dir)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Copy the VS CRT DLLs to |build_dir|. This must be done before the general
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # copy step below to ensure the CRT DLLs are added to the archive and marked
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # as a dependency in the exe manifests generated below.
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CopyVisualStudioRuntimeDLLs(target_arch, build_dir)
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # Explicitly list the component DLLs setup.exe depends on (this list may
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # contain wildcards). These will be copied to |installer_dir| in the archive.
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  setup_component_dll_globs = [ 'base.dll',
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                'crcrypto.dll',
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                'crnspr.dll',
448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                'crnss.dll',
449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                'icui18n.dll',
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                'icuuc.dll',
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                'msvc*.dll' ]
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for setup_component_dll_glob in setup_component_dll_globs:
453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    setup_component_dlls = glob.glob(os.path.join(build_dir,
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                  setup_component_dll_glob))
455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for setup_component_dll in setup_component_dlls:
456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      shutil.copy(setup_component_dll, installer_dir)
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # Stage all the component DLLs found in |build_dir| to the |version_dir| (for
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # the version assembly to be able to refer to them below and make sure
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # chrome.exe can find them at runtime). The component DLLs are considered to
461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # be all the DLLs which have not already been added to the |version_dir| by
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  # virtue of chrome.release.
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  build_dlls = glob.glob(os.path.join(build_dir, '*.dll'))
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  staged_dll_basenames = [os.path.basename(staged_dll) for staged_dll in \
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          glob.glob(os.path.join(version_dir, '*.dll'))]
466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  component_dll_filenames = []
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for component_dll in [dll for dll in build_dlls if \
468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        os.path.basename(dll) not in staged_dll_basenames]:
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    component_dll_name = os.path.basename(component_dll)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # remoting_*.dll's don't belong in the archive (it doesn't depend on them
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # in gyp). Trying to copy them causes a build race when creating the
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # installer archive in component mode. See: crbug.com/180996
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if component_dll_name.startswith('remoting_'):
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue
475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    component_dll_filenames.append(component_dll_name)
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    shutil.copy(component_dll, version_dir)
477f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # Augment {version}.manifest to include all component DLLs as part of the
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # assembly it constitutes, which will allow dependents of this assembly to
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # find these DLLs.
481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  version_assembly_dll_additions = []
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for dll_filename in component_dll_filenames:
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    version_assembly_dll_additions.append("  <file name='%s'/>" % dll_filename)
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CopyAndAugmentManifest(build_dir, version_dir,
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         '%s.manifest' % current_version,
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         '\n'.join(version_assembly_dll_additions),
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         '</assembly>')
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def main(options):
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Main method that reads input file, creates archive file and write
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  resource input file.
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_version = BuildVersion(options.build_dir)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config = Readconfig(options.input_file, current_version)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (staging_dir, temp_dir) = MakeStagingDirectories(options.staging_dir)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_version = GetPrevVersion(options.build_dir, temp_dir,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                options.last_chrome_installer,
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                options.output_name)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Preferentially copy the files we can find from the output_dir, as
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # this is where we'll find the Syzygy-optimized executables when
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # building the optimized mini_installer.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if options.build_dir != options.output_dir:
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopyAllFilesToStagingDir(config, options.distribution,
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             staging_dir, options.output_dir,
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             options.enable_hidpi)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Now copy the remainder of the files from the build dir.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CopyAllFilesToStagingDir(config, options.distribution,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           staging_dir, options.build_dir,
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           options.enable_hidpi)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if options.component_build == '1':
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DoComponentBuildTasks(staging_dir, options.build_dir,
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          options.target_arch, current_version)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_numbers = current_version.split('.')
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_build_number = version_numbers[2] + '.' + version_numbers[3]
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_build_number = ''
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if prev_version:
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    version_numbers = prev_version.split('.')
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_build_number = version_numbers[2] + '.' + version_numbers[3]
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Name of the archive file built (for example - chrome.7z or
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # patch-<old_version>-<new_version>.7z or patch-<new_version>.7z
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  archive_file = CreateArchiveFile(options, staging_dir,
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   current_build_number, prev_build_number)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  setup_file = PrepareSetupExec(options,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                current_build_number, prev_build_number)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateResourceInputFile(options.output_dir, options.setup_exe_format,
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          archive_file, setup_file, options.resource_file_path)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _ParseOptions():
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser = optparse.OptionParser()
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-i', '--input_file',
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Input file describing which files to archive.')
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-b', '--build_dir',
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Build directory. The paths in input_file are relative to this.')
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('--staging_dir',
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Staging directory where intermediate files and directories '
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           'will be created')
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-o', '--output_dir',
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='The output directory where the archives will be written. '
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'Defaults to the build_dir.')
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('--resource_file_path',
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='The path where the resource file will be output. '
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           'Defaults to %s in the build directory.' %
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               MINI_INSTALLER_INPUT_FILE)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-d', '--distribution',
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Name of Chromium Distribution. Optional.')
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-s', '--skip_rebuild_archive',
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default="False", help='Skip re-building Chrome.7z archive if it exists.')
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-l', '--last_chrome_installer',
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Generate differential installer. The value of this parameter '
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           'specifies the directory that contains base versions of '
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           'setup.exe, courgette.exe (if --diff_algorithm is COURGETTE) '
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           '& chrome.7z.')
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-f', '--setup_exe_format', default='COMPRESSED',
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='How setup.exe should be included {COMPRESSED|DIFF|FULL}.')
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-a', '--diff_algorithm', default='BSDIFF',
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Diff algorithm to use when generating differential patches '
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           '{BSDIFF|COURGETTE}.')
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('-n', '--output_name', default='chrome',
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Name used to prefix names of generated archives.')
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('--enable_hidpi', default='0',
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Whether to include HiDPI resource files.')
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser.add_option('--component_build', default='0',
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      help='Whether this archive is packaging a component build. This will '
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           'also turn off compression of chrome.7z into chrome.packed.7z and '
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           'helpfully delete any old chrome.packed.7z in |output_dir|.')
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parser.add_option('--target_arch', default='x86',
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      help='Specify the target architecture for installer - this is used '
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           'to determine which CRT runtime files to pull and package '
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           'with the installer archive {x86|x64}.')
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options, _ = parser.parse_args()
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not options.build_dir:
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.error('You must provide a build dir.')
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.build_dir = os.path.normpath(options.build_dir)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not options.staging_dir:
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.error('You must provide a staging dir.')
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not options.input_file:
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser.error('You must provide an input file')
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not options.output_dir:
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.output_dir = options.build_dir
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not options.resource_file_path:
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    options.resource_file_path = os.path.join(options.build_dir,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              MINI_INSTALLER_INPUT_FILE)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return options
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if '__main__' == __name__:
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print sys.argv
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys.exit(main(_ParseOptions()))
607