#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright 2012-2021 The Meson development team
# Copyright © 2023-2024 Intel Corporation

from __future__ import annotations

# Work around some pathlib bugs...
from mesonbuild import _pathlib
import sys
sys.modules['pathlib'] = _pathlib

import collections
import os
import time
import shutil
import subprocess
import platform
import argparse
import traceback
from io import StringIO
from enum import Enum
from glob import glob
from pathlib import Path
from unittest import mock
import typing as T

from mesonbuild.compilers.c import CCompiler
from mesonbuild.compilers.detect import detect_c_compiler
from mesonbuild.dependencies.pkgconfig import PkgConfigInterface
from mesonbuild import mesonlib
from mesonbuild import mesonmain
from mesonbuild import mtest
from mesonbuild import mlog
from mesonbuild.environment import Environment, detect_ninja, detect_machine_info
from mesonbuild.coredata import version as meson_version
from mesonbuild.options import backendlist
from mesonbuild.mesonlib import setup_vsenv
from mesonbuild.options import OptionKey

if T.TYPE_CHECKING:
    from mesonbuild.coredata import SharedCMDOptions

NINJA_1_12_OR_NEWER = False
NINJA_CMD = None
# If we're on CI, detecting ninja for every subprocess unit test that we run is slow
# Optimize this by respecting $NINJA and skipping detection, then exporting it on
# first run.
try:
    NINJA_1_12_OR_NEWER = bool(int(os.environ['NINJA_1_12_OR_NEWER']))
    NINJA_CMD = [os.environ['NINJA']]
except (KeyError, ValueError):
    # Look for 1.12, which removes -w dupbuild=err
    NINJA_CMD = detect_ninja('1.12')
    if NINJA_CMD is not None:
        NINJA_1_12_OR_NEWER = True
    else:
        NINJA_CMD = detect_ninja()

if NINJA_CMD is not None:
    os.environ['NINJA_1_12_OR_NEWER'] = str(int(NINJA_1_12_OR_NEWER))
    os.environ['NINJA'] = NINJA_CMD[0]
else:
    raise RuntimeError('Could not find Ninja.')

# Emulate running meson with -X utf8 by making sure all open() calls have a
# sane encoding. This should be a python default, but PEP 540 considered it not
# backwards compatible. Instead, much line noise in diffs to update this, and in
# python 3.10 we can also make it a warning when absent.
os.environ['PYTHONWARNDEFAULTENCODING'] = '1'
# work around https://bugs.python.org/issue34624
os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] = '1'
# python 3.11 adds a warning that in 3.15, UTF-8 mode will be default.
# This is fantastic news, we'd love that. Less fantastic: this warning is silly,
# we *want* these checks to be affected. Plus, the recommended alternative API
# would (in addition to warning people when UTF-8 mode removed the problem) also
# require using a minimum python version of 3.11 (in which the warning was added)
# or add verbose if/else soup.
if sys.version_info >= (3, 10):
    import warnings
    warnings.filterwarnings('ignore', message="UTF-8 Mode affects .*getpreferredencoding", category=EncodingWarning)

def guess_backend(backend_str: str, msbuild_exe: str) -> T.Tuple['Backend', T.List[str]]:
    # Auto-detect backend if unspecified
    backend_flags = []
    if backend_str is None:
        if msbuild_exe is not None and (mesonlib.is_windows() and not _using_intelcl()):
            backend_str = 'vs' # Meson will auto-detect VS version to use
        else:
            backend_str = 'ninja'

    # Set backend arguments for Meson
    if backend_str.startswith('vs'):
        backend_flags = ['--backend=' + backend_str]
        backend = Backend.vs
    elif backend_str == 'xcode':
        backend_flags = ['--backend=xcode']
        backend = Backend.xcode
    elif backend_str == 'ninja':
        backend_flags = ['--backend=ninja']
        backend = Backend.ninja
    else:
        raise RuntimeError(f'Unknown backend: {backend_str!r}')
    return (backend, backend_flags)


