15f9996aaSopenharmony_ci#!/usr/bin/env python
25f9996aaSopenharmony_ci# -*- coding: utf-8 -*-
35f9996aaSopenharmony_ci# Copyright (c) 2016 The Chromium Authors. All rights reserved.
45f9996aaSopenharmony_ci
55f9996aaSopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
65f9996aaSopenharmony_ci# found in the LICENSE file.
75f9996aaSopenharmony_ci
85f9996aaSopenharmony_ci"""Helper functions for gcc_toolchain.gni wrappers."""
95f9996aaSopenharmony_ci
105f9996aaSopenharmony_ciimport gzip
115f9996aaSopenharmony_ciimport os
125f9996aaSopenharmony_ciimport subprocess
135f9996aaSopenharmony_ciimport shutil
145f9996aaSopenharmony_ciimport threading
155f9996aaSopenharmony_ci
165f9996aaSopenharmony_ci_BAT_PREFIX = 'cmd /c call '
175f9996aaSopenharmony_ci
185f9996aaSopenharmony_ci
195f9996aaSopenharmony_cidef _gzip_then_delete(src_path, dest_path):
205f9996aaSopenharmony_ci    """ Results for ohos map file with GCC on a z620:
215f9996aaSopenharmony_ci    Uncompressed: 207MB
225f9996aaSopenharmony_ci    gzip -9: 16.4MB, takes 8.7 seconds.
235f9996aaSopenharmony_ci    gzip -1: 21.8MB, takes 2.0 seconds.
245f9996aaSopenharmony_ci    Piping directly from the linker via -print-map (or via -Map with a fifo)
255f9996aaSopenharmony_ci    adds a whopping 30-45 seconds!
265f9996aaSopenharmony_ci    """
275f9996aaSopenharmony_ci    with open(src_path, 'rb') as f_in, gzip.GzipFile(dest_path,
285f9996aaSopenharmony_ci                                                     'wb',
295f9996aaSopenharmony_ci                                                     1) as f_out:
305f9996aaSopenharmony_ci        shutil.copyfileobj(f_in, f_out)
315f9996aaSopenharmony_ci    os.unlink(src_path)
325f9996aaSopenharmony_ci
335f9996aaSopenharmony_ci
345f9996aaSopenharmony_cidef command_to_run(command):
355f9996aaSopenharmony_ci    """Generates commands compatible with Windows.
365f9996aaSopenharmony_ci
375f9996aaSopenharmony_ci    When running on a Windows host and using a toolchain whose tools are
385f9996aaSopenharmony_ci    actually wrapper scripts (i.e. .bat files on Windows) rather than binary
395f9996aaSopenharmony_ci    executables, the |command| to run has to be prefixed with this magic.
405f9996aaSopenharmony_ci    The GN toolchain definitions take care of that for when GN/Ninja is
415f9996aaSopenharmony_ci    running the tool directly.  When that command is passed in to this
425f9996aaSopenharmony_ci    script, it appears as a unitary string but needs to be split up so that
435f9996aaSopenharmony_ci    just 'cmd' is the actual command given to Python's subprocess module.
445f9996aaSopenharmony_ci
455f9996aaSopenharmony_ci    Args:
465f9996aaSopenharmony_ci      command: List containing the UNIX style |command|.
475f9996aaSopenharmony_ci
485f9996aaSopenharmony_ci    Returns:
495f9996aaSopenharmony_ci      A list containing the Windows version of the |command|.
505f9996aaSopenharmony_ci    """
515f9996aaSopenharmony_ci    if command[0].startswith(_BAT_PREFIX):
525f9996aaSopenharmony_ci        command = command[0].split(None, 3) + command[1:]
535f9996aaSopenharmony_ci    return command
545f9996aaSopenharmony_ci
555f9996aaSopenharmony_ci
565f9996aaSopenharmony_cidef run_link_with_optional_map_file(command, env=None, map_file=None):
575f9996aaSopenharmony_ci    """Runs the given command, adding in -Wl,-Map when |map_file| is given.
585f9996aaSopenharmony_ci
595f9996aaSopenharmony_ci    Also takes care of gzipping when |map_file| ends with .gz.
605f9996aaSopenharmony_ci
615f9996aaSopenharmony_ci    Args:
625f9996aaSopenharmony_ci      command: List of arguments comprising the command.
635f9996aaSopenharmony_ci      env: Environment variables.
645f9996aaSopenharmony_ci      map_file: Path to output map_file.
655f9996aaSopenharmony_ci
665f9996aaSopenharmony_ci    Returns:
675f9996aaSopenharmony_ci      The exit code of running |command|.
685f9996aaSopenharmony_ci    """
695f9996aaSopenharmony_ci    tmp_map_path = None
705f9996aaSopenharmony_ci    if map_file and map_file.endswith('.gz'):
715f9996aaSopenharmony_ci        tmp_map_path = map_file + '.tmp'
725f9996aaSopenharmony_ci        command.append('-Wl,-Map,' + tmp_map_path)
735f9996aaSopenharmony_ci    elif map_file:
745f9996aaSopenharmony_ci        command.append('-Wl,-Map,' + map_file)
755f9996aaSopenharmony_ci
765f9996aaSopenharmony_ci    result = subprocess.call(command, env=env)
775f9996aaSopenharmony_ci
785f9996aaSopenharmony_ci    if tmp_map_path and result == 0:
795f9996aaSopenharmony_ci        threading.Thread(
805f9996aaSopenharmony_ci            target=lambda: _gzip_then_delete(tmp_map_path, map_file)).start()
815f9996aaSopenharmony_ci    elif tmp_map_path and os.path.exists(tmp_map_path):
825f9996aaSopenharmony_ci        os.unlink(tmp_map_path)
835f9996aaSopenharmony_ci
845f9996aaSopenharmony_ci    return result
855f9996aaSopenharmony_ci
865f9996aaSopenharmony_ci
875f9996aaSopenharmony_cidef capture_command_stderr(command, env=None):
885f9996aaSopenharmony_ci    """Returns the stderr of a command.
895f9996aaSopenharmony_ci
905f9996aaSopenharmony_ci    Args:
915f9996aaSopenharmony_ci      command: A list containing the command and arguments.
925f9996aaSopenharmony_ci      env: Environment variables for the new process.
935f9996aaSopenharmony_ci    """
945f9996aaSopenharmony_ci    child = subprocess.Popen(command, stderr=subprocess.PIPE, env=env)
955f9996aaSopenharmony_ci    _, stderr = child.communicate()
965f9996aaSopenharmony_ci    return child.returncode, stderr
97