[Distutils] segmentation fault using kinterbasdb extension on cygwin.dll

eumir camara eumir_camara at yahoo.com
Fri Aug 15 02:17:40 EDT 2003


I was able to build and install kinterbasdb_3.1_pre4
on cygwin successfully. But I kept getting a
segmentation fault (core dumped) when connecting to
firebird 1.03.

ENVIRONMENT:
======================================================
win2k service pack 3
kinterbasdb 3.1_pre4
cygwin
cygwin python 2.2.3
egenix-mx-base-2.0.4
firebird 1.03 windows

STEPS:
======================================================
1) downloaded kinterbasdb 3.1_pre4 and untar to a
directory
2) modified setup.cfg
database_home_dir=c:/progra~1/firebird
database_include_dir=c:/progra~1/firebird/include
database_lib_dir=c:/progra~1/firebird/lib
3) modified setup.py
file included below
4) built kinterbasdb extension
$ python setup.py build
5) installed kinterbasdb extension
$ python setup.py install
6) tested installation
setup.py
7) resulted in segmentation fault (core dumped)

QUESTIONS:
======================================================
Did i build the extension properly?
Is it possible that it couldn't find a required
gds32.dll?
Is it possible that it could find it gds32.dll, but is
not because it uses MSVCRT.dll while the
_kinterbasdb.dll uses cygwin1.dll?

thank you,
eumir_camara at yahoo.com

setup.py begin =======================================
import ConfigParser, os, os.path, shutil, string, sys,
types
import distutils.core
import distutils.ccompiler
import distutils.sysconfig

class BuildError(Exception): pass

def doCommand(cmd, header='COMMAND EXECUTION ERROR'):
    print '\t' + cmd
    taskOutStream = os.popen(cmd)
    taskOutput = taskOutStream.read()
    taskRetCode = taskOutStream.close()
    if taskRetCode is not None:
        raise BuildError('\n%s\n  Command [%s] died
with error:\n[%s]\n'
            % (header, cmd, taskOutput)
          )
    return taskOutput

def doLibConvCmd(cmd):
    return doCommand(cmd, LIBCONVERSION_ERROR_HEADER)

def determineWindowsSystemDir():
    if sys.platform == 'cygwin':
        return doCommand('cygpath --sysdir')[:-1] #
Trailing newline.
    else:
        # (normal win32)
        # If I were willing to introduce a win32all
dependency into this build
        # script, this function would be replaced by
win32api.GetSystemDirectory.
        winDir = os.environ.get('SYSTEMROOT',
os.environ.get('WINDIR', 'C:\\Windows'))
        winSysDir = os.path.join(winDir, 'system32')
        if not os.path.isdir(winSysDir):
            winSysDir = os.path.join(winDir, 'system')
        return winSysDir

# Be careful about changing these messages; the docs
refer to them.
PYTHON_SYSTEM_ERROR_HEADER = 'PYTHON SYSTEM ERROR:'
COMPILER_CONFIGURATION_ERROR_HEADER = 'COMPILER
CONFIGURATION ERROR:'
KIDB_DISTRIBUTION_ERROR_HEADER = 'KINTERBASDB
DISTRIBUTION ERROR:'
LIBCONVERSION_ERROR_HEADER = 'LIBRARY CONVERSION
ERROR:'
AUTODETECTION_ERROR_HEADER = 'LIBRARY AUTODETECTION
ERROR:'
MANUAL_SPECIFICATION_ERROR_HEADER = 'LIBRARY MANUAL
SPECIFICATION ERROR:'

DISTUTILS_URL =
'http://www.python.org/sigs/distutils-sig/distutils.html'

# mx.DateTime is not really required now that date I/O
is handled by
# dynamic type translation.  See the
typeconv_preferred.py in this directory
# for a date I/O implementation that uses Python 2.3
stdlib datetime module
# rather than mx.DateTime.
# In any case, mx.DateTime is no longer linked to
kinterbasdb at the C level--
# it's just a standard Python import now.
# DATETIME_URL =
'http://www.lemburg.com/files/python/eGenix-mx-Extensions.html'

VERSION_FILE = 'version.txt'
CONFIG_FILE = 'setup.cfg'

PYTHON_VERSION_THRESHOLD = '2.1'

if sys.version < PYTHON_VERSION_THRESHOLD:
    sys.stderr.write(
        '%s\n'
        '  Beginning with kinterbasdb 3.1,
kinterbasdb'
        ' no longer officially supports\n  versions of
Python prior to %s.\n\n'
        % (PYTHON_SYSTEM_ERROR_HEADER,
PYTHON_VERSION_THRESHOLD)
      )
    sys.exit(-1)

DEBUG = int(os.environ.get('KINTERBASDB_DEBUG', 0))

try:
    import distutils