def _using_intelcl() -> bool:
    """
    detect if intending to using Intel-Cl compilers (Intel compilers on Windows)
    Sufficient evidence of intent is that user is working in the Intel compiler
    shell environment, otherwise this function returns False
    """
    if not mesonlib.is_windows():
        return False
    # handle where user tried to "blank" MKLROOT and left space(s)
    if not os.environ.get('MKLROOT', '').strip():
        return False
    if (os.environ.get('CC') == 'icl' or
            os.environ.get('CXX') == 'icl' or
            os.environ.get('FC') == 'ifort'):
        return True
    # Intel-Cl users might not have the CC,CXX,FC envvars set,
    # but because they're in Intel shell, the exe's below are on PATH
    if shutil.which('icl') or shutil.which('ifort'):
        return True
    mlog.warning('It appears you might be intending to use Intel compiler on Windows '
                 'since non-empty environment variable MKLROOT is set to {} '
                 'However, Meson cannot find the Intel WIndows compiler executables (icl,ifort).'
                 'Please try using the Intel shell.'.format(os.environ.get('MKLROOT')))
    return False


# Fake classes and objects for mocking
class FakeBuild:
    def __init__(self, env):
        self.environment = env

def get_fake_options(prefix: str = '') -> SharedCMDOptions:
    opts = T.cast('SharedCMDOptions', argparse.Namespace())
    opts.native_file = []
    opts.cross_file = None
    opts.wrap_mode = None
    opts.prefix = prefix
    opts.cmd_line_options = {}
    return opts

def get_fake_env(sdir: str = '', bdir: T.Optional[str] = None, prefix: str = '',
                 opts: T.Optional[SharedCMDOptions] = None) -> Environment:
    if opts is None:
        opts = get_fake_options(prefix)
    env = Environment(sdir, bdir, opts)
    env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library
    # Invalidate cache when using a different Environment object.
    clear_meson_configure_class_caches()
    return env

def get_convincing_fake_env_and_cc(bdir, prefix):
    '''
    Return a fake env and C compiler with the fake env
    machine info properly detected using that compiler.
    Useful for running compiler checks in the unit tests.
    '''
    env = get_fake_env('', bdir, prefix)
    cc = detect_c_compiler(env, mesonlib.MachineChoice.HOST)
    # Detect machine info
    env.machines.host = detect_machine_info({'c':cc})
    return (env, cc)

Backend = Enum('Backend', 'ninja vs xcode')

if 'MESON_EXE' in os.environ:
    meson_exe = mesonlib.split_args(os.environ['MESON_EXE'])
else:
    meson_exe = None

if mesonlib.is_windows() or mesonlib.is_cygwin():
    exe_suffix = '.exe'
else:
    exe_suffix = ''

def handle_meson_skip_test(out: str) -> T.Tuple[bool, str]:
    for line in out.splitlines():
        for prefix in {'Problem encountered', 'Assert failed', 'Failed to configure the CMake subproject'}:
            if f'{prefix}: MESON_SKIP_TEST' in line:
                offset = line.index('MESON_SKIP_TEST') + 16
                reason = line[offset:].strip()
                return (True, reason)
    return (False, '')

def get_meson_script() -> str:
    '''
    Guess the meson that corresponds to the `mesonbuild` that has been imported
    so we can run configure and other commands in-process, since mesonmain.run
    needs to know the meson_command to use.

    Also used by run_unittests.py to determine what meson to run when not
    running in-process (which is the default).
    '''
    # Is there a meson.py next to the mesonbuild currently in use?
    mesonbuild_dir = Path(mesonmain.__file__).resolve().parent.parent
    meson_script = mesonbuild_dir / 'meson.py'
    if meson_script.is_file():
        return str(meson_script)
    # Then if mesonbuild is in PYTHONPATH, meson must be in PATH
    mlog.warning('Could not find meson.py next to the mesonbuild module. '
                 'Trying system meson...')
    meson_cmd = shutil.which('meson')
    if meson_cmd:
        return meson_cmd
    raise RuntimeError(f'Could not find {meson_script!r} or a meson in PATH')

