#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

"""
python-qpid-proton setup script

DISCLAIMER: This script took lots of inspirations from PyZMQ, which is licensed
under the 'MODIFIED BSD LICENSE'.

Although inspired by the work in PyZMQ, this script and the modules it depends
on were largely simplified to meet the requirements of the library.

The behavior of this script is to build the registered `_cproton` extension
using the installed Qpid Proton C library and header files. If the library and
headers are not installed, or the installed version does not match the version
of these python bindings, then the script will attempt to build the extension
using the Proton C sources included in the python source distribution package.

While the above removes the need of *always* having Qpid Proton C development
files installed, it does not solve the need of having `swig` and the libraries
qpid-proton requires installed to make this setup work.

From the Python side, this scripts overrides 1 command - build_ext - and it adds a
new one. The latter - Configure - is called from the former to setup/discover what's
in the system. The rest of the commands and steps are done normally without any kind
of monkey patching.
"""

import os
import shutil

from setuptools import setup, Extension
from setuptools.command.sdist import sdist
from setuptools.command.build_ext import build_ext
from setuptools.command.build_py import build_py

import distutils.sysconfig as ds_sys
from distutils.ccompiler import new_compiler, get_default_compiler

from setuputils import log
from setuputils import misc


_PROTON_VERSION=(@PN_VERSION_MAJOR@,
                 @PN_VERSION_MINOR@,
                 @PN_VERSION_POINT@)
_PROTON_VERSION_STR = "%d.%d.%d" % _PROTON_VERSION


class Swig(build_ext):
    def run(self):
        """Run swig against the sources.  This will cause swig to compile the
        cproton.i file into a .c file called cproton_wrap.c, and create
        cproton.py.
        """
        ext = Extension('_cproton',
                             sources=['cproton.i'],
                             swig_opts=['-threads', '-Iinclude'])

        if 'SWIG' in os.environ:
            self.swig = os.environ['SWIG']

        self.swig_sources(ext.sources, ext)


class CheckSDist(sdist):
    def run(self):
        self.distribution.run_command('swig')
        sdist.run(self)


