From 7a5a907f4918b20cf77d2a3ed33ef5e6d8c3844a Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Thu, 19 May 2011 00:40:19 -0500
Subject: Ported viewer_info.py and BuildVersion.cmake from Kokua.
viewer_info.py provides a way to easily query the viewer name and
version (from viewerinfo.cpp). It replaces build_version.py, which has
been removed. BuildVersion.cmake has been updated to use
viewer_info.py instead of build_version.py.
---
linden/scripts/build_version.py | 62 ------------------------
linden/scripts/viewer_info.py | 101 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 101 insertions(+), 62 deletions(-)
delete mode 100755 linden/scripts/build_version.py
create mode 100755 linden/scripts/viewer_info.py
(limited to 'linden/scripts')
diff --git a/linden/scripts/build_version.py b/linden/scripts/build_version.py
deleted file mode 100755
index f6b88a9..0000000
--- a/linden/scripts/build_version.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env python
-#
-# Print the build information embedded in a header file.
-#
-# Expects to be invoked from the command line with a file name and a
-# list of directories to search. The file name will be one of the
-# following:
-#
-# llversionserver.h
-# llversionviewer.h
-#
-# The directory list that follows will include indra/llcommon, where
-# these files live.
-
-import errno, os, re
-
-def get_version(filename):
- fp = open(filename)
- data = fp.read()
- fp.close()
-
- vals = {}
- m = re.search('', data)
- vals['major'] = m.group(1)
- m = re.search('', data)
- vals['minor'] = m.group(1)
- m = re.search('', data)
- vals['patch'] = m.group(1)
- m = re.search('', data)
- vals['test'] = m.group(1)
-
- version = "%(major)s.%(minor)s.%(patch)s" % vals
-
- if len(vals['test']) > 0:
- # Replace some puncuation and spaces with '-' in the test version
- vals['test'] = re.sub('[ \t:;,+/\\"\'`]+', '-', vals['test'])
- version += "-%(test)s" % vals
-
- return version
-
-
-if __name__ == '__main__':
- import sys
-
- try:
- for path in sys.argv[2:]:
- name = os.path.join(path, sys.argv[1])
- try:
- print get_version(name)
- break
- except OSError, err:
- if err.errno != errno.ENOENT:
- raise
- else:
- print >> sys.stderr, 'File not found:', sys.argv[1]
- sys.exit(1)
- except AttributeError:
- print >> sys.stderr, 'Error: malformatted file: ', name
- sys.exit(1)
- except IndexError:
- print >> sys.stderr, ('Usage: %s llversion[...].h [directories]' %
- sys.argv[0])
diff --git a/linden/scripts/viewer_info.py b/linden/scripts/viewer_info.py
new file mode 100755
index 0000000..53ea432
--- /dev/null
+++ b/linden/scripts/viewer_info.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+#
+# @file viewer_info.py
+# @author Jacek Antonelli
+# @brief Scans and prints the viewer name and/or version.
+#
+# Copyright (c) 2010, Jacek Antonelli
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#
+# Usage:
+#
+# viewer_info.py --name # viewer name (e.g. "Kokua")
+# viewer_info.py --version # viewer version (e.g. "1.0.0-RC1"
+# viewer_info.py --combined # name + version (e.g. "Kokua-1.0.0-RC1")
+#
+# You can pass multiple flags to print each thing on a separate line.
+# E.g. `viewer_info.py --name --version' will print 2 lines, e.g.:
+#
+# Kokua
+# 1.0.0-RC1
+#
+
+import errno, os, re, string, sys
+
+
+class ViewerInfo:
+
+ def __init__(self, filepath=None):
+ f = open(filepath or self.default_file())
+ data = f.read()
+ f.close()
+
+ self.name = re.search('NAME\s*=\s*"([^"]*)"', data).group(1)
+ self.major = re.search('MAJOR\s*=\s*(\d+)', data).group(1)
+ self.minor = re.search('MINOR\s*=\s*(\d+)', data).group(1)
+ self.patch = re.search('PATCH\s*=\s*(\d+)', data).group(1)
+ self.extra = re.search('EXTRA\s*=\s*"([^"]*)"', data).group(1)
+ self.bundle_id = re.search('BUNDLE_ID\s*=\s*"([^"]*)"', data).group(1)
+
+ self.version = "%s.%s.%s"%(self.major, self.minor, self.patch)
+ if len(self.extra) > 0:
+ # Replace spaces and some puncuation with '-' in extra
+ extra = re.sub('[- \t:;,!+/\\"\'`]+', '-', self.extra)
+ # Strip any leading or trailing "-"s
+ extra = string.strip(extra, '-')
+ self.version += "-" + extra
+
+ self.combined = self.name + "-" + self.version
+
+ @classmethod
+ def default_file(klass):
+ scripts_dir = sys.path[0] # directory containing this script
+ viewerinfo = os.path.join('indra', 'newview', 'viewerinfo.cpp')
+ filepath = os.path.join(scripts_dir, '..', viewerinfo)
+ return os.path.abspath(filepath)
+
+
+if __name__ == '__main__':
+
+ try:
+ info = ViewerInfo()
+ except IOError, err:
+ if err.errno == errno.ENOENT:
+ print >> sys.stderr, 'File not found:', ViewerInfo.default_file()
+ sys.exit(1)
+ else:
+ raise
+
+ args = sys.argv[1:]
+
+ if not args:
+ print "Usage: %s [--name] [--version] [--combined]"%(sys.argv[0])
+ for arg in args:
+ if '--name' == arg:
+ print info.name
+ elif '--version' == arg:
+ print info.version
+ elif '--combined' == arg:
+ print info.combined
+ elif '--bundle-id' == arg:
+ print info.bundle_id
--
cgit v1.1
From 13b3170509117b6e00e612137afab1ec7a543cd3 Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Fri, 20 May 2011 20:37:38 -0500
Subject: Ported Linux packaging system from Kokua.
Run "make package" in the build directory to create a tarball.
---
linden/scripts/package.py | 338 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 338 insertions(+)
create mode 100755 linden/scripts/package.py
(limited to 'linden/scripts')
diff --git a/linden/scripts/package.py b/linden/scripts/package.py
new file mode 100755
index 0000000..59aef79
--- /dev/null
+++ b/linden/scripts/package.py
@@ -0,0 +1,338 @@
+#!/usr/bin/env python
+#
+# @file package.py
+# @author Jacek Antonelli
+# @brief Script for generating viewer installer packages.
+#
+# Usage: package.py --build-dir=PATH [options]
+#
+# Copyright (c) 2007-2009, Linden Research, Inc.
+# Copyright (c) 2010-2011, Jacek Antonelli
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+
+import os, sys
+from viewer_info import ViewerInfo
+
+
+SCRIPTS_DIR = sys.path[0] # directory containing this script
+TOP_DIR = os.path.abspath(os.path.join(SCRIPTS_DIR,'..'))
+SOURCE_DIR = os.path.abspath(os.path.join(TOP_DIR,'indra'))
+BUILD_TYPE = "RelWithDebInfo"
+
+
+class PackagerError(Exception): pass
+
+class BadDir(PackagerError): pass
+
+class WeirdPlatform(PackagerError): pass
+
+class CmdFailed(PackagerError): pass
+
+
+def indent(text, amount=4):
+ import string
+ lines = [(' '*amount + line) for line in string.split(text, '\n')]
+ return string.join(lines, '\n')
+
+def message(*args):
+ """Prints an informational message with a leading '#'."""
+ print '# ' + ' '.join([str(arg) for arg in args])
+
+def error(*args):
+ """Prints an error message to stderr."""
+ print >> sys.stderr, 'Error: ' + ' '.join([str(arg) for arg in args])
+
+
+class Packager:
+
+ def __init__(self, build_dir, opts={}):
+ options = {'source_dir': SOURCE_DIR,
+ 'build_type': BUILD_TYPE,
+ 'verbose': False,
+ }
+ options.update(opts)
+
+ self.build_dir = os.path.abspath(build_dir)
+ self.__check_build_dir()
+
+ # Package results go in the top build directory.
+ self.dest_dir = build_dir
+
+ self.source_dir = os.path.abspath(options['source_dir'])
+ self.__check_source_dir()
+
+ self.build_type = options['build_type']
+ self.platform = self.__get_platform()
+ self.verbose = options['verbose']
+ self.viewer_info = ViewerInfo()
+
+
+ def make(self):
+ plat = self.platform
+ if plat == 'linux': self.make_linux()
+ elif plat == 'mac': self.make_mac()
+ elif plat == 'windows': self.make_windows()
+
+
+ #########
+ # LINUX #
+ #########
+
+ def make_linux(self):
+ import shutil
+
+ packaged_dir = os.path.join(self.build_dir, 'newview', 'packaged')
+
+ if not os.path.exists(packaged_dir):
+ raise BadDir("invalid build dir, has no 'newview/packaged/' "
+ 'subdirectory: %(d)r'%{'d': self.build_dir})
+
+ self.__run_command( 'Checking/fixing file permissions...',
+"""find %(d)r -type d | xargs --no-run-if-empty chmod 755;
+find %(d)r -type f -perm 0700 | xargs --no-run-if-empty chmod 0755;
+find %(d)r -type f -perm 0500 | xargs --no-run-if-empty chmod 0555;
+find %(d)r -type f -perm 0600 | xargs --no-run-if-empty chmod 0644;
+find %(d)r -type f -perm 0400 | xargs --no-run-if-empty chmod 0444;
+true""" % {'d': packaged_dir})
+
+ plat = 'Linux'
+ from platform import architecture
+ if architecture()[0] == '64bit':
+ plat += '-x86_64'
+ elif architecture()[0] == '32bit':
+ plat += '-x86'
+
+ inst_name = self.viewer_info.combined + '-' + plat
+ dest_file = os.path.join(self.dest_dir, inst_name + '.tar.bz2')
+
+ if (os.path.exists(dest_file)):
+ bkp = dest_file + ".bkp"
+ message("Renaming existing package to %r..." % bkp)
+ shutil.move(dest_file, bkp)
+
+ self.__run_command(
+ 'Creating package %r (this takes a while)...'%dest_file,
+ 'tar -C %(dir)s --numeric-owner '
+ '--transform "s,^./,%(inst_name)s/," '
+ #'--verbose --show-transformed-names '
+ '-cjf %(dest_file)s .' % { 'dir': packaged_dir,
+ 'inst_name': inst_name,
+ 'dest_file': dest_file})
+
+ message('Package complete: %r' % dest_file)
+
+
+ #######
+ # MAC #
+ #######
+
+ def make_mac(self):
+ import shutil
+
+ volname = self.viewer_info.name + " Installer"
+
+ # Where the DMG files (background image, etc.) come from.
+ dmg_src = os.path.join(self.source_dir, 'newview', 'packaging', 'mac')
+
+ # Everything that will be in the package is copied to here.
+ dmg_dst = os.path.join('/Volumes', volname)
+
+ if (os.path.exists(dmg_dst)):
+ error('%r is currently attached. Eject it and try again.' % dmg_dst)
+ sys.exit(1)
+
+ app_name = self.viewer_info.name + ".app"
+ app_orig = os.path.join(self.build_dir, 'newview', self.build_type, app_name)
+ app_dst = os.path.join(dmg_dst, app_name)
+
+ if (not os.path.exists(app_orig)):
+ error("App does not exist: %r" % app_orig)
+ sys.exit(1)
+
+ dmg_name = "%s-Mac"%(self.viewer_info.combined)
+ temp_dmg = os.path.join(self.build_dir, dmg_name+".sparseimage")
+ final_dmg = os.path.join(self.dest_dir, dmg_name+".dmg")
+
+ if (os.path.exists(temp_dmg)):
+ message("Removing stale temp disk image...")
+ os.remove(temp_dmg)
+
+ self.__run_command(
+ 'Creating temp disk image...',
+ 'hdiutil create %(temp)r -volname %(volname)r -fs HFS+ '
+ '-layout SPUD -type SPARSE' %
+ {'temp': temp_dmg, 'volname': volname, 'src': dmg_dst})
+
+ self.__run_command(
+ 'Mounting temp disk image...',
+ 'hdiutil attach %r -readwrite -noautoopen' % temp_dmg)
+
+ # Move the .app to the staging area (temporarily).
+ message("Copying %r (this takes a while)..."%(app_name))
+ shutil.copytree(app_orig, app_dst, symlinks=True)
+
+ message("Copying background.png...")
+ shutil.copy2( os.path.join(dmg_src, 'background.png'),
+ os.path.join(dmg_dst, 'background.png'))
+
+ config_script = os.path.join(self.source_dir, 'newview',
+ 'packaging', 'mac', 'ConfigureDMG.scpt')
+
+ self.__run_command(
+ "Configuring temp disk image's view options...",
+ 'osascript %(script)r %(volname)r %(app_name)r' %
+ {'script': config_script, 'volname': volname, 'app_name': app_name})
+
+ # self.__run_command(
+ # 'Hiding background.png...',
+ # 'SetFile -a V %r' % os.path.join(dmg_dst, 'background.png'))
+
+ self.__run_command(
+ 'Unmounting temp disk image...',
+ 'hdiutil detach %r' % dmg_dst)
+
+ if (os.path.exists(final_dmg)):
+ bkp = final_dmg + ".bkp"
+ message("Renaming existing final disk image to %r..." % bkp)
+ shutil.move(final_dmg, bkp)
+
+ self.__run_command(
+ 'Creating compressed final disk image (this takes a while)...',
+ 'hdiutil convert %(temp)r -format UDBZ -o %(final)r' %
+ {'temp':temp_dmg, 'final':final_dmg})
+
+ message("Removing temp disk image...")
+ os.remove(temp_dmg)
+
+ message('Package complete: %r'%final_dmg)
+
+
+ ###########
+ # WINDOWS #
+ ###########
+
+ def make_windows(self):
+ print "Packaging for Windows is not supported yet."
+
+
+ ###################
+ # PRIVATE METHODS #
+ ###################
+
+ def __check_build_dir(self):
+ if not os.path.exists(self.build_dir):
+ raise BadDir('build dir %(dir)r does not exist.' %
+ {'dir': self.build_dir})
+ if not os.path.isdir(self.build_dir):
+ raise BadDir('build dir %(dir)r is not a directory.' %
+ {'dir': self.build_dir})
+
+ def __check_source_dir(self):
+ if not os.path.exists(self.source_dir):
+ raise BadDir('source dir %(dir)r does not exist.' %
+ {'dir': self.source_dir})
+ if not os.path.isdir(self.source_dir):
+ raise BadDir('source dir %(dir)r is not a directory.' %
+ {'dir': self.source_dir})
+
+ def __get_platform(self):
+ platform = sys.platform
+ try:
+ return {'linux2':'linux',
+ 'linux1':'linux',
+ 'cygwin':'windows',
+ 'win32' :'windows',
+ 'darwin':'mac',
+ }[platform]
+ except KeyError:
+ raise WeirdPlatform(
+ "Unrecognized platform/operating system: %r" % platform)
+
+ def __run_command(self, summary=None, command=None):
+ if summary: message(summary)
+
+ if not command: return
+
+ import subprocess
+
+ out = subprocess.PIPE # = intercept command's output
+ if self.verbose:
+ print indent(command)
+ out = None # = don't intercept
+
+ child = subprocess.Popen(command, shell=True, stdout=out, stderr=None)
+ status = child.wait()
+
+ if status:
+ raise CmdFailed('A command returned non-zero status (%s):\n%s'%
+ (status, indent(command)))
+
+
+
+def main(args=sys.argv[1:]):
+ from optparse import OptionParser
+
+ op = OptionParser(usage='%prog --build-dir=PATH [options]')
+
+ op.add_option('--build-dir', dest='build_dir', nargs=1, metavar='PATH',
+ help='path to the \'build\' directory, which contains '
+ 'CMakeCache.txt and the compile result subdirectories')
+
+ op.add_option('--source-dir', dest='source_dir', nargs=1, metavar='PATH',
+ default=SOURCE_DIR,
+ help='optional path to an alternate source directory, '
+ 'i.e. \'indra\'. Default: %(SOURCE_DIR)r'
+ %{ 'SOURCE_DIR': SOURCE_DIR } )
+
+ op.add_option('--build-type', dest='build_type', nargs=1, metavar='TYPE',
+ default=BUILD_TYPE,
+ help='\'Debug\', \'RelWithDebInfo\', or \'Release\'. '
+ 'Default: %(BUILD_TYPE)r'
+ %{ 'BUILD_TYPE': BUILD_TYPE } )
+
+ op.add_option('-v', '--verbose', action='store_true', default=False,
+ help='print all shell commands as they are run')
+
+ if not args:
+ op.print_help()
+ return
+
+ options = op.parse_args(args)[0]
+
+ if not options.build_dir:
+ error('--build-dir=PATH is required.')
+ sys.exit(1)
+
+ opts_dict = {'source_dir': options.source_dir,
+ 'build_type': options.build_type,
+ 'verbose': options.verbose}
+
+ try:
+ Packager(options.build_dir, opts_dict).make()
+ except PackagerError, err:
+ error(err.args[0])
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
--
cgit v1.1
From 01f983f6788a2722a08897d7613c9caab3b933a1 Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Sat, 21 May 2011 01:45:29 -0500
Subject: Ported Mac packaging system from Kokua.
Build the "package" target in Xcode to create a DMG.
---
linden/scripts/package.py | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
(limited to 'linden/scripts')
diff --git a/linden/scripts/package.py b/linden/scripts/package.py
index 59aef79..e02a9cc 100755
--- a/linden/scripts/package.py
+++ b/linden/scripts/package.py
@@ -196,17 +196,13 @@ true""" % {'d': packaged_dir})
os.path.join(dmg_dst, 'background.png'))
config_script = os.path.join(self.source_dir, 'newview',
- 'packaging', 'mac', 'ConfigureDMG.scpt')
+ 'packaging', 'mac', 'ConfigureDMG.scpt')
self.__run_command(
"Configuring temp disk image's view options...",
'osascript %(script)r %(volname)r %(app_name)r' %
{'script': config_script, 'volname': volname, 'app_name': app_name})
- # self.__run_command(
- # 'Hiding background.png...',
- # 'SetFile -a V %r' % os.path.join(dmg_dst, 'background.png'))
-
self.__run_command(
'Unmounting temp disk image...',
'hdiutil detach %r' % dmg_dst)
--
cgit v1.1