Newer
Older
Bryan O'Sullivan
committed
#!/usr/bin/env python
#
# @file develop.py
# @authors Bryan O'Sullivan, Mark Palange, Aaron Brashears
# @brief Fire and forget script to appropriately configure cmake for SL.
#
# $LicenseInfo:firstyear=2007&license=viewergpl$
#
# Copyright (c) 2007-2009, Linden Research, Inc.
Bryan O'Sullivan
committed
#
# Second Life Viewer Source Code
# The source code in this file ("Source Code") is provided by Linden Lab
# to you under the terms of the GNU General Public License, version 2.0
# ("GPL"), unless you have obtained a separate licensing agreement
# ("Other License"), formally executed by you and Linden Lab. Terms of
# the GPL can be found in doc/GPL-license.txt in this distribution, or
# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
Bryan O'Sullivan
committed
#
# There are special exceptions to the terms and conditions of the GPL as
# it is applied to this Source Code. View the full text of the exception
# in the file doc/FLOSS-exception.txt in this software distribution, or
# online at
# http://secondlifegrid.net/programs/open_source/licensing/flossexception
Bryan O'Sullivan
committed
#
# By copying, modifying or distributing this software, you acknowledge
# that you have read and understood your obligations described above,
# and agree to abide by those obligations.
#
# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
# COMPLETENESS OR PERFORMANCE.
# $/LicenseInfo$
import errno
import getopt
import os
import random
import re
import shutil
import socket
import sys
import commands
Nathan Wilcox
committed
import subprocess
Bryan O'Sullivan
committed
class CommandError(Exception):
pass
def mkdir(path):
try:
os.mkdir(path)
return path
except OSError, err:
if err.errno != errno.EEXIST or not os.path.isdir(path):
raise
Aaron Brashears
committed
def getcwd():
cwd = os.getcwd()
if 'a' <= cwd[0] <= 'z' and cwd[1] == ':':
# CMake wants DOS drive letters to be in uppercase. The above
# condition never asserts on platforms whose full path names
# always begin with a slash, so we don't need to test whether
# we are running on Windows.
cwd = cwd[0].upper() + cwd[1:]
return cwd
Bryan O'Sullivan
committed
def quote(opts):
return '"' + '" "'.join([ opt.replace('"', '') for opt in opts ]) + '"'
class PlatformSetup(object):
generator = None
build_types = {}
for t in ('Debug', 'Release', 'RelWithDebInfo'):
build_types[t.lower()] = t
build_type = build_types['relwithdebinfo']
standalone = 'OFF'
unattended = 'OFF'
Kyle McKay
committed
distcc = True
Bryan O'Sullivan
committed
cmake_opts = []
Christian Goetze
committed
word_size = 32
Bryan O'Sullivan
committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def __init__(self):
self.script_dir = os.path.realpath(
os.path.dirname(__import__(__name__).__file__))
def os(self):
'''Return the name of the OS.'''
raise NotImplemented('os')
def arch(self):
'''Return the CPU architecture.'''
return None
def platform(self):
'''Return a stringified two-tuple of the OS name and CPU
architecture.'''
ret = self.os()
if self.arch():
ret += '-' + self.arch()
return ret
def build_dirs(self):
'''Return the top-level directories in which builds occur.
This can return more than one directory, e.g. if doing a
32-bit viewer and server build on Linux.'''
return ['build-' + self.platform()]
def cmake_commandline(self, src_dir, build_dir, opts, simple):
'''Return the command line to run cmake with.'''
args = dict(
dir=src_dir,
generator=self.generator,
opts=quote(opts),
standalone=self.standalone,
unattended=self.unattended,
Christian Goetze
committed
word_size=self.word_size,
Bryan O'Sullivan
committed
type=self.build_type.upper(),
)
#if simple:
# return 'cmake %(opts)s %(dir)r' % args
Bryan O'Sullivan
committed
return ('cmake -DCMAKE_BUILD_TYPE:STRING=%(type)s '
'-DSTANDALONE:BOOL=%(standalone)s '
'-DUNATTENDED:BOOL=%(unattended)s '
Christian Goetze
committed
'-DWORD_SIZE:STRING=%(word_size)s '
Bryan O'Sullivan
committed
'-G %(generator)r %(opts)s %(dir)r' % args)
def run_cmake(self, args=[]):
'''Run cmake.'''
# do a sanity check to make sure we have a generator
if not hasattr(self, 'generator'):
raise "No generator available for '%s'" % (self.__name__,)
Aaron Brashears
committed
cwd = getcwd()
Bryan O'Sullivan
committed
created = []
try:
for d in self.build_dirs():
simple = True
if mkdir(d):
created.append(d)
simple = False
try:
os.chdir(d)
cmd = self.cmake_commandline(cwd, d, args, simple)
Bryan O'Sullivan
committed
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
print 'Running %r in %r' % (cmd, d)
self.run(cmd, 'cmake')
finally:
os.chdir(cwd)
except:
# If we created a directory in which to run cmake and
# something went wrong, the directory probably just
# contains garbage, so delete it.
os.chdir(cwd)
for d in created:
print 'Cleaning %r' % d
shutil.rmtree(d)
raise
def parse_build_opts(self, arguments):
opts, targets = getopt.getopt(arguments, 'o:', ['option='])
build_opts = []
for o, a in opts:
if o in ('-o', '--option'):
build_opts.append(a)
return build_opts, targets
def run_build(self, opts, targets):
'''Build the default targets for this platform.'''
raise NotImplemented('run_build')
def cleanup(self):
'''Delete all build directories.'''
cleaned = 0
for d in self.build_dirs():
if os.path.isdir(d):
print 'Cleaning %r' % d
shutil.rmtree(d)
cleaned += 1
if not cleaned:
print 'Nothing to clean up!'
def is_internal_tree(self):
'''Indicate whether we are building in an internal source tree.'''
return os.path.isdir(os.path.join(self.script_dir, 'newsim'))
def find_in_path(self, name, defval=None, basename=False):
for ext in self.exe_suffixes:
name_ext = name + ext
if os.sep in name_ext:
path = os.path.abspath(name_ext)
if os.access(path, os.X_OK):
return [basename and os.path.basename(path) or path]
for p in os.getenv('PATH', self.search_path).split(os.pathsep):
path = os.path.join(p, name_ext)
if os.access(path, os.X_OK):
return [basename and os.path.basename(path) or path]
if defval:
return [defval]
return []
Bryan O'Sullivan
committed
class UnixSetup(PlatformSetup):
'''Generic Unixy build instructions.'''
search_path = '/usr/bin:/usr/local/bin'
exe_suffixes = ('',)
Bryan O'Sullivan
committed
def __init__(self):
super(UnixSetup, self).__init__()
self.generator = 'Unix Makefiles'
def os(self):
return 'unix'
def arch(self):
cpu = os.uname()[-1]
Paul Oppenheim
committed
if cpu.endswith('386'):
cpu = 'i386'
elif cpu.endswith('86'):
Bryan O'Sullivan
committed
cpu = 'i686'
elif cpu in ('athlon',):
cpu = 'i686'
elif cpu == 'Power Macintosh':
Paul Oppenheim
committed
cpu = 'ppc'
Christian Goetze
committed
elif cpu == 'x86_64' and self.word_size == 32:
cpu = 'i686'
Bryan O'Sullivan
committed
return cpu
Andrew Meadows
committed
def run(self, command, name=None):
'''Run a program. If the program fails, raise an exception.'''
brad kittenbrink
committed
sys.stdout.flush()
ret = os.system(command)
if ret:
if name is None:
name = command.split(None, 1)[0]
if os.WIFEXITED(ret):
st = os.WEXITSTATUS(ret)
if st == 127:
event = 'was not found'
else:
event = 'exited with status %d' % st
elif os.WIFSIGNALED(ret):
event = 'was killed by signal %d' % os.WTERMSIG(ret)
else:
event = 'died unexpectedly (!?) with 16-bit status %d' % ret
raise CommandError('the command %r %s' %
(name, event))
Bryan O'Sullivan
committed
class LinuxSetup(UnixSetup):
def __init__(self):
super(LinuxSetup, self).__init__()
Andrew Meadows
committed
try:
self.debian_sarge = open('/etc/debian_version').read().strip() == '3.1'
except:
self.debian_sarge = False
Bryan O'Sullivan
committed
def os(self):
return 'linux'
def build_dirs(self):
Christian Goetze
committed
# Only build the server code if we have it.
platform_build = '%s-%s' % (self.platform(), self.build_type.lower())
Bryan O'Sullivan
committed
if self.arch() == 'i686' and self.is_internal_tree():
return ['viewer-' + platform_build, 'server-' + platform_build]
Andrew Meadows
committed
elif self.arch() == 'x86_64' and self.is_internal_tree():
# the viewer does not build in 64bit -- kdu5 issues
# we can either use openjpeg, or overhaul our viewer to handle kdu5 or higher
# doug knows about kdu issues
return ['server-' + platform_build]
Bryan O'Sullivan
committed
else:
return ['viewer-' + platform_build]
Bryan O'Sullivan
committed
def cmake_commandline(self, src_dir, build_dir, opts, simple):
args = dict(
dir=src_dir,
generator=self.generator,
opts=quote(opts),
standalone=self.standalone,
unattended=self.unattended,
type=self.build_type.upper(),
Christian Goetze
committed
project_name=self.project_name,
word_size=self.word_size,
Bryan O'Sullivan
committed
)
if not self.is_internal_tree():
args.update({'cxx':'g++', 'server':'OFF', 'viewer':'ON'})
Bryan O'Sullivan
committed
else:
Kyle McKay
committed
if self.distcc:
distcc = self.find_in_path('distcc')
baseonly = True
else:
distcc = []
baseonly = False
Bryan O'Sullivan
committed
if 'server' in build_dir:
Andrew Meadows
committed
gcc = distcc + self.find_in_path(
self.debian_sarge and 'g++-3.3' or 'g++-4.1',
'g++', baseonly)
args.update({'cxx': ' '.join(gcc), 'server': 'ON',
'viewer': 'OFF'})
Bryan O'Sullivan
committed
else:
Kyle McKay
committed
gcc41 = distcc + self.find_in_path('g++-4.1', 'g++', baseonly)
Andrew Meadows
committed
args.update({'cxx': ' '.join(gcc41),
'server': 'OFF',
'viewer': 'ON'})
Bryan O'Sullivan
committed
cmd = (('cmake -DCMAKE_BUILD_TYPE:STRING=%(type)s '
'-G %(generator)r -DSERVER:BOOL=%(server)s '
'-DVIEWER:BOOL=%(viewer)s -DSTANDALONE:BOOL=%(standalone)s '
'-DUNATTENDED:BOOL=%(unattended)s '
Christian Goetze
committed
'-DWORD_SIZE:STRING=%(word_size)s '
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
Bryan O'Sullivan
committed
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
'%(opts)s %(dir)r')
% args)
if 'CXX' not in os.environ:
args.update({'cmd':cmd})
cmd = ('CXX=%(cxx)r %(cmd)s' % args)
return cmd
def run_build(self, opts, targets):
job_count = None
for i in range(len(opts)):
if opts[i].startswith('-j'):
try:
job_count = int(opts[i][2:])
except ValueError:
try:
job_count = int(opts[i+1])
except ValueError:
job_count = True
def get_cpu_count():
count = 0
for line in open('/proc/cpuinfo'):
if re.match(r'processor\s*:', line):
count += 1
return count
def localhost():
count = get_cpu_count()
return 'localhost/' + str(count), count
def get_distcc_hosts():
try:
hosts = []
name = os.getenv('DISTCC_DIR', '/etc/distcc') + '/hosts'
for l in open(name):
l = l[l.find('#')+1:].strip()
if l: hosts.append(l)
return hosts
except IOError:
return (os.getenv('DISTCC_HOSTS', '').split() or
[localhost()[0]])
def count_distcc_hosts():
cpus = 0
hosts = 0
for host in get_distcc_hosts():
m = re.match(r'.*/(\d+)', host)
hosts += 1
cpus += m and int(m.group(1)) or 1
return hosts, cpus
Christian Goetze
committed
def mk_distcc_hosts(basename, range, num_cpus):
Bryan O'Sullivan
committed
'''Generate a list of LL-internal machines to build on.'''
loc_entry, cpus = localhost()
hosts = [loc_entry]
dead = []
stations = [s for s in xrange(range) if s not in dead]
Bryan O'Sullivan
committed
random.shuffle(stations)
Christian Goetze
committed
hosts += ['%s%d.lindenlab.com/%d,lzo' % (basename, s, num_cpus) for s in stations]
Bryan O'Sullivan
committed
cpus += 2 * len(stations)
return ' '.join(hosts), cpus
if job_count is None:
hosts, job_count = count_distcc_hosts()
if hosts == 1:
if hostname.startswith('station'):
Christian Goetze
committed
hosts, job_count = mk_distcc_hosts('station', 36, 2)
os.environ['DISTCC_HOSTS'] = hosts
if hostname.startswith('eniac'):
Christian Goetze
committed
hosts, job_count = mk_distcc_hosts('eniac', 71, 2)
os.environ['DISTCC_HOSTS'] = hosts
if hostname.startswith('build'):
max_jobs = 6
else:
max_jobs = 12
if job_count > max_jobs:
job_count = max_jobs;
Bryan O'Sullivan
committed
opts.extend(['-j', str(job_count)])
if targets:
targets = ' '.join(targets)
else:
targets = 'all'
for d in self.build_dirs():
cmd = 'make -C %r %s %s' % (d, ' '.join(opts), targets)
print 'Running %r' % cmd
self.run(cmd)
class DarwinSetup(UnixSetup):
def __init__(self):
super(DarwinSetup, self).__init__()
self.generator = 'Xcode'
def os(self):
return 'darwin'
def arch(self):
Paul Oppenheim
committed
return 'universal'
else:
return UnixSetup.arch(self)
Bryan O'Sullivan
committed
def cmake_commandline(self, src_dir, build_dir, opts, simple):
args = dict(
dir=src_dir,
generator=self.generator,
opts=quote(opts),
standalone=self.standalone,
Christian Goetze
committed
word_size=self.word_size,
Bryan O'Sullivan
committed
unattended=self.unattended,
project_name=self.project_name,
Christian Goetze
committed
type=self.build_type.upper(),
Bryan O'Sullivan
committed
)
Paul Oppenheim
committed
args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
#if simple:
# return 'cmake %(opts)s %(dir)r' % args
Bryan O'Sullivan
committed
return ('cmake -G %(generator)r '
'-DCMAKE_BUILD_TYPE:STRING=%(type)s '
'-DSTANDALONE:BOOL=%(standalone)s '
'-DUNATTENDED:BOOL=%(unattended)s '
Christian Goetze
committed
'-DWORD_SIZE:STRING=%(word_size)s '
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
Paul Oppenheim
committed
'%(universal)s '
'%(opts)s %(dir)r' % args)
Bryan O'Sullivan
committed
def run_build(self, opts, targets):
Aaron Brashears
committed
cwd = getcwd()
Bryan O'Sullivan
committed
if targets:
targets = ' '.join(['-target ' + repr(t) for t in targets])
else:
targets = ''
brad kittenbrink
committed
cmd = ('xcodebuild -configuration %s %s %s | grep -v "^[[:space:]]*setenv" ; exit ${PIPESTATUS[0]}' %
Bryan O'Sullivan
committed
(self.build_type, ' '.join(opts), targets))
for d in self.build_dirs():
try:
os.chdir(d)
print 'Running %r in %r' % (cmd, d)
self.run(cmd)
finally:
os.chdir(cwd)
class WindowsSetup(PlatformSetup):
gens = {
'vc71' : {
'gen' : r'Visual Studio 7 .NET 2003',
'ver' : r'7.1'
},
'vc80' : {
'gen' : r'Visual Studio 8 2005',
'ver' : r'8.0'
},
'vc90' : {
'gen' : r'Visual Studio 9 2008',
'ver' : r'9.0'
Bryan O'Sullivan
committed
}
}
gens['vs2003'] = gens['vc71']
gens['vs2005'] = gens['vc80']
gens['vs2008'] = gens['vc90']
Bryan O'Sullivan
committed
search_path = r'C:\windows'
exe_suffixes = ('.exe', '.bat', '.com')
def __init__(self):
super(WindowsSetup, self).__init__()
self._generator = None
Bryan O'Sullivan
committed
self.incredibuild = False
def _get_generator(self):
if self._generator is None:
Mark Palange
committed
for version in 'vc80 vc90 vc71'.split():
if self.find_visual_studio(version):
self._generator = version
print 'Building with ', self.gens[version]['gen']
break
else:
print >> sys.stderr, 'Cannot find a Visual Studio installation!'
sys.exit(1)
return self._generator
def _set_generator(self, gen):
self._generator = gen
generator = property(_get_generator, _set_generator)
Bryan O'Sullivan
committed
def os(self):
return 'win32'
def build_dirs(self):
return ['build-' + self.generator]
def cmake_commandline(self, src_dir, build_dir, opts, simple):
args = dict(
dir=src_dir,
generator=self.gens[self.generator.lower()]['gen'],
opts=quote(opts),
standalone=self.standalone,
unattended=self.unattended,
Christian Goetze
committed
project_name=self.project_name,
word_size=self.word_size,
Bryan O'Sullivan
committed
)
#if simple:
# return 'cmake %(opts)s "%(dir)s"' % args
Bryan O'Sullivan
committed
return ('cmake -G "%(generator)s" '
'-DSTANDALONE:BOOL=%(standalone)s '
'-DUNATTENDED:BOOL=%(unattended)s '
Christian Goetze
committed
'-DWORD_SIZE:STRING=%(word_size)s '
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
Bryan O'Sullivan
committed
'%(opts)s "%(dir)s"' % args)
def get_HKLM_registry_value(self, key_str, value_str):
import _winreg
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
key = _winreg.OpenKey(reg, key_str)
value = _winreg.QueryValueEx(key, value_str)[0]
print 'Found: %s' % value
return value
def find_visual_studio(self, gen=None):
if gen is None:
gen = self._generator
gen = gen.lower()
value_str = (r'EnvironmentDirectory')
key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VS' %
self.gens[gen]['ver'])
print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
(key_str, value_str))
Bryan O'Sullivan
committed
try:
return self.get_HKLM_registry_value(key_str, value_str)
Bryan O'Sullivan
committed
except WindowsError, err:
key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
self.gens[gen]['ver'])
try:
return self.get_HKLM_registry_value(key_str, value_str)
except:
print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
def get_build_cmd(self):
if self.incredibuild:
config = self.build_type
if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]:
config = '\"%s|Win32\"' % config
Nathan Wilcox
committed
executable = 'buildconsole'
Nathan Wilcox
committed
cmd = "%(bin)s %(prj)s.sln /build /cfg=%(cfg)s" % {'prj': self.project_name, 'cfg': config, 'bin': executable}
return (executable, cmd)
Bryan O'Sullivan
committed
# devenv.com is CLI friendly, devenv.exe... not so much.
Nathan Wilcox
committed
executable = '%sdevenv.com' % (self.find_visual_studio(),)
cmd = ('"%s" %s.sln /build %s' %
(executable, self.project_name, self.build_type))
return (executable, cmd)
Bryan O'Sullivan
committed
def run(self, command, name=None, retry_on=None, retries=1):
Bryan O'Sullivan
committed
'''Run a program. If the program fails, raise an exception.'''
Nathan Wilcox
committed
assert name is not None, 'On windows an executable path must be given in name. [DEV-44838]'
Nathan Wilcox
committed
if os.path.isfile(name):
path = name
else:
path = self.find_in_path(name)[0]
while retries:
retries = retries - 1
print "develop.py tries to run:", command
Nathan Wilcox
committed
ret = subprocess.call(command, executable=path)
if ret == 0:
break
else:
Nathan Wilcox
committed
error = 'exited with status %d' % ret
if retry_on is not None and retry_on == ret:
print "Retrying... the command %r %s" % (name, error)
else:
raise CommandError('the command %r %s' % (name, error))
Bryan O'Sullivan
committed
def run_cmake(self, args=[]):
'''Override to add the vstool.exe call after running cmake.'''
PlatformSetup.run_cmake(self, args)
if self.unattended == 'OFF':
self.run_vstool()
def run_vstool(self):
for build_dir in self.build_dirs():
stamp = os.path.join(build_dir, 'vstool.txt')
try:
prev_build = open(stamp).read().strip()
except IOError:
prev_build = ''
if prev_build == self.build_type:
# Only run vstool if the build type has changed.
continue
Nathan Wilcox
committed
executable = os.path.join('tools','vstool','VSTool.exe')
vstool_cmd = (executable +
' --solution ' +
os.path.join(build_dir,'SecondLife.sln') +
' --config ' + self.build_type +
' --startup secondlife-bin')
print 'Running %r in %r' % (vstool_cmd, getcwd())
Nathan Wilcox
committed
self.run(vstool_cmd, name=executable)
print >> open(stamp, 'w'), self.build_type
Bryan O'Sullivan
committed
def run_build(self, opts, targets):
for t in targets:
assert t.strip(), 'Unexpected empty targets: ' + repr(targets)
Aaron Brashears
committed
cwd = getcwd()
Nathan Wilcox
committed
executable, build_cmd = self.get_build_cmd()
Bryan O'Sullivan
committed
for d in self.build_dirs():
try:
os.chdir(d)
if targets:
for t in targets:
cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts))
print 'Running %r in %r' % (cmd, d)
Nathan Wilcox
committed
self.run(cmd, name=executable, retry_on=4, retries=3)
Bryan O'Sullivan
committed
else:
cmd = '%s %s' % (build_cmd, ' '.join(opts))
print 'Running %r in %r' % (cmd, d)
Nathan Wilcox
committed
self.run(cmd, name=executable, retry_on=4, retries=3)
Bryan O'Sullivan
committed
finally:
os.chdir(cwd)
class CygwinSetup(WindowsSetup):
def __init__(self):
super(CygwinSetup, self).__init__()
Bryan O'Sullivan
committed
def cmake_commandline(self, src_dir, build_dir, opts, simple):
dos_dir = commands.getoutput("cygpath -w %s" % src_dir)
Bryan O'Sullivan
committed
args = dict(
dir=dos_dir,
generator=self.gens[self.generator.lower()]['gen'],
opts=quote(opts),
standalone=self.standalone,
unattended=self.unattended,
Christian Goetze
committed
project_name=self.project_name,
word_size=self.word_size,
Bryan O'Sullivan
committed
)
#if simple:
# return 'cmake %(opts)s "%(dir)s"' % args
Bryan O'Sullivan
committed
return ('cmake -G "%(generator)s" '
'-DUNATTENDED:BOOl=%(unattended)s '
'-DSTANDALONE:BOOL=%(standalone)s '
Christian Goetze
committed
'-DWORD_SIZE:STRING=%(word_size)s '
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
Bryan O'Sullivan
committed
'%(opts)s "%(dir)s"' % args)
setup_platform = {
'darwin': DarwinSetup,
'linux2': LinuxSetup,
'win32' : WindowsSetup,
'cygwin' : CygwinSetup
}
usage_msg = '''
Usage: develop.py [options] [command [command-options]]
Bryan O'Sullivan
committed
Options:
-h | --help print this help message
--standalone build standalone, without Linden prebuild libraries
--unattended build unattended, do not invoke any tools requiring
a human response
--universal build a universal binary on Mac OS X (unsupported)
Bryan O'Sullivan
committed
-t | --type=NAME build type ("Debug", "Release", or "RelWithDebInfo")
Christian Goetze
committed
-m32 | -m64 build architecture (32-bit or 64-bit)
Kyle McKay
committed
-N | --no-distcc disable use of distcc
Bryan O'Sullivan
committed
-G | --generator=NAME generator name
Windows: VC71 or VS2003 (default), VC80 (VS2005) or
VC90 (VS2008)
Bryan O'Sullivan
committed
Mac OS X: Xcode (default), Unix Makefiles
Linux: Unix Makefiles (default), KDevelop3
-p | --project=NAME set the root project name. (Doesn't effect makefiles)
Bryan O'Sullivan
committed
Commands:
build configure and build default target
clean delete all build directories, does not affect sources
configure configure project by running cmake (default command if none given)
Bryan O'Sullivan
committed
Command-options for "configure":
We use cmake variables to change the build configuration.
-DSERVER:BOOL=OFF Don't configure simulator/dataserver/etc
-DVIEWER:BOOL=OFF Don't configure the viewer
-DPACKAGE:BOOL=ON Create "package" target to make installers
-DLOCALIZESETUP:BOOL=ON Create one win_setup target per supported language
Examples:
Set up a viewer-only project for your system:
develop.py configure -DSERVER:BOOL=OFF
Kyle Ambroff
committed
Set up a Visual Studio 2005 project with "package" target:
Kyle Ambroff
committed
develop.py -G vc80 configure -DPACKAGE:BOOL=ON
Bryan O'Sullivan
committed
'''
def main(arguments):
if os.getenv('DISTCC_DIR') is None:
distcc_dir = os.path.join(getcwd(), '.distcc')
if not os.path.exists(distcc_dir):
os.mkdir(distcc_dir)
print "setting DISTCC_DIR to %s" % distcc_dir
os.environ['DISTCC_DIR'] = distcc_dir
else:
print "DISTCC_DIR is set to %s" % os.getenv('DISTCC_DIR')
Bryan O'Sullivan
committed
setup = setup_platform[sys.platform]()
try:
opts, args = getopt.getopt(
arguments,
Christian Goetze
committed
'?hNt:p:G:m:',
['help', 'standalone', 'no-distcc', 'unattended', 'universal', 'type=', 'incredibuild', 'generator=', 'project='])
Bryan O'Sullivan
committed
except getopt.GetoptError, err:
print >> sys.stderr, 'Error:', err
print >> sys.stderr, """
Note: You must pass -D options to cmake after the "configure" command
For example: develop.py configure -DSERVER:BOOL=OFF"""
print >> sys.stderr, usage_msg.strip()
Bryan O'Sullivan
committed
sys.exit(1)
for o, a in opts:
if o in ('-?', '-h', '--help'):
print usage_msg.strip()
sys.exit(0)
elif o in ('--standalone',):
Bryan O'Sullivan
committed
elif o in ('--unattended',):
elif o in ('--universal',):
setup.universal = 'ON'
Christian Goetze
committed
elif o in ('-m',):
if a in ('32', '64'):
setup.word_size = int(a)
else:
print >> sys.stderr, 'Error: unknown word size', repr(a)
print >> sys.stderr, 'Supported word sizes: 32, 64'
sys.exit(1)
Bryan O'Sullivan
committed
elif o in ('-t', '--type'):
try:
setup.build_type = setup.build_types[a.lower()]
except KeyError:
print >> sys.stderr, 'Error: unknown build type', repr(a)
print >> sys.stderr, 'Supported build types:'
types = setup.build_types.values()
types.sort()
for t in types:
print ' ', t
sys.exit(1)
elif o in ('-G', '--generator'):
setup.generator = a
Kyle McKay
committed
elif o in ('-N', '--no-distcc'):
setup.distcc = False
elif o in ('-p', '--project'):
setup.project_name = a
Bryan O'Sullivan
committed
elif o in ('--incredibuild'):
setup.incredibuild = True
else:
print >> sys.stderr, 'INTERNAL ERROR: unhandled option', repr(o)
sys.exit(1)
if not args:
setup.run_cmake()
return
try:
cmd = args.pop(0)
if cmd in ('cmake', 'configure'):
setup.run_cmake(args)
elif cmd == 'build':
for d in setup.build_dirs():
if not os.path.exists(d):
raise CommandError('run "develop.py cmake" first')
setup.run_cmake()
opts, targets = setup.parse_build_opts(args)
setup.run_build(opts, targets)
elif cmd == 'clean':
if args:
raise CommandError('clean takes no arguments')
setup.cleanup()
else:
print >> sys.stderr, 'Error: unknown subcommand', repr(cmd)
Bryan O'Sullivan
committed
print >> sys.stderr, "(run 'develop.py --help' for help)"
sys.exit(1)
except getopt.GetoptError, err:
print >> sys.stderr, 'Error with %r subcommand: %s' % (cmd, err)
sys.exit(1)
Bryan O'Sullivan
committed
if __name__ == '__main__':
try:
main(sys.argv[1:])
except CommandError, err:
print >> sys.stderr, 'Error:', err
sys.exit(1)