diff options
Diffstat (limited to 'indra/newview/viewer_manifest.py')
-rwxr-xr-x | indra/newview/viewer_manifest.py | 227 |
1 files changed, 177 insertions, 50 deletions
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 142951da25..377c46f8e0 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -27,6 +27,7 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ import sys +import os import os.path import shutil import errno @@ -120,6 +121,24 @@ class ViewerManifest(LLManifest): settings_install['CmdLineGridChoice']['Value'] = self.grid() print "Set CmdLineGridChoice in settings_install.xml to '%s'" % self.grid() + #do not need to test for existence. If no platform is passed, llmanifest computes a default in get_default_platform + #the choice of value names (lnx, mac, win32, win) is dictated by the VMM API + build_data_json_platform = "" + if 'linux' in self.args['platform']: + build_data_json_platform = 'lnx' + elif 'darwin' in self.args['platform']: + build_data_json_platform = 'mac' + elif 'windows' in self.args['platform']: + #default case + build_data_json_platform = 'win' + if 'arch' in self.args and self.args['arch']: + if 'i686' in self.args['arch']: + build_data_json_platform = 'win32' + #we really shouldn't be here, something is very wrong at this point + else: + build_data_json_platform = 'None' + + # put_in_file(src=) need not be an actual pathname; it # only needs to be non-empty self.put_in_file(llsd.format_pretty_xml(settings_install), @@ -182,15 +201,26 @@ class ViewerManifest(LLManifest): # File in the newview/ directory self.path("gpu_table.txt") - #summary.json. Standard with exception handling is fine. If we can't open a new file for writing, we have worse problems - summary_dict = {"Type":"viewer","Version":'.'.join(self.args['version']),"Channel":self.channel_with_pkg_suffix()} - with open(os.path.join(os.pardir,'summary.json'), 'w') as summary_handle: - json.dump(summary_dict,summary_handle) + #build_data.json. Standard with exception handling is fine. If we can't open a new file for writing, we have worse problems + #platform is computed above with other arg parsing + build_data_dict = {"Type":"viewer","Version":'.'.join(self.args['version']), + "Channel Base": CHANNEL_VENDOR_BASE, + "Channel":self.channel_with_pkg_suffix(), + "Platform":build_data_json_platform, + "Update Service":"https://update.secondlife.com/update", + } + #MAINT-7294: Windows exe names depend on channel name, so write that in also + if build_data_json_platform.startswith('win'): + build_data_dict.update({'Executable':self.final_exe()}) + if build_data_json_platform.startswith('mac'): + build_data_dict.update({'Bundle Id':self.args['bundleid']}) + with open(os.path.join(os.pardir,'build_data.json'), 'w') as build_data_handle: + json.dump(build_data_dict,build_data_handle) #we likely no longer need the test, since we will throw an exception above, but belt and suspenders and we get the #return code for free. - if not self.path2basename(os.pardir, "summary.json"): - print "No summary.json file" + if not self.path2basename(os.pardir, "build_data.json"): + print "No build_data.json file" def grid(self): return self.args['grid'] @@ -222,7 +252,7 @@ class ViewerManifest(LLManifest): return channel_type def channel_variant_app_suffix(self): - # get any part of the compiled channel name after the CHANNEL_VENDOR_BASE + # get any part of the channel name after the CHANNEL_VENDOR_BASE suffix=self.channel_variant() # by ancient convention, we don't use Release in the app name if self.channel_type() == 'release': @@ -341,17 +371,42 @@ class WindowsManifest(ViewerManifest): pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") + vmpdir = os.path.join(pkgdir, "VMP") + llbasedir = os.path.join(pkgdir, "lib", "python", "llbase") if self.is_packaging_viewer(): # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe. self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe()) + # include the compiled launcher scripts so that it gets included in the file_list + self.path(src='%s/apply_update.exe' % vmpdir, dst="apply_update.exe") + self.path(src='%s/download_update.exe' % vmpdir, dst="download_update.exe") + self.path(src='%s/SL_Launcher.exe' % vmpdir, dst="SL_Launcher.exe") + self.path(src='%s/update_manager.exe' % vmpdir, dst="update_manager.exe") + + #IUM is not normally executed directly, just imported. No exe needed. + self.path2basename(vmpdir,"InstallerUserMessage.py") + + #VMP Tkinter icons + if self.prefix("vmp_icons"): + self.path("*.png") + self.path("*.gif") + self.end_prefix("vmp_icons") + + #before, we only needed llbase at build time. With VMP, we need it at run time. + llbase_path = os.path.join(self.get_dst_prefix(),'llbase') + if not os.path.exists(llbase_path): + os.makedirs(llbase_path) + if self.prefix(dst="llbase"): + self.path2basename(llbasedir,"*.py") + self.path2basename(llbasedir,"_cllsd.so") + self.end_prefix() + # Plugin host application self.path2basename(os.path.join(os.pardir, 'llplugin', 'slplugin', self.args['configuration']), "slplugin.exe") - self.path2basename("../viewer_components/updater/scripts/windows", "update_install.bat") # Get shared libs from the shared libs staging directory if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']), dst=""): @@ -389,11 +444,15 @@ class WindowsManifest(ViewerManifest): # These need to be installed as a SxS assembly, currently a 'private' assembly. # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx if self.args['configuration'].lower() == 'debug': - self.path("msvcr120d.dll") - self.path("msvcp120d.dll") + self.path("msvcr120d.dll") + self.path("msvcp120d.dll") + self.path("msvcr100d.dll") + self.path("msvcp100d.dll") else: - self.path("msvcr120.dll") - self.path("msvcp120.dll") + self.path("msvcr120.dll") + self.path("msvcp120.dll") + self.path("msvcr100.dll") + self.path("msvcp100.dll") # Vivox runtimes self.path("SLVoice.exe") @@ -401,7 +460,6 @@ class WindowsManifest(ViewerManifest): self.path("ortp.dll") self.path("libsndfile-1.dll") self.path("vivoxoal.dll") - self.path("ca-bundle.crt") # Security self.path("ssleay32.dll") @@ -423,7 +481,7 @@ class WindowsManifest(ViewerManifest): self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") - self.path("featuretable_xp.txt") + self.path("ca-bundle.crt") # Media plugins - CEF if self.prefix(src='../media_plugins/cef/%s' % self.args['configuration'], dst="llplugin"): @@ -616,10 +674,11 @@ class WindowsManifest(ViewerManifest): substitution_strings['installer_file'] = installer_file version_vars = """ - !define INSTEXE "%(final_exe)s" + !define INSTEXE "SL_Launcher.exe" !define VERSION "%(version_short)s" !define VERSION_LONG "%(version)s" !define VERSION_DASHES "%(version_dashes)s" + !define VIEWER_EXE "%(final_exe)s" """ % substitution_strings if self.channel_type() == 'release': @@ -654,6 +713,29 @@ class WindowsManifest(ViewerManifest): "%%ENGAGEREGISTRY%%":engage_registry, "%%DELETE_FILES%%":self.nsi_file_commands(False)}) + # If we're on a build machine, sign the code using our Authenticode certificate. JC + # note that the enclosing setup exe is signed later, after the makensis makes it. + sign_py = os.path.expandvars("${SIGN}") + if not sign_py or sign_py == "${SIGN}": + sign_py = 'C:\\buildscripts\\code-signing\\sign.py' + else: + sign_py = sign_py.replace('\\', '\\\\\\\\') + python = os.path.expandvars("${PYTHON}") + if not python or python == "${PYTHON}": + python = 'python' + if os.path.exists(sign_py): + #Unlike the viewer binary, the VMP filenames are invariant with respect to version, os, etc. + print "about to run signing of: ", self.dst_path_of("apply_update.exe").replace('\\', '\\\\\\\\') + self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of("apply_update.exe").replace('\\', '\\\\\\\\'))) + print "about to run signing of: ", self.dst_path_of("download_update.exe").replace('\\', '\\\\\\\\') + self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of("download_update.exe").replace('\\', '\\\\\\\\'))) + print "about to run signing of: ", self.dst_path_of("SL_Launcher.exe").replace('\\', '\\\\\\\\') + self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of("SL_Launcher.exe").replace('\\', '\\\\\\\\'))) + print "about to run signing of: ", self.dst_path_of("update_manager.exe").replace('\\', '\\\\\\\\') + self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of("update_manager.exe").replace('\\', '\\\\\\\\'))) + else: + print "Skipping code signing of vmp executables,", sign_py, "does not exist" + # We use the Unicode version of NSIS, available from # http://www.scratchpaper.com/ # Check two paths, one for Program Files, and one for Program Files (x86). @@ -677,20 +759,12 @@ class WindowsManifest(ViewerManifest): else: print >> sys.stderr, "Maximum nsis attempts exceeded; giving up" raise - # self.remove(self.dst_path_of(tempfile)) - # If we're on a build machine, sign the code using our Authenticode certificate. JC - sign_py = os.path.expandvars("${SIGN}") - if not sign_py or sign_py == "${SIGN}": - sign_py = 'C:\\buildscripts\\code-signing\\sign.py' - else: - sign_py = sign_py.replace('\\', '\\\\\\\\') - python = os.path.expandvars("${PYTHON}") - if not python or python == "${PYTHON}": - python = 'python' + if os.path.exists(sign_py): + print "about to run signing of: ", self.dst_path_of(installer_file).replace('\\', '\\\\\\\\') self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of(installer_file).replace('\\', '\\\\\\\\'))) else: - print "Skipping code signing,", sign_py, "does not exist" + print "Skipping code signing of setup executable,", sign_py, "does not exist" self.created_path(self.dst_path_of(installer_file)) self.package_file = installer_file @@ -717,17 +791,66 @@ class DarwinManifest(ViewerManifest): pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") + vmpdir = os.path.join(pkgdir, "VMP") + llbasedir = os.path.join(pkgdir, "lib", "python", "llbase") + requestsdir = os.path.join(pkgdir, "lib", "python", "requests") + urllib3dir = os.path.join(pkgdir, "lib", "python", "urllib3") + chardetdir = os.path.join(pkgdir, "lib", "python", "chardet") + idnadir = os.path.join(pkgdir, "lib", "python", "idna") if self.prefix(src="", dst="Contents"): # everything goes in Contents self.path("Info.plist", dst="Info.plist") # copy additional libs in <bundle>/Contents/MacOS/ self.path(os.path.join(relpkgdir, "libndofdev.dylib"), dst="Resources/libndofdev.dylib") - self.path(os.path.join(relpkgdir, "libhunspell-1.3.0.dylib"), dst="Resources/libhunspell-1.3.0.dylib") - - if self.prefix(dst="MacOS"): - self.path2basename("../viewer_components/updater/scripts/darwin", "*.py") - self.end_prefix() + self.path(os.path.join(relpkgdir, "libhunspell-1.3.0.dylib"), dst="Resources/libhunspell-1.3.0.dylib") + + if self.prefix(dst="MacOS"): + #this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322, SL-323 + self.path2basename(vmpdir,"SL_Launcher") + self.path2basename(vmpdir,"*.py") + # certifi will be imported by requests; this is our custom version to get our ca-bundle.crt + certifi_path = os.path.join(self.get_dst_prefix(),'certifi') + if not os.path.exists(certifi_path): + os.makedirs(certifi_path) + if self.prefix(dst="certifi"): + self.path2basename(os.path.join(vmpdir,"certifi"),"*") + self.end_prefix() + # llbase provides our llrest service layer and llsd decoding + llbase_path = os.path.join(self.get_dst_prefix(),'llbase') + if not os.path.exists(llbase_path): + os.makedirs(llbase_path) + if self.prefix(dst="llbase"): + self.path2basename(llbasedir,"*.py") + self.path2basename(llbasedir,"_cllsd.so") + self.end_prefix() + #requests module needed by llbase/llrest.py + #this is only needed on POSIX, because in Windows we compile it into the EXE + requests_path = os.path.join(self.get_dst_prefix(),'requests') + if not os.path.exists(requests_path): + os.makedirs(requests_path) + if self.prefix(dst="requests"): + self.path2basename(requestsdir,"*") + self.end_prefix() + urllib3_path = os.path.join(self.get_dst_prefix(),'urllib3') + if not os.path.exists(urllib3_path): + os.makedirs(urllib3_path) + if self.prefix(dst="urllib3"): + self.path2basename(urllib3dir,"*") + self.end_prefix() + chardet_path = os.path.join(self.get_dst_prefix(),'chardet') + if not os.path.exists(chardet_path): + os.makedirs(chardet_path) + if self.prefix(dst="chardet"): + self.path2basename(chardetdir,"*") + self.end_prefix() + idna_path = os.path.join(self.get_dst_prefix(),'idna') + if not os.path.exists(idna_path): + os.makedirs(idna_path) + if self.prefix(dst="idna"): + self.path2basename(idnadir,"*") + self.end_prefix() + self.end_prefix() # most everything goes in the Resources directory if self.prefix(src="", dst="Resources"): @@ -740,12 +863,19 @@ class DarwinManifest(ViewerManifest): self.path("licenses-mac.txt", dst="licenses.txt") self.path("featuretable_mac.txt") self.path("SecondLife.nib") + self.path("ca-bundle.crt") icon_path = self.icon_path() if self.prefix(src=icon_path, dst="") : self.path("secondlife.icns") self.end_prefix(icon_path) + #VMP Tkinter icons + if self.prefix("vmp_icons"): + self.path("*.png") + self.path("*.gif") + self.end_prefix("vmp_icons") + self.path("SecondLife.nib") # Translations @@ -812,10 +942,9 @@ class DarwinManifest(ViewerManifest): 'libvivoxoal.dylib', 'libvivoxsdk.dylib', 'libvivoxplatform.dylib', - 'ca-bundle.crt', 'SLVoice', ): - self.path2basename(relpkgdir, libfile) + self.path2basename(relpkgdir, libfile) # dylibs that vary based on configuration if self.args['configuration'].lower() == 'debug': @@ -852,8 +981,8 @@ class DarwinManifest(ViewerManifest): # Dullahan helper apps go inside SLPlugin.app if self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"): - for helperappfile in ('DullahanHelper.app'): - self.path2basename(relpkgdir, helperappfile) + helperappfile = 'DullahanHelper.app' + self.path2basename(relpkgdir, helperappfile) pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework'); # Putting a Frameworks directory under Contents/MacOS @@ -962,12 +1091,6 @@ class DarwinManifest(ViewerManifest): self.run_command('strip -S %(viewer_binary)r' % { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')}) - def copy_finish(self): - # Force executable permissions to be set for scripts - # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802 - for script in 'Contents/MacOS/update_install.py',: - self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script)) - def package_finish(self): global CHANNEL_VENDOR_BASE # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning. @@ -1152,8 +1275,16 @@ class LinuxManifest(ViewerManifest): if self.prefix(src="", dst="bin"): self.path("secondlife-bin","do-not-directly-run-secondlife-bin") self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") - self.path2basename("../llplugin/slplugin", "SLPlugin") - self.path2basename("../viewer_components/updater/scripts/linux", "update_install") + self.path2basename("../llplugin/slplugin", "SLPlugin") + #this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323 + self.path2basename("../viewer_components/manager","SL_Launcher") + self.path2basename("../viewer_components/manager","*.py") + llbase_path = os.path.join(self.get_dst_prefix(),'llbase') + if not os.path.exists(llbase_path): + os.makedirs(llbase_path) + if self.prefix(dst="llbase"): + self.path2basename("../packages/lib/python/llbase","*.py") + self.path2basename("../packages/lib/python/llbase","_cllsd.so") self.end_prefix("bin") if self.prefix("res-sdl"): @@ -1191,12 +1322,7 @@ class LinuxManifest(ViewerManifest): print "Skipping llcommon.so (assuming llcommon was linked statically)" self.path("featuretable_linux.txt") - - def copy_finish(self): - # Force executable permissions to be set for scripts - # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802 - for script in 'secondlife', 'bin/update_install': - self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script)) + self.path("ca-bundle.crt") def package_finish(self): installer_name = self.installer_base_name() @@ -1239,7 +1365,8 @@ class LinuxManifest(ViewerManifest): def strip_binaries(self): if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" - self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name update_install \! -name *.dat | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure + # makes some small assumptions about our packaged dir structure + self.run_command(r"find %(d)r/bin %(d)r/lib -type f \! -name \*.py \! -name SL_Launcher \! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) class Linux_i686_Manifest(LinuxManifest): def construct(self): |