# Copyright 2020, 2021 Google LLC
#
# 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
#
#     https://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.

"""This program configures and builds Emacs.

It’s an internal implementation detail of the Bazel rules for Emacs Lisp; don’t
use it outside the rules or depend on its behavior."""

import argparse
import pathlib
import shlex
import shutil
import subprocess
import tempfile


def main() -> None:
    """Configures and builds Emacs."""
    parser = argparse.ArgumentParser(allow_abbrev=False)
    parser.add_argument('--source', type=pathlib.Path, required=True)
    parser.add_argument('--install', type=pathlib.Path, required=True)
    parser.add_argument('--cc', type=pathlib.Path, required=True)
    parser.add_argument('--cflags', required=True)
    parser.add_argument('--ldflags', required=True)
    parser.add_argument('--module-header', type=pathlib.Path)
    args = parser.parse_args()
    with tempfile.TemporaryDirectory() as temp:
        temp = pathlib.Path(temp)
        build = temp / 'build'
        install = args.install.resolve()
        shutil.copytree(args.source, build)

        def run(*command: str) -> None:
            try:
                subprocess.run(command, check=True, cwd=build,
                               stdin=subprocess.DEVNULL,
                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                               encoding='utf-8', errors='backslashescape')
            except subprocess.CalledProcessError as ex:
                print('command', ' '.join(map(shlex.quote, command)),
                      'failed, output follows:')
                print(ex.stdout)
                print()
                try:
                    config_log = build / 'config.log'
                    content = config_log.read_text('utf-8', 'backslashescape')
                    print('config.log follows:')
                    print(content)
                except FileNotFoundError:
                    print('config.log not found')
                raise

        run(str(build / 'configure'), '--prefix=' + str(install),
            '--without-all', '--without-ns', '--with-x-toolkit=no',
            # Enable threads explicitly to work around
            # https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30106 in older
            # Emacs versions.
            '--with-modules', '--with-threads',
            '--disable-build-details',
            'CC=' + str(args.cc.resolve()),
            'CFLAGS=' + args.cflags,
            'LDFLAGS=' + args.ldflags)
        run('make', 'install')
    # Delete source files that have a corresponding compiled file, as these
    # files don’t work well with Coverage (see
    # e.g. https://debbugs.gnu.org/cgi/bugreport.cgi?bug=40766).
    for compiled in install.glob('share/emacs/*/lisp/**/*.elc'):
        compiled.with_suffix('.el').unlink()
    # Sanity check to verify that the resulting binary works.
    subprocess.run([install / 'bin' / 'emacs', '--quick', '--batch'],
                   check=True, stdin=subprocess.DEVNULL)
    if args.module_header:
        # Copy emacs-module.h to the desired location.
        shutil.copy(install / 'include' / 'emacs-module.h', args.module_header)


if __name__ == '__main__':
    main()

@@ -773,16 +773,26 @@
 rgparse%0A
+import os%0A
 import p
@@ -1380,16 +1380,97 @@
 _args()%0A
+    windows = os.name == 'nt'%0A    if windows:%0A        bash = _find_bash(args.cc)%0A
     with
@@ -1696,24 +1696,427 @@
 r) -%3E None:%0A
+            env = None%0A            if windows:%0A                # Building Emacs requires MinGW, see nt/INSTALL.W64.  Therefore%0A                # we invoke commands through the MinGW shell, see%0A                # https://www.msys2.org/wiki/Launchers/#the-idea.%0A                env = dict(os.environ, MSYSTEM='MINGW64', CHERE_INVOKING='1')%0A                command = %5Bbash, '-l', '-c', shlex.join(command)%5D%0A
             
@@ -2182,16 +2182,25 @@
 d=build,
+ env=env,
 %0A       
@@ -4173,16 +4173,383 @@
 ader)%0A%0A%0A
+def _find_bash(c_compiler: pathlib.Path) -%3E pathlib.Path:%0A    if c_compiler.parts%5B-2:%5D != ('mingw64', 'bin'):%0A        raise ValueError(f'unsupported C compiler location %7Bc_compiler%7D')%0A    msys = c_compiler.parents%5B2%5D%0A    bash = msys / 'bin' / 'bash.exe'%0A    if not bash.is_file():%0A        raise FileNotFoundError(f'no Bash program found in %7Bmsys%7D')%0A    return bash%0A%0A%0A
 if __nam

Support MinGW when building Emacs on Windows