class Configure(build_ext):
    description = "Discover Qpid Proton version"

    @property
    def compiler_type(self):
        compiler = self.compiler
        if compiler is None:
            return get_default_compiler()
        elif isinstance(compiler, str):
            return compiler
        else:
            return compiler.compiler_type

    def use_bundled_proton(self):
        """The proper version of libqpid-proton-core is not installed on the system,
        so use the included proton-c sources to build the extension
        """
        log.info("Building the bundled proton-c sources into the extension")

        setup_path = os.path.dirname(os.path.realpath(__file__))
        base = self.get_finalized_command('build').build_base
        build_include = os.path.join(base, 'include')
        proton_base = os.path.abspath(os.path.join(setup_path))
        proton_src = os.path.join(proton_base, 'src')
        proton_core_src = os.path.join(proton_base, 'src', 'core')
        proton_include = os.path.join(proton_base, 'include')

        log.debug("Using Proton C sources: %s" % proton_base)

        # Collect all the Proton C files packaged in the sdist and strip out
        # anything windows and configuration-dependent

        sources = []
        for root, _, files in os.walk(proton_core_src):
            for file_ in files:
                if file_.endswith(('.c', '.cpp')):
                    sources.append(os.path.join(root, file_))

        # Look for any optional libraries that proton needs, and adjust the
        # source list and compile flags as necessary.
        libraries = []
        includes = []
        macros = []

        # -D flags (None means no value, just define)
        macros += [('PROTON_DECLARE_STATIC', None)]

        if self.compiler_type=='msvc':
            sources += [
                os.path.join(proton_src, 'compiler', 'msvc', 'snprintf.c'),
                os.path.join(proton_src, 'compiler', 'msvc', 'start.c')
            ]
        elif self.compiler_type=='unix':
            sources += [
                os.path.join(proton_src, 'compiler' , 'gcc', 'start.c')
            ]

        # Check whether openssl is installed by poking
        # pkg-config for a minimum version 0. If it's installed, it should
        # return True and we'll use it. Otherwise, we'll use the stub.
        if misc.pkg_config_version_installed('openssl', atleast='0'):
            libraries += ['ssl', 'crypto']
            includes += [misc.pkg_config_get_var('openssl', 'includedir')]
            sources.append(os.path.join(proton_src, 'ssl', 'openssl.c'))
        elif os.name=='nt':
            libraries += ['crypt32', 'secur32']
            sources.append(os.path.join(proton_src, 'ssl', 'schannel.c'))
        else:
            sources.append(os.path.join(proton_src, 'ssl', 'ssl_stub.c'))
            log.warn("OpenSSL not installed - disabling SSL support!")

        # create a temp compiler to check for optional compile-time features
        cc = new_compiler(compiler=self.compiler_type)
        cc.output_dir = self.build_temp

        # 0.10 added an implementation for cyrus. Check
        # if it is available before adding the implementation to the sources
        # list. 'sasl.c` and 'default_sasl.c' are added and one of the existing
        # implementations will be used.
        sources.append(os.path.join(proton_src, 'sasl', 'sasl.c'))
        sources.append(os.path.join(proton_src, 'sasl', 'default_sasl.c'))

        # Skip the SASL detection on Windows.
        # MSbuild scans output of Exec tasks and fails the build if it notices error-like
        # strings there. This is a known issue with CMake and msbuild, see
        # * https://github.com/Microsoft/msbuild/issues/2424
        # * https://cmake.org/pipermail/cmake-developers/2015-October/026775.html
        if cc.compiler_type!='msvc':
            if cc.has_function('sasl_client_done', includes=['sasl/sasl.h'], libraries=['sasl2']):
                libraries.append('sasl2')
                sources.append(os.path.join(proton_src, 'sasl', 'cyrus_sasl.c'))
            else:
                log.warn("Cyrus SASL not installed - only the ANONYMOUS and PLAIN mechanisms will be supported!")
                sources.append(os.path.join(proton_src, 'sasl', 'cyrus_stub.c'))
        else:
            log.warn("Windows - only the ANONYMOUS and PLAIN mechanisms will be supported!")
            sources.append(os.path.join(proton_src, 'sasl', 'cyrus_stub.c'))

        # Hack for Windows/msvc: We need to compile proton as C++, but it seems the only way to
        # force this in setup.py is to use a .cpp extension! So copy all the source files to .cpp
        # and use these as the compile sources
        if self.compiler_type=='msvc':
            targets = []
            target_base = os.path.join(self.build_temp, 'srcs')
            try:
                # Might need to make intermediate directories use os.makedirs() not os.mkdir()
                os.makedirs(target_base)
            except OSError:
                pass

            for f in sources:
                # We know each file ends in '.c' as we filtered on that above so just add 'pp' to end
                target = os.path.join(target_base, os.path.basename(f) + 'pp')
                shutil.copy(f, target)
                targets.append(target)

            # Copy .h files into temp tree too as we need them to compile
            for root, _, files in os.walk(proton_core_src):
                for file_ in files:
                    if file_.endswith('.h'):
                        shutil.copy(os.path.join(root, file_), os.path.join(target_base, file_))

            # Copy ssl/sasl .h files
            shutil.copy(os.path.join(proton_src, 'sasl', 'sasl-internal.h'), os.path.join(target_base, 'sasl-internal.h'))
            shutil.copy(os.path.join(proton_src, 'ssl', 'ssl-internal.h'), os.path.join(target_base, 'ssl-internal.h'))

            sources = targets

        # compile all the proton sources.  We'll add the resulting list of
        # objects to the _cproton extension as 'extra objects'.  We do this
        # instead of just lumping all the sources into the extension to prevent
        # any proton-specific compilation flags from affecting the compilation
        # of the generated swig code

        cc = new_compiler(compiler=self.compiler_type)
        ds_sys.customize_compiler(cc)

        extra = []
        if self.compiler_type=='unix':
            extra.append('-std=gnu99')
        objects = cc.compile(sources,
                             macros=macros,
                             include_dirs=[build_include,
                                           proton_include,
                                           proton_src]+includes,
                             # compiler command line options:
                             extra_preargs=extra,
                             output_dir=self.build_temp)

        #
        # Now update the _cproton extension instance passed to setup to include
        # the objects and libraries
        #
        _cproton = self.distribution.ext_modules[-1]
        _cproton.extra_objects = objects
        _cproton.include_dirs.append(build_include)
        _cproton.include_dirs.append(proton_include)

        # lastly replace the libqpid-proton-core dependency with libraries required
        # by the Proton objects:
        _cproton.libraries=libraries

    def libqpid_proton_installed(self, version):
        """Check to see if the proper version of the Proton development library
        and headers are already installed
        """
        return misc.pkg_config_version_installed('libqpid-proton-core', version)

    def use_installed_proton(self):
        """The Proton development headers and library are installed, update the
        _cproton extension to tell it where to find the library and headers.
        """
        # update the Extension instance passed to setup() to use the installed
        # headers and link library
        _cproton = self.distribution.ext_modules[-1]
        incs = misc.pkg_config_get_var('libqpid-proton-core', 'includedir')
        for i in incs.split():
            _cproton.swig_opts.append('-I%s' % i)
            _cproton.include_dirs.append(i)
        ldirs = misc.pkg_config_get_var('libqpid-proton-core', 'libdir')
        _cproton.library_dirs.extend(ldirs.split())

    def run(self):
        # check if the Proton library and headers are installed and are
        # compatible with this version of the binding.
        if self.libqpid_proton_installed(_PROTON_VERSION_STR):
            self.use_installed_proton()
        else:
            # Proton not installed or compatible, use bundled proton-c sources
            self.use_bundled_proton()


