| #!/usr/bin/env python3 |
| # Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| # for details. All rights reserved. Use of this source code is governed by a |
| # BSD-style license that can be found in the LICENSE file. |
| # |
| # This python script creates a tar archive and a C++ source file which contains |
| # the tar archive as an array of bytes. |
| |
| import os |
| import sys |
| from os.path import join, splitext |
| import time |
| from optparse import OptionParser |
| from datetime import date |
| import tarfile |
| import tempfile |
| import gzip |
| |
| |
| def CreateTarArchive(tar_path, client_root, compress, files): |
| mode_string = 'w' |
| tar = tarfile.open(tar_path, mode=mode_string) |
| for input_file_name in files: |
| # Chop off client_root. |
| archive_file_name = input_file_name[len(client_root):] |
| # Replace back slash with forward slash. So we do not have Windows paths. |
| archive_file_name = archive_file_name.replace("\\", "/") |
| # Open input file and add it to the archive. |
| with open(input_file_name, 'rb') as input_file: |
| tarInfo = tarfile.TarInfo(name=archive_file_name) |
| input_file.seek(0, 2) |
| tarInfo.size = input_file.tell() |
| tarInfo.mtime = 0 # For deterministic builds. |
| input_file.seek(0) |
| tar.addfile(tarInfo, fileobj=input_file) |
| tar.close() |
| if compress: |
| with open(tar_path, "rb") as fin: |
| uncompressed = fin.read() |
| with open(tar_path, "wb") as fout: |
| # mtime=0 for deterministic builds. |
| gz = gzip.GzipFile(fileobj=fout, mode="wb", filename="", mtime=0) |
| gz.write(uncompressed) |
| gz.close() |
| |
| |
| def MakeArchive(options): |
| if not options.client_root: |
| sys.stderr.write('--client_root not specified') |
| return -1 |
| |
| files = [] |
| for dirname, dirnames, filenames in os.walk(options.client_root): |
| # strip out all dot files. |
| filenames = [f for f in filenames if not f[0] == '.'] |
| dirnames[:] = [d for d in dirnames if not d[0] == '.'] |
| for f in filenames: |
| src_path = os.path.join(dirname, f) |
| if (os.path.isdir(src_path)): |
| continue |
| files.append(src_path) |
| |
| # Ensure consistent file ordering for reproducible builds. |
| files.sort() |
| |
| # Write out archive. |
| CreateTarArchive(options.tar_output, options.client_root, options.compress, |
| files) |
| return 0 |
| |
| |
| def WriteCCFile( |
| output_file, |
| outer_namespace, |
| inner_namespace, |
| name, |
| tar_archive, |
| ): |
| with open(output_file, 'w') as out: |
| out.write(''' |
| // Copyright (c) %d, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| ''' % date.today().year) |
| out.write(''' |
| |
| #include <stdint.h> |
| |
| ''') |
| out.write('namespace %s {\n' % outer_namespace) |
| if inner_namespace != None: |
| out.write('namespace %s {\n' % inner_namespace) |
| out.write('\n\n') |
| # Write the byte contents of the archive as a comma separated list of |
| # integers, one integer for each byte. |
| out.write('static const uint8_t %s_[] = {\n' % name) |
| line = ' ' |
| lineCounter = 0 |
| for byte in tar_archive: |
| line += r" %d," % (byte if isinstance(byte, int) else ord(byte)) |
| lineCounter += 1 |
| if lineCounter == 10: |
| out.write(line + '\n') |
| line = ' ' |
| lineCounter = 0 |
| if lineCounter != 0: |
| out.write(line + '\n') |
| out.write('};\n') |
| out.write('\nunsigned int %s_len = %d;\n' % (name, len(tar_archive))) |
| out.write('\nconst uint8_t* %s = %s_;\n\n' % (name, name)) |
| if inner_namespace != None: |
| out.write('} // namespace %s\n' % inner_namespace) |
| out.write('} // namespace %s\n' % outer_namespace) |
| |
| |
| def MakeCCFile(options): |
| if not options.output: |
| sys.stderr.write('--output not specified\n') |
| return -1 |
| if not options.name: |
| sys.stderr.write('--name not specified\n') |
| return -1 |
| if not options.tar_input: |
| sys.stderr.write('--tar_input not specified\n') |
| return -1 |
| |
| # Read it back in. |
| with open(options.tar_input, 'rb') as tar_file: |
| tar_archive = tar_file.read() |
| |
| # Write CC file. |
| WriteCCFile(options.output, options.outer_namespace, |
| options.inner_namespace, options.name, tar_archive) |
| return 0 |
| |
| |
| def Main(args): |
| try: |
| # Parse input. |
| parser = OptionParser() |
| parser.add_option( |
| "--output", action="store", type="string", help="output file name") |
| parser.add_option("--tar_input",\ |
| action="store", type="string", |
| help="input tar archive") |
| parser.add_option( |
| "--tar_output", |
| action="store", |
| type="string", |
| help="tar output file name") |
| parser.add_option( |
| "--outer_namespace", |
| action="store", |
| type="string", |
| help="outer C++ namespace", |
| default="dart") |
| parser.add_option( |
| "--inner_namespace", |
| action="store", |
| type="string", |
| help="inner C++ namespace", |
| default="bin") |
| parser.add_option( |
| "--name", |
| action="store", |
| type="string", |
| help="name of tar archive symbol") |
| parser.add_option("--compress", action="store_true", default=False) |
| parser.add_option( |
| "--client_root", |
| action="store", |
| type="string", |
| help="root directory client resources") |
| |
| (options, args) = parser.parse_args() |
| |
| if options.tar_output: |
| return MakeArchive(options) |
| else: |
| return MakeCCFile(options) |
| |
| except Exception as inst: |
| sys.stderr.write('create_archive.py exception\n') |
| sys.stderr.write(str(inst)) |
| sys.stderr.write('\n') |
| return -1 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(Main(sys.argv)) |