root/juggler/tags/2.0_beta_2/buildwin32.py

Revision 16600, 77.1 kB (checked in by patrickh, 4 years ago)

Specify the path to the Microsoft Speech SDK through an environment
variable. My Visual C++ 7.0 installation has the Speech SDK included, but
my VC++ 7.1 installation does not.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #python
2
3 # ************** <auto-copyright.pl BEGIN do not edit this line> **************
4 #
5 # VR Juggler is (C) Copyright 1998-2005 by Iowa State University
6 #
7 # Original Authors:
8 #   Allen Bierbaum, Christopher Just,
9 #   Patrick Hartling, Kevin Meinert,
10 #   Carolina Cruz-Neira, Albert Baker
11 #
12 # This library is free software; you can redistribute it and/or
13 # modify it under the terms of the GNU Library General Public
14 # License as published by the Free Software Foundation; either
15 # version 2 of the License, or (at your option) any later version.
16 #
17 # This library is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 # Library General Public License for more details.
21 #
22 # You should have received a copy of the GNU Library General Public
23 # License along with this library; if not, write to the
24 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 # Boston, MA 02111-1307, USA.
26 #
27 # -----------------------------------------------------------------
28 # File:          $RCSfile$
29 # Date modified: $Date$
30 # Version:       $Revision$
31 # -----------------------------------------------------------------
32 #
33 # *************** <auto-copyright.pl END do not edit this line> ***************
34
35 import glob
36 import os
37 import re
38 import shutil
39 import sys
40 import time
41 import traceback
42 import getopt
43
44 EXIT_STATUS_SUCCESS           = 0
45 EXIT_STATUS_NO_MSVS           = 1
46 EXIT_STATUS_MISSING_DATA_FILE = 2
47 EXIT_STATUS_MSVS_START_ERROR  = 3
48 EXIT_STATUS_INVALID_PATH      = 4
49 EXIT_STATUS_MISSING_REQ_VALUE = 5
50
51 gJugglerDir      = os.path.dirname(os.path.abspath(sys.argv[0]))
52 gOptionsFileName = "options.cache"
53
54 gHaveTk = False
55 try:
56    import Tkinter
57    import tkMessageBox
58    import tkFileDialog
59    import threading
60    gHaveTk = True
61 except ImportError, ex:
62    print ex
63
64 class BuildOption:
65    def __init__(self, envVar, desc, defaultValue, isDirectory = True,
66                 required = True):
67       self.envVar      = envVar
68       self.desc        = desc
69       self.default     = defaultValue
70       self.required    = required
71       self.isDirectory = isDirectory
72
73 def guessBoostToolset(reattempt = False):
74    (cl_stdin, cl_stdout, cl_stderr) = os.popen3('cl')
75    cl_version_line = cl_stderr.readline()
76
77    cl_ver_match = re.compile(r'Compiler Version ((\d+)\.(\d+)\.(\d+)) for')
78    ver_string_match = cl_ver_match.search(cl_version_line)
79
80    if ver_string_match is not None:
81       cl_major = int(ver_string_match.group(2))
82       cl_minor = int(ver_string_match.group(3))
83
84       if cl_major == 13 and cl_minor < 10:
85          vs_ver = '.NET 2002'
86          boost_tool_guess = 'vc7'
87       else:
88          vs_ver = '.NET 2003'
89          boost_tool_guess = 'vc71'
90
91       printStatus("It appears that we will be using Visual Studio " + vs_ver)
92    else:
93       boost_tool_guess = ''
94
95    in_status  = cl_stdin.close()
96    out_status = cl_stdout.close()
97    err_status = cl_stderr.close()
98
99    # If there was an error closing any of the streams returned by
100    # os.popen3(), then the command was not opened correctly.  That means
101    # that CL.EXE is not in the user's path.
102    if in_status is not None or out_status is not None or err_status is not None:
103       # If this is not a reattempt to guess the Visual Studio version, then
104       # be nice and extend the user's path to include their Visual Studio
105       # installation.
106       if not reattempt:
107          # Common installation directories for Visual Studio 7.x.
108          vs_dirs = [r'C:\Program Files\Microsoft Visual Studio .NET',
109                     r'C:\Program Files\Microsoft Visual Studio .NET 2003']
110
111          for d in vs_dirs:
112             if os.path.exists(d):
113                printStatus("NOTE: Using Visual Studio installation in")
114                printStatus("      " + d)
115                vs_path = [os.path.join(d, r'Common7\IDE'),
116                           os.path.join(d, r'VC7\BIN'),
117                           os.path.join(d, r'Common7\Tools'),
118                           os.path.join(d, r'Common7\Tools\bin\prerelease'),
119                           os.path.join(d, r'Common7\Tools\bin')]
120                path_add = ';'.join(vs_path)
121                os.environ['PATH'] = path_add + os.pathsep + os.getenv('PATH', '')
122
123                # Try again to guess the Visual Studio version.
124                return guessBoostToolset(True)
125
126          # If execution reaches this point, our attempts to guess the
127          # location of a Visual Studio 7.x installation failed.
128          noVisualStudioError()
129
130       # If this is a reattempt to guess the Visual Studio version, then
131       # something is wrong with the user's Visual Studio installation.
132       else:
133          noVisualStudioError()
134
135    return boost_tool_guess
136
137 def printStatus(msg):
138    '''
139    This is a simple wrapper around the standard Python print function.
140    We will use a wrapper function for key status messages so that they
141    can be redirected either to the console or to a GUI easily.
142    '''
143    print msg
144
145 def noVisualStudioError():
146    print "ERROR: Visual Studio commands are not in your path!"
147    print "Run vsvars32.bat in this shell or update the %PATH% environment"
148    print "variable on your system."
149    sys.exit(EXIT_STATUS_NO_MSVS)
150
151 def getCacheFileName():
152    return os.path.join(gJugglerDir, gOptionsFileName)
153
154 def processInput(optionDict, envVar, inputDesc, required = False):
155    default_value = optionDict[envVar]
156    print "  %s [%s]: " % (inputDesc, default_value),
157    input_str = sys.stdin.readline().strip(" \n")
158
159    if input_str == '':
160       if required and (default_value is None or default_value == ''):
161          print "ERROR: %s value required" % inputDesc
162          sys.exit(EXIT_STATUS_MISSING_REQ_VALUE)
163       else:
164          value_str = default_value
165    else:
166       value_str = input_str
167
168    optionDict[envVar] = value_str
169    os.environ[envVar] = value_str
170
171    return value_str
172
173 def getDefaultVars():
174    boost_tool_fallback = guessBoostToolset()
175
176    required = []
177    required.append(BuildOption('BOOST_ROOT',
178                                'Boost C++ installation directory', ''))
179    required.append(BuildOption('BOOST_VERSION', 'Boost C++ version',
180                                '1_31', False))
181    required.append(BuildOption('BOOST_INCLUDES',
182                                'Directory containing the Boost C++ header tree',
183                                ''))
184    required.append(BuildOption('BOOST_TOOL',
185                                'The Boost.Build toolset used to compile Boost C++',
186                                boost_tool_fallback, False))
187    required.append(BuildOption('NSPR_ROOT', 'NSPR installation directory', ''))
188    required.append(BuildOption('CPPDOM_ROOT', 'CppDOM installation directory',
189                                ''))
190    required.append(BuildOption('GMTL_ROOT', 'GMTL installation directory', ''))
191
192    optional = []
193    optional.append(BuildOption('JAVA_HOME', 'Java installation directory',
194                                r'C:\java', required = False))
195    optional.append(BuildOption('JOGL_HOME', 'Jogl installation directory',
196                                os.getenv('JAVA_HOME', ''), required = False))
197    optional.append(BuildOption('JAVA3D_HOME', 'Java 3D installation directory',
198                                os.getenv('JAVA_HOME', ''), required = False))
199    optional.append(BuildOption('OMNIORB_ROOT',
200                                'omniORB installation directory', '',
201                                required = False))
202    optional.append(BuildOption('PFROOT',
203                                'OpenGL Performer installation directory',
204                                r'C:\Program Files\Silicon Graphics\OpenGL Performer',
205                                required = False))
206    optional.append(BuildOption('MS_SPEECH_SDK_ROOT',
207                                'Microsoft Speech SDK directory', '',
208                                required = False))
209    optional.append(BuildOption('VRPN_ROOT', 'VRPN installation directory', '',
210                                required = False))
211    optional.append(BuildOption('AUDIERE_ROOT',
212                                'Audiere installation directory', '',
213                                required = False))
214    optional.append(BuildOption('OPENAL_ROOT',
215                                'OpenAL SDK installation directory', '',
216                                required = False))
217    optional.append(BuildOption('TRACKD_API_ROOT',
218                                'TrackdAPI installation directory', '',
219                                required = False))
220
221    options = {
222       'prefix'      : r'C:\vrjuggler',
223       'deps-prefix' : r'C:\vrjuggler-deps'
224    }
225
226    for opt in required + optional:
227       options[opt.envVar] = os.getenv(opt.envVar, opt.default)
228
229    # If there are cached options, read them in.
230    cache_file = getCacheFileName()
231    if os.path.exists(cache_file):
232       execfile(cache_file)
233
234    return required, optional, options
235
236 def setVars():
237    required, optional, options = getDefaultVars()
238
239    print "+++ Required Settings"
240    processInput(options, 'prefix', 'Installation prefix')
241
242    boost_dir = ''
243    boost_ver = ''
244    for opt in required:
245       result = processInput(options, opt.envVar, opt.desc, opt.required)
246
247       # The following is a little hack to get a reasonable default set for
248       # the BOOST_INCLUDES variable before the user has to enter it manually.
249       if opt.envVar == 'BOOST_ROOT':
250          boost_dir = result
251       elif opt.envVar == 'BOOST_VERSION':
252          boost_ver = result
253          options['BOOST_INCLUDES'] = boost_dir + r'\include\boost-' + boost_ver
254
255    print "+++ Optional Settings"
256    processInput(options, 'deps-prefix', 'Dependency installation prefix')
257
258    for opt in optional:
259       processInput(options, opt.envVar, opt.desc, opt.required)
260
261    postProcessOptions(options)
262    writeCacheFile(options)
263
264    return options
265
266 def postProcessOptions(options):
267    # Check for Boost 1.32 Visual C++ toolset names.
268    match = re.compile(r'vc-(\d)_(\d)').match(options['BOOST_TOOL'])
269
270    if match is not None:
271       os.environ['BOOST_TOOL'] = 'vc%s%s' % (match.group(1), match.group(2))
272
273    # If the %JAVA_HOME% setting is a valid directory, add its bin subdirectory
274    # to the path.
275    if os.environ['JAVA_HOME'] != '' and os.path.exists(os.environ['JAVA_HOME']):
276       jdk_path = os.path.join(os.environ['JAVA_HOME'], 'bin')
277       os.environ['PATH'] = jdk_path + os.pathsep + os.environ['PATH']
278       os.environ['JACORB_PATH'] = os.path.join(gJugglerDir, r'external\JacORB')
279
280    if os.environ['OMNIORB_ROOT'] != '' and os.path.exists(os.environ['OMNIORB_ROOT']):
281       omni_bin = os.path.join(os.environ['OMNIORB_ROOT'], 'bin')
282
283       if os.path.exists(os.path.join(omni_bin, 'omniidl.exe')):
284          os.environ['OMNIORB_BIN'] = omni_bin
285       else:
286          os.environ['OMNIORB_BIN'] = os.path.join(omni_bin, 'x86_win32')
287
288       # Extend the path to include omniORB's bin directory.
289       os.environ['PATH'] = os.environ['OMNIORB_BIN'] + os.pathsep + os.environ['PATH']
290
291       omni_lib = os.path.join(os.environ['OMNIORB_ROOT'], 'lib')
292
293       if os.getenv('PYTHONPATH', '') != '':
294          os.environ['PYTHONPATH'] = os.path.join(omni_lib, 'python') + os.pathsep + os.environ['PYTHONPATH']
295       else:
296          os.environ['PYTHONPATH'] = os.path.join(omni_lib, 'python')
297
298       if os.path.exists(os.path.join(omni_lib, 'omnithread.lib')):
299          os.environ['OMNIORB_LIB'] = omni_lib
300       else:
301          os.environ['OMNIORB_LIB'] = os.path.join(omni_lib, 'x86_win32')
302
303       omni_glob = os.path.join(os.environ['OMNIORB_LIB'], 'omniORB*_rt.lib')
304       libs = glob.glob(omni_glob)
305       omni_ver_re = re.compile(r'omniORB(\d\d\d)_rt.lib')
306
307       for l in libs:
308          match = omni_ver_re.search(l)
309          if match is not None:
310             os.environ['OMNIORB_VERSION'] = match.group(1)
311             break
312
313 def writeCacheFile(optionDict):
314    cache_file = open(getCacheFileName(), 'w')
315    for k, v in optionDict.iteritems():
316       output = "options['%s'] = r'%s'\n" % (k, v)
317       cache_file.write(output)
318    cache_file.close()
319
320 def generateVersionHeaders():
321    class JugglerModule:
322       def __init__(self, srcDir, projDir, genFiles = None):
323          self.source_dir     = os.path.join(gJugglerDir, srcDir)
324          self.version_params = os.path.join(self.source_dir, 'Makefile.inc.in')
325          self.version_file   = os.path.join(self.source_dir, 'VERSION')
326          self.param_files    = []
327
328          if genFiles is not None:
329             for f in genFiles:
330                output = os.path.join(gJugglerDir, 'vc7', projDir, f[0])
331
332                if len(f) == 1 or f[1] is None:
333                   template = os.path.join(self.source_dir, f[0] + '.in')
334                else:
335                   template = f[1]
336
337                self.param_files.append((output, template))
338
339       def generateParamFiles(self):
340          for (output, template) in self.param_files:
341             if os.path.exists(output):
342                mtime = os.path.getmtime
343                # This test to determine if the module's param header needs to
344                # be regenerated is equivalent to that used by the UNIX build
345                # system.
346                if mtime(self.version_file) > mtime(output) or \
347                   mtime(template) > mtime(output):
348                   self.__genParamFile(output, template)
349             else:
350                self.__genParamFile(output, template)
351
352       version_re      = re.compile(r'((\d+)\.(\d+)\.(\d+)-(\d+))\s')
353       branch_re       = re.compile(r'BRANCH\s*=\s*(\w+)')
354       canon_name_re   = re.compile(r'CANON_NAME\s*=\s*(\S.+)')
355       vernum_re       = re.compile(r'@VER_NUMBER@')
356       major_vernum_re = re.compile(r'@MAJOR_VER_NUMBER@')
357       minor_vernum_re = re.compile(r'@MINOR_VER_NUMBER@')
358       patch_vernum_re = re.compile(r'@PATCH_VER_NUMBER@')
359       verstr_re       = re.compile(r'@VER_STRING@')
360       zero_strip_re   = re.compile(r'^0*([^0]\d+)')
361
362       def __genParamFile(self, output, template):
363          ver_file = open(self.version_file)
364          cur_ver  = ver_file.readline()
365          ver_file.close()
366          ver_match = self.version_re.match(cur_ver)
367          version = ver_match.group(1)
368          major   = int(ver_match.group(2))
369          minor   = int(ver_match.group(3))
370          patch   = int(ver_match.group(4))
371
372          # NOTE: This will not always be identical to the UNIX version because
373          # Python does not have %e as a time formatting directive.
374          date       = time.strftime('%b %d, %Y %H:%M:%S')
375          canon_name = ''
376          branch     = ''
377
378          param_file = open(self.version_params, 'r')
379          params     = param_file.readlines()
380          param_file.close()
381
382          # This is basically a poor man's grep.  Can this be done better?
383          for line in params:
384             match = self.branch_re.match(line)
385             if match is not None:
386                branch_name = match.group(1)
387                continue
388
389             match = self.canon_name_re.match(line)
390             if match is not None:
391                canon_name = match.group(1)
392                continue
393
394          version_number = '%03d%03d%03d' % (major, minor, patch)
395          version_string = "\"v%s '%s' (NSPR) %s %s\"" % \
396                              (version, canon_name, branch, date)
397
398          # Strip leading zeroes from version_number.  Is there an easier way
399          # to do this?
400          version_number = self.zero_strip_re.match(version_number).group(1)
401
402          try:
403             input_file  = open(template, 'r')
404             input_lines = input_file.readlines()
405             input_file.close()
406
407             for i in xrange(len(input_lines)):
408                line = input_lines[i]
409                if self.vernum_re.search(line):
410                   input_lines[i] = self.vernum_re.sub(version_number, line)
411                elif self.major_vernum_re.search(line):
412                   input_lines[i] = self.major_vernum_re.sub(str(major), line)
413                elif self.minor_vernum_re.search(line):
414                   input_lines[i] = self.minor_vernum_re.sub(str(minor), line)
415                elif self.patch_vernum_re.search(line):
416                   input_lines[i] = self.patch_vernum_re.sub(str(patch), line)
417                elif self.verstr_re.search(line):
418                   input_lines[i] = self.verstr_re.sub(version_string, line)
419
420             printStatus("Generating updated " + output)
421             param_header = open(output, 'w')
422             param_header.writelines(input_lines)
423             param_header.close()
424          except IOError, ex:
425             printStatus("ERROR: Could not read from %s" % template)
426             printStatus(ex)
427             printStatus("Cannot continue; exiting with error status.")
428             sys.exit(EXIT_STATUS_MISSING_DATA_FILE)
429
430    mods = []
431    mods.append(JugglerModule(r'modules\vapor', 'VPR',
432                              [(r'vpr\vprParam.h',), (r'vpr\vprParam.cpp',)]))
433    mods.append(JugglerModule(r'modules\tweek', 'Tweek_CXX',
434                              [(r'tweek\tweekParam.h',),
435                               (r'tweek\tweekParam.cpp',)]))
436    mods.append(JugglerModule(r'modules\jackal', 'JCCL',
437                              [(r'jccl\jcclParam.h',
438                                os.path.join(gJugglerDir,
439                                             r'modules\jackal\common\jccl\jcclParam.h.in')),
440                               (r'jccl\jcclParam.cpp',
441                                os.path.join(gJugglerDir,
442                                             r'modules\jackal\common\jccl\jcclParam.cpp.in'))
443                              ]))
444    mods.append(JugglerModule(r'modules\sonix', 'Sonix',
445                              [(r'snx\snxParam.h',), (r'snx\snxParam.cpp',)]))
446    mods.append(JugglerModule(r'modules\gadgeteer', 'Gadgeteer',
447                              [(r'gadget\gadgetParam.h',),
448                               (r'gadget\gadgetParam.cpp',)]))
449    mods.append(JugglerModule(r'modules\vrjuggler', 'VRJuggler',
450                              [(r'vrj\vrjParam.h',), (r'vrj\vrjParam.cpp',)]))
451
452    for m in mods:
453       m.generateParamFiles()
454
455 def generateAntBuildFiles():
456    class AntTarget:
457       def __init__(self, srcdir, moduleName, outputFile = 'build.xml'):
458          self.srcdir      = os.path.join(gJugglerDir, srcdir)
459          self.topdir      = os.path.join(gJugglerDir, r'vc7')
460          self.module_name = os.path.join(self.topdir, moduleName)
461          self.output_file = os.path.join(self.module_name, outputFile)
462
463          if not os.path.exists(self.module_name):
464             os.mkdir(self.module_name)
465          elif not os.path.isdir(self.module_name):
466             printStatus("ERROR: %s exists, but it is not a directory!" % self.module_name)
467             sys.exit(EXIT_STATUS_INVALID_PATH)
468
469       # This form of regular expressions appears to be necessary because
470       # the sub() method does not handle backslashes in the replacement string
471       # the way I would like.
472       srcdir_re         = re.compile(r'^(.*)@srcdir@(.*)$')
473       topdir_re         = re.compile(r'^(.*)@topdir@(.*)$')
474       juggler_root_re   = re.compile(r'^(.*)@JUGGLERROOT_ABS@(.*)$')
475       jdom_jar_re       = re.compile(r'^(.*)@JDOM_JAR@(.*)$')
476       tweek_jars_re     = re.compile(r'^(.*)@TWEEK_JARS@(.*)$')
477       tweek_ext_jars_re = re.compile(r'^(.*)@TWEEK_EXT_JARS@(.*)$')
478       jccl_jars_re      = re.compile(r'^(.*)@JCCL_JARS@(.*)$')
479       java_orb_jar_re   = re.compile(r'^(.*)@JAVA_ORB_JAR@(.*)$')
480       jogl_jars_re      = re.compile(r'^(.*)@JOGL_JARS@(.*)$')
481       java3d_jars_re    = re.compile(r'^(.*)@JAVA3D_JAR@(.*)$')
482
483       jdom_jars = [
484          os.path.join(gJugglerDir, r'external\jdom\build\jdom.jar'),
485          os.path.join(gJugglerDir, r'external\jdom\lib\jaxen-core.jar'),
486          os.path.join(gJugglerDir, r'external\jdom\lib\xalan.jar'),
487          os.path.join(gJugglerDir, r'external\jdom\lib\jaxen-jdom.jar'),
488          os.path.join(gJugglerDir, r'external\jdom\lib\xerces.jar'),
489          os.path.join(gJugglerDir, r'external\jdom\lib\xml-apis.jar'),
490          os.path.join(gJugglerDir, r'external\jdom\lib\saxpath.jar')
491       ]
492
493       tweek_jars = [
494          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'Tweek.jar'),
495          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'TweekBeans.jar'),
496          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'TweekEvents.jar'),
497          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'TweekNet.jar'),
498          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'TweekBeanDelivery.jar'),
499          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'TweekServices.jar'),
500          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'Viewers.jar'),
501          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'kunststoff-mod.jar')
502       ]
503
504       tweek_ext_jars = [
505          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'ui.jar'),
506          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'wizard.jar'),
507          os.path.join(gJugglerDir, r'vc7\Tweek_Java', 'WizardBuilder.jar')
508       ]
509
510       jccl_jars = [
511          os.path.join(gJugglerDir, r'vc7\JCCL_Java', 'jccl_config.jar'),
512          os.path.join(gJugglerDir, r'vc7\JCCL_Java', 'jccl_editors.jar')
513       ]
514
515       jccl_rtrc_jars = [
516          os.path.join(gJugglerDir, r'vc7\JCCL_Java\RTRC_Plugin_Java',
517                       'jccl_rtrc.jar')
518       ]
519
520       jogl_jars = [
521          os.path.join(os.environ['JOGL_HOME'], 'jogl.jar'),
522          os.path.join(os.environ['JOGL_HOME'], 'jogl-demos-util.jar')
523       ]
524
525       java3d_jars = [
526          os.path.join(os.environ['JAVA3D_HOME'], r'jre\lib\ext\j3daudio.jar'),
527          os.path.join(os.environ['JAVA3D_HOME'], r'jre\lib\ext\j3dcore.jar'),
528          os.path.join(os.environ['JAVA3D_HOME'], r'jre\lib\ext\j3dutils.jar'),
529          os.path.join(os.environ['JAVA3D_HOME'], r'jre\lib\ext\vecmath.jar')
530       ]
531
532       def generateBuildFile(self):
533          input_file = open(os.path.join(self.srcdir, 'build.xml.in'), 'r')
534          input = input_file.readlines()
535          input_file.close()
536
537          for i in xrange(len(input)):
538             line = input[i]
539
540             if self.srcdir_re.search(line):
541                match = self.srcdir_re.search(line)
542                input[i] = '%s%s%s\n' % (match.groups()[0], self.srcdir,
543                                         match.groups()[1])
544             elif self.topdir_re.search(line):
545                match = self.topdir_re.search(line)
546                input[i] = '%s%s%s\n' % (match.groups()[0], self.topdir,
547                                         match.groups()[1])
548             elif self.juggler_root_re.search(line):
549                match = self.juggler_root_re.search(line)
550                input[i] = '%s%s%s\n' % (match.groups()[0], gJugglerDir,
551                                         match.groups()[1])
552             elif self.java_orb_jar_re.search(line):
553                match = self.java_orb_jar_re.search(line)
554                input[i] = '%s%s%s\n' % (match.groups()[0], "",
555                                         match.groups()[1])
556             elif self.jdom_jar_re.search(line):
557                jars = os.pathsep.join(self.jdom_jars)
558                match = self.jdom_jar_re.search(line)
559                input[i] = '%s%s%s\n' % (match.groups()[0], jars,
560                                         match.groups()[1])
561             elif self.tweek_jars_re.search(line):
562                jars = os.pathsep.join(self.tweek_jars + self.jdom_jars)
563                match = self.tweek_jars_re.search(line)
564                input[i] = '%s%s%s\n' % (match.groups()[0], jars,
565                                         match.groups()[1])
566             elif self.tweek_ext_jars_re.search(line):
567                jars = os.pathsep.join(self.tweek_ext_jars)
568                match = self.tweek_ext_jars_re.search(line)
569                input[i] = '%s%s%s\n' % (match.groups()[0], jars,
570                                         match.groups()[1])
571             elif self.jccl_jars_re.search(line):
572                jars = os.pathsep.join(self.jccl_jars + self.jccl_rtrc_jars)
573                match = self.jccl_jars_re.search(line)
574                input[i] = '%s%s%s\n' % (match.groups()[0], jars,
575                                         match.groups()[1])
576             elif self.jogl_jars_re.search(line):
577                jars = os.pathsep.join(self.jogl_jars)
578                match = self.jogl_jars_re.search(line)
579                input[i] = '%s%s%s\n' % (match.groups()[0], jars,
580                                         match.groups()[1])
581             elif self.java3d_jars_re.search(line):
582                jars = os.pathsep.join(self.java3d_jars)
583                match = self.java3d_jars_re.search(line)
584                input[i] = '%s%s%s\n' % (match.groups()[0], jars,
585                                         match.groups()[1])
586
587          build_file = open(self.output_file, 'w')
588          build_file.writelines(input)
589          build_file.close()
590
591    mods = []
592    mods.append(AntTarget(r'modules\tweek\java', 'Tweek_Java'))
593    mods.append(AntTarget(r'modules\tweek\extensions\java', 'Tweek_Java',
594                          'build-ext.xml'))
595    mods.append(AntTarget(r'modules\jackal\config', 'JCCL_Java',
596                          'build-config.xml'))
597    mods.append(AntTarget(r'modules\jackal\editors', 'JCCL_Java',
598                          'build-editors.xml'))
599    mods.append(AntTarget(r'modules\jackal\plugins\corba_rtrc',
600                          r'JCCL_Java\RTRC_Plugin_Java', 'build.xml'))
601    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig', 'VRJConfig',
602                          'build.xml'))
603    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\commoneditors',
604                          r'VRJConfig\commoneditors',
605                          'build-commoneditors.xml'))
606    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\display_window',
607                          'VRJConfig', 'build-display_window.xml'))
608    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\flock',
609                          'VRJConfig', 'build-flock.xml'))
610    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\intersense',
611                          'VRJConfig', 'build-intersense.xml'))
612    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\motionstar',
613                          'VRJConfig', 'build-motionstar.xml'))
614    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\pinchglove',
615                          'VRJConfig', 'build-pinchglove.xml'))
616    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\proxyeditor',
617                          'VRJConfig', 'build-proxyeditor.xml'))
618    mods.append(AntTarget(r'modules\vrjuggler\vrjconfig\customeditors\surfacedisplayeditor',
619                          'VRJConfig', 'build-surfacedisplayeditor.xml'))
620    mods.append(AntTarget(r'modules\vrjuggler\plugins\corba_perf_mon',
621                          r'VRJugglerPlugins\Perf_Plugin_Java', 'build.xml'))
622
623    for m in mods:
624       m.generateBuildFile()
625
626 def doInstall(prefix):
627    makeTree(prefix)
628    installExternal(prefix)
629    installVPR(prefix)
630    installTweek(prefix)
631    installTweekJava(prefix)
632    installJCCL(prefix)
633    installJCCLJava(prefix)
634    installJCCLPlugins(prefix)
635    installJCCLPluginsJava(prefix)
636    installSonix(prefix)
637    installSonixPlugins(prefix)
638    installGadgeteer(prefix)
639    installGadgeteerDrivers(prefix)
640    installGadgeteerPlugins(prefix)
641    installVRJuggler(prefix)
642    installVRJConfig(prefix)
643    installVRJugglerPlugins(prefix)
644    installVRJugglerPluginsJava(prefix)
645    installMsvcRT(prefix)
646
647 def mkinstalldirs(dir):
648 #   print "Checking for", dir
649    if not os.path.exists(dir):
650       (head, tail) = os.path.split(dir)
651       mkinstalldirs(head)
652       os.mkdir(dir)
653
654 def makeTree(prefix):
655    mkinstalldirs(os.path.join(prefix, 'bin'))
656    mkinstalldirs(os.path.join(prefix, 'include'))
657    mkinstalldirs(os.path.join(prefix, 'lib'))
658    mkinstalldirs(os.path.join(prefix, 'share'))
659
660 def installDir(startDir, destDir, allowedExts = None, disallowedExts = None,
661                disallowedFiles = None):
662    cwd = os.getcwd()
663    mkinstalldirs(destDir)
664
665    os.chdir(startDir)
666    contents = os.listdir(startDir)
667
668    if disallowedExts is None:
669       disallowedExts = []
670
671    if disallowedFiles is None:
672       disallowedFiles = []
673
674    # Add some extensions that should always be disallowed.  This relieves the
675    # caller from having to add these repeatedly.
676    disallowedExts.append('.ilk')
677    disallowedExts.append('.ncb')
678    disallowedExts.append('.pdb')
679    disallowedExts.append('.suo')
680
681    skip_dirs = ['CVS', 'autom4te.cache']
682    for f in contents:
683       if os.path.isdir(f):
684          if f in skip_dirs:
685             continue
686
687          start_dir = os.path.join(startDir, f)
688          dest_dir  = os.path.join(destDir, f)
689          installDir(start_dir, dest_dir, allowedExts, disallowedExts)
690       else:
691          (root, f_ext) = os.path.splitext(f)
692          if allowedExts is None:
693             if f_ext not in disallowedExts:
694                shutil.copy2(f, destDir)
695          elif f_ext in allowedExts:
696             (head, tail) = os.path.split(f)
697             if f not in disallowedFiles:
698                shutil.copy2(f, destDir)
699
700    os.chdir(cwd)
701
702 def installLibs(srcRoot, destdir,
703                 buildTypes = ['ReleaseDLL', 'DebugDLL', 'Release', 'Debug'],
704                 extensions = ['.dll', '.lib']):
705    for t in buildTypes:
706       srcdir = os.path.join(srcRoot, t)
707       if os.path.exists(srcdir):
708          installDir(srcdir, destdir, extensions)
709
710 def installExternal(prefix):
711    # Install Doozer (even though it probably won't be used).
712    printStatus("Installing Doozer ...")
713    destdir = os.path.join(prefix, 'share', 'Doozer')
714    srcdir  = os.path.join(gJugglerDir, 'external', 'Doozer')
715    installDir(srcdir, destdir, ['.mk'])
716
717 def installVPR(prefix):
718    printStatus("Installing VPR headers and libraries ...")
719
720    destdir = os.path.join(prefix, 'include', 'vpr')
721    srcdir  = os.path.join(gJugglerDir, 'modules', 'vapor', 'vpr')
722    installDir(srcdir, destdir, ['.h'])
723
724    srcdir  = os.path.join(gJugglerDir, 'vc7', 'VPR', 'vpr')
725    installDir(srcdir, destdir, ['.h'])
726
727    destdir = os.path.join(prefix, 'lib')
728    srcroot = os.path.join(gJugglerDir, 'vc7', 'VPR')
729    installLibs(srcroot, destdir)
730
731    destdir = os.path.join(prefix, 'share', 'vpr', 'test')
732    srcdir  = os.path.join(gJugglerDir, 'modules', 'vapor', 'test')
733    installDir(srcdir, destdir, None, ['.in'])
734
735    # Install additional files into <prefix>\share\vpr
7