class BuildExtFirst(build_py):
    def run(self):
        # Make sure swig runs first and adds file etc
        self.distribution.run_command('build_ext')
        build_py.run(self)


class CheckingBuildExt(build_ext):
    def run(self):
        # Discover qpid-proton and prerequisites in the system
        self.distribution.run_command('configure')
        build_ext.run(self)


setup(name='python-qpid-proton',
      version=_PROTON_VERSION_STR + os.environ.get('PROTON_VERSION_SUFFIX', ''),
      description='An AMQP based messaging library.',
      author='Apache Qpid',
      author_email='users@qpid.apache.org',
      url='http://qpid.apache.org/proton/',
      packages=['proton'],
      py_modules=['cproton'],
      license="Apache Software License",
      classifiers=["License :: OSI Approved :: Apache Software License",
                   "Intended Audience :: Developers",
                   "Programming Language :: Python",
                   "Programming Language :: Python :: 2",
                   "Programming Language :: Python :: 2.6",
                   "Programming Language :: Python :: 2.7",
                   "Programming Language :: Python :: 3",
                   "Programming Language :: Python :: 3.5",
                   "Programming Language :: Python :: 3.6",
                   "Programming Language :: Python :: 3.7",
                   "Programming Language :: Python :: 3.8"],
      cmdclass = {
          'configure': Configure,
          'swig': Swig,
          'build_py': BuildExtFirst,
          'build_ext': CheckingBuildExt,
          'sdist': CheckSDist
      },
      extras_require={
          'opentracing': ['opentracing', 'jaeger_client']
      },
      # Note well: the following extension instance is modified during the
      # installation!  If you make changes below, you may need to update the
      # Configure class above
      ext_modules=[Extension('_cproton',
                             sources=['cproton_wrap.c'],
                             extra_compile_args=['-pthread', '-DPROTON_DECLARE_STATIC'],
                             libraries=['qpid-proton-core'])])