except ImportError:
    sys.stderr.write(
            "%s\n"
            "  Cannot import the standard package
'distutils'.\n"
            "  distutils did not join the standard
library until Python 1.6,\n"
            "  and some some nonstandard Python
distributions do not\n"
            "  include the package.\n"
            "  You must either upgrade to a Python
version with distutils\n"
            "  integrated, or download the package
from:\n"
            "    %s"
            % (PYTHON_SYSTEM_ERROR_HEADER,
DISTUTILS_URL,)
        )
    sys.exit(1)

import distutils.core
import distutils.ccompiler
import distutils.sysconfig

# Module name and version number:
kinterbasdb_name = 'kinterbasdb'
# Retrive the kinterbasdb version number from a
standard text file for the sake
# of maintainability:
try:
    kinterbasdb_version =
string.strip(open(VERSION_FILE).read())
except IOError:
    sys.stderr.write(
            "%s\n"
            " Missing file 'version.txt'; cannot
determine kinterbasdb"
            " version."
            % KIDB_DISTRIBUTION_ERROR_HEADER
        )
    sys.exit(1)

# These config parameters are user-specifiable via
setup.cfg:
DATETIME_INCLUDE_DIR = None

DATABASE_IS_FIREBIRD = None
DATABASE_HOME_DIR = None
DATABASE_INCLUDE_DIR = None
DATABASE_LIB_DIR = None
DATABASE_LIB_NAME = None

# These config parameters are not drawn from
setup.cfg:
CUSTOM_PREPROCESSOR_DEFS = []
PLATFORM_SPECIFIC_INCLUDE_DIRS = []
PLATFORM_SPECIFIC_LIB_DIRS = []
PLATFORM_SPECIFIC_LIB_NAMES = []
PLATFORM_SPECIFIC_EXTRA_COMPILER_ARGS = []
PLATFORM_SPECIFIC_EXTRA_LINKER_ARGS = []

# See if the user manually specified various build
options in the setup config
# file.  If so, skip autodetection for the options
that the user has specified.
config = ConfigParser.ConfigParser()
config.read(CONFIG_FILE)

if config.has_section('manual_config'):
    # It would be better to test against
sys.version_info rather than the
    # string sys.version, but it's not available on
older Python versions.
    if sys.version < '1.6':
        # Compensate for 1.5.2's lack of
ConfigParser.ConfigParser.has_option:
        def config_has_option(section, option,
config=config):
            try:
                return config.get(section, option)
            except ConfigParser.NoOptionError:
                return None
        config.has_option = config_has_option
    if config.has_option('manual_config',
'datetime_include_dir'):
        DATETIME_INCLUDE_DIR =
config.get('manual_config', 'datetime_include_dir')

    if config.has_option('manual_config',
'database_is_firebird'):
        DATABASE_IS_FIREBIRD =
config.get('manual_config', 'database_is_firebird')
    if config.has_option('manual_config',
'database_home_dir'):
        DATABASE_HOME_DIR =
config.get('manual_config', 'database_home_dir')
    if config.has_option('manual_config',
'database_include_dir'):
        DATABASE_INCLUDE_DIR =
config.get('manual_config', 'database_include_dir')
    if config.has_option('manual_config',
'database_lib_dir'):
        DATABASE_LIB_DIR = config.get('manual_config',
'database_lib_dir')
    if config.has_option('manual_config',
'database_lib_name'):
        DATABASE_LIB_NAME =
config.get('manual_config', 'database_lib_name')

if DEBUG:
    print "*** CONFIG OPTIONS SPECIFIED IN %s SECTION
'manual_config' ***" % CONFIG_FILE
    for key in config.options('manual_config'):
        print '%s:' % (key)
        print '    %s' % (config.get('manual_config',
key))

ALL_AUTODETECT_OPTIONS_MANUALLY_SPECIFIED = (
            DATETIME_INCLUDE_DIR

        and DATABASE_IS_FIREBIRD is not None
        and DATABASE_HOME_DIR
        and DATABASE_INCLUDE_DIR
        and DATABASE_LIB_DIR
        and DATABASE_LIB_NAME
    )

# Utility functions:

def verifyAutodetectedDatabaseIncludeDir():
    if not os.path.exists(DATABASE_INCLUDE_DIR):
        sys.stderr.write(
                "%s\n"
                "  Cannot autodetect the database
header file directory.\n"
                "  (Tried %s)\n"
                "  Try specifying the
'database_include_dir' option in\n"
                "  the 'manual_config' section of the
setup config file (%s).\n"
                % (AUTODETECTION_ERROR_HEADER,
DATABASE_INCLUDE_DIR, CONFIG_FILE)
            )
        sys.exit(1)

def verifyUserSpecifiedDatabaseIncludeDir():
    if not os.path.exists(DATABASE_INCLUDE_DIR):
        sys.stderr.write(
                "%s\n"
                "  The user-specified database header
file directory\n"
                "    %s\n"
                "  does not exist.\n"
                "  Try modifying the
'database_include_dir' option in\n"
                "  the 'manual_config' section of the
setup config file (%s),\n"
                "  or comment out that option to force
this script to\n"
                "  to autodetect it.\n"
                % (MANUAL_SPECIFICATION_ERROR_HEADER,
DATABASE_INCLUDE_DIR, CONFIG_FILE)
            )
        sys.exit(1)