def get_backend_args_for_dir(backend: Backend, builddir: str) -> T.List[str]:
    '''
    Visual Studio backend needs to be given the solution to build
    '''
    if backend is Backend.vs:
        sln_name = glob(os.path.join(builddir, '*.sln'))[0]
        return [os.path.split(sln_name)[-1]]
    return []

def find_vcxproj_with_target(builddir, target):
    import re, fnmatch
    t, ext = os.path.splitext(target)
    if ext:
        p = fr'<TargetName>{t}</TargetName>\s*<TargetExt>\{ext}</TargetExt>'
    else:
        p = fr'<TargetName>{t}</TargetName>'
    for _, _, files in os.walk(builddir):
        for f in fnmatch.filter(files, '*.vcxproj'):
            f = os.path.join(builddir, f)
            with open(f, encoding='utf-8') as o:
                if re.search(p, o.read(), flags=re.MULTILINE):
                    return f
    raise RuntimeError(f'No vcxproj matching {p!r} in {builddir!r}')

def get_builddir_target_args(backend: Backend, builddir, target):
    dir_args = []
    if not target:
        dir_args = get_backend_args_for_dir(backend, builddir)
    if target is None:
        return dir_args
    if backend is Backend.vs:
        vcxproj = find_vcxproj_with_target(builddir, target)
        target_args = [vcxproj]
    elif backend is Backend.xcode:
        target_args = ['-target', target]
    elif backend is Backend.ninja:
        target_args = [target]
    else:
        raise AssertionError(f'Unknown backend: {backend!r}')
    return target_args + dir_args

def get_backend_commands(backend: Backend, debug: bool = False) -> \
        T.Tuple[T.List[str], T.List[str], T.List[str], T.List[str], T.List[str]]:
    install_cmd: T.List[str] = []
    uninstall_cmd: T.List[str] = []
    clean_cmd: T.List[str]
    cmd: T.List[str]
    test_cmd: T.List[str]
    if backend is Backend.vs:
        cmd = ['msbuild']
        clean_cmd = cmd + ['/target:Clean']
        test_cmd = cmd + ['RUN_TESTS.vcxproj']
    elif backend is Backend.xcode:
        cmd = ['xcodebuild']
        clean_cmd = cmd + ['-alltargets', 'clean']
        test_cmd = cmd + ['-target', 'RUN_TESTS']
    elif backend is Backend.ninja:
        global NINJA_CMD
        cmd = NINJA_CMD + ['-d', 'explain']
        if not NINJA_1_12_OR_NEWER:
            cmd += ['-w', 'dupbuild=err']
        if debug:
            cmd += ['-v']
        clean_cmd = cmd + ['clean']
        test_cmd = cmd + ['test', 'benchmark']
        install_cmd = cmd + ['install']
        uninstall_cmd = cmd + ['uninstall']
    else:
        raise AssertionError(f'Unknown backend: {backend!r}')
    return cmd, clean_cmd, test_cmd, install_cmd, uninstall_cmd

def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str]:
    out = StringIO()
    with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out):
        returncode = mtest.run_with_args(commandlist)
    return returncode, out.getvalue()

def clear_meson_configure_class_caches() -> None:
    CCompiler.find_library_cache.clear()
    CCompiler.find_framework_cache.clear()
    PkgConfigInterface.class_impl.assign(False, False)
    mesonlib.project_meson_versions.clear()

def run_configure_inprocess(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]:
    stderr = StringIO()
    stdout = StringIO()
    returncode = 0
    with mock.patch.dict(os.environ, env or {}), mock.patch.object(sys, 'stdout', stdout), mock.patch.object(sys, 'stderr', stderr):
        try:
            returncode = mesonmain.run(commandlist, get_meson_script())
        except Exception:
            if catch_exception:
                returncode = 1
                traceback.print_exc()
            else:
                raise
        finally:
            clear_meson_configure_class_caches()
    return returncode, stdout.getvalue(), stderr.getvalue()

