| Index: chrome/tools/build/win/create_installer_archive.py
|
| ===================================================================
|
| --- chrome/tools/build/win/create_installer_archive.py (revision 110935)
|
| +++ chrome/tools/build/win/create_installer_archive.py (working copy)
|
| @@ -14,10 +14,10 @@
|
|
|
| import ConfigParser
|
| import glob
|
| +import md5
|
| import optparse
|
| import os
|
| import shutil
|
| -import subprocess
|
| import sys
|
|
|
|
|
| @@ -35,14 +35,24 @@
|
| COMPRESSED_FILE_EXT = ".packed.7z" # extension of patch archive file
|
| COURGETTE_EXEC = "courgette.exe"
|
| MINI_INSTALLER_INPUT_FILE = "packed_files.txt"
|
| +PACKED_FILE_COMMENTS = """
|
| +// This file is automatically generated by create_installer_archive.py.
|
| +// It contains the resource entries that are going to be linked inside
|
| +// mini_installer.exe. For each file to be linked there should be two
|
| +// lines:
|
| +// - The first line contains the output filename (without path) and the
|
| +// type of the resource ('BN' - not compressed , 'BL' - LZ compressed,
|
| +// 'B7' - LZMA compressed)
|
| +// - The second line contains the path to the input file. Uses '/' to
|
| +// separate path components.
|
| +"""
|
| PATCH_FILE_EXT = '.diff'
|
| SETUP_EXEC = "setup.exe"
|
| SETUP_PATCH_FILE_PREFIX = "setup_patch"
|
| TEMP_ARCHIVE_DIR = "temp_installer_archive"
|
| VERSION_FILE = "VERSION"
|
|
|
| -
|
| -def BuildVersion(build_dir):
|
| +def BuildVersion(output_dir):
|
| """Returns the full build version string constructed from information in
|
| VERSION_FILE. Any segment not found in that file will default to '0'.
|
| """
|
| @@ -50,7 +60,7 @@
|
| minor = 0
|
| build = 0
|
| patch = 0
|
| - for line in open(os.path.join(build_dir, '../../chrome', VERSION_FILE), 'r'):
|
| + for line in open(os.path.join(output_dir, "..", "..", "chrome", VERSION_FILE), 'r'):
|
| line = line.rstrip()
|
| if line.startswith('MAJOR='):
|
| major = line[6:]
|
| @@ -62,11 +72,9 @@
|
| patch = line[6:]
|
| return '%s.%s.%s.%s' % (major, minor, build, patch)
|
|
|
| -
|
| -def CompressUsingLZMA(build_dir, compressed_file, input_file):
|
| - lzma_exec = GetLZMAExec(build_dir)
|
| - cmd = [lzma_exec,
|
| - 'a', '-t7z',
|
| +def CompressUsingLZMA(output_dir, compressed_file, input_file):
|
| + lzma_exec = GetLZMAExec(output_dir)
|
| + cmd = ('%s a -t7z '
|
| # Flags equivalent to -mx9 (ultra) but with the bcj2 turned on (exe
|
| # pre-filter). This results in a ~2.3MB decrease in installer size on
|
| # a 24MB installer.
|
| @@ -75,34 +83,36 @@
|
| # 26bit = 64MB. This results in an additional ~3.5MB decrease.
|
| # Older 7zip versions can support these settings, as these changes
|
| # rely on existing functionality in the lzma format.
|
| - '-m0=BCJ2',
|
| - '-m1=LZMA:d26:fb64',
|
| - '-m2=LZMA:d20:fb64:mf=bt2',
|
| - '-m3=LZMA:d20:fb64:mf=bt2',
|
| - '-mb0:1',
|
| - '-mb0s1:2',
|
| - '-mb0s2:3',
|
| - compressed_file,
|
| - input_file,]
|
| + '-m0=BCJ2 '
|
| + '-m1=LZMA:d26:fb64 '
|
| + '-m2=LZMA:d20:fb64:mf=bt2 '
|
| + '-m3=LZMA:d20:fb64:mf=bt2 '
|
| + '-mb0:1 -mb0s1:2 '
|
| + '-mb0s2:3 '
|
| + '"%s" "%s"') % (lzma_exec, compressed_file, input_file)
|
| if os.path.exists(compressed_file):
|
| os.remove(compressed_file)
|
| RunSystemCommand(cmd)
|
|
|
| -
|
| -def CopyAllFilesToStagingDir(config, distribution, staging_dir, build_dir):
|
| +def CopyAllFilesToStagingDir(config, distribution, staging_dir, output_dir):
|
| """Copies the files required for installer archive.
|
| Copies all common files required for various distributions of Chromium and
|
| also files for the specific Chromium build specified by distribution.
|
| """
|
| - CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, build_dir)
|
| + CopySectionFilesToStagingDir(config, 'GENERAL', staging_dir, output_dir)
|
| if distribution:
|
| if len(distribution) > 1 and distribution[0] == '_':
|
| distribution = distribution[1:]
|
| CopySectionFilesToStagingDir(config, distribution.upper(),
|
| - staging_dir, build_dir)
|
| + staging_dir, output_dir)
|
|
|
| +def IsChromeFrameFile(file):
|
| + for cf_file in ['npchrome_frame', 'chrome_launcher']:
|
| + if file.lower().find(cf_file) != -1:
|
| + return True
|
| + return False
|
|
|
| -def CopySectionFilesToStagingDir(config, section, staging_dir, build_dir):
|
| +def CopySectionFilesToStagingDir(config, section, staging_dir, output_dir):
|
| """Copies installer archive files specified in section to staging dir.
|
| This method copies reads section from config file and copies all the files
|
| specified to staging dir.
|
| @@ -114,55 +124,63 @@
|
| dst = os.path.join(staging_dir, config.get(section, option))
|
| if not os.path.exists(dst):
|
| os.makedirs(dst)
|
| - for file in glob.glob(os.path.join(build_dir, option)):
|
| - shutil.copy(file, dst)
|
| + for file in glob.glob(os.path.join(output_dir, option)):
|
| + if IsChromeFrameFile(file):
|
| + try:
|
| + shutil.copy(file, dst)
|
| + except IOError:
|
| + # TODO(robertshield): Temporary hack to work around problems building
|
| + # Chrome Frame binaries on non-Chrome Frame builders. Remove this
|
| + # asap.
|
| + print 'Error attempting to copy ' + file + ' to ' + dst
|
| + else:
|
| + shutil.copy(file, dst)
|
|
|
| def GenerateDiffPatch(options, orig_file, new_file, patch_file):
|
| if (options.diff_algorithm == "COURGETTE"):
|
| exe_file = os.path.join(options.last_chrome_installer, COURGETTE_EXEC)
|
| cmd = '%s -gen "%s" "%s" "%s"' % (exe_file, orig_file, new_file, patch_file)
|
| else:
|
| - exe_file = os.path.join(options.build_dir, BSDIFF_EXEC)
|
| - cmd = [exe_file, orig_file, new_file, patch_file,]
|
| + exe_file = os.path.join(options.output_dir, BSDIFF_EXEC)
|
| + cmd = '%s "%s" "%s" "%s"' % (exe_file, orig_file, new_file, patch_file)
|
| RunSystemCommand(cmd)
|
|
|
| -def GetLZMAExec(build_dir):
|
| - lzma_exec = os.path.join(build_dir, "..", "..", "third_party",
|
| +def GetLZMAExec(output_dir):
|
| + lzma_exec = os.path.join(output_dir, "..", "..", "third_party",
|
| "lzma_sdk", "Executable", "7za.exe")
|
| return lzma_exec
|
|
|
| -def GetPrevVersion(build_dir, temp_dir, last_chrome_installer):
|
| +def GetPrevVersion(output_dir, temp_dir, last_chrome_installer):
|
| if not last_chrome_installer:
|
| return ''
|
|
|
| - lzma_exec = GetLZMAExec(options.build_dir)
|
| + lzma_exec = GetLZMAExec(options.output_dir)
|
| prev_archive_file = os.path.join(options.last_chrome_installer,
|
| options.output_name + ARCHIVE_SUFFIX)
|
| - cmd = [lzma_exec,
|
| - 'x',
|
| - '-o"%s"' % temp_dir,
|
| - prev_archive_file,
|
| - 'Chrome-bin/*/chrome.dll',]
|
| + cmd = '%s x -o"%s" "%s" Chrome-bin/*/chrome.dll' % (lzma_exec, temp_dir,
|
| + prev_archive_file)
|
| RunSystemCommand(cmd)
|
| dll_path = glob.glob(os.path.join(temp_dir, 'Chrome-bin', '*', 'chrome.dll'))
|
| return os.path.split(os.path.split(dll_path[0])[0])[1]
|
|
|
| -def MakeStagingDirectories(staging_dir):
|
| +def MakeStagingDirectories(output_dir):
|
| """Creates a staging path for installer archive. If directory exists already,
|
| deletes the existing directory.
|
| """
|
| - file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
|
| + prefixed_archive_dir = (options.archive_prefix or "") + ARCHIVE_DIR
|
| + file_path = os.path.join(output_dir, prefixed_archive_dir)
|
| if os.path.exists(file_path):
|
| shutil.rmtree(file_path)
|
| os.makedirs(file_path)
|
|
|
| - temp_file_path = os.path.join(staging_dir, TEMP_ARCHIVE_DIR)
|
| + prefixed_temp_archive_dir = (options.archive_prefix or "") + TEMP_ARCHIVE_DIR
|
| + temp_file_path = os.path.join(output_dir, prefixed_temp_archive_dir)
|
| if os.path.exists(temp_file_path):
|
| shutil.rmtree(temp_file_path)
|
| os.makedirs(temp_file_path)
|
| return (file_path, temp_file_path)
|
|
|
| -def Readconfig(build_dir, input_file, current_version):
|
| +def Readconfig(output_dir, input_file, current_version):
|
| """Reads config information from input file after setting default value of
|
| global variabes.
|
| """
|
| @@ -175,8 +193,8 @@
|
| return config
|
|
|
| def RunSystemCommand(cmd):
|
| - print 'Running', cmd
|
| - exit_code = subprocess.call(cmd)
|
| + print 'Running [' + cmd + ']'
|
| + exit_code = os.system(cmd)
|
| if (exit_code != 0):
|
| raise Exception("Error while running cmd: %s, exit_code: %s" %
|
| (cmd, exit_code))
|
| @@ -185,15 +203,11 @@
|
| """Creates a new installer archive file after deleting any existing old file.
|
| """
|
| # First create an uncompressed archive file for the current build (chrome.7z)
|
| - lzma_exec = GetLZMAExec(options.build_dir)
|
| - archive_file = os.path.join(options.build_dir,
|
| + lzma_exec = GetLZMAExec(options.output_dir)
|
| + archive_file = os.path.join(options.output_dir,
|
| options.output_name + ARCHIVE_SUFFIX)
|
| - cmd = [lzma_exec,
|
| - 'a',
|
| - '-t7z',
|
| - archive_file,
|
| - os.path.join(staging_dir, CHROME_DIR),
|
| - '-mx0',]
|
| + cmd = '%s a -t7z "%s" "%s" -mx0' % (lzma_exec, archive_file,
|
| + os.path.join(staging_dir, CHROME_DIR))
|
| # There doesnt seem to be any way in 7za.exe to override existing file so
|
| # we always delete before creating a new one.
|
| if not os.path.exists(archive_file):
|
| @@ -209,7 +223,7 @@
|
| if options.last_chrome_installer:
|
| prev_archive_file = os.path.join(options.last_chrome_installer,
|
| options.output_name + ARCHIVE_SUFFIX)
|
| - patch_file = os.path.join(options.build_dir, patch_name_prefix +
|
| + patch_file = os.path.join(options.output_dir, patch_name_prefix +
|
| PATCH_FILE_EXT)
|
| GenerateDiffPatch(options, prev_archive_file, archive_file, patch_file)
|
| compressed_archive_file = patch_name_prefix + '_' + \
|
| @@ -220,9 +234,9 @@
|
| compressed_archive_file = options.output_name + COMPRESSED_ARCHIVE_SUFFIX
|
| orig_file = archive_file
|
|
|
| - compressed_archive_file_path = os.path.join(options.build_dir,
|
| + compressed_archive_file_path = os.path.join(options.output_dir,
|
| compressed_archive_file)
|
| - CompressUsingLZMA(options.build_dir, compressed_archive_file_path, orig_file)
|
| + CompressUsingLZMA(options.output_dir, compressed_archive_file_path, orig_file)
|
|
|
| return compressed_archive_file
|
|
|
| @@ -236,88 +250,63 @@
|
| raise Exception(
|
| "To use DIFF for setup.exe, --last_chrome_installer is needed.")
|
| prev_setup_file = os.path.join(options.last_chrome_installer, SETUP_EXEC)
|
| - new_setup_file = os.path.join(options.build_dir, SETUP_EXEC)
|
| - patch_file = os.path.join(options.build_dir, SETUP_PATCH_FILE_PREFIX +
|
| + new_setup_file = os.path.join(options.output_dir, SETUP_EXEC)
|
| + patch_file = os.path.join(options.output_dir, SETUP_PATCH_FILE_PREFIX +
|
| PATCH_FILE_EXT)
|
| GenerateDiffPatch(options, prev_setup_file, new_setup_file, patch_file)
|
| setup_file = SETUP_PATCH_FILE_PREFIX + '_' + current_version + \
|
| '_from_' + prev_version + COMPRESSED_FILE_EXT
|
| - setup_file_path = os.path.join(options.build_dir, setup_file)
|
| - CompressUsingLZMA(options.build_dir, setup_file_path, patch_file)
|
| + setup_file_path = os.path.join(options.output_dir, setup_file)
|
| + CompressUsingLZMA(options.output_dir, setup_file_path, patch_file)
|
| else:
|
| - cmd = ['makecab.exe',
|
| - '/D', 'CompressionType=LZX',
|
| - '/V1',
|
| - '/L', options.build_dir,
|
| - os.path.join(options.build_dir, SETUP_EXEC),]
|
| + cmd = 'makecab.exe /D CompressionType=LZX /V1 /L "%s" "%s"' % (
|
| + options.output_dir, os.path.join(options.output_dir, SETUP_EXEC))
|
| RunSystemCommand(cmd)
|
| - setup_file = SETUP_EXEC[:-1] + "_"
|
| + setup_file = SETUP_EXEC[:len(SETUP_EXEC) - 1] + "_"
|
| return setup_file
|
|
|
|
|
| -_RESOURCE_FILE_TEMPLATE = """
|
| -// This file is automatically generated by create_installer_archive.py.
|
| -// It contains the resource entries that are going to be linked inside
|
| -// mini_installer.exe. For each file to be linked there should be two
|
| -// lines:
|
| -// - The first line contains the output filename (without path) and the
|
| -// type of the resource ('BN' - not compressed , 'BL' - LZ compressed,
|
| -// 'B7' - LZMA compressed)
|
| -// - The second line contains the path to the input file. Uses '/' to
|
| -// separate path components.
|
| -
|
| -%(setup_file)s %(setup_file_resource_type)s
|
| - %(setup_file_path)s
|
| -
|
| -%(archive_file)s B7
|
| - %(archive_file_path)s
|
| -"""
|
| -
|
| -
|
| -def CreateResourceInputFile(
|
| - build_dir, setup_format, archive_file, setup_file, resource_file_path):
|
| +def CreateResourceInputFile(output_dir, setup_format, archive_file, setup_file):
|
| """Creates resource input file (packed_files.txt) for mini_installer project.
|
|
|
| This method checks the format of setup.exe being used and according sets
|
| its resource type.
|
| """
|
| setup_resource_type = "BL"
|
| - if (setup_format == "FULL"):
|
| + if (options.setup_exe_format == "FULL"):
|
| setup_resource_type = "BN"
|
| - elif (setup_format == "DIFF"):
|
| + elif (options.setup_exe_format == "DIFF"):
|
| setup_resource_type = "B7"
|
| + setup_file_entry = "%s\t\t%s\n\"%s\"" % (setup_file, setup_resource_type,
|
| + os.path.join(output_dir, setup_file).replace("\\","/"))
|
|
|
| - # Expand the resource file template.
|
| - args = {
|
| - 'setup_file': setup_file,
|
| - 'setup_file_resource_type': setup_resource_type,
|
| - 'setup_file_path':
|
| - os.path.join(build_dir, setup_file).replace("\\","/"),
|
| - 'archive_file': archive_file,
|
| - 'archive_file_path':
|
| - os.path.join(build_dir, archive_file).replace("\\","/"),
|
| - }
|
| - resource_file = _RESOURCE_FILE_TEMPLATE % args
|
| + archive_file_entry = "\n%s\t\tB7\n\"%s\"\n" % (archive_file,
|
| + os.path.join(output_dir, archive_file).replace("\\","/"))
|
| + output_file = os.path.join(output_dir, MINI_INSTALLER_INPUT_FILE)
|
| + f = open(output_file, 'w')
|
| + try:
|
| + f.write(PACKED_FILE_COMMENTS)
|
| + f.write(setup_file_entry)
|
| + f.write(archive_file_entry)
|
| + finally:
|
| + f.close()
|
|
|
| - with open(resource_file_path, 'w') as f:
|
| - f.write(resource_file)
|
|
|
| -
|
| def main(options):
|
| """Main method that reads input file, creates archive file and write
|
| resource input file.
|
| """
|
| - current_version = BuildVersion(options.build_dir)
|
| + current_version = BuildVersion(options.output_dir)
|
|
|
| - config = Readconfig(options.build_dir, options.input_file, current_version)
|
| + config = Readconfig(options.output_dir, options.input_file, current_version)
|
|
|
| - (staging_dir, temp_dir) = MakeStagingDirectories(options.staging_dir)
|
| + (staging_dir, temp_dir) = MakeStagingDirectories(options.output_dir)
|
|
|
| - prev_version = GetPrevVersion(options.build_dir, temp_dir,
|
| + prev_version = GetPrevVersion(options.output_dir, temp_dir,
|
| options.last_chrome_installer)
|
|
|
| CopyAllFilesToStagingDir(config, options.distribution,
|
| - staging_dir, options.build_dir)
|
| + staging_dir, options.output_dir)
|
|
|
| version_numbers = current_version.split('.')
|
| current_build_number = version_numbers[2] + '.' + version_numbers[3]
|
| @@ -334,54 +323,34 @@
|
| setup_file = PrepareSetupExec(options, staging_dir,
|
| current_build_number, prev_build_number)
|
|
|
| - CreateResourceInputFile(options.build_dir, options.setup_exe_format,
|
| - archive_file, setup_file, options.resource_file_path)
|
| + CreateResourceInputFile(options.output_dir, options.setup_exe_format,
|
| + archive_file, setup_file)
|
|
|
| -def _ParseOptions():
|
| - parser = optparse.OptionParser()
|
| - parser.add_option('-i', '--input_file',
|
| - help='Input file describing which files to archive.')
|
| - parser.add_option('-o', '--build_dir',
|
| - help='Build directory. The paths in input_file are relative to this.')
|
| - parser.add_option('--staging_dir',
|
| - help='Staging directory where intermediate files and directories '
|
| - 'will be created'),
|
| - parser.add_option('--resource_file_path',
|
| - help='The path where the resource file will be output. '
|
| - 'Defaults to %s in the build directory.' %
|
| - MINI_INSTALLER_INPUT_FILE),
|
| - parser.add_option('-d', '--distribution',
|
| +
|
| +if '__main__' == __name__:
|
| + option_parser = optparse.OptionParser()
|
| + option_parser.add_option('-o', '--output_dir', help='Output directory')
|
| + option_parser.add_option('-i', '--input_file', help='Input file')
|
| + option_parser.add_option('-d', '--distribution',
|
| help='Name of Chromium Distribution. Optional.')
|
| - parser.add_option('-s', '--skip_rebuild_archive',
|
| + option_parser.add_option('-s', '--skip_rebuild_archive',
|
| default="False", help='Skip re-building Chrome.7z archive if it exists.')
|
| - parser.add_option('-l', '--last_chrome_installer',
|
| - help='Generate differential installer. The value of this parameter '
|
| - 'specifies the directory that contains base versions of '
|
| - 'setup.exe, courgette.exe (if --diff_algorithm is COURGETTE) '
|
| + option_parser.add_option('-l', '--last_chrome_installer',
|
| + help='Generate differential installer. The value of this parameter ' +
|
| + 'specifies the directory that contains base versions of ' +
|
| + 'setup.exe, courgette.exe (if --diff_algorithm is COURGETTE) ' +
|
| '& chrome.7z.')
|
| - parser.add_option('-f', '--setup_exe_format', default='COMPRESSED',
|
| + option_parser.add_option('-p', '--archive_prefix',
|
| + help='Specifies a prefix to the archive path. Useful if building ' +
|
| + 'multiple installer archives.')
|
| + option_parser.add_option('-f', '--setup_exe_format', default='COMPRESSED',
|
| help='How setup.exe should be included {COMPRESSED|DIFF|FULL}.')
|
| - parser.add_option('-a', '--diff_algorithm', default='BSDIFF',
|
| - help='Diff algorithm to use when generating differential patches '
|
| + option_parser.add_option('-a', '--diff_algorithm', default='BSDIFF',
|
| + help='Diff algorithm to use when generating differential patches ' +
|
| '{BSDIFF|COURGETTE}.')
|
| - parser.add_option('-n', '--output_name', default='chrome',
|
| + option_parser.add_option('-n', '--output_name', default='chrome',
|
| help='Name used to prefix names of generated archives.')
|
|
|
| - options, args = parser.parse_args()
|
| -
|
| - if not options.build_dir:
|
| - parser.error('You must provide a build dir.')
|
| -
|
| - if not options.staging_dir:
|
| - parser.error('You must provide a staging dir.')
|
| -
|
| - if not options.resource_file_path:
|
| - options.options.resource_file_path = os.path.join(options.build_dir,
|
| - MINI_INSTALLER_INPUT_FILE)
|
| -
|
| + options, args = option_parser.parse_args()
|
| print sys.argv
|
| - return options
|
| -
|
| -
|
| -if '__main__' == __name__:
|
| - sys.exit(main(_ParseOptions()))
|
| + sys.exit(main(options))
|
|
|