def verifyAutodetectedDatabaseLibraryDir():
    if not os.path.exists(DATABASE_LIB_DIR):
        sys.stderr.write(
                "%s\n"
                "  Cannot autodetect the database lib
directory.\n"
                "  (Tried %s)\n"
                "  Try specifying the
'database_include_dir' option in\n"
                "  the 'manual_config' section of the
setup config file (%s).\n"
                % (AUTODETECTION_ERROR_HEADER,
DATABASE_LIB_DIR, CONFIG_FILE)
            )
        sys.exit(1)

def verifyUserSpecifiedDatabaseLibraryDir():
    if not os.path.exists(DATABASE_LIB_DIR):
        sys.stderr.write(
                "%s\n"
                "  The user-specified database lib
directory\n"
                "    %s\n"
                "  does not exist.\n"
                "  Try modifying the
'database_lib_dir' option in\n"
                "  the 'manual_config' section of the
setup config file (%s),\n"
                "  or comment out that option to force
this script to\n"
                "  to autodetect it.\n"
                % (MANUAL_SPECIFICATION_ERROR_HEADER,
DATABASE_LIB_DIR, CONFIG_FILE)
            )
        sys.exit(1)

def findSpacelessDirName(d):
    # On Windows, try to find the spaceless version of
the provided directory
    # name.
    # This function was added on 2002.03.14 as part of
an ugly hack to
    # surmount a bug in the distutils package.

    # Sometime distutils causes None to be fed to this
function.
    if not d:
        return d

    d = os.path.normpath(os.path.abspath(d))

    if ' ' not in d:
        return d

    # If d doesn't exist, its short equivalent can't
be determined.
    # However, for the purposes of this program (which
is solely for
    # convenience anyway) it's better just to risk
feeding the
    # compiler/linker a path with a space in it than
it is to raise
    # an exception when there's still a *chance* of
success.
    if not os.path.isdir(d):
        return d

    try:
        import win32api

        return
os.path.normcase(win32api.GetShortPathName(d))
    except ImportError:
        # Since win32api is not available, we'll
revert to a lame,
        # manual approximation of GetShortPathName.
        pass

    ds = d.split(os.sep) # Split into components.

    if DEBUG:
        print 'ds is', ds

    ds[0] = ds[0] + '\\' # Add slash back onto drive
designation so that
                         # it's like c:\ rather than
just c:

    dsNoSpaces = [] # Will contain a version of the
directory components
                    # with all spaces removed.
    for x in range(len(ds)):
        dir = ds[x]
        if DEBUG:
            print 'dir is', dir

        if dir.find(' ') == -1:
            shortDir = dir
        else:
            fullDir = apply(os.path.join, ds[:x + 1])

            if DEBUG:
                print 'fullDir is', fullDir

            # Must deal with names like 'abc de' that
have their space
            # before the sixth character.
            dirNoSpaces = dir.replace(' ', '')
            if len(dirNoSpaces) < 6:
                shortDirBase = dirNoSpaces
            else:
                shortDirBase = dirNoSpaces[:6]

            # Search for shortDirBase~i until we find
it.
            shortDir = None
            i = 1
            while i < 9: # This code doesn't handle
situations where there are
                         # more than nine directories
with the same prefix.
                maybeShortDir = '%s~%d' %
(shortDirBase, i)
                fullMaybeShortDir = os.path.join(
                    os.path.dirname(fullDir),
maybeShortDir)
                if not
os.path.isdir(fullMaybeShortDir):
                    continue

                # There follows a *really* lame
approximation of
                # os.path.samefile, which is not
available on Windows.
                if os.listdir(fullMaybeShortDir) ==
os.listdir(fullDir):
                    shortDir = maybeShortDir
                    break

                i = i + 1

            if shortDir is None:
                raise Exception('Unable to find
shortened version of'
                    ' directory named %s' % d)

        dsNoSpaces.append(shortDir)

    if DEBUG:
        print 'dsNoSpaces is', dsNoSpaces

    return os.path.normcase(apply(os.path.join,
dsNoSpaces))


# Perform generic compilation parameter setup, then
switch to platform-
# specific.

curdirAbs = os.path.abspath(os.curdir)

# Autodetect Python directory info.
if DEBUG:
    print '*** PYTHON SETTINGS ***'

pythonHomeDir = sys.exec_prefix
pythonPkgDir = distutils.sysconfig.get_python_lib()

if DEBUG:
    print '\tPython home dir:', pythonHomeDir
    print '\tPython package dir:', pythonPkgDir
    print '\tPlatform', sys.platform



# Begin platform-specific compilation parameter setup:
if sys.platform == 'win32':
   
