# -*- python -*-
#
# Copyright 2011-2012 Justin Erenkrantz and Greg Stein
#
# 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.
#

import sys
import os
import re
import platform

HEADER_FILES = ['serf.h',
                'serf_bucket_types.h',
                'serf_bucket_util.h',
                ]

# where we save the configuration variables
SAVED_CONFIG = '.saved_config'

opts = Variables(files=[SAVED_CONFIG])
opts.AddVariables(
  PathVariable('PREFIX',
               'Directory to install under',
               '/usr/local',
               PathVariable.PathIsDir),
  PathVariable('APR',
               "Path to apr-1-config, or to APR's install area",
               '/usr',
               PathVariable.PathAccept),
  PathVariable('APU',
               "Path to apu-1-config, or to APR's install area",
               '/usr',
               PathVariable.PathAccept),
  PathVariable('ZLIB',
               "Path to zlib's install area",
               '/usr',
               PathVariable.PathIsDir),
  PathVariable('GSSAPI',
               "Path to GSSAPI's install area",
               None,
               None),
  BoolVariable('DEBUG',
               "Enable debugging info and strict compile warnings",
               False),
  )

if sys.platform == 'darwin':
  opts.AddVariables(
    PathVariable('OPENSSL',
                 "Path to OpenSSL's install area",
                 None,
                 None))
else:
  opts.AddVariables(
    PathVariable('OPENSSL',
                 "Path to OpenSSL's install area",
                 '/usr',
                 PathVariable.PathIsDir))

env = Environment(variables=opts,
                  tools=('default', 'textfile',),
                  CPPPATH=['.', ],
                  )

match = re.search('SERF_MAJOR_VERSION ([0-9]+).*'
                  'SERF_MINOR_VERSION ([0-9]+).*'
                  'SERF_PATCH_VERSION ([0-9]+)',
                  env.File('serf.h').get_contents(),
                  re.DOTALL)
MAJOR, MINOR, PATCH = [int(x) for x in match.groups()]
env.Append(MAJOR=str(MAJOR))

# Calling external programs is okay if we're not cleaning or printing help.
# (cleaning: no sense in fetching information; help: we may not know where
# they are)
CALLOUT_OKAY = not (env.GetOption('clean') or env.GetOption('help'))


# HANDLING OF OPTION VARIABLES

unknown = opts.UnknownVariables()
if unknown:
  print 'Unknown variables:', ', '.join(unknown.keys())
  Exit(1)

apr = str(env['APR'])
apu = str(env['APU'])
zlib = str(env['ZLIB'])
gssapi = env.get('GSSAPI', None)

if gssapi and os.path.isdir(gssapi):
  krb5_config = os.path.join(gssapi, 'bin', 'krb5-config')
  if os.path.isfile(krb5_config):
    gssapi = krb5_config
    env['GSSAPI'] = krb5_config

openssl = env.get('OPENSSL', None)
if openssl and os.path.isdir(str(openssl)):
  env.Append(CPPPATH='$OPENSSL/include')
  env.Append(LIBPATH='$OPENSSL/lib')
  env.Append(CFLAGS='-DSERF_HAVE_OPENSSL')
debug = env.get('DEBUG', None)

Help(opts.GenerateHelpText(env))
opts.Save(SAVED_CONFIG, env)


# PLATFORM-SPECIFIC BUILD TWEAKS

def link_rpath(d):
  if sys.platform == 'sunos5':
    return '-Wl,-R,%s' % (d,)
  return '-Wl,-rpath,%s' % (d,)


thisdir = os.getcwd()
libdir = '$PREFIX/lib'
incdir = '$PREFIX/include/serf-$MAJOR'

LIBNAME = 'libserf-${MAJOR}'
if sys.platform != 'win32':
  LIBNAMESTATIC = LIBNAME
else:
  LIBNAMESTATIC = 'serf-${MAJOR}'

linkflags = []

if sys.platform != 'win32':
  linkflags.append(link_rpath(libdir))
else:
  linkflags.append(['/nologo'])

