[M120 Migration][Gamepad]Add gamepad event latency Test code
[platform/framework/web/chromium-efl.git] / build / toolchain / wrapper_utils.py
1 # Copyright 2016 The Chromium Authors
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Helper functions for gcc_toolchain.gni wrappers."""
6
7 import gzip
8 import os
9 import re
10 import subprocess
11 import shlex
12 import shutil
13 import sys
14 import threading
15
16 import whole_archive
17
18 _BAT_PREFIX = 'cmd /c call '
19
20
21 def _GzipThenDelete(src_path, dest_path):
22   # Results for Android map file with GCC on a z620:
23   # Uncompressed: 207MB
24   # gzip -9: 16.4MB, takes 8.7 seconds.
25   # gzip -1: 21.8MB, takes 2.0 seconds.
26   # Piping directly from the linker via -print-map (or via -Map with a fifo)
27   # adds a whopping 30-45 seconds!
28   with open(src_path, 'rb') as f_in, gzip.GzipFile(dest_path, 'wb', 1) as f_out:
29     shutil.copyfileobj(f_in, f_out)
30   os.unlink(src_path)
31
32
33 def CommandToRun(command):
34   """Generates commands compatible with Windows.
35
36   When running on a Windows host and using a toolchain whose tools are
37   actually wrapper scripts (i.e. .bat files on Windows) rather than binary
38   executables, the |command| to run has to be prefixed with this magic.
39   The GN toolchain definitions take care of that for when GN/Ninja is
40   running the tool directly.  When that command is passed in to this
41   script, it appears as a unitary string but needs to be split up so that
42   just 'cmd' is the actual command given to Python's subprocess module.
43
44   Args:
45     command: List containing the UNIX style |command|.
46
47   Returns:
48     A list containing the Windows version of the |command|.
49   """
50   if command[0].startswith(_BAT_PREFIX):
51     command = command[0].split(None, 3) + command[1:]
52   return command
53
54
55 def RunLinkWithOptionalMapFile(command, env=None, map_file=None):
56   """Runs the given command, adding in -Wl,-Map when |map_file| is given.
57
58   Also takes care of gzipping when |map_file| ends with .gz.
59
60   Args:
61     command: List of arguments comprising the command.
62     env: Environment variables.
63     map_file: Path to output map_file.
64
65   Returns:
66     The exit code of running |command|.
67   """
68   tmp_map_path = None
69   if map_file and map_file.endswith('.gz'):
70     tmp_map_path = map_file + '.tmp'
71     command.append('-Wl,-Map,' + tmp_map_path)
72   elif map_file:
73     command.append('-Wl,-Map,' + map_file)
74
75   # We want to link rlibs as --whole-archive if they are part of a unit test
76   # target. This is determined by switch `-LinkWrapper,add-whole-archive`.
77   command = whole_archive.wrap_with_whole_archive(command)
78
79   result = subprocess.call(command, env=env)
80
81   if tmp_map_path and result == 0:
82     threading.Thread(
83         target=lambda: _GzipThenDelete(tmp_map_path, map_file)).start()
84   elif tmp_map_path and os.path.exists(tmp_map_path):
85     os.unlink(tmp_map_path)
86
87   return result
88
89
90 def CaptureCommandStderr(command, env=None):
91   """Returns the stderr of a command.
92
93   Args:
94     command: A list containing the command and arguments.
95     env: Environment variables for the new process.
96   """
97   child = subprocess.Popen(command, stderr=subprocess.PIPE, env=env)
98   _, stderr = child.communicate()
99   return child.returncode, stderr