Update build instructions for Windows.
[jelmer/subvertpy.git] / setup.py
index 204869a5086c64e3ba9b82581dfdcdbe74464e8c..acaf60b3f201639636077746f682f00a942199b8 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 # Setup file for subvertpy
-# Copyright (C) 2005-2009 Jelmer Vernooij <jelmer@samba.org>
+# Copyright (C) 2005-2010 Jelmer Vernooij <jelmer@samba.org>
 
 from distutils.core import setup
 from distutils.extension import Extension
@@ -10,21 +10,8 @@ import sys
 import os
 import re
 
-# Build instructions for Windows:
-# * Install the SVN dev kit ZIP for Windows from
-#   http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91
-#   At time of writing, this was svn-win32-1.4.6_dev.zip
-# * Find the SVN binary ZIP file with the binaries for your dev kit.
-#   At time of writing, this was svn-win32-1.4.6.zip
-#   Unzip this in the *same directory* as the dev kit - README.txt will be
-#   overwritten, but that is all. This is the default location the .ZIP file
-#   will suggest (ie, the directory embedded in both .zip files are the same)
-# * Set SVN_DEV to point at this directory.
-# * Install the APR BDB and INTL packages - see README.txt from the devkit
-# * Set SVN_BDB and SVN_LIBINTL to point at these dirs.
-
 class CommandException(Exception):
-    """Encapsulate exit status of apr-config execution"""
+    """Encapsulate exit status of command execution"""
     def __init__(self, msg, cmd, arg, status, val):
         self.message = msg % (cmd, val)
         Exception.__init__(self, self.message)
@@ -35,6 +22,10 @@ class CommandException(Exception):
         return os.WIFEXITED(self.status) and os.WEXITSTATUS(self.status) == 127
 
 
+def split_shell_results(line):
+    return [s for s in line.split(" ") if s != ""]
+
+
 def run_cmd(cmd, arg):
     """Run specified command with given arguments, handling status"""
     f = os.popen("'%s' %s" % (cmd, arg))
@@ -56,25 +47,33 @@ def run_cmd(cmd, arg):
                            cmd, arg, status, status)
 
 
+def config_value(command, arg):
+    cmds = [command] + [os.path.join(p, command) for p in ["/usr/local/apr/bin/", "/opt/local/bin/"]]
+    for cmd in cmds:
+        try:
+            return run_cmd(cmd, arg)
+        except CommandException, e:
+            if not e.not_found():
+                raise
+    else:
+        raise Exception("apr-config not found."
+                        " Please set APR_CONFIG environment variable")
+
+
 def apr_config(arg):
-    apr_config_cmd = os.getenv("APR_CONFIG")
-    if apr_config_cmd is None:
-        cmds = ["apr-1-config", "/usr/local/apr/bin/apr-1-config", 
-                "/opt/local/bin/apr-1-config", ]
-        for cmd in cmds:
-            try:
-                res = run_cmd(cmd, arg)
-                apr_config_cmd = cmd
-                break
-            except CommandException, e:
-                if not e.not_found():
-                    raise
-        else:
-            raise Exception("apr-config not found."
-                            " Please set APR_CONFIG environment variable")
+    config_cmd = os.getenv("APR_CONFIG")
+    if config_cmd is None:
+        return config_value("apr-1-config", arg)
     else:
-        res = run_cmd(apr_config_cmd, arg)
-    return res
+        return run_cmd(config_cmd, arg)
+
+
+def apu_config(arg):
+    config_cmd = os.getenv("APU_CONFIG")
+    if config_cmd is None:
+        return config_value("apu-1-config", arg)
+    else:
+        return run_cmd(config_cmd, arg)
 
 
 def apr_build_data():
@@ -82,13 +81,23 @@ def apr_build_data():
     includedir = apr_config("--includedir")
     if not os.path.isdir(includedir):
         raise Exception("APR development headers not found")
