# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides functionality common for all tools."""

import ctypes
import os
import re
import subprocess
import sys


def GetPath(name, **kwargs):
  """Computes a path to a tool.

  All tools understand the same 4 path-related arguments: 'path', 'dir',
  'prefix', and 'name'. When the 'path' argument is provided, it overrides the
  path to a tool. Otherwise, 'dir', 'prefix', and 'name' arguments, all of which
  are optional, are joined as {dir}/{prefix}{name} to compute the path.

  Args:
    name: A default name of a tool.
    **kwargs: A dictionary that optionally contains 'path', 'dir', 'prefix', and
        'name' arguments.

  Returns:
    The computed path.
  """
  if 'path' in kwargs:
    return kwargs['path']

  path = kwargs.get('prefix', '') + kwargs.get('name', name)
  if 'dir' in kwargs:
    path = os.path.join(kwargs['dir'], path)
  return path


def GetRuleName(rule_name_base, toolset):
  """Computes a Ninja name for target and host rules."""
  suffix = '' if toolset == 'target' else '_{0}'.format(toolset)
  return rule_name_base + suffix


def EstimateMaxConcurrentLinkers():
  """Estimates a number of dynamic linkers to run concurrently.

  The estimate takes into account available RAM and conservatively assumes that
  Chromium is being built.

  Returns:
    An estimated number of processes.
  """
  # TODO: Introduce _TryGetPhysicalMemoryInBytes().
  if sys.platform in ('win32', 'cygwin'):

    class MEMORYSTATUSEX(ctypes.Structure):
      _fields_ = [
          ('dwLength', ctypes.c_ulong),
          ('dwMemoryLoad', ctypes.c_ulong),
          ('ullTotalPhys', ctypes.c_ulonglong),
          ('ullAvailPhys', ctypes.c_ulonglong),
          ('ullTotalPageFile', ctypes.c_ulonglong),
          ('ullAvailPageFile', ctypes.c_ulonglong),
          ('ullTotalVirtual', ctypes.c_ulonglong),
          ('ullAvailVirtual', ctypes.c_ulonglong),
          ('sullAvailExtendedVirtual', ctypes.c_ulonglong),
      ]  # pylint: disable=invalid-name

    stat = MEMORYSTATUSEX()
    stat.dwLength = ctypes.sizeof(stat)
    ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))

    # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM
    # on a 64 GB machine.
    return max(1, stat.ullTotalPhys / (5 * (2**30)))  # total / 5GB
  elif sys.platform.startswith('linux'):
    if os.path.exists('/proc/meminfo'):
      with open('/proc/meminfo') as meminfo:
        memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB')
        for line in meminfo:
          match = memtotal_re.match(line)
          if not match:
            continue
          # Allow 6Gb per link on Linux because Gold is quite memory hungry
          return max(1, int(match.group(1)) / (6 * (2**20)))
    return 1
  elif sys.platform == 'darwin':
    try:
      avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize']))
      # A static library debug build of Chromium's unit_tests takes ~2.7GB, so
      # 4GB per ld process allows for some more bloat.
      return max(1, avail_bytes / (4 * (2**30)))  # total / 4GB
    except subprocess.CalledProcessError:
      return 1
  else:
    return 1
