| # |
| # 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, '\\') |