-    return (includedir,)
+    extra_link_flags = apr_config("--link-ld --libs")
+    return (includedir, split_shell_results(extra_link_flags))
+
+
+def apu_build_data():
+    """Determine the APR util header file location."""
+    includedir = apu_config("--includedir")
+    if not os.path.isdir(includedir):
+        raise Exception("APR util development headers not found")
+    extra_link_flags = apu_config("--link-ld --libs")
+    return (includedir, split_shell_results(extra_link_flags))
 
 
 def svn_build_data():
     """Determine the Subversion header file location."""
     if "SVN_HEADER_PATH" in os.environ and "SVN_LIBRARY_PATH" in os.environ:
-        return ([os.getenv("SVN_HEADER_PATH")], [os.getenv("SVN_LIBRARY_PATH")], [])
+        return ([os.getenv("SVN_HEADER_PATH")], [os.getenv("SVN_LIBRARY_PATH")], [], [])
     svn_prefix = os.getenv("SVN_PREFIX")
     if svn_prefix is None:
         basedirs = ["/usr/local", "/usr"]
@@ -99,7 +108,7 @@ def svn_build_data():
                 break
     if svn_prefix is not None:
         return ([os.path.join(svn_prefix, "include/subversion-1")], 
-                [os.path.join(svn_prefix, "lib")], [])
+                [os.path.join(svn_prefix, "lib")], [], [])
     raise Exception("Subversion development files not found. "
                     "Please set SVN_PREFIX or (SVN_LIBRARY_PATH and SVN_HEADER_PATH) environment variable. ")
 
@@ -121,7 +130,9 @@ int main(int argc, const char* arv[]) {
     gcc_out.read()
     return (gcc_out.close() is None)
 
+
 class VersionQuery(object):
+
     def __init__(self, filename):
         self.filename = filename
         f = file(filename, "rU")
@@ -133,20 +144,23 @@ class VersionQuery(object):
     def grep(self, what):
         m = re.search(r"^#define\s+%s\s+(\d+)\s*$" % (what,), self.text, re.MULTILINE)
         if not m:
-            raise Exception, "Definition for %s was not found in file %s." % (what, self.filename)
+            raise Exception("Definition for %s was not found in file %s." % (what, self.filename))
         return int(m.group(1))
 
 # Windows versions - we use environment variables to locate the directories
 # and hard-code a list of libraries.
 if os.name == "nt":
     def get_apr_version():
-        apr_version_file = os.path.join(os.environ["SVN_DEV"], r"include\apr\apr_version.h")
+        apr_version_file = os.path.join(os.environ["SVN_DEV"],
+                r"include\apr\apr_version.h")
         if not os.path.isfile(apr_version_file):
             raise Exception(
                 "Please check that your SVN_DEV location is correct.\n"
                 "Unable to find required apr\\apr_version.h file.")
         query = VersionQuery(apr_version_file)
-        return query.grep("APR_MAJOR_VERSION"), query.grep("APR_MINOR_VERSION"), query.grep("APR_PATCH_VERSION")
+        return (query.grep("APR_MAJOR_VERSION"),
+                query.grep("APR_MINOR_VERSION"),
+                query.grep("APR_PATCH_VERSION"))
 
     def get_svn_version():
         svn_version_file = os.path.join(os.environ["SVN_DEV"], r"include\svn_version.h")
@@ -155,12 +169,17 @@ if os.name == "nt":
                 "Please check that your SVN_DEV location is correct.\n"
                 "Unable to find required svn_version.h file.")
         query = VersionQuery(svn_version_file)
-        return query.grep("SVN_VER_MAJOR"), query.grep("SVN_VER_MINOR"), query.grep("SVN_VER_PATCH")
+        return (query.grep("SVN_VER_MAJOR"),
+                query.grep("SVN_VER_MINOR"),
+                query.grep("SVN_VER_PATCH"))
 
     # just clobber the functions above we can't use
     # for simplicitly, everything is done in the 'svn' one
     def apr_build_data():
-        return '.', 
+        return '.', []
+
+    def apu_build_data():
+        return '.', []
 
     def svn_build_data():
         # environment vars for the directories we need.
