diff options
Diffstat (limited to 'indra/develop.py')
-rwxr-xr-x | indra/develop.py | 194 |
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)" |