import libtbx.load_env
from libtbx.str_utils import show_string
import md5
import sys, os
Import("env_base", "env_etc")
env_etc.boost_dist = libtbx.env.dist_path("boost")
env_etc.boost_include = env_etc.boost_dist
if (not env_etc.no_boost_python):
  env_etc.cxxflags_bpl_defines_base = ["-DBOOST_PYTHON_MAX_BASES=2"]
  env_no_includes_boost_python_ext = env_base.Copy(
    CXXFLAGS=env_etc.cxxflags_base,
    CCFLAGS=env_etc.ccflags_base,
    SHCXXFLAGS=env_etc.cxxflags_base,
    SHLINKFLAGS=env_etc.shlinkflags_bpl,
    SHLIBPREFIX="",
    LIBPATH=["#lib"] + env_etc.libpath_python,
    LIBS=["boost_python"] + env_etc.libs_python + env_etc.libm,
  )
  env_no_includes_boost_python_ext.Append(
    SHCXXFLAGS=env_etc.cxxflags_bpl_defines_base)
  env_no_includes_boost_python_ext.Replace(
    SHLIBSUFFIX=env_etc.extension_module_suffix)
  Export("env_no_includes_boost_python_ext")
  env_pure_boost_python_ext = env_no_includes_boost_python_ext.Copy()
  env_etc.include_registry.set_boost_dir_name(env_etc.boost_dist)
  env_etc.include_registry.append(
    env=env_pure_boost_python_ext,
    paths=[env_etc.boost_include,
           env_etc.python_include])
  env_boost_python_ext = env_pure_boost_python_ext.Copy()
  env_etc.include_registry.prepend(
    env=env_boost_python_ext,
    paths=[env_etc.libtbx_include])
  Export("env_boost_python_ext")

  env_pure_boost_python_ext.SharedLibrary(
    target="#lib/boost_python_meta_ext",
    source="meta_ext.cpp")

  env_pure_boost_python_ext.SharedLibrary(
    target="#lib/boost_python_hybrid_times_ext",
    source="hybrid_times_ext.cpp")

  env_pure_boost_python_ext.SharedLibrary(
    target="#lib/boost_rational_ext",
    source="rational_ext.cpp")

  env = env_pure_boost_python_ext.Copy()
  env_etc.include_registry.prepend(
    env=env,
    paths=[os.path.dirname(libtbx.env.dist_path("boost_adaptbx"))])
  env.SharedLibrary(
    target="#lib/boost_optional_ext",
    source="optional_ext.cpp")

  import os, os.path
  env = env_base.Copy(
    LIBS=env_etc.libs_python,
    LIBPATH=env_etc.libpath_python,
  )
  env.Replace(SHCXXFLAGS=env_etc.cxxflags_base)
  env.Append(SHCXXFLAGS=env_etc.cxxflags_bpl_defines_base)
  env.Append(SHCXXFLAGS="-DBOOST_PYTHON_SOURCE")
  env.Replace(SHLINKFLAGS=env_etc.shlinkflags)
  env.Replace(CXXFLAGS=env_etc.cxxflags_base)
  env.Append(CXXFLAGS=env_etc.cxxflags_bpl_defines_base)
  env.Append(CXXFLAGS="-DBOOST_PYTHON_SOURCE")
  env.Replace(LINKFLAGS=env_etc.shlinkflags)
  env_etc.include_registry.append(
    env=env,
    paths=[env_etc.boost_include, env_etc.python_include])

  if (env_etc.compiler == "darwin_c++"):
    env.Replace(SHLINK="libtbx.mac_os_x_ld_bpl_dll")
    env.Prepend(SHLINKFLAGS=[
      "c++", "-F"+env_etc.darwin_framework_path(), "-framework", "Python"])
  elif (env_etc.compiler == "darwin_gcc"):
    env.Replace(SHLINK="libtbx.mac_os_x_ld_bpl_dll")
    env.Prepend(SHLINKFLAGS=[
      "g++", "-F"+env_etc.darwin_framework_path(), "-framework", "Python"])

  jamfile_path = libtbx.env.under_dist("boost", "libs/python/build/Jamfile")
  jamfile_all =   open(str(jamfile_path), "r").read()
  jam_rhs = jamfile_all.split("local sources =")[1]
  jam_middle = jam_rhs.split(";")[0]
  jamfile_lines = jam_middle.split("\n")
  jamfile_lines = [line.strip() for line in jamfile_lines]
  while (jamfile_lines.count("") > 0):
    jamfile_lines.remove("")
  bpl_dll_sources = []
  prefix = "#"+os.path.join(
    os.path.basename(env_etc.boost_dist), "libs", "python", "src")
  for line in jamfile_lines:
    bpl_dll_sources.append(os.path.join(prefix, line))
  assert len(bpl_dll_sources) > 0
  env.Repository(os.path.dirname(env_etc.boost_dist))
  if (env_etc.static_bpl):
    env.StaticLibrary(target="#lib/boost_python", source=bpl_dll_sources)
  else:
    env.SharedLibrary(target="#lib/boost_python", source=bpl_dll_sources)

  if (int(ARGUMENTS.get("boost_python_tests", 0))):
    jamfile_path = libtbx.env.under_dist("boost", "libs/python/test/Jamfile")
    jamfile = " ".join(
      [line.rstrip() for line in open(jamfile_path).readlines()])
    m = md5.new()
    m.update(jamfile)
    # based on boost/libs/python/test/Jamfile revision 1.86
    jamfile_md5 = "d8fe4634e5a18620bdd56bc113cdcb48"
    if (m.hexdigest() != jamfile_md5):
      print "***************************************************"
      print "Warning: boost/libs/python/test/Jamfile has changed"
      print "New md5 signature:", m.hexdigest()
      print "***************************************************"
    if (env_etc.compiler in ["irix_CC", "tru64_cxx"]):
      disabled = "#"
    else:
      disabled = ""
    bpl_tests = Split("""
staticmethod
shared_ptr
andreas_beyer
polymorphism
polymorphism2
auto_ptr
minimal
args
numpy
enum
exception_translator
test_pointer_adoption
operators
callbacks
defaults
object
list
long
dict
tuple
str
virtual_functions
back_reference
implicit
data_members
ben_scott1
bienstman1
bienstman2
bienstman3
multi_arg_constructor
extract
opaque
pickle1
pickle2
pickle3
pickle4
nested
docstring
bienstman4
bienstman5
test_builtin_converters,builtin_converters,test_builtin_converters
cltree,cltree,test_cltree
m1,m1,newtest
m2,m2,newtest
iterator,iterator_ext,iterator
input_iterator,input_iterator,iterator
crossmod_exception_a,crossmod_exception_a,crossmod_exception
crossmod_exception_b,crossmod_exception_b,crossmod_exception
vector_indexing_suite
return_arg
keywords,keywords,keywords_test
%sproperties
map_indexing_suite;int_map_indexing_suite,map_indexing_suite_ext,map_indexing_suite
injected
slice
const_argument
raw_ctor
pointer_vector
wrapper_held_type
polymorphism2_auto_ptr
""" % disabled)
    Import("env_boost_python_ext")
    test_dir = libtbx.env.under_dist("boost", "libs/python/test")
    all_tst = []
    for bpl_test in bpl_tests:
      if (bpl_test[0] == "#"):
        print "Warning: disabled Boost.Python test:", bpl_test
        continue
      flds = bpl_test.split(",")
      assert len(flds) in (1,3)
      if (len(flds) == 1):
        src = bpl_test
        pyd = bpl_test + "_ext"
        tst = bpl_test
      else:
        src = flds[0]
        pyd = flds[1]
        tst = flds[2]
      env = env_pure_boost_python_ext.Copy()
      env.Repository(os.path.dirname(env_etc.boost_dist))
      prefix = "#"+os.path.join(
        os.path.basename(env_etc.boost_dist), "libs", "python", "test")
      ok = True
      source = []
      for s in src.split(";"):
        cpp = "%s.cpp" % s
        file_name = os.path.join(test_dir, cpp)
        if (not os.path.isfile(file_name)):
          print "Warning: source file not available:", show_string(file_name)
          ok = False
        else:
          source.append(os.path.join(prefix, cpp))
      if (ok):
        if (not tst in all_tst):
          all_tst.append(tst)
        env.SharedLibrary(target="#lib/%s" % pyd, source=source)
    all_tst = [os.path.join(test_dir, tst+".py") for tst in all_tst]
    #
    if (sys.platform != "win32"):
      env.SharedLibrary(
        target="#lib/boost_adaptbx_char_array_ext",
        source=["char_array_ext.cpp"])
      all_tst.append(
        libtbx.env.under_dist("boost_adaptbx", "tst_char_array.py"))
    #
    if (sys.platform == "win32"):
      boost_python_run_tests = \
        "%s\\boost_python_run_tests.bat" % libtbx.env.build_path
      f = open(boost_python_run_tests, "w")
      for tst in all_tst:
        print >> f, 'call libtbx.python "%s"' % tst
      f.close()
    else:
      boost_python_run_tests = \
        "%s/boost_python_run_tests.csh" % libtbx.env.build_path
      f = open(boost_python_run_tests, "w")
      print >> f, "#! /bin/csh -f"
      print >> f, "set verbose"
      for tst in all_tst:
        print >> f, 'libtbx.python "%s"' % tst
      f.close()
      os.chmod(boost_python_run_tests, 0755)

  if (os.path.isfile(libtbx.env.under_build("lib/libswig_class_example.a"))):
    # this example requires these manual steps:
    #   gunzip -c swig-1.3.24.tar.gz | tar xf -
    #   cd SWIG-1.3.24
    #   ./configure
    #   make
    #   cd Examples/python/class
    #   make
    #   cp _example.so example.py $LIBTBX_BUILD/lib
    #   ar r $LIBTBX_BUILD/lib/libswig_class_example.a example.o
    env = env_pure_boost_python_ext.Copy()
    env.Prepend(LIBS=["swig_class_example"])
    env.SharedLibrary(
      target="#lib/boost_python_swig_args_ext",
      source="swig_args_ext.cpp")
