blob: 4fa06c5a480539651fdf6c46b1b5aff9c75e9528 [file] [log] [blame]
#
# gen_win.py -- base class for generating windows projects
#
import os
import sys
import string
import fnmatch
import re
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import gen_base
import ezt
class WinGeneratorBase(gen_base.GeneratorBase):
"Base class for all Windows project files generators"
_extension_map = {
('exe', 'target'): '.exe',
('exe', 'object'): '.obj',
('lib', 'target'): '.dll',
('lib', 'object'): '.obj',
('script', 'target'): '',
('script', 'object'): '',
}
def parse_options(self, options):
self.apr_path = 'apr'
self.apr_util_path = 'apr-util'
self.apr_iconv_path = 'apr-iconv'
self.bdb_path = 'db4-win32'
self.httpd_path = None
self.zlib_path = None
self.openssl_path = None
self.junit_path = None
self.skip_sections = { 'mod_dav_svn': None,
'mod_authz_svn': None }
# Instrumentation options
self.instrument_apr_pools = None
self.instrument_purify_quantify = None
self.configure_apr_util = None
# NLS options
self.enable_nls = None
for opt, val in options:
if opt == '--with-berkeley-db':
self.bdb_path = val
elif opt == '--with-apr':
self.apr_path = val
elif opt == '--with-apr-util':
self.apr_util_path = val
elif opt == '--with-apr-iconv':
self.apr_iconv_path = val
elif opt == '--with-httpd':
self.httpd_path = val
del self.skip_sections['mod_dav_svn']
del self.skip_sections['mod_authz_svn']
elif opt == '--with-junit':
self.junit_path = val
elif opt == '--with-zlib':
self.zlib_path = val
elif opt == '--with-openssl':
self.openssl_path = val
elif opt == '--enable-purify':
self.instrument_purify_quantify = 1
self.instrument_apr_pools = 1
elif opt == '--enable-quantify':
self.instrument_purify_quantify = 1
elif opt == '--enable-pool-debug':
self.instrument_apr_pools = 1
elif opt == '--enable-nls':
self.enable_nls = 1
elif opt == '--enable-bdb-in-apr-util':
self.configure_apr_util = 1
def __init__(self, fname, verfname, options, subdir):
"""
Do some Windows specific setup
Build the list of Platforms & Configurations &
create the necessary paths
"""
# parse (and save) the options that were passed to us
self.parse_options(options)
# Find db-4.0.x or db-4.1.x
self._find_bdb()
# Find the right Perl library name to link SWIG bindings with
self._find_perl()
# Find the installed SWIG version to adjust swig options
self._find_swig()
# Run apr-util's w32locatedb.pl script
self._configure_apr_util()
#Make some files for the installer so that we don't need to
#require sed or some other command to do it
### GJS: don't do this right now
if 0:
buf = open(os.path.join("packages","win32-innosetup","svn.iss.in"), 'rb').read()
buf = buf.replace("@VERSION@", "0.16.1+").replace("@RELEASE@", "4365")
buf = buf.replace("@DBBINDLL@", self.dbbindll)
svnissrel = os.path.join("packages","win32-innosetup","svn.iss.release")
svnissdeb = os.path.join("packages","win32-innosetup","svn.iss.debug")
if self.write_file_if_changed(svnissrel, buf.replace("@CONFIG@", "Release")):
print 'Wrote %s' % svnissrel
if self.write_file_if_changed(svnissdeb, buf.replace("@CONFIG@", "Debug")):
print 'Wrote %s' % svnissdeb
# Generate the build_neon.bat file
data = {'expat_path': self.apr_util_path
and (os.path.abspath(self.apr_util_path)
+ '/xml/expat/lib'),
'zlib_path': self.zlib_path
and os.path.abspath(self.zlib_path),
'openssl_path': self.openssl_path
and os.path.abspath(self.openssl_path)}
self.write_with_template(os.path.join('build', 'win32', 'build_neon.bat'),
'build_neon.ezt', data)
# Generate the build_locale.bat file
pofiles = []
if self.enable_nls:
for po in os.listdir(os.path.join('subversion', 'po')):
if fnmatch.fnmatch(po, '*.po'):
pofiles.append(POFile(po[:-3]))
data = {'pofiles': pofiles}
self.write_with_template(os.path.join('build', 'win32', 'build_locale.bat'),
'build_locale.ezt', data)
#Initialize parent
gen_base.GeneratorBase.__init__(self, fname, verfname)
#Make the project files directory if it doesn't exist
#TODO win32 might not be the best path as win64 stuff will go here too
self.projfilesdir=os.path.join("build","win32",subdir)
self.rootpath = ".." + "\\.." * string.count(self.projfilesdir, os.sep)
if not os.path.exists(self.projfilesdir):
os.makedirs(self.projfilesdir)
#Here we can add additional platforms to compile for
self.platforms = ['Win32']
#Here we can add additional modes to compile for
self.configs = ['Debug','Release']
def path(self, *paths):
"""Convert build path to msvc path and prepend root"""
return msvc_path_join(self.rootpath, *map(msvc_path, paths))
def apath(self, path, *paths):
"""Convert build path to msvc path and prepend root if not absolute"""
### On Unix, os.path.isabs won't do the right thing if "item"
### contains backslashes or drive letters
if os.path.isabs(path):
return msvc_path_join(msvc_path(path), *map(msvc_path, paths))
else:
return msvc_path_join(self.rootpath, msvc_path(path),
*map(msvc_path, paths))
def get_install_targets(self):
"Generate the list of targets"
# Get list of targets to generate project files for
install_targets = self.graph.get_all_sources(gen_base.DT_INSTALL) \
+ self.graph.get_sources(gen_base.DT_LIST,
gen_base.LT_PROJECT)
# Don't create projects for scripts
install_targets = filter(lambda x: not isinstance(x, gen_base.TargetScript),
install_targets)
for target in install_targets:
if isinstance(target, gen_base.TargetLib) and target.msvc_fake:
install_targets.append(self.create_fake_target(target))
# sort these for output stability, to watch out for regressions.
install_targets.sort(lambda t1, t2: cmp(t1.name, t2.name))
return install_targets
def create_fake_target(self, dep):
"Return a new target which depends on another target but builds nothing"
section = gen_base.TargetProject.Section({'path': 'build/win32'},
gen_base.TargetProject)
section.create_targets(self.graph, dep.name + "_fake", self.cfg,
self._extension_map)
section.target.msvc_name = dep.msvc_name and dep.msvc_name + "_fake"
self.graph.add(gen_base.DT_LINK, section.target.name, dep)
dep.msvc_fake = section.target
return section.target
def get_configs(self, target):
"Get the list of configurations for the project"
configs = [ ]
for cfg in self.configs:
configs.append(
ProjectItem(name=cfg,
lower=string.lower(cfg),
defines=self.get_win_defines(target, cfg),
libdirs=self.get_win_lib_dirs(target, cfg),
libs=self.get_win_libs(target, cfg),
))
return configs
def get_proj_sources(self, quote_path, target):
"Get the list of source files for each project"
sources = [ ]
if not isinstance(target, gen_base.TargetProject):
cbuild = None
ctarget = None
for source, object, reldir in self.get_win_sources(target):
if isinstance(target, gen_base.TargetJavaHeaders):
classes = self.path(target.classes)
if self.junit_path is not None:
classes = "%s;%s" % (classes, self.junit_path)
headers = self.path(target.headers)
classname = target.package + "." + source.class_name
cbuild = "javah -verbose -force -classpath %s -d %s %s" \
% (self.quote(classes), self.quote(headers), classname)
ctarget = self.path(object.filename_win)
elif isinstance(target, gen_base.TargetJavaClasses):
classes = targetdir = self.path(target.classes)
if self.junit_path is not None:
classes = "%s;%s" % (classes, self.junit_path)
sourcepath = self.path(source.sourcepath)
cbuild = "javac -g -classpath %s -d %s -sourcepath %s $(InputPath)" \
% tuple(map(self.quote, (classes, targetdir, sourcepath)))
ctarget = self.path(object.filename)
rsrc = self.path(str(source))
if quote_path and '-' in rsrc:
rsrc = '"%s"' % rsrc
sources.append(ProjectItem(path=rsrc, reldir=reldir, user_deps=[],
custom_build=cbuild, custom_target=ctarget))
if isinstance(target, gen_base.TargetJavaClasses) and target.jar:
classdir = self.path(target.classes)
jarfile = msvc_path_join(classdir, target.jar)
cbuild = "jar cf %s -C %s %s" \
% (jarfile, classdir, string.join(target.packages))
deps = map(lambda x: x.custom_target, sources)
sources.append(ProjectItem(path='makejar', reldir='', user_deps=deps,
custom_build=cbuild, custom_target=jarfile))
if isinstance(target, gen_base.TargetSWIGRuntime):
for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
if isinstance(obj, gen_base.SWIGObject):
for cobj in self.graph.get_sources(gen_base.DT_OBJECT, obj):
if isinstance(cobj, gen_base.SWIGObject):
csrc = self.path(cobj.filename)
bsrc = self.path("build/win32/gen_swig_runtime.py")
cbuild = "python $(InputPath) %s %s %s" \
% (target.lang, csrc, self.quote(self.swig_libdir))
sources.append(ProjectItem(path=bsrc, reldir=None,
custom_build=cbuild,
custom_target=csrc,
user_deps=[]))
elif isinstance(target, gen_base.TargetSWIG):
swig_options = ["-" + target.lang]
swig_deps = []
if self.swig_vernum >= 103020:
swig_options.append("-noruntime")
else:
swig_options.append("-c")
if target.lang == "java":
swig_options.append("-package org.tigris.subversion.swig")
swig_options.append("-outdir " + self.path("subversion/bindings/swig"
"/java/org/tigris"
"/subversion/swig"))
elif target.lang == "perl":
if self.swig_vernum >= 103020:
swig_options.append("-noproxy")
swig_options.append("-nopm")
objects = (("svn_delta_editor_t", "svn_delta.h", "delta_editor.hi"),
("svn_ra_plugin_t", "svn_ra.h", "ra_plugin.hi"),
("svn_ra_reporter_t", "svn_ra.h", "ra_reporter.hi"))
pfile = self.path("subversion/bindings/swig/perl/native/h2i.pl")
for objname, header, output in objects:
ifile = self.path("subversion/include", header)
ofile = self.path("subversion/bindings/swig", output)
obuild = "perl %s %s %s > %s" % (pfile, ifile, objname,
ofile)
sources.append(ProjectItem(path=ifile, reldir=None,
custom_build=obuild,
custom_target=ofile,
user_deps=()))
swig_deps.append(ofile)
for include_dir in self.get_win_includes(target):
swig_options.append("-I%s" % self.quote(include_dir))
for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
if isinstance(obj, gen_base.SWIGObject):
for cobj in self.graph.get_sources(gen_base.DT_OBJECT, obj):
if isinstance(cobj, gen_base.SWIGObject):
csrc = self.path(cobj.filename)
if self.swig_vernum < 103020 and target.lang == "python":
# workaround for a bug in the python module of old swigs.
# output path passed to swig has to use forward slashes,
# otherwise the generated python files (for shadow
# classes) will be saved to the wrong directory
cout = string.replace(csrc, '\\', '/')
else:
cout = csrc
# included header files that the generated c file depends on
user_deps = swig_deps[:]
for iobj in self.graph.get_sources(gen_base.DT_SWIG_C, cobj):
isrc = self.path(str(iobj))
if not isinstance(iobj, gen_base.SWIGSource):
user_deps.append(isrc)
continue
cbuild = "swig %s -o %s $(InputPath)" \
% (string.join(swig_options), cout)
sources.append(ProjectItem(path=isrc, reldir=None,
custom_build=cbuild,
custom_target=csrc,
user_deps=user_deps))
def_file = self.get_def_file(target)
if def_file is not None:
gsrc = self.path("build/generator/extractor.py")
deps = []
for header in target.msvc_export:
deps.append(self.path(target.path, header))
cbuild = "python $(InputPath) %s > %s" \
% (string.join(deps), def_file)
sources.append(ProjectItem(path=gsrc, reldir=None, custom_build=cbuild,
user_deps=deps, custom_target=def_file))
sources.append(ProjectItem(path=def_file, reldir=None,
custom_build=None, user_deps=[]))
sources.sort(lambda x, y: cmp(x.path, y.path))
return sources
def get_output_name(self, target):
if isinstance(target, gen_base.TargetExe):
return target.name + '.exe'
elif isinstance(target, gen_base.TargetJava):
return None
elif isinstance(target, gen_base.TargetApacheMod):
return target.name + '.so'
elif isinstance(target, gen_base.TargetLib):
if target.msvc_static:
return '%s-%d.lib' % (target.name, self.cfg.version)
else:
return os.path.basename(target.filename)
elif isinstance(target, gen_base.TargetProject):
### Since this target type doesn't produce any output, we shouldn't
### need to specify an output filename. But to keep the VC.NET template
### happy for now we have to return something
return target.name + '.exe'
elif isinstance(target, gen_base.TargetI18N):
return target.name
def get_output_dir(self, target):
if isinstance(target, gen_base.TargetJavaHeaders):
return msvc_path("../" + target.headers)
elif isinstance(target, gen_base.TargetJavaClasses):
return msvc_path("../" + target.classes)
else:
return msvc_path(target.path)
def get_intermediate_dir(self, target):
if isinstance(target, gen_base.TargetSWIG):
return msvc_path_join(msvc_path(target.path), target.name)
else:
return self.get_output_dir(target)
def get_def_file(self, target):
if isinstance(target, gen_base.TargetLib) and target.msvc_export:
return self.path(target.path, target.name + ".def")
return None
def gen_proj_names(self, install_targets):
"Generate project file names for the targets"
# Generate project file names for the targets: replace dashes with
# underscores and replace *-test with test_* (so that the test
# programs are visually separare from the rest of the projects)
for target in install_targets:
if target.msvc_name:
target.proj_name = target.msvc_name
continue
name = target.name
pos = string.find(name, '-test')
if pos >= 0:
proj_name = 'test_' + string.replace(name[:pos], '-', '_')
elif isinstance(target, gen_base.TargetSWIG):
proj_name = 'swig_' + string.replace(name, '-', '_')
else:
proj_name = string.replace(name, '-', '_')
target.proj_name = proj_name
def get_external_project(self, target, proj_ext):
if not ((isinstance(target, gen_base.TargetLinked)
or isinstance(target, gen_base.TargetI18N))
and target.external_project):
return None
if target.external_project[:10] == 'apr-iconv/':
path = self.apr_iconv_path + target.external_project[9:]
elif target.external_project[:9] == 'apr-util/':
path = self.apr_util_path + target.external_project[8:]
elif target.external_project[:4] == 'apr/':
path = self.apr_path + target.external_project[3:]
else:
path = target.external_project
return "%s.%s" % (gen_base.native_path(path), proj_ext)
def adjust_win_depends(self, target, name):
"Handle special dependencies if needed"
if name == '__CONFIG__':
depends = []
else:
depends = self.sections['__CONFIG__'].get_dep_targets(target)
depends.extend(self.get_win_depends(target, FILTER_PROJECTS))
return depends
def get_win_depends(self, target, mode):
"""Return the list of dependencies for target"""
dep_dict = {}
if isinstance(target, gen_base.TargetLib) and target.msvc_static:
self.get_static_win_depends(target, dep_dict)
else:
self.get_linked_win_depends(target, dep_dict)
deps = []
if mode == FILTER_PROJECTS:
for dep, (is_proj, is_lib, is_static) in dep_dict.items():
if is_proj:
deps.append(dep)
elif mode == FILTER_LIBS:
for dep, (is_proj, is_lib, is_static) in dep_dict.items():
if is_static or (is_lib and not is_proj):
deps.append(dep)
else:
raise NotImplementedError
deps.sort(lambda d1, d2: cmp(d1.name, d2.name))
return deps
def get_direct_depends(self, target):
"""Read target dependencies from graph
return value is list of (dependency, (is_project, is_lib, is_static)) tuples
"""
deps = []
for dep in self.graph.get_sources(gen_base.DT_LINK, target.name):
if not isinstance(dep, gen_base.Target):
continue
is_project = hasattr(dep, 'proj_name')
is_lib = isinstance(dep, gen_base.TargetLib)
is_static = is_lib and dep.msvc_static
deps.append((dep, (is_project, is_lib, is_static)))
for dep in self.graph.get_sources(gen_base.DT_NONLIB, target.name):
is_project = hasattr(dep, 'proj_name')
is_lib = isinstance(dep, gen_base.TargetLib)
is_static = is_lib and dep.msvc_static
deps.append((dep, (is_project, is_lib, is_static)))
return deps
def get_static_win_depends(self, target, deps):
"""Find project dependencies for a static library project"""
for dep, dep_kind in self.get_direct_depends(target):
is_proj, is_lib, is_static = dep_kind
# recurse for projectless targets
if not is_proj:
self.get_static_win_depends(dep, deps)
# Only add project dependencies on non-library projects. If we added
# project dependencies on libraries, MSVC would copy those libraries
# into the static archive. This would waste space and lead to linker
# warnings about multiply defined symbols. Instead, the library
# dependencies get added to any DLLs or EXEs that depend on this static
# library (see get_linked_win_depends() implementation).
if not is_lib:
deps[dep] = dep_kind
# a static library can depend on another library through a fake project
elif dep.msvc_fake:
deps[dep.msvc_fake] = dep_kind
def get_linked_win_depends(self, target, deps, static_recurse=0):
"""Find project dependencies for a DLL or EXE project"""
for dep, dep_kind in self.get_direct_depends(target):
is_proj, is_lib, is_static = dep_kind
# recurse for projectless dependencies
if not is_proj:
self.get_linked_win_depends(dep, deps, 0)
# also recurse into static library dependencies
elif is_static:
self.get_linked_win_depends(dep, deps, 1)
# add all top level dependencies and any libraries that
# static library dependencies depend on.
if not static_recurse or is_lib:
deps[dep] = dep_kind
def get_win_defines(self, target, cfg):
"Return the list of defines for target"
fakedefines = ["WIN32","_WINDOWS","alloca=_alloca",
"snprintf=_snprintf"]
if isinstance(target, gen_base.TargetApacheMod):
if target.name == 'mod_dav_svn':
fakedefines.extend(["AP_DECLARE_EXPORT"])
if isinstance(target, gen_base.TargetSWIG):
fakedefines.append("SWIG_GLOBAL")
fakedefines.append(self.swig_defines)
if target.lang == 'java':
fakedefines.append('SWIGJAVA')
if isinstance(target, gen_base.TargetSWIGLib):
fakedefines.append(self.swig_defines)
if cfg == 'Debug':
fakedefines.extend(["_DEBUG","SVN_DEBUG"])
elif cfg == 'Release':
fakedefines.append("NDEBUG")
# XXX: Check if db is present, and if so, let apr-util know
# XXX: This is a hack until the apr build system is improved to
# XXX: know these things for itself.
if self.bdb_lib:
fakedefines.append("APU_HAVE_DB=1")
# check if they wanted nls
if self.enable_nls:
fakedefines.append("ENABLE_NLS")
return fakedefines
def get_win_includes(self, target):
"Return the list of include directories for target"
if isinstance(target, gen_base.TargetApacheMod):
fakeincludes = [ self.path("subversion/include"),
self.apath(self.bdb_path, "include"),
self.path("subversion") ]
fakeincludes.extend([
self.apath(self.apr_path, "include"),
self.apath(self.apr_util_path, "include"),
self.apath(self.apr_util_path, "xml/expat/lib"),
self.apath(self.httpd_path, "include")
])
elif isinstance(target, gen_base.TargetSWIG):
util_includes = "subversion/bindings/swig/%s/libsvn_swig_%s" \
% (target.lang,
gen_base.lang_utillib_suffix[target.lang])
fakeincludes = [ self.path("subversion/bindings/swig"),
self.path("subversion/include"),
self.path(util_includes),
self.apath(self.apr_path, "include"),
self.apath(self.apr_util_path, "include") ]
else:
fakeincludes = [ self.path("subversion/include"),
self.apath(self.apr_path, "include"),
self.apath(self.apr_util_path, "include"),
self.apath(self.apr_util_path, "xml/expat/lib"),
self.path("neon/src"),
self.apath(self.bdb_path, "include"),
self.path("subversion") ]
if self.swig_libdir \
and (isinstance(target, gen_base.TargetSWIG)
or isinstance(target, gen_base.TargetSWIGLib)):
fakeincludes.append(self.swig_libdir)
return fakeincludes
def get_win_lib_dirs(self, target, cfg):
"Return the list of library directories for target"
libcfg = string.replace(string.replace(cfg, "Debug", "LibD"),
"Release", "LibR")
fakelibdirs = [ self.apath(self.bdb_path, "lib") ]
if isinstance(target, gen_base.TargetApacheMod):
fakelibdirs.append(self.apath(self.httpd_path, cfg))
if target.name == 'mod_dav_svn':
fakelibdirs.append(self.apath(self.httpd_path, "modules/dav/main",
cfg))
return fakelibdirs
def get_win_libs(self, target, cfg):
"Return the list of external libraries needed for target"
dblib = self.bdb_lib+(cfg == 'Debug' and 'd.lib' or '.lib')
if not isinstance(target, gen_base.TargetLinked):
return []
if isinstance(target, gen_base.TargetLib) and target.msvc_static:
return []
nondeplibs = target.msvc_libs[:]
if self.enable_nls:
nondeplibs.extend(['intl.lib'])
if isinstance(target, gen_base.TargetExe):
nondeplibs.append('setargv.obj')
if ((isinstance(target, gen_base.TargetSWIG)
or isinstance(target, gen_base.TargetSWIGLib))
and target.lang == 'perl'):
nondeplibs.append(self.perl_lib)
for dep in self.get_win_depends(target, FILTER_LIBS):
nondeplibs.extend(dep.msvc_libs)
if dep.external_lib == '$(SVN_DB_LIBS)':
nondeplibs.append(dblib)
return gen_base.unique(nondeplibs)
def get_win_sources(self, target, reldir_prefix=''):
"Return the list of source files that need to be compliled for target"
sources = { }
for obj in self.graph.get_sources(gen_base.DT_LINK, target.name):
if isinstance(obj, gen_base.Target):
continue
for src in self.graph.get_sources(gen_base.DT_OBJECT, obj):
if isinstance(src, gen_base.SourceFile):
if reldir_prefix:
if src.reldir:
reldir = reldir_prefix + '\\' + src.reldir
else:
reldir = reldir_prefix
else:
reldir = src.reldir
else:
reldir = ''
sources[src] = src, obj, reldir
return sources.values()
def write_file_if_changed(self, fname, new_contents):
"""Rewrite the file if new_contents are different than its current content.
If you have your windows projects open and generate the projects
it's not a small thing for windows to re-read all projects so
only update those that have changed.
"""
try:
old_contents = open(fname, 'rb').read()
except IOError:
old_contents = None
if old_contents != new_contents:
open(fname, 'wb').write(new_contents)
print "Wrote:", fname
def write_with_template(self, fname, tname, data):
fout = StringIO()
template = ezt.Template(compress_whitespace = 0)
template.parse_file(os.path.join('build', 'generator', tname))
template.generate(fout, data)
self.write_file_if_changed(fname, fout.getvalue())
def write(self):
"Override me when creating a new project type"
raise NotImplementedError
def _find_bdb(self):
"Find the Berkley DB library and version"
for lib in ("libdb42", "libdb41", "libdb40"):
path = os.path.join(self.bdb_path, "lib")
if os.path.exists(os.path.join(path, lib + ".lib")):
sys.stderr.write("Found %s.lib in %s\n" % (lib, path))
self.bdb_lib = lib
break
else:
sys.stderr.write("DB not found; assuming db-4.2.x in db4-win32 "
"by default\n")
self.bdb_lib = "libdb42"
def _find_perl(self):
"Find the right perl library name to link swig bindings with"
fp = os.popen('perl -MConfig -e ' + escape_shell_arg(
'print "$Config{PERL_REVISION}$Config{PERL_VERSION}"'), 'r')
try:
num = fp.readline()
if num:
msg = 'Found installed perl version number.'
self.perl_lib = 'perl' + string.rstrip(num) + '.lib'
else:
msg = 'Could not detect perl version.'
self.perl_lib = 'perl56.lib'
sys.stderr.write('%s\n Perl bindings will be linked with %s\n'
% (msg, self.perl_lib))
finally:
fp.close()
def _find_swig(self):
# Require (and assume) version 1.3.19
base_version = '1.3.19'
vernum = base_vernum = 103019
libdir = ''
infp, outfp = os.popen4('swig -version')
infp.close()
try:
txt = outfp.read()
if (txt):
vermatch = re.compile(r'^SWIG\ Version\ (\d+)\.(\d+)\.(\d+)$', re.M) \
.search(txt)
else:
vermatch = None
if (vermatch):
version = (int(vermatch.group(1)),
int(vermatch.group(2)),
int(vermatch.group(3)))
# build/ac-macros/swig.m4 explains the next incantation
vernum = int('%d%02d%03d' % version)
sys.stderr.write('Found installed SWIG version %d.%d.%d\n' % version)
if vernum < base_vernum:
sys.stderr.write('WARNING: Subversion requires version %s\n'
% base_version)
libdir = self._find_swig_libdir()
else:
sys.stderr.write('Could not find installed SWIG,'
' assuming version %s\n' % base_version)
self.swig_libdir = ''
finally:
outfp.close()
self.swig_defines = 'SVN_SWIG_VERSION=%d' % vernum
self.swig_vernum = vernum
self.swig_libdir = libdir
def _find_swig_libdir(self):
fp = os.popen('swig -swiglib', 'r')
try:
libdir = string.rstrip(fp.readline())
if libdir:
sys.stderr.write('Using SWIG library directory %s\n' % libdir)
return libdir
else:
sys.stderr.write('WARNING: could not find SWIG library directory\n')
finally:
fp.close()
return ''
def _configure_apr_util(self):
if not self.configure_apr_util:
return
script_path = os.path.join(self.apr_util_path, "build", "w32locatedb.pl")
inc_path = os.path.join(self.bdb_path, "include")
lib_path = os.path.join(self.bdb_path, "lib")
cmdline = "perl %s dll %s %s" % (escape_shell_arg(script_path),
escape_shell_arg(inc_path),
escape_shell_arg(lib_path))
sys.stderr.write('Configuring apr-util library...\n%s\n' % cmdline)
if os.system(cmdline):
sys.stderr.write('WARNING: apr-util library was not configured'
' successfully\n')
class ProjectItem:
"A generic item class for holding sources info, config info, etc for a project"
def __init__(self, **kw):
vars(self).update(kw)
if sys.platform == "win32":
def escape_shell_arg(str):
return '"' + string.replace(str, '"', '"^""') + '"'
else:
def escape_shell_arg(str):
return "'" + string.replace(str, "'", "'\\''") + "'"
FILTER_LIBS = 1
FILTER_PROJECTS = 2
class POFile:
"Item class for holding po file info"
def __init__(self, base):
self.po = base + '.po'
self.spo = base + '.spo'
self.mo = base + '.mo'
# MSVC paths always use backslashes regardless of current platform
def msvc_path(path):
"""Convert a build path to an msvc path"""
return string.replace(path, '/', '\\')
def msvc_path_join(*path_parts):
"""Join path components into an msvc path"""
return string.join(path_parts, '\\')