#!/bin/sh
#
# Copyright (C) 2004-2025 ZNC, see the NOTICE file for details.
#
# 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.
#

# http://stackoverflow.com/questions/18993438/shebang-env-preferred-python-version
# http://stackoverflow.com/questions/12070516/conditional-shebang-line-for-different-versions-of-python
""":"
which python3 >/dev/null 2>&1 && exec python3 "$0" "$@"
which python  >/dev/null 2>&1 && exec python  "$0" "$@"
which python2 >/dev/null 2>&1 && exec python2 "$0" "$@"
echo "Error: znc-buildmod requires python"
exec echo "Either install python, or use cmake directly"
":"""

from __future__ import print_function

import argparse
import glob
import os
import shutil
import subprocess
import sys
import tempfile

if sys.version_info < (3, 0):
    class TemporaryDirectory(object):
        def __enter__(self):
            self.name = tempfile.mkdtemp()
            return self.name
        def __exit__(self, *a, **k):
            shutil.rmtree(self.name)
    tempfile.TemporaryDirectory = TemporaryDirectory

parser = argparse.ArgumentParser(
        description='Build external ZNC modules and place the results to '
        'current directory. Several modules can be built at once.',
        epilog='Adjustable environment variables: CXXFLAGS, LDFLAGS, LIBS')
parser.add_argument('-v', '--verbose', action='count', default=0,
        help='use -vvv for more verbosity')
parser.add_argument('files', nargs='+', metavar='file.cpp',
        help="path to the module's source file")
args = parser.parse_args()

with tempfile.TemporaryDirectory() as cmdir:
    with open(os.path.join(cmdir, 'CMakeLists.txt'), 'w') as cm:
        print('cmake_minimum_required(VERSION 3.13)', file=cm)
        print('project(ExternalModules LANGUAGES CXX)', file=cm)
        print('find_package(ZNC @ZNC_VERSION_MAJOR@.@ZNC_VERSION_MINOR@ HINTS '
            '@CMAKE_INSTALL_FULL_DATADIR@/znc REQUIRED)', file=cm)
        if args.verbose > 0:
            print('set(CMAKE_VERBOSE_MAKEFILE true)', file=cm)

        for mod_cpp in args.files:
            mod, _ = os.path.splitext(os.path.basename(mod_cpp))
            print(file=cm)
            print('add_library(module_{} MODULE {})'.format(
                mod, os.path.abspath(mod_cpp)), file=cm)
            print('znc_setup_module(TARGET module_{} NAME {})'.format(mod, mod),
                    file=cm)
            print('target_link_libraries(module_{} PRIVATE {})'.format(
                mod, os.environ.get('LIBS', '')), file=cm)

    if args.verbose > 0:
        with open(os.path.join(cmdir, 'CMakeLists.txt')) as cm:
            print(cm.read())

    with tempfile.TemporaryDirectory() as build:
        command = ['cmake', cmdir]
        if args.verbose > 1:
            command.append('--debug-output')
        if args.verbose > 2:
            command.append('--trace')
        if args.verbose > 0:
            print(command)
        subprocess.check_call(command, cwd=build)
        subprocess.check_call(['cmake', '--build', '.'], cwd=build)

        for so in glob.iglob(os.path.join(build, '*.so')):
            print('Writing {}'.format(os.path.join(os.getcwd(), os.path.basename(so))))
            try:
                os.remove(os.path.basename(so))
            except OSError:
                pass
            shutil.copy(so, os.getcwd())