if sys.platform == 'darwin':
#  linkflags.append('-Wl,-install_name,@executable_path/%s.dylib' % (LIBNAME,))
  linkflags.append('-Wl,-install_name,%s/%s.dylib' % (thisdir, LIBNAME,))
  # 'man ld' says positive non-zero for the first number, so we add one.
  # Mac's interpretation of compatibility is the same as our MINOR version.
  linkflags.append('-Wl,-compatibility_version,%d' % (MINOR+1,))
  linkflags.append('-Wl,-current_version,%d.%d' % (MINOR+1, PATCH,))

  # enable macosxssl_buckets only on Mac OS X 10.7+
  macosxssl = False
  ver, _, _ = platform.mac_ver()
  ver = float('.'.join(ver.split('.')[:2]))
  if ver >= 10.7:
    macosxssl = True
    env.Append(CFLAGS='-DSERF_HAVE_MACOSXSSL')

if sys.platform == 'win32':
  ### we should create serf.def for Windows DLLs and add it into the link
  ### step somehow.
  pass

ccflags = [ ]
if sys.platform != 'win32':
  ### gcc only. figure out appropriate test / better way to check these
  ### flags, and check for gcc.
  ccflags = ['-std=c89',
             '-Wdeclaration-after-statement',
             '-Wmissing-prototypes',
             ]

  ### -Wall is not available on Solaris
  if sys.platform != 'sunos5': 
    ccflags.append(['-Wall', ])

  if debug:
    ccflags.append(['-g'])
  else:
    ccflags.append('-O2')
else:
  ccflags.append(['/nologo', '/W4', '/Zi'])
  if debug:
    ccflags.append(['/Od'])
  else:
    ccflags.append(['/O2'])
  
libs = [ ]
if sys.platform != 'win32':
  ### works for Mac OS. probably needs to change
  libs = ['ssl', 'crypto', 'z', ]

  if macosxssl:
    env.Append(FRAMEWORKS=['Security', 'SecurityInterface', 'CoreFoundation',
                           'AppKit'])
    libs.append('objc')

  if sys.platform == 'sunos5':
    libs.append('m')

env.Replace(LINKFLAGS=linkflags,
            CCFLAGS=ccflags,
            LIBS=libs,
            )


# PLAN THE BUILD

SOURCES = Glob('*.c') + Glob('buckets/*.c') + Glob('auth/*.c')
if macosxssl:
    SOURCES += ['buckets/macosxssl_helper.m']

lib_static = env.StaticLibrary(LIBNAMESTATIC, SOURCES)
lib_shared = env.SharedLibrary(LIBNAME, SOURCES)

if sys.platform == 'win32':
  if debug:
    env.Append(CFLAGS='/MDd')
  else:
    env.Append(CFLAGS='/MD')
  
  env.Append(LIBS=['user32.lib', 'advapi32.lib', 'gdi32.lib', 'ws2_32.lib',
                   'crypt32.lib', 'mswsock.lib', 'rpcrt4.lib', 'secur32.lib'])

  # Get apr/apu information into our build
  env.Append(CFLAGS='-DWIN32 ' + \
                    '/I "$APR/include" /I "$APU/include" ' + \
                    '-DWIN32 -DWIN32_LEAN_AND_MEAN -DNOUSER' + \
                    '-DNOGDI -DNONLS -DNOCRYPT')
  env.Append(LIBPATH=['$APR/Release','$APU/Release'],
             LIBS=['libapr-1.lib', 'libaprutil-1.lib'])
  apr_libs='libapr-1.lib'
  apu_libs='libaprutil-1.lib'

  # zlib
  env.Append(CFLAGS='/I "$ZLIB"')
  env.Append(LIBPATH='$ZLIB', LIBS='zlib.lib')

  # openssl
  env.Append(CPPPATH='$OPENSSL/inc32')
  env.Append(LIBPATH='$OPENSSL/out32dll', LIBS=['libeay32.lib', 'ssleay32.lib'])

else:
  if os.path.isdir(apr):
    apr = os.path.join(apr, 'bin', 'apr-1-config')
    env['APR'] = apr
  if os.path.isdir(apu):
    apu = os.path.join(apu, 'bin', 'apu-1-config')
    env['APU'] = apu

  ### we should use --cc, but that is giving some scons error about an implict
  ### dependency upon gcc. probably ParseConfig doesn't know what to do with
  ### the apr-1-config output
  if CALLOUT_OKAY:
    env.ParseConfig('$APR --cflags --cppflags --ldflags --includes'
                    ' --link-ld --libs')
    env.ParseConfig('$APU --ldflags --includes --link-ld --libs')

  ### there is probably a better way to run/capture output.
  ### env.ParseConfig() may be handy for getting this stuff into the build
  if CALLOUT_OKAY:
    apr_libs = os.popen(env.subst('$APR --link-libtool --libs')).read().strip()
    apu_libs = os.popen(env.subst('$APU --link-libtool --libs')).read().strip()
  else:
    apr_libs = ''
    apu_libs = ''
  
  env.Append(CPPPATH='$OPENSSL/include')
  env.Append(LIBPATH='$OPENSSL/lib')