ALL_AUTODETECT_WINDOWS_REGISTRY_OPTIONS_MANUALLY_SPECIFIED
= (
                DATABASE_HOME_DIR
            and DATABASE_INCLUDE_DIR
            and DATABASE_LIB_DIR
            and DATABASE_LIB_NAME
        )

    CUSTOM_PREPROCESSOR_DEFS.append( ('WIN32', None) )

    # If this is a source distribution, add a couple
of necessary include and
    # lib directories.
    pcbuildDir = os.path.join(
       
os.path.split(distutils.sysconfig.get_python_inc())[0],
'PCBuild')
    if os.path.exists(pcbuildDir):
        PLATFORM_SPECIFIC_LIB_DIRS.append(pcbuildDir)

        pySrcDistExtraIncludeDir = os.path.join(
           
os.path.split(distutils.sysconfig.get_python_inc())[0],
'PC')
       
PLATFORM_SPECIFIC_INCLUDE_DIRS.append(pySrcDistExtraIncludeDir)

    # Verify the various directories (such as include
and library dirs) that
    # will be used during compilation.

    # Open the registry in preparation for reading
various installation
    # directories from it.
    try:
        import _winreg
    except ImportError:
        # If the user has manually specified all of
the options that would
        # require registry access to autodetect, we
can proceed despite the
        # lack of _winreg.
        if not
ALL_AUTODETECT_WINDOWS_REGISTRY_OPTIONS_MANUALLY_SPECIFIED:
            sys.stderr.write(
                    "%s\n"
                    "  Cannot import the standard
package '_winreg'.\n"
                    "  _winreg did not join the
standard library until\n"
                    "  Python 2.0.  If you are using a
source distribution\n"
                    "  of Python 2.0 or later, you may
have simply forgotten\n"
                    "  to compile the _winreg C
extension.\n"
                    "  You can get around the lack of
_winreg by manually\n"
                    "  specifying all of the
configuration options in the\n"
                    "  'manual_config' section of the
setup config file (%s)."
                    % (AUTODETECTION_ERROR_HEADER,
CONFIG_FILE)
                )
            sys.exit(1)

    if not
ALL_AUTODETECT_WINDOWS_REGISTRY_OPTIONS_MANUALLY_SPECIFIED:
        try:
            r = _winreg.ConnectRegistry(None,
_winreg.HKEY_LOCAL_MACHINE)
        except WindowsError, e:
            sys.stderr.write(
                    "%s\n"
                    "  Unable to connect to the
HKEY_LOCAL_MACHINE section of\n"
                    "  the Windows registry.\n"
                    "  The specific error encountered
is:\n"
                    "  %s"
                    % (AUTODETECTION_ERROR_HEADER,
str(e))
                )
            sys.exit(1)

    if DEBUG:
        print '*** DATABASE SETTINGS ***'

    # Autodetect database directory info if the user
did not specify it.
    if not DATABASE_HOME_DIR:
        def findDatabaseHomeDir(databaseInfoKey,
databaseHomeValueName):
            databaseCurrentVersionKey =
_winreg.OpenKey(r, databaseInfoKey)
            try:
                return _winreg.QueryValueEx(
                        databaseCurrentVersionKey,
                        databaseHomeValueName
                    )[0]
            finally:
               
_winreg.CloseKey(databaseCurrentVersionKey)

        # Try to find Firebird first; revert to
Interbase only if necessary.
        try:
            try:
                DATABASE_HOME_DIR =
findDatabaseHomeDir(
                       
r'SOFTWARE\FirebirdSQL\Firebird\CurrentVersion',
                        'RootDirectory'
                    )
                DATABASE_IS_FIREBIRD = 1

                if DEBUG:
                    print '    Autodetected database
is Firebird.'
            except WindowsError:
                # Revert to Interbase.
                DATABASE_IS_FIREBIRD = 0
                DATABASE_HOME_DIR =
findDatabaseHomeDir(
                       
r'SOFTWARE\Borland\InterBase\CurrentVersion',
                        'RootDirectory'
                    )

                if DEBUG:
                    print '    Autodetected database
is Interbase.'
        except WindowsError, e:
            sys.stderr.write(
                    "%s\n"
                    "  Unable to retrieve database
directory from the\n"
                    "  Windows registry.\n"
                    "  Try specifying the
'database_home_dir' option in the\n"
                    "  'manual_config' section of the
setup config file (%s).\n"
                    "  The specific error encountered
is:\n"
                    "  %s"
                    % (AUTODETECTION_ERROR_HEADER,
CONFIG_FILE, str(e))
                )
            sys.exit(1)

    if DATABASE_INCLUDE_DIR:
        verifyUserSpecifiedDatabaseIncludeDir()
        databaseSDKDir =
os.path.dirname(DATABASE_INCLUDE_DIR)
    else: # user-specified DATABASE_INCLUDE_DIR
        databaseSDKDir =
os.path.join(DATABASE_HOME_DIR, 'SDK')
        if DATABASE_IS_FIREBIRD or not
