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