def run_configure_external(full_command: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> T.Tuple[int, str, str]:
    pc, o, e = mesonlib.Popen_safe(full_command, env=env)
    return pc.returncode, o, e

def run_configure(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[bool, T.Tuple[int, str, str]]:
    global meson_exe
    if meson_exe:
        return (False, run_configure_external(meson_exe + commandlist, env=env))
    return (True, run_configure_inprocess(commandlist, env=env, catch_exception=catch_exception))

def print_system_info():
    print(mlog.bold('System information.'))
    print('Architecture:', platform.architecture())
    print('Machine:', platform.machine())
    print('Platform:', platform.system())
    print('Processor:', platform.processor())
    print('System:', platform.system())
    print('')
    print(flush=True)

def subprocess_call(cmd, **kwargs):
    print(f'$ {mesonlib.join_args(cmd)}')
    return subprocess.call(cmd, **kwargs)

def main():
    print_system_info()
    parser = argparse.ArgumentParser()
    parser.add_argument('--backend', default=None, dest='backend',
                        choices=backendlist)
    parser.add_argument('--cross', default=[], dest='cross', action='append')
    parser.add_argument('--cross-only', action='store_true')
    parser.add_argument('--failfast', action='store_true')
    parser.add_argument('--no-unittests', action='store_true', default=False)
    (options, _) = parser.parse_known_args()
    returncode = 0
    _, backend_flags = guess_backend(options.backend, shutil.which('msbuild'))
    no_unittests = options.no_unittests
    # Running on a developer machine? Be nice!
    if not mesonlib.is_windows() and not mesonlib.is_haiku() and 'CI' not in os.environ:
        os.nice(20)
    # Appveyor sets the `platform` environment variable which completely messes
    # up building with the vs2010 and vs2015 backends.
    #
    # Specifically, MSBuild reads the `platform` environment variable to set
    # the configured value for the platform (Win32/x64/arm), which breaks x86
    # builds.
    #
    # Appveyor setting this also breaks our 'native build arch' detection for
    # Windows in environment.py:detect_windows_arch() by overwriting the value
    # of `platform` set by vcvarsall.bat.
    #
    # While building for x86, `platform` should be unset.
    if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86':
        os.environ.pop('platform')
    # Run tests
    # Can't pass arguments to unit tests, so set the backend to use in the environment
    env = os.environ.copy()
    if not options.cross:
        cmd = mesonlib.python_command + ['run_meson_command_tests.py', '-v']
        if options.failfast:
            cmd += ['--failfast']
        returncode += subprocess_call(cmd, env=env)
        if options.failfast and returncode != 0:
            return returncode
        if no_unittests:
            print('Skipping all unit tests.')
            print(flush=True)
            returncode = 0
        else:
            print(mlog.bold('Running unittests.'))
            print(flush=True)
            cmd = mesonlib.python_command + ['run_unittests.py'] + backend_flags
            if options.failfast:
                cmd += ['--failfast']
            returncode += subprocess_call(cmd, env=env)
            if options.failfast and returncode != 0:
                return returncode
        cmd = mesonlib.python_command + ['run_project_tests.py'] + sys.argv[1:]
        returncode += subprocess_call(cmd, env=env)
    else:
        cross_test_args = mesonlib.python_command + ['run_cross_test.py']
        for cf in options.cross:
            print(mlog.bold(f'Running {cf} cross tests.'))
            print(flush=True)
            cmd = cross_test_args + ['cross/' + cf]
            if options.failfast:
                cmd += ['--failfast']
            if options.cross_only:
                cmd += ['--cross-only']
            returncode += subprocess_call(cmd, env=env)
            if options.failfast and returncode != 0:
                return returncode
    return returncode

if __name__ == '__main__':
    setup_vsenv()
    print('Meson build system', meson_version, 'Project and Unit Tests')
    raise SystemExit(main())
