summaryrefslogtreecommitdiff
path: root/indra/develop.py
diff options
context:
space:
mode:
Diffstat (limited to 'indra/develop.py')
-rwxr-xr-xindra/develop.py194
1 files changed, 128 insertions, 66 deletions
diff --git a/indra/develop.py b/indra/develop.py
index 1d7ac42c9c..36c947327a 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -4,31 +4,25 @@
# @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.
-#
+# $LicenseInfo:firstyear=2007&license=viewerlgpl$
# 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
+# Copyright (C) 2010, Linden Research, Inc.
#
-# 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
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation;
+# version 2.1 of the License only.
#
-# 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.
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
#
-# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
-# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
-# COMPLETENESS OR PERFORMANCE.
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
# $/LicenseInfo$
@@ -41,6 +35,7 @@ import shutil
import socket
import sys
import commands
+import subprocess
class CommandError(Exception):
pass
@@ -76,10 +71,12 @@ class PlatformSetup(object):
build_type = build_types['relwithdebinfo']
standalone = 'OFF'
unattended = 'OFF'
+ universal = 'OFF'
project_name = 'SecondLife'
distcc = True
cmake_opts = []
word_size = 32
+ using_express = False
def __init__(self):
self.script_dir = os.path.realpath(
@@ -238,6 +235,7 @@ class UnixSetup(PlatformSetup):
def run(self, command, name=None):
'''Run a program. If the program fails, raise an exception.'''
+ sys.stdout.flush()
ret = os.system(command)
if ret:
if name is None:
@@ -383,16 +381,20 @@ class LinuxSetup(UnixSetup):
if job_count is None:
hosts, job_count = count_distcc_hosts()
+ hostname = socket.gethostname()
if hosts == 1:
- hostname = socket.gethostname()
if hostname.startswith('station'):
hosts, job_count = mk_distcc_hosts('station', 36, 2)
os.environ['DISTCC_HOSTS'] = hosts
if hostname.startswith('eniac'):
hosts, job_count = mk_distcc_hosts('eniac', 71, 2)
os.environ['DISTCC_HOSTS'] = hosts
- if job_count > 12:
- job_count = 12;
+ if hostname.startswith('build'):
+ max_jobs = 6
+ else:
+ max_jobs = 12
+ if job_count > max_jobs:
+ job_count = max_jobs;
opts.extend(['-j', str(job_count)])
if targets:
@@ -415,7 +417,7 @@ class DarwinSetup(UnixSetup):
return 'darwin'
def arch(self):
- if self.unattended == 'ON':
+ if self.universal == 'ON':
return 'universal'
else:
return UnixSetup.arch(self)
@@ -429,10 +431,10 @@ class DarwinSetup(UnixSetup):
word_size=self.word_size,
unattended=self.unattended,
project_name=self.project_name,
- universal='',
+ universal=self.universal,
type=self.build_type.upper(),
)
- if self.unattended == 'ON':
+ if self.universal == 'ON':
args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
#if simple:
# return 'cmake %(opts)s %(dir)r' % args
@@ -451,9 +453,7 @@ class DarwinSetup(UnixSetup):
targets = ' '.join(['-target ' + repr(t) for t in targets])
else:
targets = ''
- # cmd = ('xcodebuild -parallelizeTargets ' # parallelizeTargets is suspected of non-deterministic build failures. + poppy 2009-06-05
- cmd = ('xcodebuild '
- '-configuration %s %s %s' %
+ cmd = ('xcodebuild -configuration %s %s %s | grep -v "^[[:space:]]*setenv" ; exit ${PIPESTATUS[0]}' %
(self.build_type, ' '.join(opts), targets))
for d in self.build_dirs():
try:
@@ -498,9 +498,17 @@ class WindowsSetup(PlatformSetup):
self._generator = version
print 'Building with ', self.gens[version]['gen']
break
- else:
- print >> sys.stderr, 'Cannot find a Visual Studio installation!'
- eys.exit(1)
+ else:
+ print >> sys.stderr, 'Cannot find a Visual Studio installation, testing for express editions'
+ for version in 'vc80 vc90 vc71'.split():
+ if self.find_visual_studio_express(version):
+ self._generator = version
+ self.using_express = True
+ print 'Building with ', self.gens[version]['gen'] , "Express edition"
+ break
+ else:
+ print >> sys.stderr, 'Cannot find any Visual Studio installation'
+ sys.exit(1)
return self._generator
def _set_generator(self, gen):
@@ -563,37 +571,82 @@ class WindowsSetup(PlatformSetup):
return ''
+ def find_visual_studio_express(self, gen=None):
+ if gen is None:
+ gen = self._generator
+ gen = gen.lower()
+ try:
+ import _winreg
+ key_str = (r'SOFTWARE\Microsoft\VCEXpress\%s\Setup\VC' %
+ self.gens[gen]['ver'])
+ value_str = (r'ProductDir')
+ print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
+ (key_str, value_str))
+ print key_str
+
+ reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
+ key = _winreg.OpenKey(reg, key_str)
+ value = _winreg.QueryValueEx(key, value_str)[0]+"IDE"
+ print 'Found: %s' % value
+ return value
+ except WindowsError, err:
+ print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
+ return ''
+
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
- return "buildconsole %s.sln /build %s" % (self.project_name, config)
+ executable = 'buildconsole'
+ cmd = "%(bin)s %(prj)s.sln /build /cfg=%(cfg)s" % {'prj': self.project_name, 'cfg': config, 'bin': executable}
+ return (executable, cmd)
+
+ environment = self.find_visual_studio()
+ if environment == '':
+ environment = self.find_visual_studio_express()
+ if environment == '':
+ print >> sys.stderr, "Something went very wrong during build stage, could not find a Visual Studio installation."
+ else:
+ build_dirs=self.build_dirs();
+ print >> sys.stderr, "\nSolution generation complete, it can can now be found in:", build_dirs[0]
+ print >> sys.stderr, "\nPlease see https://wiki.secondlife.com/wiki/Microsoft_Visual_Studio#Extra_steps_for_Visual_Studio_Express_editions for express specific information"
+ exit(0)
# devenv.com is CLI friendly, devenv.exe... not so much.
- return ('"%sdevenv.com" %s.sln /build %s' %
- (self.find_visual_studio(), self.project_name, self.build_type))
+ executable = '%sdevenv.com' % (self.find_visual_studio(),)
+ cmd = ('"%s" %s.sln /build %s' %
+ (executable, self.project_name, self.build_type))
+ return (executable, cmd)
- def run(self, command, name=None):
+ def run(self, command, name=None, retry_on=None, retries=1):
'''Run a program. If the program fails, raise an exception.'''
- ret = os.system(command)
- if ret:
- if name is None:
- name = command.split(None, 1)[0]
- path = self.find_in_path(name)
- if not path:
- ret = 'was not found'
+ assert name is not None, 'On windows an executable path must be given in name. [DEV-44838]'
+ 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
+ ret = subprocess.call(command, executable=path)
+ print "got ret", ret, "from", command
+ if ret == 0:
+ break
else:
- ret = 'exited with status %d' % ret
- raise CommandError('the command %r %s' %
- (name, ret))
+ 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))
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()
+ if self.using_express == False:
+ self.run_vstool()
def run_vstool(self):
for build_dir in self.build_dirs():
@@ -605,18 +658,21 @@ class WindowsSetup(PlatformSetup):
if prev_build == self.build_type:
# Only run vstool if the build type has changed.
continue
- vstool_cmd = (os.path.join('tools','vstool','VSTool.exe') +
+ 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())
- self.run(vstool_cmd)
+ self.run(vstool_cmd, name=executable)
print >> open(stamp, 'w'), self.build_type
def run_build(self, opts, targets):
+ for t in targets:
+ assert t.strip(), 'Unexpected empty targets: ' + repr(targets)
cwd = getcwd()
- build_cmd = self.get_build_cmd()
+ executable, build_cmd = self.get_build_cmd()
for d in self.build_dirs():
try:
@@ -625,11 +681,11 @@ class WindowsSetup(PlatformSetup):
for t in targets:
cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts))
print 'Running %r in %r' % (cmd, d)
- self.run(cmd)
+ self.run(cmd, name=executable, retry_on=4, retries=3)
else:
cmd = '%s %s' % (build_cmd, ' '.join(opts))
print 'Running %r in %r' % (cmd, d)
- self.run(cmd)
+ self.run(cmd, name=executable, retry_on=4, retries=3)
finally:
os.chdir(cwd)
@@ -674,6 +730,7 @@ Options:
--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)
-t | --type=NAME build type ("Debug", "Release", or "RelWithDebInfo")
-m32 | -m64 build architecture (32-bit or 64-bit)
-N | --no-distcc disable use of distcc
@@ -685,9 +742,10 @@ Options:
-p | --project=NAME set the root project name. (Doesn't effect makefiles)
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)
+ build configure and build default target
+ clean delete all build directories, does not affect sources
+ configure configure project by running cmake (default if none given)
+ printbuilddirs print the build directory that will be used
Command-options for "configure":
We use cmake variables to change the build configuration.
@@ -705,21 +763,12 @@ Examples:
'''
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')
-
setup = setup_platform[sys.platform]()
try:
opts, args = getopt.getopt(
arguments,
'?hNt:p:G:m:',
- ['help', 'standalone', 'no-distcc', 'unattended', 'type=', 'incredibuild', 'generator=', 'project='])
+ ['help', 'standalone', 'no-distcc', 'unattended', 'universal', 'type=', 'incredibuild', 'generator=', 'project='])
except getopt.GetoptError, err:
print >> sys.stderr, 'Error:', err
print >> sys.stderr, """
@@ -736,6 +785,8 @@ For example: develop.py configure -DSERVER:BOOL=OFF"""
setup.standalone = 'ON'
elif o in ('--unattended',):
setup.unattended = 'ON'
+ elif o in ('--universal',):
+ setup.universal = 'ON'
elif o in ('-m',):
if a in ('32', '64'):
setup.word_size = int(a)
@@ -773,6 +824,14 @@ For example: develop.py configure -DSERVER:BOOL=OFF"""
if cmd in ('cmake', 'configure'):
setup.run_cmake(args)
elif cmd == 'build':
+ 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')
for d in setup.build_dirs():
if not os.path.exists(d):
raise CommandError('run "develop.py cmake" first')
@@ -783,6 +842,9 @@ For example: develop.py configure -DSERVER:BOOL=OFF"""
if args:
raise CommandError('clean takes no arguments')
setup.cleanup()
+ elif cmd == 'printbuilddirs':
+ for d in setup.build_dirs():
+ print >> sys.stdout, d
else:
print >> sys.stderr, 'Error: unknown subcommand', repr(cmd)
print >> sys.stderr, "(run 'develop.py --help' for help)"