# If build with gssapi, get its information and define SERF_HAVE_GSSAPI
if gssapi and CALLOUT_OKAY:
    env.ParseConfig('$GSSAPI --libs gssapi')
    env.Append(CFLAGS='-DSERF_HAVE_GSSAPI')
if sys.platform == 'win32':
  env.Append(CFLAGS='-DSERF_HAVE_SPNEGO -DSERF_HAVE_SSPI')

# On Solaris, the -R values that APR describes never make it into actual
# RPATH flags. We'll manually map all directories in LIBPATH into new
# flags to set RPATH values.
if sys.platform == 'sunos5':
  for d in env['LIBPATH']:
    env.Append(LINKFLAGS=link_rpath(d))

# Set up the construction of serf-*.pc
# TODO: add gssapi libs
pkgconfig = env.Textfile('serf-%d.pc' % (MAJOR,),
                         env.File('build/serf.pc.in'),
                         SUBST_DICT = {
                           '@MAJOR@': str(MAJOR),
                           '@PREFIX@': '$PREFIX',
                           '@INCLUDE_SUBDIR@': 'serf-%d' % (MAJOR,),
                           '@VERSION@': '%d.%d.%d' % (MAJOR, MINOR, PATCH),
                           '@LIBS@': '%s %s -lz' % (apu_libs, apr_libs),
                           })

env.Default(lib_static, lib_shared, pkgconfig)

if CALLOUT_OKAY:
  conf = Configure(env)

  ### some configuration stuffs

  env = conf.Finish()


# INSTALLATION STUFF

install_static = env.Install(libdir, lib_static)
install_shared = env.Install(libdir, lib_shared)

if sys.platform == 'darwin':
  install_shared_path = install_shared[0].abspath
  env.AddPostAction(install_shared, ('install_name_tool -id %s %s'
                                     % (install_shared_path,
                                        install_shared_path)))
  ### construct shared lib symlinks. this also means install the lib
  ### as libserf-2.1.0.0.dylib, then add the symlinks.
  ### note: see InstallAs

env.Alias('install-lib', [install_static, install_shared,
                          ])
env.Alias('install-inc', env.Install(incdir, HEADER_FILES))
env.Alias('install-pc', env.Install(os.path.join(libdir, 'pkgconfig'),
                                    pkgconfig))
env.Alias('install', ['install-lib', 'install-inc', 'install-pc', ])


# TESTS
### make move to a separate scons file in the test/ subdir?

tenv = env.Clone()

TEST_PROGRAMS = [
  'test/serf_get',
  'test/serf_response',
  'test/serf_request',
  'test/serf_spider',
  'test/test_all',
  'test/serf_bwtp',
]

env.AlwaysBuild(env.Alias('check', TEST_PROGRAMS, 'build/check.sh'))

# Find the (dynamic) library in this directory
linkflags = [link_rpath(thisdir,), ]
tenv.Replace(LINKFLAGS=linkflags)
tenv.Prepend(LIBS=['libserf-2', ],
             LIBPATH=[thisdir, ])

for proggie in TEST_PROGRAMS:
  if proggie.endswith('test_all'):
    tenv.Program('test/test_all', [
        'test/test_all.c',
        'test/CuTest.c',
        'test/test_util.c',
        'test/test_context.c',
        'test/test_buckets.c',
        'test/test_auth.c',
        'test/mock_buckets.c',
        'test/test_ssl.c',
        'test/server/test_server.c',
        'test/server/test_sslserver.c',
        ])
  else:
    tenv.Program(proggie, [proggie + '.c'])


# HANDLE CLEANING

if env.GetOption('clean'):
  # When we're cleaning, we want the dependency tree to include "everything"
  # that could be built. Thus, include all of the tests.
  env.Default('check')
