def main()

in scripts/merge_libraries.py [0:0]


def main(argv):
  global binutils_force_target_format
  binutils_force_target_format = FLAGS.force_binutils_target
  try:
    working_root = None
    input_paths = []
    for filename in argv[1:]:
      input_paths.append([filename, os.path.abspath(filename)])
    if not input_paths:
      logging.fatal("No input files specified")
    output_path = os.path.abspath(FLAGS.output)
    additional_input_paths = []
    for filename in FLAGS.scan_libs:
      additional_input_paths.append([filename, os.path.abspath(filename)])

    # Create the working directory.
    working_root = tempfile.mkdtemp(suffix="merge")
    if not working_root:
      raise Error("Couldn't create temp directory")

    # Add absolute paths to these commands if they specify any directory.
    FLAGS.binutils_ar_cmd = add_abspath(FLAGS.binutils_ar_cmd)
    FLAGS.binutils_nm_cmd = add_abspath(FLAGS.binutils_nm_cmd)
    FLAGS.binutils_objcopy_cmd = add_abspath(FLAGS.binutils_objcopy_cmd)
    FLAGS.demangle_cmds = [add_abspath(c) for c in FLAGS.demangle_cmds]
    FLAGS.cache = (os.path.abspath(FLAGS.cache) if FLAGS.cache else None)

    init_cache()

    # Scan through subset of libs in FLAGS.hide_c_symbols to find C symbols to
    # rename.
    rename_symbols = {}
    for libfile_and_regex in FLAGS.hide_c_symbols:
      if ':' not in libfile_and_regex:
        libfile_and_regex += ':.'
      [libfile, regex] = libfile_and_regex.split(":", 1)
      logging.debug("Scanning for C symbols in %s", libfile)
      regex_compiled = re.compile(regex)
      if os.path.abspath(libfile) in _cache["symbols"]:
        (defined_symbols,
         all_symbols) = _cache["symbols"][os.path.abspath(libfile)]
      else:
        (defined_symbols, all_symbols) = read_symbols_from_archive(libfile)
        _cache["symbols"][os.path.abspath(libfile)] = (defined_symbols,
                                                       all_symbols)
      for symbol in defined_symbols:
        # For C symbols, only use them if they are defined.
        if (not is_cpp_symbol(symbol)) and regex_compiled.match(symbol):
          rename_symbols.update(rename_symbol(symbol))

    os.chdir(working_root)

    if FLAGS.hide_cpp_namespaces or FLAGS.auto_hide_cpp_namespaces:
      init_demanglers()
      # Scan through all input libraries for C++ symbols matching any of the
      # hide_cpp_namespaces.
      cpp_symbols = set()
      for input_path in input_paths + additional_input_paths:
        logging.debug("Scanning for C++ symbols in %s", input_path[1])
        if os.path.abspath(input_path[1]) in _cache["symbols"]:
          (defined_symbols,
           all_symbols) = _cache["symbols"][os.path.abspath(input_path[1])]
        else:
          (defined_symbols,
           all_symbols) = read_symbols_from_archive(input_path[1])
          _cache["symbols"][os.path.abspath(input_path[1])] = (defined_symbols,
                                                               all_symbols)
        cpp_symbols.update(all_symbols
                           if FLAGS.rename_external_cpp_symbols
                           else defined_symbols)

      # If we are set to scan for namespaces, do that now.
      if FLAGS.auto_hide_cpp_namespaces:
        add_automatic_namespaces(defined_symbols)

      for symbol in cpp_symbols:
        if is_cpp_symbol(symbol):
          rename_symbols.update(rename_symbol(symbol))
      shutdown_demanglers()

    logging.debug("Creating symbol redefinition file for %d symbols",
                  len(rename_symbols))
    symbol_redefinition_file = create_symbol_redefinition_file(rename_symbols)

    # List of all object files, which will be renamed to have unique names.
    all_obj_files = []
    for input_path in input_paths:
      logging.debug("Checking input archive %s", input_path[1])
      # Create a unique directory name from a hash of the input filename.
      lib_name_hash = hashlib.md5(
          input_path[0].encode(DEFAULT_ENCODING)).hexdigest()
      (obj_file_list, errors) = list_objects_in_archive(input_path[1])
      if errors:
        logging.fatal("Error listing archive %s: %s", input_path[1], errors)

      # If any of the filenames in this archive contain a "/" or "\", we need to
      # replace them with "_".
      obj_file_renames = {}
      for obj_file in obj_file_list:
        if "/" in obj_file or "\\" in obj_file:
          # Extracting this will fail because it contains subdirectories.
          obj_file_bin = obj_file.encode(DEFAULT_ENCODING)
          new_obj_file_bin = re.sub(b"[^0-9a-zA-Z_.]", b"_", obj_file_bin)
          old_obj_regex_bin = re.sub(b"[^0-9a-zA-Z_.]", b".", obj_file_bin)
          obj_file_renames[old_obj_regex_bin] = new_obj_file_bin
      if obj_file_renames:
        # We renamed some object files within the .a file.
        input_path[1] = replace_strings_in_archive(input_path[1],
                                                   obj_file_renames)

      logging.debug("Extracting input archive %s", input_path[1])
      (obj_file_list, errors) = extract_archive(input_path[1])
      if errors:
        logging.fatal("Error extracting archive %s: %s", input_path[1], errors)

      if symbol_redefinition_file:
        logging.debug("Redefining symbols in %d files", len(obj_file_list))

      for obj_file in obj_file_list:
        new_obj_file = "%s_%s" % (lib_name_hash, obj_file)
        if len(new_obj_file) > 255:
          # Filename is above the limit, hash the first N characters to bring
          # the length down to 255 or less.
          # Hashes are 32 characters plus an underscore.
          # If len = 256 hash the first 34 chars.
          # If len = 257 hash the first 35 chars.
          split = len(new_obj_file) - (255 - 32 - 1)
          new_obj_file = "%s_%s" % (hashlib.md5(
              new_obj_file[:split].encode(DEFAULT_ENCODING)).hexdigest(),
                                    new_obj_file[split:])

        # Move the .o file to its new name, renaming symbols if needed.
        move_object_file(obj_file, new_obj_file, symbol_redefinition_file.name
                         if symbol_redefinition_file else None)
        all_obj_files.append(new_obj_file)

    symbol_redefinition_file = None

    # Remove any existing output lib so we can create a new one from scratch.
    if os.path.isfile(output_path):
      os.remove(output_path)

    if (FLAGS.skip_creating_archives):
      output_path_dir = output_path + ".dir"
      logging.debug("Copying object files to %s", output_path_dir)
      if not os.path.exists(output_path_dir):
        os.makedirs(output_path_dir)
      for obj_file in all_obj_files:
        logging.debug("Copy %s to %s" % (obj_file, os.path.join(output_path_dir, os.path.basename(obj_file))))
        shutil.copyfile(obj_file, os.path.join(output_path_dir, os.path.basename(obj_file)))
    else:
      logging.debug("Creating output archive %s", output_path)
      create_archive(output_path, all_obj_files, input_path[1])

    shutdown_cache()

  except Exception as e:
    logging.error("Got error: %s", e)
    raise
  finally:
    if working_root:
      shutil.rmtree(working_root)

  return 0