#
#
# 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.
#
#
#
# gen_make.py -- generate makefiles and dependencies
#

import os
import stat
import sys
try:
  # Python >=3.0
  import configparser
except ImportError:
  # Python <3.0
  import ConfigParser as configparser

if sys.version_info[0] >= 3:
  # Python >=3.0
  from io import StringIO
else:
  # Python <3.0
  try:
    from cStringIO import StringIO
  except ImportError:
    from StringIO import StringIO

import ezt

import gen_base
import generator.swig.header_wrappers
import generator.swig.checkout_swig_header
import generator.swig.external_runtime

from gen_base import build_path_join, build_path_strip, build_path_splitfile, \
      build_path_basename, build_path_dirname, build_path_retreat, unique


def _normstr(x):
  if os.sep == '/':
    return os.path.normpath(str(x))
  else:
    return os.path.normpath(str(x).replace('/', os.sep)).replace(os.sep, '/')

class Generator(gen_base.GeneratorBase):

  _extension_map = {
    ('exe', 'target'): '$(EXEEXT)',
    ('exe', 'object'): '.lo',
    ('lib', 'target'): '.la',
    ('lib', 'object'): '.lo',
    ('pyd', 'target'): '.la',
    ('pyd', 'object'): '.lo',
    ('so', 'target'): '.la',
    ('so', 'object'): '.lo',
    }

  def __init__(self, fname, verfname, options=None):
    gen_base.GeneratorBase.__init__(self, fname, verfname, options)
    self.assume_shared_libs = False
    if ('--assume-shared-libs', '') in options:
      self.assume_shared_libs = True

  def write(self):
    install_deps = self.graph.get_deps(gen_base.DT_INSTALL)
    install_sources = self.graph.get_all_sources(gen_base.DT_INSTALL)

    cp = configparser.ConfigParser()
    cp.read('gen-make.opts')
    if cp.has_option('options', '--installed-libs'):
      self.installed_libs = cp.get('options', '--installed-libs').split(',')
    else:
      self.installed_libs = []

    # ensure consistency between runs
    install_deps.sort()
    install_sources.sort(key = lambda s: s.name)

    class _eztdata(object):
      def __init__(self, **kw):
        vars(self).update(kw)

    data = _eztdata(
      modules=[ ],
      swig_langs=[ ],
      swig_c=[ ],
      target=[ ],
      itargets=[ ],
      areas=[ ],
      isources=[ ],
      deps=[ ],
      sql=[],
      )

    ########################################

    for target in install_sources:
      if isinstance(target, gen_base.TargetRaModule) or \
         isinstance(target, gen_base.TargetFsModule):
        # name of the module: strip 'libsvn_' and upper-case it
        name = target.name[7:].upper()

        # construct a list of the other .la libs to link against
        retreat = build_path_retreat(target.path)
        if target.name in self.installed_libs:
          deps = []
          link = [ '-l%s-%s' % (target.name[3:], self.version) ]
        else:
          deps = [ target.filename ]
          link = [ build_path_join(retreat, target.filename) ]
        for source in self.graph.get_sources(gen_base.DT_LINK, target.name):
          if not isinstance(source, gen_base.TargetLib) or source.external_lib:
            continue
          elif source.name in self.installed_libs:
            continue
          deps.append(source.filename)
          link.append(build_path_join(retreat, source.filename))

        data.modules.append(_eztdata(name=name, deps=deps, link=link))

    # write a list of directories in which things are built
    #   get all the test scripts' directories
    script_dirs = list(map(build_path_dirname, self.scripts + self.bdb_scripts))

    #   remove duplicate directories between targets and tests
    build_dirs = unique(self.target_dirs + script_dirs + self.swig_dirs)
    data.build_dirs = build_dirs

    # write lists of test files
    # deps = all, progs = not including those marked "testing = skip"
    data.bdb_test_deps = self.bdb_test_deps + self.bdb_scripts
    data.bdb_test_progs = self.bdb_test_progs + self.bdb_scripts
    data.test_deps = self.test_deps + self.scripts
    data.test_progs = self.test_progs + self.scripts
    data.test_helpers = self.test_helpers

    # write list of all manpages
    data.manpages = self.manpages

    # write a list of files to remove during "make clean"
    cfiles = [ ]
    for target in install_sources:
      # .la files are handled by the standard 'clean' rule; clean all the
      # other targets
      if not isinstance(target, gen_base.TargetScript) \
         and not isinstance(target, gen_base.TargetProject) \
         and not isinstance(target, gen_base.TargetI18N) \
         and not isinstance(target, gen_base.TargetJava) \
         and not target.external_lib \
         and target.filename[-3:] != '.la':
        cfiles.append(target.filename)
    for script in self.scripts:
      if script.endswith('.py'):
        cfiles.append(script + 'c')
    data.cfiles = sorted(cfiles)

    # here are all the SQL files and their generated headers. the Makefile
    # has an implicit rule for generating these, so there isn't much to do
    # except to clean them out. we only do that for 'make extraclean' since
    # these are included as part of the tarball. the files are transformed
    # by gen-make, and developers also get a Make rule to keep them updated.
    for hdrfile, sqlfile in sorted(self.graph.get_deps(gen_base.DT_SQLHDR),
                                   key=lambda t: t[0]):
      data.sql.append(_eztdata(header=hdrfile, source=sqlfile[0]))

    data.release_mode = ezt.boolean(self.release_mode)

    ########################################

    if not self.release_mode:
      swig_rules = StringIO()
      for swig in (generator.swig.header_wrappers,
                   generator.swig.checkout_swig_header,
                   generator.swig.external_runtime):
        gen = swig.Generator(self.conf, "swig")
        gen.write_makefile_rules(swig_rules)

      data.swig_rules = swig_rules.getvalue()

    ########################################

    # write dependencies and build rules for generated .c files
    swig_c_deps = sorted(self.graph.get_deps(gen_base.DT_SWIG_C),
                         key=lambda t: t[0].filename)

    swig_lang_deps = {}
    for lang in self.swig.langs:
      swig_lang_deps[lang] = []

    for objname, sources in swig_c_deps:
      swig_lang_deps[objname.lang].append(str(objname))

    for lang in self.swig.langs:
      data.swig_langs.append(_eztdata(name=lang,
                                      short=self.swig.short[lang],
                                      short_upper=self.swig.short[lang].upper(),
                                      deps=swig_lang_deps[lang]))

    ########################################

    if not self.release_mode:
      for objname, sources in swig_c_deps:
        data.swig_c.append(_eztdata(c_file=str(objname),
                                    deps=list(map(str, sources)),
                                    opts=self.swig.opts[objname.lang],
                                    source=str(sources[0])))

    ########################################

    for target_ob in install_sources:

      if isinstance(target_ob, gen_base.TargetScript):
        # there is nothing to build
        continue

      target = target_ob.name
      if isinstance(target_ob, gen_base.TargetJava):
        path = target_ob.output_dir
      else:
        path = target_ob.path

      retreat = build_path_retreat(path)

      # get the source items (.o and .la) for the link unit
      objects = [ ]
      objdeps = [ ]
      object_srcs = [ ]
      headers = [ ]
      header_classes = [ ]
      header_class_filenames = [ ]
      deps = [ ]
      libs = [ ]
      add_deps = target_ob.add_deps.split()

      for link_dep in self.graph.get_sources(gen_base.DT_LINK, target_ob.name):
        if isinstance(link_dep, gen_base.TargetJava):
          deps.append(link_dep.name)
        elif isinstance(link_dep, gen_base.TargetLinked):
          if link_dep.external_lib:
            libs.append(link_dep.external_lib)
          elif link_dep.external_project:
            # FIXME: This is a temporary workaround to fix build breakage
            # expeditiously.  It is of questionable validity for a build
            # node to have external_project but not have external_lib.
            pass
          elif link_dep.name in self.installed_libs:
            libs.append('-l%s-%s' % (link_dep.name[3:], self.version))
          else:
            # append the output of the target to our stated dependencies
            if not self.assume_shared_libs:
              deps.append(link_dep.filename)

            # link against the library
            libs.append(build_path_join(retreat, link_dep.filename))
        elif isinstance(link_dep, gen_base.ObjectFile):
          # link in the object file
          objects.append(link_dep.filename)
          objdeps.append(_normstr(link_dep.filename))
          for dep in self.graph.get_sources(gen_base.DT_OBJECT, link_dep, gen_base.SourceFile):
            object_srcs.append(
              build_path_join('$(abs_srcdir)', dep.filename))
        elif isinstance(link_dep, gen_base.HeaderFile):
          # link in the header file
          # N.B. that filename_win contains the '_'-escaped class name
          headers.append(link_dep.filename_win)
          header_classes.append(link_dep.classname)
          for dep in self.graph.get_sources(gen_base.DT_OBJECT, link_dep, gen_base.ObjectFile):
            header_class_filenames.append(dep.filename)
        else:
          ### we don't know what this is, so we don't know what to do with it
          raise UnknownDependency

      for nonlib in self.graph.get_sources(gen_base.DT_NONLIB, target_ob.name):
        if isinstance(nonlib, gen_base.TargetLinked):
          if not nonlib.external_lib:
            deps.append(nonlib.filename)

      targ_varname = target.replace('-', '_')
      objnames = build_path_strip(path, objects)

      ezt_target = _eztdata(name=target_ob.name,
                            varname=targ_varname,
                            path=path,
                            install=None,
                            add_deps=add_deps,
                            objects=objects,
                            objdeps=objdeps,
                            deps=deps,
                            when=target_ob.when,
                            )
      data.target.append(ezt_target)

      if hasattr(target_ob, 'link_cmd'):
        ezt_target.link_cmd = target_ob.link_cmd
      if hasattr(target_ob, 'output_dir'):
        ezt_target.output_dir = target_ob.output_dir
      if hasattr(target_ob, 'headers_dir'):
        ezt_target.headers_dir = target_ob.headers_dir

      # Add additional install dependencies if necessary
      if target_ob.add_install_deps:
        ezt_target.install = target_ob.install
        ezt_target.install_deps = target_ob.add_install_deps

      if isinstance(target_ob, gen_base.TargetJava):
        ezt_target.type = 'java'
        ezt_target.headers = headers
        ezt_target.sources = None
        ezt_target.jar = None
        ezt_target.classes = target_ob.classes

        # Build the headers from the header_classes with one 'javah' call
        if headers:
          ezt_target.header_class_filenames = header_class_filenames
          ezt_target.header_classes = header_classes

        # Build the objects from the object_srcs with one 'javac' call
        if object_srcs:
          ezt_target.sources = object_srcs

        # Once the bytecodes have been compiled up, we produce the
        # JAR.
        if target_ob.jar:
          ezt_target.jar_path = build_path_join(target_ob.classes,
                                                target_ob.jar)
          ezt_target.packages = target_ob.packages

      elif isinstance(target_ob, gen_base.TargetI18N):
        ezt_target.type = 'i18n'
      else:
        ezt_target.type = 'n/a'
        ezt_target.filename = target_ob.filename
        ezt_target.path = path
        if (isinstance(target_ob, gen_base.TargetLib)
            and not target_ob.undefined_lib_symbols):
          ezt_target.undefined_flag = '$(LT_NO_UNDEFINED)'
        else:
          ezt_target.undefined_flag = ''
        ezt_target.libs = gen_base.unique(libs)
        ezt_target.objnames = objnames
        ezt_target.basename = build_path_basename(target_ob.filename)

    ########################################

    for itype, i_targets in install_deps:

      # perl bindings do their own thing, "swig-pl" target is
      # already specified in Makefile.in
      if itype == "swig-pl":
        continue

      outputs = [ ]

      for t in i_targets:
        if hasattr(t, 'filename'):
          outputs.append(t.filename)

      data.itargets.append(_eztdata(type=itype, outputs=outputs))

    ########################################

    # for each install group, write a rule to install its outputs
    for area, inst_targets in install_deps:

      # perl bindings do their own thing, "install-swig-pl" target is
      # already specified in Makefile.in
      if area == "swig-pl":
        continue

      # get the output files for these targets, sorted in dependency order
      files = gen_base._sorted_files(self.graph, area)

      ezt_area_type = (area == 'apache-mod' and 'mods-shared' or area)
      ezt_area = _eztdata(type=ezt_area_type, files=[], extra_install=None)

      def file_to_eztdata(file):
          # cd to dirname before install to work around libtool 1.4.2 bug.
          dirname, fname = build_path_splitfile(file.filename)
          return _eztdata(mode=None,
                          dirname=dirname, fullname=file.filename,
                          filename=fname, when=file.when,
                          pc_fullname=None,
                          pc_installdir=None,
                          pc_install_fname=None,)

      def apache_file_to_eztdata(file):
          # cd to dirname before install to work around libtool 1.4.2 bug.
          dirname, fname = build_path_splitfile(file.filename)
          base, ext = os.path.splitext(fname)
          name = base.replace('mod_', '')
          return _eztdata(mode='apache-mod',
                          fullname=file.filename, dirname=dirname,
                          name=name, filename=fname, when=file.when)

      if area != 'test' and area != 'bdb-test':
        data.areas.append(ezt_area)

        area_var = area.replace('-', '_')
        upper_var = area_var.upper()
        ezt_area.varname = area_var
        ezt_area.uppervar = upper_var

        for file in files:
          if isinstance(file.target, gen_base.TargetApacheMod):
            ezt_file = apache_file_to_eztdata(file)
          else:
            ezt_file = file_to_eztdata(file)
            if area == 'locale':
              lang, objext = os.path.splitext(ezt_file.filename)
              installdir = ('$(DESTDIR)$(%sdir)/%s/LC_MESSAGES'
                            % (area_var, lang))
              ezt_file.installdir = installdir
              ezt_file.objext = objext
            else:
              ezt_file.install_fname = build_path_join('$(%sdir)' % area_var,
                                                       ezt_file.filename)

          # Install pkg-config files
          if (isinstance(file.target, gen_base.TargetLib) and
              ezt_file.fullname.startswith('subversion/libsvn_')):
            ezt_file.pc_fullname = ezt_file.fullname.replace('-1.la', '.pc')
            ezt_file.pc_installdir = '$(pkgconfig_dir)'
            pc_install_fname = ezt_file.filename.replace('-1.la', '.pc')
            ezt_file.pc_install_fname = build_path_join(ezt_file.pc_installdir,
                                                        pc_install_fname)
          ezt_area.files.append(ezt_file)

        # certain areas require hooks for extra install rules defined
        # in Makefile.in
        ### we should turn AREA into an object, then test it instead of this
        if area[:5] == 'swig-' and area[-4:] != '-lib' \
           or area[:7] == 'javahl-' \
           or area[:6] == 'svnxx-' \
           or area == 'tools':
          ezt_area.extra_install = 'yes'

    ########################################

    includedir = build_path_join('$(includedir)',
                                 'subversion-%s' % self.version)
    data.includes = [_eztdata(file=file,
                              src=build_path_join('$(abs_srcdir)', file),
                              dst=build_path_join(includedir,
                                                  build_path_basename(file)))
                      for file in self.includes]
    data.includedir = includedir

    ########################################

    for target in install_sources:
      if not isinstance(target, gen_base.TargetScript) and \
         not isinstance(target, gen_base.TargetJava) and \
         not isinstance(target, gen_base.TargetI18N):
        data.isources.append(_eztdata(name=target.name,
                                      filename=target.filename))

    ########################################

    # write dependencies and build rules (when not using suffix rules)
    # for all other generated files which will not be installed
    # (or will be installed, but not by the main generated build)
    obj_deps = sorted(self.graph.get_deps(gen_base.DT_OBJECT),
                      key=lambda t: t[0].filename)

    for objname, sources in obj_deps:
      dep = _eztdata(name=_normstr(objname),
                     when=objname.when,
                     deps=list(map(_normstr, sources)),
                     cmd=objname.compile_cmd,
                     source=_normstr(sources[0]))
      data.deps.append(dep)
      dep.generated = ezt.boolean(getattr(objname, 'source_generated', 0))

    template = ezt.Template(os.path.join('build', 'generator', 'templates',
                                         'build-outputs.mk.ezt'),
                            compress_whitespace=False)
    template.generate(open('build-outputs.mk', 'w'), data)

    self.write_standalone()

    self.write_transform_libtool_scripts(install_sources)

    self.write_pkg_config_dot_in_files(install_sources)

  def write_standalone(self):
    """Write autogen-standalone.mk"""

    standalone = open("autogen-standalone.mk", "w")
    standalone.write('# DO NOT EDIT -- AUTOMATICALLY GENERATED '
                     'BY build/generator/gen_make.py\n')
    standalone.write('# FROM build-outputs.mk\n')
    standalone.write('abs_srcdir = %s\n' % os.getcwd())
    standalone.write('abs_builddir = %s\n' % os.getcwd())
    standalone.write('top_srcdir = .\n')
    standalone.write('top_builddir = .\n')
    standalone.write('SWIG = swig\n')
    swig_py_opts = os.environ.get('SWIG_PY_OPTS',
                                  '-python -py3 -nofastunpack -modern')
    standalone.write('SWIG_PY_OPTS = %s\n' % (swig_py_opts))
    standalone.write('PYTHON = ' + sys.executable + '\n')
    standalone.write('\n')
    standalone.write(open("build-outputs.mk","r").read())
    standalone.close()

  def write_transform_libtool_scripts(self, install_sources):
    """Write build/transform_libtool_scripts.sh"""
    script = 'build/transform_libtool_scripts.sh'
    fd = open(script, 'w')
    fd.write('''#!/bin/sh
# DO NOT EDIT -- AUTOMATICALLY GENERATED BY build/generator/gen_make.py

transform()
{
  SCRIPT="$1"
  LIBS="$2"
  if [ -f $SCRIPT ]; then
    if grep LD_PRELOAD "$SCRIPT" > /dev/null; then
      :
    elif grep LD_LIBRARY_PATH "$SCRIPT" > /dev/null; then
      echo "Transforming $SCRIPT"
      EXISTINGLIBS=""
      for LIB in $LIBS; do
        # exclude libsvn_test since the undefined test_funcs breaks libtool
        case $LIB in
          *libsvn_test-*) continue ;;
        esac
        if [ ! -f $LIB ]; then
          continue
        fi
        if [ -z "$EXISTINGLIBS" ]; then
          EXISTINGLIBS="$LIB"
        else
          EXISTINGLIBS="$EXISTINGLIBS $LIB"
        fi
      done
      if [ ! -z "$EXISTINGLIBS" ]; then
        cat "$SCRIPT" |
        (
          read LINE
          echo "$LINE"
          read LINE
          echo "$LINE"
          read LINE
          echo "$LINE"
          read LINE
          echo "$LINE"
          echo "LD_PRELOAD=\\"$EXISTINGLIBS\\""
          echo "export LD_PRELOAD"
          cat
        ) < "$SCRIPT" > "$SCRIPT.new"
        mv -f "$SCRIPT.new" "$SCRIPT"
        chmod +x "$SCRIPT"
      fi
    fi
  fi
}

DIR=`pwd`

''')
    libdep_cache = {}
    paths = {}
    for lib in ('libsvn_auth_gnome_keyring', 'libsvn_auth_kwallet'):
      paths[lib] = self.sections[lib].options.get('path')
    for target_ob in install_sources:
      if not isinstance(target_ob, gen_base.TargetExe):
        continue
      name = target_ob.name
      libs = self._get_all_lib_deps(target_ob.name, libdep_cache, paths)
      path = paths[name]
      for i in range(0, len(libs)):
        lib = libs[i]
        libpath = paths[libs[i]]
        libs[i] = '$DIR/%s/.libs/%s-%s.so' % (libpath, lib, self.version)
      fd.write('transform %s/%s "%s"\n' % (path, name, " ".join(libs)))
    fd.close()
    mode = stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH
    os.chmod(script, mode)

  def _get_all_lib_deps(self, target_name, libdep_cache, paths):
    if not target_name in libdep_cache:
      libs = set()
      path = None
      if target_name in self.sections:
        section = self.sections[target_name]
        opt_libs = self.sections[target_name].options.get('libs')
        paths[target_name] = section.options.get('path')
        if opt_libs:
          for lib_name in opt_libs.split():
            if lib_name.startswith('libsvn_'):
              libs.add(lib_name)
            for lib in self._get_all_lib_deps(lib_name, libdep_cache, paths):
              libs.add(lib)
      if target_name == 'libsvn_subr':
        libs.update(('libsvn_auth_gnome_keyring', 'libsvn_auth_kwallet'))
      libdep_cache[target_name] = sorted(libs)
    return libdep_cache[target_name]

  def write_pkg_config_dot_in_files(self, install_sources):
    """Write pkg-config .pc.in files for Subversion libraries."""
    for target_ob in install_sources:
      if not (isinstance(target_ob, gen_base.TargetLib) and
              target_ob.path.startswith('subversion/libsvn_')):
        continue

      lib_name = target_ob.name
      lib_path = self.sections[lib_name].options.get('path')
      lib_deps = self.sections[lib_name].options.get('libs')
      lib_desc = self.sections[lib_name].options.get('description')
      output_path = build_path_join(lib_path, lib_name + '.pc.in')
      template = ezt.Template(os.path.join('build', 'generator', 'templates',
                                           'pkg-config.in.ezt'),
                              compress_whitespace=False)
      class _eztdata(object):
        def __init__(self, **kw):
          vars(self).update(kw)

      data = _eztdata(
        lib_name=lib_name,
        lib_desc=lib_desc,
        lib_deps=[],
        lib_required=[],
        lib_required_private=[],
        version=self.version,
        )
      # libsvn_foo -> -lsvn_foo-1
      data.lib_deps.append('-l%s-%s' % (lib_name.replace('lib', '', 1), data.version))
      for lib_dep in lib_deps.split():
        if lib_dep == 'apriconv':
          # apriconv is part of apr-util, skip it
          continue
        external_lib = self.sections[lib_dep].options.get('external-lib')
        if external_lib:
          ### Some of Subversion's internal libraries can appear as external
          ### libs to handle conditional compilation. Skip these for now.
          if external_lib in ['$(SVN_RA_LIB_LINK)', '$(SVN_FS_LIB_LINK)']:
            continue
          # If the external library is known to support pkg-config,
          # add it to the Required: or Required.private: section.
          # Otherwise, add the external library to linker flags.
          pkg_config = self.sections[lib_dep].options.get('pkg-config')
          if pkg_config:
            private = self.sections[lib_dep].options.get('pkg-config-private')
            if private:
              data.lib_required_private.append(pkg_config)
            else:
              data.lib_required.append(pkg_config)
          else:
            # $(EXTERNAL_LIB) -> @EXTERNAL_LIB@
            data.lib_deps.append('@%s@' % external_lib[2:-1])
        else:
          data.lib_required_private.append(lib_dep)

      template.generate(open(output_path, 'w'), data)

class UnknownDependency(Exception):
  "We don't know how to deal with the dependent to link it in."
  pass

### End of file.