os.path.exists(databaseSDKDir):
            databaseSDKDir = DATABASE_HOME_DIR

        DATABASE_INCLUDE_DIR =
os.path.join(databaseSDKDir, 'include')

        if DEBUG:
            print '\tDATABASE_INCLUDE_DIR exists
at\n\t  %s: %d' \
                % (DATABASE_INCLUDE_DIR,
os.path.exists(DATABASE_INCLUDE_DIR))

        verifyAutodetectedDatabaseIncludeDir()

    if DATABASE_LIB_DIR:
        verifyUserSpecifiedDatabaseLibraryDir()
    else: # user-specified DATABASE_LIB_DIR
        DATABASE_LIB_DIR =
os.path.join(databaseSDKDir, 'lib')

        verifyAutodetectedDatabaseLibraryDir()

    # Perform compiler-specific setup.
    if not DATABASE_LIB_NAME:
        DATABASE_LIB_NAME = 'gds32'

    # I should discover a way to ask distutils what
compiler it's
    # configured to use--the current code would only
detect a compiler
    # change via the command line.  I've looked at the
compiler subpackage
    # of distutils, and can't find any such facility
(though it can be
    # queried for the system's default compiler).

    customCompilerName = 'msvc'
    import re
    argJam = string.lower(string.join(sys.argv[1:]))

    match = re.search(r'--compiler=(?P<cname>\S+)',
argJam)
    if match:
        customCompilerName = match.group('cname')
    else:
        match = re.search(r'-c\s+(?P<cname>\S+)',
argJam)
        if match:
            customCompilerName = match.group('cname')

    if customCompilerName == 'msvc':
        if not DATABASE_IS_FIREBIRD:
            DATABASE_LIB_DIR =
os.path.join(databaseSDKDir, r'lib_ms')
            if not os.path.exists(DATABASE_LIB_DIR):
                DATABASE_LIB_DIR =
os.path.join(databaseSDKDir, r'lib')
        if not DATABASE_LIB_NAME or DATABASE_LIB_NAME
== 'gds32':
            DATABASE_LIB_NAME = 'gds32_ms'
    elif customCompilerName == 'bcpp':
        COMPILER_EXE_NAME = 'bcc32.exe'

        # Try to find the home directory of the
Borland compiler by searching
        # each directory listed in the PATH.
        osPath = string.split(os.environ['PATH'],
os.pathsep)
        bccHome = None
        for dir in osPath:
            if os.path.exists(os.path.join(dir,
COMPILER_EXE_NAME)):
                bccHome = os.path.split(dir)[0]
                break
        else:
            # Couldn't find it.
            sys.stderr.write(
                    "%s\n"
                    "  Unable to find the home
directory of the Borland"
                    " compiler.\n"
                    "  You must add the 'bin'
subdirectory of the"
                    " compiler's\n"
                    "  home directory to your PATH.\n"
                    "  One way to do this is to type a
command of the"
                    " format\n"
                    "    SET
PATH=%%PATH%%;c:\\EXAMPLE_DIR\\bin\n"
                    "  in the same command prompt you
use to run the"
                    " kinterbasdb setup script."
                    %
(COMPILER_CONFIGURATION_ERROR_HEADER,)
                )
            sys.exit(1)


        # Override the default behavior of
distutils.bcppcompiler.BCPPCompiler
        # in order to force it to issue the correct
command.
        from distutils.bcppcompiler import
BCPPCompiler
        def _makeDirNameSpacless(kwargs, argName):
            x = kwargs.get(argName, None)
            if x is None:
                return
            elif isinstance(x, types.StringType):
                kwargs[argName] =
findSpacelessDirName(x)
            else: # sequence of strings
                kwargs[argName] = [
findSpacelessDirName(d) for d in x ]

        class BCPP_UGLY_Hack(BCPPCompiler):
            def compile (self, *args, **kwargs):
                bccIncludePreargDir =
findSpacelessDirName('%s\include' % bccHome)
                bccLibPreargDir =
findSpacelessDirName('%s\lib' % bccHome)
                bccLibPSDKPreargDir =
findSpacelessDirName('%s\lib\psdk' % bccHome)

                kwargs['extra_preargs'] = (
                    [
                        r'-I"%s"' %
bccIncludePreargDir,
                        r'-L"%s"' % bccLibPreargDir,
                        r'-L"%s"' %
bccLibPSDKPreargDir
                    ]
                    + kwargs.get('extra_preargs', [])
                  )
                for argName in ('output_dir',
'include_dirs'):
                    _makeDirNameSpacless(kwargs,
argName)

                return BCPPCompiler.compile(self,
*args, **kwargs)


            def link (self, *args, **kwargs):
                ilinkLibPreargDir =
findSpacelessDirName('%s\lib' % bccHome)
                ilinkLibPSDKPreargDir =
findSpacelessDirName('%s\lib\psdk' % bccHome)

                myPreArgs = [
                    r'/L"%s"' % ilinkLibPreargDir,
                    r'/L"%s"' % ilinkLibPSDKPreargDir
                  ]
                if not
kwargs.has_key('extra_preargs'):
                    argsAsList = list(args)
                    argsAsList[9] = myPreArgs # see
distuils.ccompiler.py
                    args = tuple(argsAsList)
                else:
                    kwargs['extra_preargs'] =
myPreArgs + kwargs.get['extra_preargs']

                for argName in (
                    'output_dir', 'library_dirs',
                    'runtime_library_dirs',
'build_temp'
                  ):
                    _makeDirNameSpacless(kwargs,
argName)

                return BCPPCompiler.link(self, *args,
**kwargs)


        compilerSetupTuple =
distutils.ccompiler.compiler_class['bcpp']
        import distutils.bcppcompiler
        distutils.bcppcompiler.BCPP_UGLY_Hack =
BCPP_UGLY_Hack
        distutils.ccompiler.compiler_class['bcpp'] = (
            compilerSetupTuple[0], 'BCPP_UGLY_Hack',
compilerSetupTuple[2])

        # Use coff2omf to create a
Borland-compiler-compatible library file,
        # "pythonVV_bcpp.lib", from the standard
"pythonVV.lib".

        # It would be better to use sys.version_info
rather than the
        # string sys.version, but it's not available
on older Python
        # versions.
        pyLibVersionSuffix = sys.version[0] +
sys.version[2]

        # 2003.03.28: Accomodate source dists of
Python on Windows (give the
        # PCBuild\pythonVV.lib file (if any)
precedence over the
        # libs\pythonVV.lib file (if any)):
        pythonLibsDir = os.path.join(pythonHomeDir,
'PCbuild')
        if not
os.path.exists(os.path.join(pythonLibsDir,
'python%s.lib' % pyLibVersionSuffix)):
            pythonLibsDir =
os.path.join(pythonHomeDir, 'libs')

        newLibFilename = os.path.join(pythonLibsDir,
'python%s_bcpp.lib' % pyLibVersionSuffix)

        print 'setup.py is trying to create %s' %
newLibFilename
        if not
os.path.exists(os.path.join(newLibFilename)):
            # oldLibFilename = '%s\libs\python%s.lib'
% (
            oldLibFilename =
os.path.join(pythonLibsDir, 'python%s.lib' %
pyLibVersionSuffix)
            coff2omfCommand = ('coff2omf %s %s' %
(oldLibFilename, newLibFilename))

            os.system(coff2omfCommand)
            # Do this test instead of checking the
return value of
            # os.system, which will not reliably
indicate an error
            # condition on Win9x.
            if not os.path.exists(newLibFilename):
                sys.stderr.write(
                        "%s\n"
                        "  Unable to create a
Borland-compatible Python"
                        " library file using the\n"
                        "  coff2omf utility.\n"
                        "  Tried command:\n"
                        "    %s"
                        % (
COMPILER_CONFIGURATION_ERROR_HEADER,
                            coff2omfCommand)
                    )
                sys.exit(1)
        assert os.path.exists(newLibFilename)

    if DEBUG:
        print '\tDATABASE_LIB_DIR exists at\n\t  %s:
%d' \
            % (DATABASE_LIB_DIR,
os.path.exists(DATABASE_LIB_DIR))
        print '\tDATABASE_LIB_NAME is\n\t  %s' %
DATABASE_LIB_NAME
elif sys.platform == 'cygwin':
    print '  *** CYGWIN LIBRARY GENERATION : begin
***'
    DATABASE_LIB_NAME = 'gds32'
    PLATFORM_SPECIFIC_LIB_DIRS.append('/usr/lib')
   
PLATFORM_SPECIFIC_EXTRA_COMPILER_ARGS.append('-DUSE_DL_IMPORT')
    # PLATFORM_SPECIFIC_EXTRA_LINKER_ARGS = []
    winSysDir = determineWindowsSystemDir()
    libUltimateDest = '/usr/lib/libgds32.a'
    libUltimateDir, libName =
os.path.split(libUltimateDest)
    fbDir = 'c:/progra~1/firebird'
    if os.path.isfile(libUltimateDest):
        print ('\tCygwin-compatible Firebird library
already exists at:\n\t  %s'
            % libUltimateDest
          )
    else:
        print (
            '\n\tsetup.py is trying to create
cygwin-compatible Firebird'
            ' library at:\n'
            '\t  "%s"'
            % libUltimateDest
          )
        fbClientLibFilename = os.path.join(fbDir,
'lib', 'gds32.lib')
        origCurDir = os.path.abspath(os.curdir)
        os.chdir(winSysDir)
        try:
            # Create def file containing symbols from
gds32.lib.
            doLibConvCmd(
                '''(echo EXPORTS; nm %s  | grep " T
_"'''
                ''' | sed 's/.* T _//g' | sed
's/@.*$//g')'''
                ''' > gds32.def'''
                % fbClientLibFilename
              )
            # End lame pexports substitute.

            # Create lib file from DLL and the
just-generated def file.
            doLibConvCmd(
                'dlltool --dllname gds32.dll --def
gds32.def --output-lib %s'
                % libName
              )
            os.remove('gds32.def')
            # Move the lib file to a location where
cygwin-GCC's linker will
            # find it.
            shutil.copyfile(libName, libUltimateDest)
            os.remove(libName)
        finally:
            os.chdir(origCurDir)
    assert os.path.isfile(libUltimateDest)
    print '  *** CYGWIN LIBRARY GENERATION : end
***\n'

else: # not Windows
    # If the platform isn't Linux, issue a warning.
    if len(sys.platform) < 5 or not
string.lower(sys.platform)[:5] == 'linux':
        sys.stderr.write("Warning:  The kinterbasdb
setup code was not"
            " specifically written to support your
platform (%s), and"
            " may not work properly.\n"
            % sys.platform
          )
    else:
        # The platform is Linux.
        pass

    # Is libcrypt necessary on all POSIX OSes, or just
Linux?
    # Until someone informs me otherwise, I'll assume
all.
    if os.name == 'posix':
        PLATFORM_SPECIFIC_LIB_NAMES.append('crypt')

    # Verify the various directories (such as include
and library dirs) that
    # will be used during compilation.

    # Assumption:
    # This is a Unix-like OS, where a proper
installation routine would have
    # placed the database [header, library] files in a
system-wide dirs.
    # We have no way of knowing beyond the shadow of a
doubt whether that
    # has happened (as opposed to the situation on
Windows, where we can
    # consult the registry to determine where a binary
installer placed its
    # files), so we'll just let the compiler complain
if it can't find the
    # [header, library] files.
    # If, on the other hand, the user manually
specified the directories, we
    # may verify that they exist.

    if DATABASE_INCLUDE_DIR: # the user manually
specified it
        verifyUserSpecifiedDatabaseIncludeDir()

    if DATABASE_LIB_DIR: # the user manually specified
it
        verifyUserSpecifiedDatabaseLibraryDir()

    # 2003.04.12: begin block
    # On FreeBSD 4, the header and library files
apparently are not made
    # visible by default (perhaps because the
installation that prompted this
    # change was from a source distribution rather
than an RPM, as all of my
    # testing on Linux has been?).
    # This script attempts to "autodetect" an
installation at the default
    # location, but only if:
    # - no DATABASE_HOME_DIR has been manually
specified
    # - the default installation directory actually
exists
    #
    # This "autodetection" will probably work for some
other Unixes as well.
    if not DATABASE_HOME_DIR:
        DEFAULT_FREEBSD_HOME_DIR =
'/usr/local/firebird'
        if os.path.isdir(DEFAULT_FREEBSD_HOME_DIR):
            DATABASE_HOME_DIR =
DEFAULT_FREEBSD_HOME_DIR
            if not DATABASE_INCLUDE_DIR:
                DATABASE_INCLUDE_DIR =
os.path.join(DATABASE_HOME_DIR, 'include')
            if not DATABASE_LIB_DIR:
                DATABASE_LIB_DIR =
os.path.join(DATABASE_HOME_DIR, 'lib')
    # 2003.04.12: end block


    if not DATABASE_LIB_NAME:
       DATABASE_LIB_NAME = 'gds'

# Now finished with platform-specific compilation
parameter setup.

# Create a list of all INCLUDE dirs to be passed to
setup():
allIncludeDirs = []

# Add Python include directory:
allIncludeDirs.append(distutils.sysconfig.get_python_inc())

if len(PLATFORM_SPECIFIC_INCLUDE_DIRS) > 0:
   
allIncludeDirs.extend(PLATFORM_SPECIFIC_INCLUDE_DIRS)

if DATETIME_INCLUDE_DIR:
    allIncludeDirs.append(DATETIME_INCLUDE_DIR)

if DATABASE_INCLUDE_DIR:
    allIncludeDirs.append(DATABASE_INCLUDE_DIR)

# Create a list of all LIB names to be passed to
setup():
allLibNames = []
if DATABASE_LIB_NAME:
    allLibNames.append(DATABASE_LIB_NAME)
allLibNames.extend(PLATFORM_SPECIFIC_LIB_NAMES)
if DEBUG:
    print '\tLIBRARY NAMES ', allLibNames

# Create a list of all LIB directories to be passed to
setup():
allLibDirs = []
if len(PLATFORM_SPECIFIC_LIB_DIRS) > 0:
    allLibDirs.extend(PLATFORM_SPECIFIC_LIB_DIRS)

if DATABASE_LIB_DIR:
    allLibDirs.append(DATABASE_LIB_DIR)

if DEBUG:
    print '\tLIBRARY DIRS ', allLibDirs 

# Create a list of all macro definitions that must be
passed to distutils.
allMacroDefs = []

if len(CUSTOM_PREPROCESSOR_DEFS) > 0:
    allMacroDefs.extend(CUSTOM_PREPROCESSOR_DEFS)

# Create a list of all extra options to pass to the
compiler, linker.
allExtraCompilerArgs = []
if len(PLATFORM_SPECIFIC_EXTRA_COMPILER_ARGS) > 0:
   
allExtraCompilerArgs.extend(PLATFORM_SPECIFIC_EXTRA_COMPILER_ARGS)

allExtraLinkerArgs = []
if len(PLATFORM_SPECIFIC_EXTRA_LINKER_ARGS) > 0:
   
allExtraLinkerArgs.extend(PLATFORM_SPECIFIC_EXTRA_LINKER_ARGS)

extensionModules = [
    distutils.core.Extension(
"kinterbasdb._kinterbasdb",
        sources=["_kinterbasdb.c", "_kievents.c"],
        libraries=allLibNames,
        include_dirs=allIncludeDirs,
        library_dirs=allLibDirs,
        define_macros=allMacroDefs,
        extra_compile_args=allExtraCompilerArgs,
        extra_link_args=allExtraLinkerArgs
    ),
  ]


# 2003.02.18: IB 5.5 build hack:
allPythonModules = [
    'kinterbasdb.__init__',
    'kinterbasdb.k_exceptions',

    # 2003.03.30: dynamic type conv:
    'kinterbasdb.typeconv_active',
    'kinterbasdb.typeconv_backcompat',
    'kinterbasdb.typeconv_preferred',
    # 2003.05.19: additional components of refactored
dynamic type conv:
    'kinterbasdb.typeconv_fixed_stdlib',
    'kinterbasdb.typeconv_fixed_fixedpoint',
    'kinterbasdb.typeconv_datetime_mx',
    'kinterbasdb.typeconv_datetime_stdlib',
    'kinterbasdb.typeconv_util_isinstance',
  ]

# Build somewhat differently if we're dealing with an
IB version before 6.0.
# (Innocent until proven guilty.)
isIBLessThan_6_0 = 0
for incDir in allIncludeDirs:
    headerFilename = os.path.join(incDir, 'ibase.h')
    if os.path.exists(headerFilename):
        # Using the isc_decode_sql_time symbol as the
detector is kinda arbitrary.
        if
open(headerFilename).read().find('isc_decode_sql_time')
== -1:
            isIBLessThan_6_0 = 1
            break

if isIBLessThan_6_0:
    print >> sys.stderr, \
        'WARNING:  Not building the
kinterbasdb._services module because' \
        ' IB 5.5 does not support it.'
else:
    # Only include the services module if dealing with
>= IB 6.0.
    allPythonModules.append('kinterbasdb.services')
    extensionModules.append(
        distutils.core.Extension(
"kinterbasdb._kiservices",
            sources=["_kiservices.c"],
            libraries=allLibNames,
            include_dirs=allIncludeDirs,
            library_dirs=allLibDirs,
            define_macros=allMacroDefs,
            extra_compile_args=allExtraCompilerArgs,
            extra_link_args=allExtraLinkerArgs
          )
      )
# end IB 5.5 build hack of 2003.02.18

# Now we've detected and verified all compilation
parameters, and are ready to
# compile.

if DEBUG:
    print '*** SETTINGS DETECTION PHASE COMPLETE;
READY FOR BUILD ***'
    print ("\tThe DEBUG flag is enabled, so the setup
script stops\n"
           "\t  before actually invoking the distutils
setup procedure."
        )
    sys.exit(0)

# The MEAT:
distutils.core.setup(
    name=kinterbasdb_name,
    version=kinterbasdb_version,
    author='''Originally by Alexander Kuznetsov ;
                   rewritten and expanded by David
Rushby
                   with contributions from several
others
                   (see docs/license.txt for
details).''',
    author_email='woodsplitter at rocketmail.com',
    url='http://kinterbasdb.sourceforge.net',
    description='Python DB API 2.0 extension for
Firebird and Interbase',
    long_description=
        'kinterbasdb allows Python to access the
Firebird and Interbase\n'
        'SQL servers according to the interface
defined by the Python\n'
        'Database API Specification version 2.0.',
    license='see docs/license.txt',

    # 2003.02.18: IB 5.5 build hack:
    # For IB 5.5, need to include only specific
components of the kinterbasdb
    # package, not the whole package.
    #packages=['kinterbasdb'],
    package_dir={'kinterbasdb': os.curdir},
    py_modules=allPythonModules,

    ext_modules=extensionModules,
    data_files = [
        # documentation:
        ('Lib/site-packages/kinterbasdb/docs',
            [
                'docs/index.html',
                'docs/installation-source.html',
                'docs/installation-binary.html',
                'docs/usage.html',
                'docs/changelog.txt',
                'docs/license.txt',
                'docs/Python-DB-API-2.0.html',
                'docs/links.html',
                'docs/global.css',
                'docs/w3c.png',
            ]
        )
    ]
)
setup.py end =========================================






__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com



More information about the Distutils-SIG mailing list