#!/usr/bin/env python
#
# USAGE: gen-build.py TYPE
#
# where TYPE is one of: make, dsp, vcproj
#
# It reads build.conf from the current directory, and produces its output
# into the current directory.
#


import os
try:
  import configparser
except ImportError:
  import ConfigParser as configparser
import codecs
import getopt
import string
import glob
import re

#import ezt

#
# legal platforms: aix, beos, netware, os2, os390, unix, win32
# 'make' users: aix, beos, os2, os390, unix, win32 (mingw)
#
PLATFORMS = [ 'aix', 'beos', 'netware', 'os2', 'os390', 'unix', 'win32' ]
MAKE_PLATFORMS = [
  ('unix', None),
  ('aix', 'unix'),
  ('beos', 'unix'),
  ('os2', 'unix'),
  ('os390', 'unix'),
  ('win32', 'unix'),
  ]
# note: MAKE_PLATFORMS is an ordered set. we want to generate unix symbols
#       first, so that the later platforms can reference them.


def main():
  parser = configparser.ConfigParser()
  parser.read('build.conf')

  if parser.has_option('options', 'dsp'):
    dsp_file = parser.get('options', 'dsp')
  else:
    dsp_file = None

  headers = get_files(parser.get('options', 'headers'))

  # compute the relevant headers, along with the implied includes
  legal_deps = { }
  for fname in headers:
    legal_deps[os.path.basename(fname)] = fname

  h_deps = { }
  for fname in headers:
    h_deps[os.path.basename(fname)] = extract_deps(fname, legal_deps)
  resolve_deps(h_deps)

  f = open('build-outputs.mk', 'w')
  f.write('# DO NOT EDIT. AUTOMATICALLY GENERATED.\n\n')

  # write out the platform-independent files
  files = get_files(parser.get('options', 'paths'))
  objects, dirs = write_objects(f, legal_deps, h_deps, files)
  f.write('\nOBJECTS_all = %s\n\n' % " ".join(objects))

  # for each platform and each subdirectory holding platform-specific files,
  # write out their compilation rules, and an OBJECT_<subdir>_<plat> symbol.
  for platform, parent in MAKE_PLATFORMS:

    # record the object symbols to build for each platform
    group = [ '$(OBJECTS_all)' ]

    # If we're doing win32, we're going to look in the libapr.dsp file
    # for those files that we have to manually add to our list.
    inherit_parent = { }
    if platform == 'win32' and dsp_file:
      for line in open(dsp_file).readlines():
        if line[:7] != 'SOURCE=':
          continue
        if line[7:].find('unix') != -1:
          # skip the leading .\ and split it out
          inherit_files = line[9:].strip().split('\\')
          # change the .c to .lo
          assert inherit_files[-1][-2:] == '.c'
          inherit_files[-1] = inherit_files[-1][:-2] + '.lo'
          # replace the \\'s with /'s
          inherit_line = '/'.join(inherit_files)
          if inherit_files[0] not in inherit_parent:
            inherit_parent[inherit_files[0]] = []
          inherit_parent[inherit_files[0]].append(inherit_line)

    for subdir in parser.get('options', 'platform_dirs').split():
      path = '%s/%s' % (subdir, platform)
      if not os.path.exists(path):
        # this subdir doesn't have a subdir for this platform, so we'll
        # use the parent-platform's set of symbols
        if parent:
          group.append('$(OBJECTS_%s_%s)' % (subdir, parent))
        continue

      # remember that this directory has files/objects
      dirs[path] = None

      # write out the compilation lines for this subdir
      files = get_files(path + '/*.c')
      objects, _unused = write_objects(f, legal_deps, h_deps, files)

      if subdir in inherit_parent:
        objects = objects + inherit_parent[subdir]

      symname = 'OBJECTS_%s_%s' % (subdir, platform)

      objects.sort()

      # and write the symbol for the whole group
      f.write('\n%s = %s\n\n' % (symname, " ".join(objects)))

      # and include that symbol in the group
      group.append('$(%s)' % symname)

    group.sort()

    # write out a symbol which contains the necessary files
    f.write('OBJECTS_%s = %s\n\n' % (platform, " ".join(group)))

  f.write('HEADERS = $(top_srcdir)/%s\n\n' % ' $(top_srcdir)/'.join(headers))
  f.write('SOURCE_DIRS = %s $(EXTRA_SOURCE_DIRS)\n\n' % " ".join(dirs.keys()))

  if parser.has_option('options', 'modules'):
    modules = parser.get('options', 'modules')

    for mod in modules.split():
      files = get_files(parser.get(mod, 'paths'))
      objects, _unused = write_objects(f, legal_deps, h_deps, files)
      flat_objects = " ".join(objects)
      f.write('OBJECTS_%s = %s\n' % (mod, flat_objects))

      if parser.has_option(mod, 'target'):
        target = parser.get(mod, 'target')
        f.write('MODULE_%s = %s\n' % (mod, target))
        f.write('%s: %s\n' % (target, flat_objects))
        f.write('\t$(LINK_MODULE) -o $@ $(OBJECTS_%s) $(LDADD_%s)\n' % (mod, mod))

      f.write('\n')

  if parser.has_option('options', 'libraries'):
    libs = parser.get('options', 'libraries')

    for lib in libs.split():
      files = get_files(parser.get(lib, 'paths'))
      objects, _unused = write_objects(f, legal_deps, h_deps, files)
      flat_objects = " ".join(objects)
      f.write('OBJECTS_%s = %s\n' % (lib, flat_objects))

      if parser.has_option(lib, 'target'):
        target = parser.get(lib, 'target')
        f.write('MODULE_%s = %s\n' % (lib, target))
        f.write('%s: $(OBJECTS_%s)\n' % (target, lib))
        f.write('\t$(LINK_LIBRARY) -o $@ $(OBJECTS_%s) $(LDADD_%s)\n' % (lib, lib))

      f.write('\n')

  # Build a list of all necessary directories in build tree
  alldirs = { }
  for dir in dirs.keys():
    d = dir
    while d:
      alldirs[d] = None
      d = os.path.dirname(d)

  # Sort so 'foo' is before 'foo/bar'
  keys = list(alldirs.keys())
  keys.sort()
  f.write('BUILD_DIRS = %s\n\n' % " ".join(keys))

  f.write('.make.dirs: $(srcdir)/build-outputs.mk\n' \
          '\t@for d in $(BUILD_DIRS); do test -d $$d || mkdir $$d; done\n' \
          '\t@echo timestamp > $@\n')