@@ -169,17 +188,17 @@ if os.name == "nt":
             raise Exception(
                 "Please set SVN_DEV to the location of the svn development "
                 "packages.\nThese can be downloaded from:\n"
-                "http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91")
+                "http://sourceforge.net/projects/win32svn/files/")
         svn_bdb_dir = os.environ.get("SVN_BDB")
         if not svn_bdb_dir or not os.path.isdir(svn_bdb_dir):
             raise Exception(
                 "Please set SVN_BDB to the location of the svn BDB packages "
-                "- see README.txt in the SV_DEV dir")
+                "- see README.txt in the SVN_DEV dir")
         svn_libintl_dir = os.environ.get("SVN_LIBINTL")
         if not svn_libintl_dir or not os.path.isdir(svn_libintl_dir):
             raise Exception(
                 "Please set SVN_LIBINTL to the location of the svn libintl "
-                "packages - see README.txt in the SV_DEV dir")
+                "packages - see README.txt in the SVN_DEV dir")
 
         svn_version = get_svn_version()
         apr_version = get_apr_version()
@@ -187,7 +206,7 @@ if os.name == "nt":
         includes = [
             # apr dirs.
             os.path.join(svn_dev_dir, r"include\apr"),
-            os.path.join(svn_dev_dir, r"include\apr-utils"),
+            os.path.join(svn_dev_dir, r"include\apr-util"),
             os.path.join(svn_dev_dir, r"include\apr-iconv"),
             # svn dirs.
             os.path.join(svn_dev_dir, "include"), 
@@ -220,26 +239,37 @@ if os.name == "nt":
             # Since 1.5.0 libsvn_ra_dav-1 was removed
             libs.remove("libsvn_ra_dav-1")
 
-        return includes, lib_dirs, aprlibs+libs,
+        return includes, lib_dirs, [], aprlibs+libs,
 
-(apr_includedir, ) = apr_build_data()
-(svn_includedirs, svn_libdirs, extra_libs) = svn_build_data()
+(apr_includedir, apr_link_flags) = apr_build_data()
+(apu_includedir, apu_link_flags) = apu_build_data()
+(svn_includedirs, svn_libdirs, svn_link_flags, extra_libs) = svn_build_data()
 
-def SvnExtension(name, *args, **kwargs):
-    kwargs["include_dirs"] = [apr_includedir] + svn_includedirs + ["subvertpy"]
-    kwargs["library_dirs"] = svn_libdirs
-    if os.name == 'nt':
-        # on windows, just ignore and overwrite the libraries!
-        kwargs["libraries"] = extra_libs
-        # APR needs WIN32 defined.
-        kwargs["define_macros"] = [("WIN32", None)]
-    if sys.platform == 'darwin':
-        # on Mac OS X, we need to check for Keychain availability
-        if is_keychain_provider_available():
-            if "define_macros" not in kwargs:
-                kwargs["define_macros"] = []
-            kwargs["define_macros"].extend((('DARWIN', None), ('SVN_KEYCHAIN_PROVIDER_AVAILABLE', '1')))
-    return Extension(name, *args, **kwargs)
+class SvnExtension(Extension):
+
+    def __init__(self, name, *args, **kwargs):
+        kwargs["include_dirs"] = ([apr_includedir, apu_includedir] + svn_includedirs +
+                                  ["subvertpy"])
+        kwargs["library_dirs"] = svn_libdirs
+        # Note that the apr-util link flags are not included here, as
+        # subvertpy only uses some apr util constants but does not use
+        # the library directly.
+        kwargs["extra_link_args"] = apr_link_flags + svn_link_flags
+        if os.name == 'nt':
+            # on windows, just ignore and overwrite the libraries!
+            kwargs["libraries"] = extra_libs
+            # APR needs WIN32 defined.
+            kwargs["define_macros"] = [("WIN32", None)]
+        if sys.platform == 'darwin':
+            # on Mac OS X, we need to check for Keychain availability
+            if is_keychain_provider_available():
+                if "define_macros" not in kwargs:
+                    kwargs["define_macros"] = []
+                kwargs["define_macros"].extend((
+                    ('DARWIN', None),
+                    ('SVN_KEYCHAIN_PROVIDER_AVAILABLE', '1'))
+                    )
+        Extension.__init__(self, name, *args, **kwargs)
 
 
 # On Windows, we install the apr binaries too.
@@ -247,7 +277,8 @@ class install_lib_with_dlls(install_lib):
     def _get_dlls(self):
         # return a list of of (FQ-in-name, relative-out-name) tuples.
         ret = []
-        apr_bins = [libname + ".dll" for libname in extra_libs if libname.startswith("libapr")]
+        apr_bins = [libname + ".dll" for libname in extra_libs
+                    if libname.startswith("libapr")]
         if get_svn_version() >= (1,5,0):
             # Since 1.5.0 these libraries became shared
             apr_bins += """libsvn_client-1.dll libsvn_delta-1.dll libsvn_diff-1.dll
@@ -288,33 +319,41 @@ def source_path(filename):
     return os.path.join("subvertpy", filename)
 
 
-def subvertpy_modules(basemodule):
+def subvertpy_modules():
     return [
-        SvnExtension("%s.client" % basemodule, [source_path(n) for n in "client.c", "editor.c", "util.c", "_ra.c", "wc.c"], libraries=["svn_client-1", "svn_subr-1"]), 
-        SvnExtension("%s._ra" % basemodule, [source_path(n) for n in "_ra.c", "util.c", "editor.c"], libraries=["svn_ra-1", "svn_delta-1", "svn_subr-1"]),
-        SvnExtension("%s.repos" % basemodule, [source_path(n) for n in "repos.c", "util.c"], libraries=["svn_repos-1", "svn_subr-1"]),
-        SvnExtension("%s.wc" % basemodule, [source_path(n) for n in "wc.c", "util.c", "editor.c"], libraries=["svn_wc-1", "svn_subr-1"])
+        SvnExtension("subvertpy.client", [source_path(n) for n in
+            ("client.c", "editor.c", "util.c", "_ra.c", "wc.c")],
+            libraries=["svn_client-1", "svn_subr-1", "svn_ra-1", "svn_wc-1"]),
+        SvnExtension("subvertpy._ra", [source_path(n) for n in
+            ("_ra.c", "util.c", "editor.c")],
+            libraries=["svn_ra-1", "svn_delta-1", "svn_subr-1"]),
+        SvnExtension("subvertpy.repos", [source_path(n) for n in ("repos.c", "util.c")],
+            libraries=["svn_repos-1", "svn_subr-1", "svn_fs-1"]),
+        SvnExtension("subvertpy.wc", [source_path(n) for n in ("wc.c",
+            "util.c", "editor.c")], libraries=["svn_wc-1", "svn_subr-1"])
         ]
 
 
-subvertpy_version = (0, 6, 9)
+subvertpy_version = (0, 8, 10)
 subvertpy_version_string = ".".join(map(str, subvertpy_version))
 
 
 if __name__ == "__main__":
     setup(name='subvertpy',
           description='Alternative Python bindings for Subversion',
-          keywords='plugin svn',
+          keywords='svn subvertpy subversion bindings',
           version=subvertpy_version_string,
           url='http://samba.org/~jelmer/subvertpy',
-          download_url="http://samba.org/~jelmer/subvertpy/subvertpy-%s.tar.gz" % subvertpy_version_string,
+          download_url="http://samba.org/~jelmer/subvertpy/subvertpy-%s.tar.gz" % (
+              subvertpy_version_string, ),
           license='LGPLv2.1 or later',
           author='Jelmer Vernooij',
           author_email='jelmer@samba.org',
           long_description="""
-          Alternative Python bindings for Subversion, split out from bzr-svn. The goal is to have complete, portable and "Pythonic" Python bindings. 
+          Alternative Python bindings for Subversion. The goal is to have complete, portable and "Pythonic" Python bindings. 
           """,
           packages=['subvertpy', 'subvertpy.tests'],
-          ext_modules=subvertpy_modules("subvertpy"),
+          ext_modules=subvertpy_modules(),
+          scripts=['bin/subvertpy-fast-export'],
           cmdclass = { 'install_lib': install_lib_with_dlls },
           )