def write_objects(f, legal_deps, h_deps, files):
  dirs = { }
  objects = [ ]

  for file in files:
    if file[-10:] == '/apr_app.c':
      continue
    assert file[-2:] == '.c'
    obj = file[:-2] + '.lo'
    objects.append(obj)

    dirs[os.path.dirname(file)] = None

    # what headers does this file include, along with the implied headers
    deps = extract_deps(file, legal_deps)
    for hdr in list(deps.keys()):
      deps.update(h_deps.get(hdr, {}))

    vals = list(deps.values())
    vals.sort()
    f.write('%s: %s .make.dirs %s\n' % (obj, file, " ".join(vals)))

  objects.sort()

  return objects, dirs


def extract_deps(fname, legal_deps):
  "Extract the headers this file includes."
  deps = { }
  for line in codecs.open(fname, 'r', 'utf-8').readlines():
    if line[:8] != '#include':
      continue
    inc = _re_include.match(line).group(1)
    if inc in legal_deps.keys():
      deps[inc] = legal_deps[inc]
  return deps
_re_include = re.compile('#include *["<](.*)[">]')


def resolve_deps(header_deps):
  "Alter the provided dictionary to flatten includes-of-includes."
  altered = 1
  while altered:
    altered = 0
    for hdr, deps in header_deps.items():
      # print hdr, deps
      start = len(deps)
      for dep in list(deps.keys()):
        deps.update(header_deps.get(dep, {}))
      if len(deps) != start:
        altered = 1

def clean_path(path):
    return path.replace("\\", "/")

def get_files(patterns):
  files = [ ]
  for pat in patterns.split():
    files.extend(map(clean_path, glob.glob(pat)))
  files.sort()
  return files


if __name__ == '__main__':
  main()
