From b51972bac7f0b11955474baebebd3f1d7c9e60e3 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 4 Sep 2018 12:39:56 -0400 Subject: [PATCH 01/59] use copy_if_different to copy CrashReporter.nib so that it creates the directory if needed --- indra/mac_crash_logger/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt index ab20388261..f6c4dfb59d 100644 --- a/indra/mac_crash_logger/CMakeLists.txt +++ b/indra/mac_crash_logger/CMakeLists.txt @@ -85,7 +85,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} ARGS -E - copy_directory + copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/CrashReporter.nib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-crash-logger.app/Contents/Resources/CrashReporter.nib ) From 65dd31631f385d6ad85ed78b2fa07525dbd9d360 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 8 Sep 2018 10:05:26 -0400 Subject: [PATCH 02/59] DRTVWR-474, MAINT-9047: Restore viewer to top-level Mac app. The relationship to MAINT-9047 is that we hope this will improve the behavior of Mac code signing. --- indra/newview/viewer_manifest.py | 575 ++++++++++++------------------- 1 file changed, 225 insertions(+), 350 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 541112a765..14ff2c194e 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -880,394 +880,269 @@ class DarwinManifest(ViewerManifest): return True def construct(self): - # These are the names of the top-level application and the embedded - # applications for the VMP and for the actual viewer, respectively. - # These names, without the .app suffix, determine the flyover text for - # their corresponding Dock icons. - toplevel_app, toplevel_icon = "Second Life.app", "secondlife.icns" - launcher_app, launcher_icon = "Second Life Launcher.app", "secondlife.icns" - viewer_app, viewer_icon = "Second Life Viewer.app", "secondlife.icns" - # copy over the build result (this is a no-op if run within the xcode script) - self.path(os.path.join(self.args['configuration'], toplevel_app), dst="") + self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") - # -------------------- top-level Second Life.app --------------------- - # top-level Second Life application is only a container with self.prefix(src="", dst="Contents"): # everything goes in Contents - # top-level Info.plist is as generated by CMake - Info_plist = "Info.plist" - ## This self.path() call reports 0 files... skip? - self.path(Info_plist) - Info_plist = self.dst_path_of(Info_plist) + # CEF framework goes inside Contents/Frameworks. + # Remember where we parked this car. + with self.prefix(src="", dst="Frameworks"): + CEF_framework = "Chromium Embedded Framework.framework" + self.path2basename(relpkgdir, CEF_framework) + CEF_framework = self.dst_path_of(CEF_framework) - # the one file in top-level MacOS directory is the trampoline to - # our nested launcher_app with self.prefix(dst="MacOS"): - toplevel_MacOS = self.get_dst_prefix() - trampoline = self.put_in_file("""\ -#!/bin/bash -open "%s" --args "$@" -""" % - # up one directory from MacOS to its sibling Resources directory - os.path.join('$(dirname "$0")', os.pardir, 'Resources', launcher_app), - "SL_Launcher", # write this file - "trampoline") # flag to add to list of copied files - # Script must be executable - self.run_command(["chmod", "+x", trampoline]) + # NOTE: the -S argument to strip causes it to keep + # enough info for annotated backtraces (i.e. function + # names in the crash log). 'strip' with no arguments + # yields a slightly smaller binary but makes crash + # logs mostly useless. This may be desirable for the + # final release. Or not. + if ("package" in self.args['actions'] or + "unpacked" in self.args['actions']): + self.run_command( + ['strip', '-S', self.dst_path_of('Second Life')]) - # Make a symlink to a nested app Frameworks directory that doesn't - # yet exist. We shouldn't need this; the only things that need - # Frameworks are nested apps under viewer_app, and they should - # simply find its Contents/Frameworks by relative pathnames. But - # empirically, we do: if we omit this symlink, CEF doesn't work -- - # the login splash screen doesn't even display. SIIIIGH. - # We're passing a path that's already relative, hence symlinkf() - # rather than relsymlinkf(). - self.symlinkf(os.path.join("Resources", viewer_app, "Contents", "Frameworks")) + with self.prefix(dst="Resources"): + # defer cross-platform file copies until we're in the + # nested Resources directory + super(DarwinManifest, self).construct() - with self.prefix(src="", dst="Resources"): - # top-level Resources directory should be pretty sparse - # need .icns file referenced by top-level Info.plist + # need .icns file referenced by Info.plist with self.prefix(src=self.icon_path(), dst="") : - self.path(toplevel_icon) + self.path("secondlife.icns") - # ------------------- nested launcher_app -------------------- - with self.prefix(dst=os.path.join(launcher_app, "Contents")): - # Info.plist is just like top-level one... - Info = plistlib.readPlist(Info_plist) - # except for these replacements: - Info["CFBundleExecutable"] = "SL_Launcher" - Info["CFBundleIconFile"] = launcher_icon - self.put_in_file( - plistlib.writePlistToString(Info), - os.path.basename(Info_plist), - "Info.plist") + with self.prefix(src=relpkgdir, dst=""): + self.path("libndofdev.dylib") + self.path("libhunspell-1.3.0.dylib") - # copy VMP libs to MacOS - with self.prefix(dst="MacOS"): - #this copies over the python wrapper script, - #associated utilities and required libraries, see - #SL-321, SL-322, SL-323 - with self.prefix(src=os.path.join(pkgdir, "VMP"), dst=""): - self.path("SL_Launcher") - self.path("*.py") - # certifi will be imported by requests; this is - # our custom version to get our ca-bundle.crt - self.path("certifi") - with self.prefix(src=os.path.join(pkgdir, "lib", "python"), dst=""): - # llbase provides our llrest service layer and llsd decoding - with self.prefix("llbase"): - # (Why is llbase treated specially here? What - # DON'T we want to copy out of lib/python/llbase?) - self.path("*.py") - self.path("_cllsd.so") - #requests module needed by llbase/llrest.py - #this is only needed on POSIX, because in Windows - #we compile it into the EXE - for pypkg in "chardet", "idna", "requests", "urllib3": - self.path(pypkg) + with self.prefix("cursors_mac"): + self.path("*.tif") - # launcher_app/Contents/Resources - with self.prefix(dst="Resources"): - with self.prefix(src=self.icon_path(), dst="") : - self.path(launcher_icon) - with self.prefix(dst="vmp_icons"): - self.path("secondlife.ico") - #VMP Tkinter icons - with self.prefix("vmp_icons"): - self.path("*.png") - self.path("*.gif") + self.path("licenses-mac.txt", dst="licenses.txt") + self.path("featuretable_mac.txt") + self.path("SecondLife.nib") - # -------------------- nested viewer_app --------------------- - with self.prefix(dst=os.path.join(viewer_app, "Contents")): - # Info.plist is just like top-level one... - Info = plistlib.readPlist(Info_plist) - # except for these replacements: - # (CFBundleExecutable may be moot: SL_Launcher directly - # runs the executable, instead of launching the app) - Info["CFBundleExecutable"] = "Second Life" - Info["CFBundleIconFile"] = viewer_icon - self.put_in_file( - plistlib.writePlistToString(Info), - os.path.basename(Info_plist), - "Info.plist") + with self.prefix(src=pkgdir,dst=""): + self.path("ca-bundle.crt") - # CEF framework goes inside viewer_app/Contents/Frameworks. - # Remember where we parked this car. - with self.prefix(src="", dst="Frameworks"): - CEF_framework = "Chromium Embedded Framework.framework" - self.path2basename(relpkgdir, CEF_framework) - CEF_framework = self.dst_path_of(CEF_framework) + self.path("SecondLife.nib") - with self.prefix(dst="MacOS"): - # CMake constructs the Second Life executable in the - # MacOS directory belonging to the top-level Second - # Life.app. Move it here. - here = self.get_dst_prefix() - relbase = os.path.realpath(os.path.dirname(Info_plist)) - self.cmakedirs(here) - for f in os.listdir(toplevel_MacOS): - if f == os.path.basename(trampoline): - # don't move the trampoline script we just made! - continue - fromwhere = os.path.join(toplevel_MacOS, f) - towhere = os.path.join(here, f) - print "Moving %s => %s" % \ - (self.relpath(fromwhere, relbase), - self.relpath(towhere, relbase)) - # now do it, only without relativizing paths - os.rename(fromwhere, towhere) + # Translations + self.path("English.lproj/language.txt") + self.replace_in(src="English.lproj/InfoPlist.strings", + dst="English.lproj/InfoPlist.strings", + searchdict={'%%VERSION%%':'.'.join(self.args['version'])} + ) + self.path("German.lproj") + self.path("Japanese.lproj") + self.path("Korean.lproj") + self.path("da.lproj") + self.path("es.lproj") + self.path("fr.lproj") + self.path("hu.lproj") + self.path("it.lproj") + self.path("nl.lproj") + self.path("pl.lproj") + self.path("pt.lproj") + self.path("ru.lproj") + self.path("tr.lproj") + self.path("uk.lproj") + self.path("zh-Hans.lproj") - # NOTE: the -S argument to strip causes it to keep - # enough info for annotated backtraces (i.e. function - # names in the crash log). 'strip' with no arguments - # yields a slightly smaller binary but makes crash - # logs mostly useless. This may be desirable for the - # final release. Or not. - if ("package" in self.args['actions'] or - "unpacked" in self.args['actions']): - self.run_command( - ['strip', '-S', self.dst_path_of('Second Life')]) + def path_optional(src, dst): + """ + For a number of our self.path() calls, not only do we want + to deal with the absence of src, we also want to remember + which were present. Return either an empty list (absent) + or a list containing dst (present). Concatenate these + return values to get a list of all libs that are present. + """ + # This was simple before we started needing to pass + # wildcards. Fortunately, self.path() ends up appending a + # (source, dest) pair to self.file_list for every expanded + # file processed. Remember its size before the call. + oldlen = len(self.file_list) + self.path(src, dst) + # The dest appended to self.file_list has been prepended + # with self.get_dst_prefix(). Strip it off again. + added = [os.path.relpath(d, self.get_dst_prefix()) + for s, d in self.file_list[oldlen:]] + if not added: + print "Skipping %s" % dst + return added - with self.prefix(dst="Resources"): - # defer cross-platform file copies until we're in the right - # nested Resources directory - super(DarwinManifest, self).construct() + # dylibs is a list of all the .dylib files we expect to need + # in our bundled sub-apps. For each of these we'll create a + # symlink from sub-app/Contents/Resources to the real .dylib. + # Need to get the llcommon dll from any of the build directories as well. + libfile_parent = self.get_dst_prefix() + libfile = "libllcommon.dylib" + dylibs = path_optional(self.find_existing_file(os.path.join(os.pardir, + "llcommon", + self.args['configuration'], + libfile), + os.path.join(relpkgdir, libfile)), + dst=libfile) - with self.prefix(src=self.icon_path(), dst="") : - self.path(viewer_icon) + for libfile in ( + "libapr-1.0.dylib", + "libaprutil-1.0.dylib", + "libcollada14dom.dylib", + "libexpat.1.dylib", + "libexception_handler.dylib", + "libGLOD.dylib", + # libnghttp2.dylib is a symlink to + # libnghttp2.major.dylib, which is a symlink to + # libnghttp2.version.dylib. Get all of them. + "libnghttp2.*dylib", + ): + dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) - with self.prefix(src=relpkgdir, dst=""): - self.path("libndofdev.dylib") - self.path("libhunspell-1.3.0.dylib") + # SLVoice and vivox lols, no symlinks needed + for libfile in ( + 'libortp.dylib', + 'libsndfile.dylib', + 'libvivoxoal.dylib', + 'libvivoxsdk.dylib', + 'libvivoxplatform.dylib', + 'SLVoice', + ): + self.path2basename(relpkgdir, libfile) - with self.prefix("cursors_mac"): - self.path("*.tif") + # dylibs that vary based on configuration + if self.args['configuration'].lower() == 'debug': + for libfile in ( + "libfmodexL.dylib", + ): + dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) + else: + for libfile in ( + "libfmodex.dylib", + ): + dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) - self.path("licenses-mac.txt", dst="licenses.txt") - self.path("featuretable_mac.txt") - self.path("SecondLife.nib") + # our apps + executable_path = {} + for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"), + # plugin launcher + (os.path.join("llplugin", "slplugin"), "SLPlugin.app"), + ): + self.path2basename(os.path.join(os.pardir, + app_bld_dir, self.args['configuration']), + app) + executable_path[app] = \ + self.dst_path_of(os.path.join(app, "Contents", "MacOS")) - with self.prefix(src=pkgdir,dst=""): - self.path("ca-bundle.crt") + # our apps dependencies on shared libs + # for each app, for each dylib we collected in dylibs, + # create a symlink to the real copy of the dylib. + with self.prefix(dst=os.path.join(app, "Contents", "Resources")): + for libfile in dylibs: + self.relsymlinkf(os.path.join(libfile_parent, libfile)) - self.path("SecondLife.nib") + # Dullahan helper apps go inside SLPlugin.app + with self.prefix(dst=os.path.join( + "SLPlugin.app", "Contents", "Frameworks")): - # Translations - self.path("English.lproj/language.txt") - self.replace_in(src="English.lproj/InfoPlist.strings", - dst="English.lproj/InfoPlist.strings", - searchdict={'%%VERSION%%':'.'.join(self.args['version'])} - ) - self.path("German.lproj") - self.path("Japanese.lproj") - self.path("Korean.lproj") - self.path("da.lproj") - self.path("es.lproj") - self.path("fr.lproj") - self.path("hu.lproj") - self.path("it.lproj") - self.path("nl.lproj") - self.path("pl.lproj") - self.path("pt.lproj") - self.path("ru.lproj") - self.path("tr.lproj") - self.path("uk.lproj") - self.path("zh-Hans.lproj") + frameworkname = 'Chromium Embedded Framework' - def path_optional(src, dst): - """ - For a number of our self.path() calls, not only do we want - to deal with the absence of src, we also want to remember - which were present. Return either an empty list (absent) - or a list containing dst (present). Concatenate these - return values to get a list of all libs that are present. - """ - # This was simple before we started needing to pass - # wildcards. Fortunately, self.path() ends up appending a - # (source, dest) pair to self.file_list for every expanded - # file processed. Remember its size before the call. - oldlen = len(self.file_list) - self.path(src, dst) - # The dest appended to self.file_list has been prepended - # with self.get_dst_prefix(). Strip it off again. - added = [os.path.relpath(d, self.get_dst_prefix()) - for s, d in self.file_list[oldlen:]] - if not added: - print "Skipping %s" % dst - return added + # This code constructs a relative symlink from the + # target framework folder back to the real CEF framework. + # It needs to be relative so that the symlink still works when + # (as is normal) the user moves the app bundle out of the DMG + # and into the /Applications folder. Note we pass catch=False, + # letting the uncaught exception terminate the process, since + # without this symlink, Second Life web media can't possibly work. - # dylibs is a list of all the .dylib files we expect to need - # in our bundled sub-apps. For each of these we'll create a - # symlink from sub-app/Contents/Resources to the real .dylib. - # Need to get the llcommon dll from any of the build directories as well. - libfile_parent = self.get_dst_prefix() - libfile = "libllcommon.dylib" - dylibs = path_optional(self.find_existing_file(os.path.join(os.pardir, - "llcommon", - self.args['configuration'], - libfile), - os.path.join(relpkgdir, libfile)), - dst=libfile) + # It might seem simpler just to symlink Frameworks back to + # the parent of Chromimum Embedded Framework.framework. But + # that would create a symlink cycle, which breaks our + # packaging step. So make a symlink from Chromium Embedded + # Framework.framework to the directory of the same name, which + # is NOT an ancestor of the symlink. - for libfile in ( - "libapr-1.0.dylib", - "libaprutil-1.0.dylib", - "libcollada14dom.dylib", - "libexpat.1.dylib", - "libexception_handler.dylib", - "libGLOD.dylib", - # libnghttp2.dylib is a symlink to - # libnghttp2.major.dylib, which is a symlink to - # libnghttp2.version.dylib. Get all of them. - "libnghttp2.*dylib", - ): - dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) + # from SLPlugin.app/Contents/Frameworks/Chromium Embedded + # Framework.framework back to + # $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework + SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False) - # SLVoice and vivox lols, no symlinks needed - for libfile in ( - 'libortp.dylib', - 'libsndfile.dylib', - 'libvivoxoal.dylib', - 'libvivoxsdk.dylib', - 'libvivoxplatform.dylib', - 'SLVoice', - ): - self.path2basename(relpkgdir, libfile) + # copy DullahanHelper.app + self.path2basename(relpkgdir, 'DullahanHelper.app') - # dylibs that vary based on configuration - if self.args['configuration'].lower() == 'debug': - for libfile in ( - "libfmodexL.dylib", - ): - dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) - else: - for libfile in ( - "libfmodex.dylib", - ): - dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) + # and fix that up with a Frameworks/CEF symlink too + with self.prefix(dst=os.path.join( + 'DullahanHelper.app', 'Contents', 'Frameworks')): + # from Dullahan Helper.app/Contents/Frameworks/Chromium Embedded + # Framework.framework back to + # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework + # Since SLPlugin_framework is itself a + # symlink, don't let relsymlinkf() resolve -- + # explicitly call relpath(symlink=True) and + # create that symlink here. + DullahanHelper_framework = \ + self.symlinkf(self.relpath(SLPlugin_framework, symlink=True), + catch=False) - # our apps - executable_path = {} - for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"), - # plugin launcher - (os.path.join("llplugin", "slplugin"), "SLPlugin.app"), - ): - self.path2basename(os.path.join(os.pardir, - app_bld_dir, self.args['configuration']), - app) - executable_path[app] = \ - self.dst_path_of(os.path.join(app, "Contents", "MacOS")) + # change_command includes install_name_tool, the + # -change subcommand and the old framework rpath + # stamped into the executable. To use it with + # run_command(), we must still append the new + # framework path and the pathname of the + # executable to change. + change_command = [ + 'install_name_tool', '-change', + '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework'] - # our apps dependencies on shared libs - # for each app, for each dylib we collected in dylibs, - # create a symlink to the real copy of the dylib. - with self.prefix(dst=os.path.join(app, "Contents", "Resources")): - for libfile in dylibs: - self.relsymlinkf(os.path.join(libfile_parent, libfile)) + with self.prefix(dst=os.path.join( + 'DullahanHelper.app', 'Contents', 'MacOS')): + # Now self.get_dst_prefix() is, at runtime, + # @executable_path. Locate the helper app + # framework (which is a symlink) from here. + newpath = os.path.join( + '@executable_path', + self.relpath(DullahanHelper_framework, symlink=True), + frameworkname) + # and restamp the DullahanHelper executable + self.run_command( + change_command + + [newpath, self.dst_path_of('DullahanHelper')]) - # Dullahan helper apps go inside SLPlugin.app - with self.prefix(dst=os.path.join( - "SLPlugin.app", "Contents", "Frameworks")): + # SLPlugin plugins + with self.prefix(dst="llplugin"): + dylibexecutable = 'media_plugin_cef.dylib' + self.path2basename("../media_plugins/cef/" + self.args['configuration'], + dylibexecutable) - frameworkname = 'Chromium Embedded Framework' + # Do this install_name_tool *after* media plugin is copied over. + # Locate the framework lib executable -- relative to + # SLPlugin.app/Contents/MacOS, which will be our + # @executable_path at runtime! + newpath = os.path.join( + '@executable_path', + self.relpath(SLPlugin_framework, executable_path["SLPlugin.app"], + symlink=True), + frameworkname) + # restamp media_plugin_cef.dylib + self.run_command( + change_command + + [newpath, self.dst_path_of(dylibexecutable)]) - # This code constructs a relative symlink from the - # target framework folder back to the real CEF framework. - # It needs to be relative so that the symlink still works when - # (as is normal) the user moves the app bundle out of the DMG - # and into the /Applications folder. Note we pass catch=False, - # letting the uncaught exception terminate the process, since - # without this symlink, Second Life web media can't possibly work. + # copy LibVLC plugin itself + self.path2basename("../media_plugins/libvlc/" + self.args['configuration'], + "media_plugin_libvlc.dylib") - # It might seem simpler just to symlink Frameworks back to - # the parent of Chromimum Embedded Framework.framework. But - # that would create a symlink cycle, which breaks our - # packaging step. So make a symlink from Chromium Embedded - # Framework.framework to the directory of the same name, which - # is NOT an ancestor of the symlink. - - # from SLPlugin.app/Contents/Frameworks/Chromium Embedded - # Framework.framework back to - # $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework - SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False) - - # copy DullahanHelper.app - self.path2basename(relpkgdir, 'DullahanHelper.app') - - # and fix that up with a Frameworks/CEF symlink too - with self.prefix(dst=os.path.join( - 'DullahanHelper.app', 'Contents', 'Frameworks')): - # from Dullahan Helper.app/Contents/Frameworks/Chromium Embedded - # Framework.framework back to - # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework - # Since SLPlugin_framework is itself a - # symlink, don't let relsymlinkf() resolve -- - # explicitly call relpath(symlink=True) and - # create that symlink here. - DullahanHelper_framework = \ - self.symlinkf(self.relpath(SLPlugin_framework, symlink=True), - catch=False) - - # change_command includes install_name_tool, the - # -change subcommand and the old framework rpath - # stamped into the executable. To use it with - # run_command(), we must still append the new - # framework path and the pathname of the - # executable to change. - change_command = [ - 'install_name_tool', '-change', - '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework'] - - with self.prefix(dst=os.path.join( - 'DullahanHelper.app', 'Contents', 'MacOS')): - # Now self.get_dst_prefix() is, at runtime, - # @executable_path. Locate the helper app - # framework (which is a symlink) from here. - newpath = os.path.join( - '@executable_path', - self.relpath(DullahanHelper_framework, symlink=True), - frameworkname) - # and restamp the DullahanHelper executable - self.run_command( - change_command + - [newpath, self.dst_path_of('DullahanHelper')]) - - # SLPlugin plugins - with self.prefix(dst="llplugin"): - dylibexecutable = 'media_plugin_cef.dylib' - self.path2basename("../media_plugins/cef/" + self.args['configuration'], - dylibexecutable) - - # Do this install_name_tool *after* media plugin is copied over. - # Locate the framework lib executable -- relative to - # SLPlugin.app/Contents/MacOS, which will be our - # @executable_path at runtime! - newpath = os.path.join( - '@executable_path', - self.relpath(SLPlugin_framework, executable_path["SLPlugin.app"], - symlink=True), - frameworkname) - # restamp media_plugin_cef.dylib - self.run_command( - change_command + - [newpath, self.dst_path_of(dylibexecutable)]) - - # copy LibVLC plugin itself - self.path2basename("../media_plugins/libvlc/" + self.args['configuration'], - "media_plugin_libvlc.dylib") - - # copy LibVLC dynamic libraries - with self.prefix(src=relpkgdir, dst="lib"): - self.path( "libvlc*.dylib*" ) - # copy LibVLC plugins folder - with self.prefix(src='plugins', dst=""): - self.path( "*.dylib" ) - self.path( "plugins.dat" ) + # copy LibVLC dynamic libraries + with self.prefix(src=relpkgdir, dst="lib"): + self.path( "libvlc*.dylib*" ) + # copy LibVLC plugins folder + with self.prefix(src='plugins', dst=""): + self.path( "*.dylib" ) + self.path( "plugins.dat" ) def package_finish(self): global CHANNEL_VENDOR_BASE From a74b3691aff94dfbd0fbfdce05f8a03168328ca7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sun, 9 Sep 2018 09:22:06 -0400 Subject: [PATCH 03/59] DRTVWR-474, MAINT-9047: Make viewer_manifest use same bundle name. --- indra/newview/viewer_manifest.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 14ff2c194e..bddacf357d 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -871,6 +871,9 @@ class Windows_x86_64_Manifest(WindowsManifest): class DarwinManifest(ViewerManifest): build_data_json_platform = 'mac' + def app_bundle(self): + return self.app_name() + ".app" + def finish_build_data_dict(self, build_data_dict): build_data_dict.update({'Bundle Id':self.args['bundleid']}) return build_data_dict @@ -881,7 +884,10 @@ class DarwinManifest(ViewerManifest): def construct(self): # copy over the build result (this is a no-op if run within the xcode script) - self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") + # Second Life.app is what CMake / Xcode builds + # self.app_bundle() is what we ultimately expect to sign and package + self.path(os.path.join(self.args['configuration'], "Second Life.app"), + dst=self.app_bundle()) pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") @@ -930,8 +936,6 @@ class DarwinManifest(ViewerManifest): with self.prefix(src=pkgdir,dst=""): self.path("ca-bundle.crt") - self.path("SecondLife.nib") - # Translations self.path("English.lproj/language.txt") self.replace_in(src="English.lproj/InfoPlist.strings", @@ -1180,8 +1184,6 @@ class DarwinManifest(ViewerManifest): # Copy everything in to the mounted .dmg - app_name = self.app_name() - # Hack: # Because there is no easy way to coerce the Finder into positioning # the app bundle in the same place with different app names, we are @@ -1195,7 +1197,7 @@ class DarwinManifest(ViewerManifest): if not os.path.exists (self.src_path_of(dmg_template)): dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') - for s,d in {self.get_dst_prefix():app_name + ".app", + for s,d in {self.get_dst_prefix(): self.app_bundle(), os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns", os.path.join(dmg_template, "background.jpg"): "background.jpg", os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): @@ -1238,7 +1240,7 @@ class DarwinManifest(ViewerManifest): # the signature are preserved; moving the files using python will leave them behind # and invalidate the signatures. if 'signature' in self.args: - app_in_dmg=os.path.join(volpath,self.app_name()+".app") + app_in_dmg=os.path.join(volpath,self.app_bundle()) print "Attempting to sign '%s'" % app_in_dmg identity = self.args['signature'] if identity == '': @@ -1293,9 +1295,6 @@ class DarwinManifest(ViewerManifest): raise self.run_command(['spctl', '-a', '-texec', '-vv', app_in_dmg]) - imagename="SecondLife_" + '_'.join(self.args['version']) - - finally: # Unmount the image even if exceptions from any of the above self.run_command(['hdiutil', 'detach', '-force', devfile]) From 886da87c43447040afbafa6628e158e66965141d Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 10 Sep 2018 09:31:08 -0400 Subject: [PATCH 04/59] by default print location in log files --- indra/newview/app_settings/logcontrol.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 8ced81fdb3..71445ea541 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -2,6 +2,7 @@ default-level INFO + print-location true settings From 299d4807ab6bc35c3643134a142fb59d5931bed9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 10 Sep 2018 12:23:42 -0400 Subject: [PATCH 05/59] DRTVWR-474, MAINT-9047: Back out changeset 2ed01671b974. We'll try to address the Mac app bundle name discrepancy a different way. --- indra/newview/viewer_manifest.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index bddacf357d..14ff2c194e 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -871,9 +871,6 @@ class Windows_x86_64_Manifest(WindowsManifest): class DarwinManifest(ViewerManifest): build_data_json_platform = 'mac' - def app_bundle(self): - return self.app_name() + ".app" - def finish_build_data_dict(self, build_data_dict): build_data_dict.update({'Bundle Id':self.args['bundleid']}) return build_data_dict @@ -884,10 +881,7 @@ class DarwinManifest(ViewerManifest): def construct(self): # copy over the build result (this is a no-op if run within the xcode script) - # Second Life.app is what CMake / Xcode builds - # self.app_bundle() is what we ultimately expect to sign and package - self.path(os.path.join(self.args['configuration'], "Second Life.app"), - dst=self.app_bundle()) + self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") @@ -936,6 +930,8 @@ class DarwinManifest(ViewerManifest): with self.prefix(src=pkgdir,dst=""): self.path("ca-bundle.crt") + self.path("SecondLife.nib") + # Translations self.path("English.lproj/language.txt") self.replace_in(src="English.lproj/InfoPlist.strings", @@ -1184,6 +1180,8 @@ class DarwinManifest(ViewerManifest): # Copy everything in to the mounted .dmg + app_name = self.app_name() + # Hack: # Because there is no easy way to coerce the Finder into positioning # the app bundle in the same place with different app names, we are @@ -1197,7 +1195,7 @@ class DarwinManifest(ViewerManifest): if not os.path.exists (self.src_path_of(dmg_template)): dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') - for s,d in {self.get_dst_prefix(): self.app_bundle(), + for s,d in {self.get_dst_prefix():app_name + ".app", os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns", os.path.join(dmg_template, "background.jpg"): "background.jpg", os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): @@ -1240,7 +1238,7 @@ class DarwinManifest(ViewerManifest): # the signature are preserved; moving the files using python will leave them behind # and invalidate the signatures. if 'signature' in self.args: - app_in_dmg=os.path.join(volpath,self.app_bundle()) + app_in_dmg=os.path.join(volpath,self.app_name()+".app") print "Attempting to sign '%s'" % app_in_dmg identity = self.args['signature'] if identity == '': @@ -1295,6 +1293,9 @@ class DarwinManifest(ViewerManifest): raise self.run_command(['spctl', '-a', '-texec', '-vv', app_in_dmg]) + imagename="SecondLife_" + '_'.join(self.args['version']) + + finally: # Unmount the image even if exceptions from any of the above self.run_command(['hdiutil', 'detach', '-force', devfile]) From 298a52f96a92f4368b3c5d955eab6b37a58f4931 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 10 Sep 2018 17:01:53 -0400 Subject: [PATCH 06/59] DRTVWR-474, MAINT-9047: Try *not* copying the viewer built by CMake. The start of viewer_manifest.DarwinManifest.construct() is a path() call to copy the whole viewer tree from where CMake constructs it. The comment is: "(this is a no-op if run within the xcode script)." Unfortunately, for unclear reasons, this has recently started nesting Second Life.app within the Second Life.app directory, and even to multiple levels. When that happens, copying the outermost .app directory to the sparseimage in order to convert to dmg runs out of room because we're trying to pack multiple copies of the whole viewer tree into the fixed-size sparseimage. But if it works to simply skip that entire initial copy operation, so much the better. --- indra/newview/viewer_manifest.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 14ff2c194e..d16b5d9a7c 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -880,8 +880,8 @@ class DarwinManifest(ViewerManifest): return True def construct(self): - # copy over the build result (this is a no-op if run within the xcode script) - self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") +## # copy over the build result (this is a no-op if run within the xcode script) +## self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") @@ -1238,6 +1238,11 @@ class DarwinManifest(ViewerManifest): # the signature are preserved; moving the files using python will leave them behind # and invalidate the signatures. if 'signature' in self.args: + print 72*'=' + print 'In {}:'.format(volpath) + for f in os.listdir(volpath): + print ' {}'.format(f) + print 72*'=' app_in_dmg=os.path.join(volpath,self.app_name()+".app") print "Attempting to sign '%s'" % app_in_dmg identity = self.args['signature'] From e0467f506136dd1fa044da130c7ffd3e817acc07 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Sep 2018 09:18:56 -0400 Subject: [PATCH 07/59] DRTVWR-474, MAINT-9047: Must copy CMake-built viewer for EDU. --- indra/newview/viewer_manifest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index d16b5d9a7c..4e6c112cda 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -880,8 +880,8 @@ class DarwinManifest(ViewerManifest): return True def construct(self): -## # copy over the build result (this is a no-op if run within the xcode script) -## self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") + # copy over the build result (this is a no-op if run within the xcode script) + self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") From c6865bcd366379028029a24281812cf320de8aff Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Sep 2018 13:56:21 -0400 Subject: [PATCH 08/59] DRTVWR-474, MAINT-9047: Make failing spctl command more verbose. --- indra/newview/viewer_manifest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 4e6c112cda..de296bec75 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1296,7 +1296,7 @@ class DarwinManifest(ViewerManifest): else: print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" raise - self.run_command(['spctl', '-a', '-texec', '-vv', app_in_dmg]) + self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg]) imagename="SecondLife_" + '_'.join(self.args['version']) From 517e1605e9feb203c9ccd9a115a21cae9bbc704b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Sep 2018 16:04:33 -0400 Subject: [PATCH 09/59] DRTVWR-474, MAINT-9047: Display top-level app bundle in sparseimage. codesign claims to succeed, but spctl says: /Volumes/Second Life Installer/Second Life Test.app: rejected (the code is valid but does not seem to be an app) Why not? Display what's in Second Life.app/Contents on the mounted sparseimage: show Info.plist, list Frameworks, MacOS, Resources. --- indra/newview/viewer_manifest.py | 36 +++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index de296bec75..5078f323ae 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1238,11 +1238,6 @@ class DarwinManifest(ViewerManifest): # the signature are preserved; moving the files using python will leave them behind # and invalidate the signatures. if 'signature' in self.args: - print 72*'=' - print 'In {}:'.format(volpath) - for f in os.listdir(volpath): - print ' {}'.format(f) - print 72*'=' app_in_dmg=os.path.join(volpath,self.app_name()+".app") print "Attempting to sign '%s'" % app_in_dmg identity = self.args['signature'] @@ -1296,11 +1291,36 @@ class DarwinManifest(ViewerManifest): else: print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" raise + print 72*'=' + import stat + print app_in_dmg + # Second Life.app + for sub0 in os.listdir(app_in_dmg): + print '--{}'.format(sub0) + path0 = os.path.join(app_in_dmg, sub0) + if os.path.isfile(path0): + # shouldn't be any file here + with open(path0) as inf: + for line in inf: + print ' {}'.format(line.rstrip()) + elif os.path.isdir(path0): + # Contents + for sub1 in os.listdir(path0): + print '----{}'.format(sub1) + path1 = os.path.join(path0, sub1) + if os.path.isfile(path1): + # Info.plist, PkgInfo + with open(path1) as inf: + for line in inf: + print ' {}'.format(line.rstrip()) + elif os.path.isdir(path1): + # Frameworks, MacOS, Resources + for sub2 in os.listdir(path1): + path2 = os.path.join(path1, sub2) + print ' {:04o} {}'.format(stat.S_IMODE(os.stat(path2).st_mode), sub2) + print 72*'=' self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg]) - imagename="SecondLife_" + '_'.join(self.args['version']) - - finally: # Unmount the image even if exceptions from any of the above self.run_command(['hdiutil', 'detach', '-force', devfile]) From e3d16dcb70da26c7952b45252b74716b1a632b97 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Sep 2018 19:57:42 -0400 Subject: [PATCH 10/59] DRTVWR-474: Remove nag about SL_Launcher. --- indra/newview/llappviewer.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 687b76c224..dd1d4cea39 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1083,26 +1083,6 @@ bool LLAppViewer::init() } } -// don't nag developers who need to run the executable directly -#if LL_RELEASE_FOR_DOWNLOAD - // MAINT-8305: If we're processing a SLURL, skip the launcher check. - if (gSavedSettings.getString("CmdLineLoginLocation").empty()) - { - const char* PARENT = getenv("PARENT"); - if (! (PARENT && std::string(PARENT) == "SL_Launcher")) - { - // Don't directly run this executable. Please run the launcher, which - // will run the viewer itself. - // Naturally we do not consider this bulletproof. The point is to - // gently remind a user who *inadvertently* finds him/herself in this - // situation to do things the Right Way. Anyone who intentionally - // bypasses this mechanism needs no reminder that s/he's shooting - // him/herself in the foot. - LLNotificationsUtil::add("RunLauncher"); - } - } -#endif - #if LL_WINDOWS if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) { From aaf45f0f63a1c79393e6316e04f78476d2a2af6e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 Sep 2018 19:59:03 -0400 Subject: [PATCH 11/59] DRTVWR-474, MAINT-9047: Set viewer name in Info.plist, not launcher. --- indra/newview/CMakeLists.txt | 8 +------- indra/newview/Info-SecondLife.plist | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2fc722d4c3..212677717e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2056,13 +2056,7 @@ endif (LINUX) if (DARWIN) # These all get set with PROPERTIES set(product "Second Life") - # this is the setting for the Python wrapper, see SL-322 and WRAPPER line in Info-SecondLife.plist - if (PACKAGE) - set(MACOSX_WRAPPER_EXECUTABLE_NAME "SL_Launcher") - else (PACKAGE) - # force the name of the actual executable to allow running it within Xcode for debugging - set(MACOSX_WRAPPER_EXECUTABLE_NAME "../Resources/Second Life Viewer.app/Contents/MacOS/Second Life") - endif (PACKAGE) + set(MACOSX_EXECUTABLE_NAME "Second Life") set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer") set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns") set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer") diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index af4cf26ac6..31b4201f47 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion English CFBundleExecutable - ${MACOSX_WRAPPER_EXECUTABLE_NAME} + ${MACOSX_EXECUTABLE_NAME} CFBundleGetInfoString ${MACOSX_BUNDLE_INFO_STRING} CFBundleIconFile From a1a2b672accbcf6f309e01b4717013a7386484bb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 12 Sep 2018 11:30:43 -0400 Subject: [PATCH 12/59] DRTVWR-474: Update to viewer-manager build 519565 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f07cae8e81..67130a60fd 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3260,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - f45c0a5e7b4601b355e163bf62f5718e + cc08a265bd620a5c6756a6c8ddb104ef url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/20587/147509/viewer_manager-1.0.517052-darwin64-517052.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24391/190021/viewer_manager-1.0.519565-darwin64-519565.tar.bz2 name darwin64 @@ -3284,9 +3284,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - d2443caf062697430071d458a965f611 + 40f0b7ecb420e0aa8761e434311e2d20 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/20588/147516/viewer_manager-1.0.517052-windows-517052.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24393/190032/viewer_manager-1.0.519565-windows-519565.tar.bz2 name windows @@ -3297,7 +3297,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 1.0.517052 + 1.0.519565 vlc-bin From d56ef598f64807100febe5efd835fd287c5f9698 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 12 Sep 2018 12:12:30 -0400 Subject: [PATCH 13/59] DRTVWR-474: Update to viewer-manager build 519568 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 67130a60fd..c12cf8108b 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3260,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - cc08a265bd620a5c6756a6c8ddb104ef + 7ce54dcea1607e7cb6a9cccd9a58e628 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24391/190021/viewer_manager-1.0.519565-darwin64-519565.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24396/190047/viewer_manager-2.0.519568-darwin64-519568.tar.bz2 name darwin64 @@ -3284,9 +3284,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 40f0b7ecb420e0aa8761e434311e2d20 + 8a06295a3b351b943d2b925eb589ff2b url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24393/190032/viewer_manager-1.0.519565-windows-519565.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24395/190053/viewer_manager-2.0.519568-windows-519568.tar.bz2 name windows @@ -3297,7 +3297,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 1.0.519565 + 2.0.519568 vlc-bin From 2081b8a654fa78c4414ec2619522c8ef461a1881 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 12 Sep 2018 12:15:41 -0400 Subject: [PATCH 14/59] DRTVWR-474: Make NSIS run new updater.exe after install. But change shortcuts and registry entries and everything else back to the real viewer executable, so that every subsequent run directly launches the viewer. Eliminate SL_Launcher references from viewer_manifest.py. --- .../installers/windows/installer_template.nsi | 41 ++++++++++++------- indra/newview/viewer_manifest.py | 9 ++-- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 14c8dba39f..c53d7989fc 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -299,7 +299,7 @@ StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)" CreateDirectory "$SMPROGRAMS\$INSTSHORTCUT" SetOutPath "$INSTDIR" CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \ - "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" + "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \ @@ -317,9 +317,9 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \ # Other shortcuts SetOutPath "$INSTDIR" CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \ - "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" + "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \ - "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" + "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE" CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \ '"$INSTDIR\uninst.exe"' '' @@ -327,7 +327,7 @@ CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \ WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" "$INSTDIR" WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" "${VERSION_LONG}" WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" "$INSTSHORTCUT" -WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$INSTEXE" +WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$VIEWER_EXE" WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "Publisher" "Linden Research, Inc." WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "URLInfoAbout" "http://secondlife.com/whatis/" WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "URLUpdateInfo" "http://secondlife.com/support/downloads/" @@ -338,10 +338,10 @@ WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninst WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "EstimatedSize" "0x0001D500" # ~117 MB # from FS:Ansariel -WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayIcon" '"$INSTDIR\$INSTEXE"' +WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayIcon" '"$INSTDIR\$VIEWER_EXE"' # BUG-2707 Disable SEHOP for installed viewer. -WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$INSTEXE" "DisableExceptionChainValidation" 1 +WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$VIEWER_EXE" "DisableExceptionChainValidation" 1 # Write URL registry info WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "(default)" "URL:Second Life" @@ -358,9 +358,8 @@ WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$ # URL param must be last item passed to viewer, it ignores subsequent params to avoid parameter injection attacks. WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$VIEWER_EXE" -url "%1"' -# Only allow Launcher to be the icon -WriteRegStr HKEY_CLASSES_ROOT "Applications\$INSTEXE" "IsHostApp" "" -WriteRegStr HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" "NoStartPage" "" +WriteRegStr HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "IsHostApp" "" +##WriteRegStr HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" "NoStartPage" "" # Write out uninstaller WriteUninstaller "$INSTDIR\uninst.exe" @@ -398,8 +397,8 @@ Call un.CloseSecondLife DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" # BUG-2707 Remove entry that disabled SEHOP -DeleteRegKey HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$INSTEXE" -DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE" +DeleteRegKey HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$VIEWER_EXE" +##DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE" DeleteRegKey HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" # Clean up shortcuts @@ -537,6 +536,7 @@ Function RemoveProgFilesOnInst # Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575 Delete "$INSTDIR\$INSTEXE" +Delete "$INSTDIR\$VIEWER_EXE" # Remove old shader files first so fallbacks will work. See DEV-5663 RMDir /r "$INSTDIR\app_settings\shaders" @@ -673,7 +673,7 @@ FunctionEnd ;; After install completes, launch app ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function .onInstSuccess -Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch. + Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch. Push $R0 Push $0 ;; MAINT-7812: Only write nsis.winstall file with /marker switch @@ -694,8 +694,21 @@ Call CheckWindowsServPack # Warn if not on the latest SP before asking to launc Pop $R0 Push $R0 # Option value, unused# StrCmp $SKIP_AUTORUN "true" +2; -# Assumes SetOutPath $INSTDIR - Exec '"$WINDIR\explorer.exe" "$INSTDIR\$INSTSHORTCUT.lnk"' + # Assumes SetOutPath $INSTDIR + # Run INSTEXE (our updater), passing VIEWER_EXE plus the command-line + # arguments built into our shortcuts. This gives the updater a chance + # to verify that the viewer we just installed is appropriate for the + # running system -- or, if not, to download and install a different + # viewer. For instance, if a user running 32-bit Windows installs a + # 64-bit viewer, it cannot run on this system. But since the updater + # is a 32-bit executable even in the 64-bit viewer package, the + # updater can detect the problem and adapt accordingly. + # Once everything is in order, the updater will run the specified + # viewer with the specified params. + # Quote the updater executable and the viewer executable because each + # must be a distinct command-line token, but DO NOT quote the language + # string because it must decompose into separate command-line tokens. + Exec '"$INSTDIR\$INSTEXE" "$INSTDIR\VIEWER_EXE" $SHORTCUT_LANG_PARAM' Pop $R0 # FunctionEnd diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 5078f323ae..6540aa9f6b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -490,7 +490,7 @@ class WindowsManifest(ViewerManifest): with self.prefix(src=os.path.join(pkgdir, "VMP"), dst=""): # include the compiled launcher scripts so that it gets included in the file_list - self.path('SL_Launcher.exe') + self.path('updater.exe') #IUM is not normally executed directly, just imported. No exe needed. self.path("InstallerUserMessage.py") @@ -768,7 +768,7 @@ class WindowsManifest(ViewerManifest): substitution_strings['installer_file'] = installer_file version_vars = """ - !define INSTEXE "SL_Launcher.exe" + !define INSTEXE "updater.exe" !define VERSION "%(version_short)s" !define VERSION_LONG "%(version)s" !define VERSION_DASHES "%(version_dashes)s" @@ -812,7 +812,7 @@ class WindowsManifest(ViewerManifest): # note that the enclosing setup exe is signed later, after the makensis makes it. # Unlike the viewer binary, the VMP filenames are invariant with respect to version, os, etc. for exe in ( - "SL_Launcher.exe", + "updater.exe", ): self.sign(exe) @@ -1376,7 +1376,6 @@ class LinuxManifest(ViewerManifest): 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 with self.prefix(src="../viewer_components/manager", dst=""): - self.path("SL_Launcher") self.path("*.py") with self.prefix(src=os.path.join("lib", "python", "llbase"), dst="llbase"): self.path("*.py") @@ -1455,7 +1454,7 @@ class LinuxManifest(ViewerManifest): self.run_command( ["find"] + [os.path.join(self.get_dst_prefix(), dir) for dir in ('bin', 'lib')] + - ['-type', 'f', '!', '-name', '*.py', '!', '-name', 'SL_Launcher', + ['-type', 'f', '!', '-name', '*.py', '!', '-name', 'update_install', '-exec', 'strip', '-S', '{}', ';']) class Linux_i686_Manifest(LinuxManifest): From 0c995db8dc90f64263d09a11274088a9b3df9305 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 12 Sep 2018 14:04:36 -0400 Subject: [PATCH 15/59] DRTVWR-474: Update to viewer-manager build 519577 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index c12cf8108b..6b87d5575a 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3260,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 7ce54dcea1607e7cb6a9cccd9a58e628 + 876dbbf0f479948488f04eae74dff04b url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24396/190047/viewer_manager-2.0.519568-darwin64-519568.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24410/190107/viewer_manager-2.0.519577-darwin64-519577.tar.bz2 name darwin64 @@ -3284,9 +3284,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 8a06295a3b351b943d2b925eb589ff2b + 6616fec70baf8375ed3afca9767b6be5 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24395/190053/viewer_manager-2.0.519568-windows-519568.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24411/190113/viewer_manager-2.0.519577-windows-519577.tar.bz2 name windows @@ -3297,7 +3297,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.519568 + 2.0.519577 vlc-bin From d41245f252442d91432f06b039abea81831cc083 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 12 Sep 2018 20:13:53 -0400 Subject: [PATCH 16/59] DRTVWR-474: $VIEWER_EXE, rather than plain VIEWER_EXE --- indra/newview/installers/windows/installer_template.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index c53d7989fc..3117cf6b85 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -708,7 +708,7 @@ Function .onInstSuccess # Quote the updater executable and the viewer executable because each # must be a distinct command-line token, but DO NOT quote the language # string because it must decompose into separate command-line tokens. - Exec '"$INSTDIR\$INSTEXE" "$INSTDIR\VIEWER_EXE" $SHORTCUT_LANG_PARAM' + Exec '"$INSTDIR\$INSTEXE" "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM' Pop $R0 # FunctionEnd From 289813994eb492d16e3af0fa30835e2b26a84ced Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 16:20:05 -0400 Subject: [PATCH 17/59] DRTVWR-474: Clean up use of LLDir::getAppRODataDir(), esp. on Mac. Clearly it's not obvious to maintainers that on the Mac, getAppRODataDir() returns the app's Resources directory: in a number of places the code starts with the executable directory and appends "../Resources" to find that. --- indra/llvfs/lldir_mac.cpp | 4 ++-- indra/llwindow/llwindowmacosx.cpp | 10 ++++------ indra/newview/llstartup.cpp | 3 +-- indra/newview/llvoicevivox.cpp | 9 ++++----- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 79c4362747..87dc1b9795 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -171,9 +171,9 @@ void LLDir_Mac::initAppDirs(const std::string &app_name, if (!app_read_only_data_dir.empty()) { mAppRODataDir = app_read_only_data_dir; - mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; + mSkinBaseDir = add(mAppRODataDir, "skins"); } - mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "../Resources", "ca-bundle.crt"); + mCAFile = add(mAppRODataDir, "ca-bundle.crt"); } std::string LLDir_Mac::getCurPath() diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 843294c239..d4afbb15df 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1429,12 +1429,10 @@ static CursorRef gCursors[UI_CURSOR_COUNT]; static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY) { // cursors are in /Contents/Resources/cursors_mac/UI_CURSOR_FOO.tif - std::string fullpath = gDirUtilp->getAppRODataDir(); - fullpath += gDirUtilp->getDirDelimiter(); - fullpath += "cursors_mac"; - fullpath += gDirUtilp->getDirDelimiter(); - fullpath += cursorIDToName(cursorid); - fullpath += ".tif"; + std::string fullpath = gDirUtilp->add( + gDirUtilp->getAppRODataDir(), + "cursors_mac", + cursorIDToName(cursorid) + std::string(".tif")); gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspotX, hotspotY); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7a4c41779a..4c51873715 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -479,8 +479,7 @@ bool idle_startup() if (!found_template) { message_template_path = - gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, - "../Resources/app_settings", + gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "message_template.msg"); found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ } diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index b90e09b739..88d17a31a4 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -770,14 +770,13 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() { #ifndef VIVOXDAEMON_REMOTEHOST // Launch the voice daemon - std::string exe_path = gDirUtilp->getExecutableDir(); - exe_path += gDirUtilp->getDirDelimiter(); + std::string exe_path = gDirUtilp->getAppRODataDir(); #if LL_WINDOWS - exe_path += "SLVoice.exe"; + gDirUtilp->append(exe_path, "SLVoice.exe"); #elif LL_DARWIN - exe_path += "../Resources/SLVoice"; + gDirUtilp->append(exe_path, "SLVoice"); #else - exe_path += "SLVoice"; + gDirUtilp->append(exe_path, "SLVoice"); #endif // See if the vivox executable exists llstat s; From 08fefb454bfbf98e90e95af329b21d7e6e146330 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 16:21:50 -0400 Subject: [PATCH 18/59] DRTVWR-474: Update to viewer-manager build 519640 --- autobuild.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 6b87d5575a..1277f70b0b 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3248,7 +3248,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors description Linden Lab Viewer Management Process suite. license - Proprietary + viewerlgpl license_file LICENSE name @@ -3260,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 876dbbf0f479948488f04eae74dff04b + 952c2e32e37ef67115ba3074892961c3 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24410/190107/viewer_manager-2.0.519577-darwin64-519577.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24508/190821/viewer_manager-2.0.519640-darwin64-519640.tar.bz2 name darwin64 @@ -3284,9 +3284,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 6616fec70baf8375ed3afca9767b6be5 + 7c8b210c1687a100f0b295d60ffac2c5 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24411/190113/viewer_manager-2.0.519577-windows-519577.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24507/190827/viewer_manager-2.0.519640-windows-519640.tar.bz2 name windows @@ -3297,7 +3297,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.519577 + 2.0.519640 vlc-bin From 83b40329fd822277ff5b47e6f36a7897c85e6260 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 16:22:38 -0400 Subject: [PATCH 19/59] DRTVWR-474: Make NSIS installer invoke updater precheck subcommand. --- indra/newview/installers/windows/installer_template.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 3117cf6b85..76187b49a5 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -708,7 +708,7 @@ Function .onInstSuccess # Quote the updater executable and the viewer executable because each # must be a distinct command-line token, but DO NOT quote the language # string because it must decompose into separate command-line tokens. - Exec '"$INSTDIR\$INSTEXE" "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM' + Exec '"$INSTDIR\$INSTEXE" precheck "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM' Pop $R0 # FunctionEnd From cc99cd65cf0355f201157d8f71743899af6f2ade Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 16:23:45 -0400 Subject: [PATCH 20/59] DRTVWR-474: Copy updater and its icons into Mac app's Resources. --- indra/newview/viewer_manifest.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 6540aa9f6b..32ff7f6ea8 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -470,7 +470,7 @@ class WindowsManifest(ViewerManifest): pass except NoMatchingAssemblyException as err: pass - + self.ccopy(src,dst) else: raise Exception("Directories are not supported by test_CRT_and_copy_action()") @@ -916,6 +916,15 @@ class DarwinManifest(ViewerManifest): with self.prefix(src=self.icon_path(), dst="") : self.path("secondlife.icns") + # Copy in the updater script and helper modules + self.path(src=os.path.join(pkgdir, 'VMP'), dst="updater") + + with self.prefix(src="", dst=os.path.join("updater", "icons")): + self.path2basename(os.path.join(self.icon_path(), "secondlife.ico")) + with self.prefix(src="vmp_icons", dst=""): + self.path("*.png") + self.path("*.gif") + with self.prefix(src=relpkgdir, dst=""): self.path("libndofdev.dylib") self.path("libhunspell-1.3.0.dylib") From a6e2201d2cff8fe03c83a75a2766d1ab71d35a21 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 16:24:53 -0400 Subject: [PATCH 21/59] DRTVWR-474: Run the new updater in LEAP mode. --- indra/newview/llappviewer.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index dd1d4cea39..68bb20386a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1130,6 +1130,21 @@ bool LLAppViewer::init() gGLActive = FALSE; +#if LL_WINDOWS + std::string updater( + "\"" + gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe") + "\""); +#elif LL_DARWIN + std::string updater( + "python \"" + gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py") + "\""); +#else + std::string updater( + "\"" + gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater") + "\""); +#endif + + // Run the updater, specifying LEAP mode. An exception from the updater + // should bother us. + LLLeap::create("updater process", (updater + " leap"), true); + // Iterate over --leap command-line options. But this is a bit tricky: if // there's only one, it won't be an array at all. LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand")); From e00a8dee3f9675296df5c614b4483509c2ff55bb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 20:26:21 -0400 Subject: [PATCH 22/59] DRTVWR-474: Fix path2basename("secondlife.ico") call. --- indra/newview/viewer_manifest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 32ff7f6ea8..4f0f4b17d9 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -920,7 +920,7 @@ class DarwinManifest(ViewerManifest): self.path(src=os.path.join(pkgdir, 'VMP'), dst="updater") with self.prefix(src="", dst=os.path.join("updater", "icons")): - self.path2basename(os.path.join(self.icon_path(), "secondlife.ico")) + self.path2basename(self.icon_path(), "secondlife.ico") with self.prefix(src="vmp_icons", dst=""): self.path("*.png") self.path("*.gif") From 807992adca4708bd2050b1fee8074d3e4521dd30 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 13 Sep 2018 20:55:05 -0400 Subject: [PATCH 23/59] DRTVWR-474: Pass updater cmd to LLLeap::create() as vector. This avoids having to tokenize a single string, avoiding swallowing backslashes in Windows pathnames in the mistaken belief they're escape characters. Alternatively, it avoids us having to double-escape them or convert them to forward slashes or whatever. --- indra/newview/llappviewer.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 68bb20386a..c0fcdd7c79 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1131,19 +1131,21 @@ bool LLAppViewer::init() gGLActive = FALSE; #if LL_WINDOWS - std::string updater( - "\"" + gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe") + "\""); + std::vector updater + { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe") }; #elif LL_DARWIN - std::string updater( - "python \"" + gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py") + "\""); + // explicitly run the system Python interpreter on updater.py + std::vector updater + { "python", gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py") }; #else - std::string updater( - "\"" + gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater") + "\""); + std::vector updater + { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater") }; #endif + // add LEAP mode command-line argument to whichever of these we selected + updater.push_back("leap"); - // Run the updater, specifying LEAP mode. An exception from the updater - // should bother us. - LLLeap::create("updater process", (updater + " leap"), true); + // Run the updater. An exception from the updater should bother us. + LLLeap::create("updater process", updater, true); // Iterate over --leap command-line options. But this is a bit tricky: if // there's only one, it won't be an array at all. From 8761e87ac526034f7a601eee5fdb667eba6eefda Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 24 Sep 2018 14:02:23 -0400 Subject: [PATCH 24/59] DRTVWR-474: Remove Python autobuild packages and references to them. We expect the viewer-manager package to be self-contained: we expect it to bring with it any Python packages it requires. We no longer force developers to wrap third-party Python packages as autobuild packages. --- autobuild.xml | 176 ------------------------------- indra/cmake/LLBase.cmake | 4 - indra/cmake/Requests.cmake | 7 -- indra/newview/CMakeLists.txt | 2 - indra/newview/viewer_manifest.py | 8 -- 5 files changed, 197 deletions(-) delete mode 100644 indra/cmake/LLBase.cmake delete mode 100644 indra/cmake/Requests.cmake diff --git a/autobuild.xml b/autobuild.xml index 1277f70b0b..29066d7c49 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -225,36 +225,6 @@ version 1.57 - chardet - - copyright - Contributors to charset (see https://github.com/chardet/chardet) - description - Python Character Encoding Library - license - LGPL - license_file - LICENSES/chardet.txt - name - chardet - platforms - - darwin64 - - archive - - hash - 0124862b6a1b88455c78a68f8b823d21 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6662/23578/chardet-3.0.4-darwin64-506651.tar.bz2 - - name - darwin64 - - - version - 3.0.4 - colladadom copyright @@ -1465,36 +1435,6 @@ version 2012.1-2 - idna - - copyright - Copyright (c) 2013-2017, Kim Davies. All rights reserved. - description - Python Internationalized Domain Names in Applications (IDNA) Library - license - see idna.rst - license_file - LICENSES/idna.rst - name - idna - platforms - - darwin64 - - archive - - hash - 7dfe9fc4023d7d4f511dd9fac7258266 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6663/23584/idna-2.5-darwin64-506652.tar.bz2 - - name - darwin64 - - - version - 2.5 - jpeglib copyright @@ -2173,46 +2113,6 @@ version 0.0.1 - llbase - - copyright - Copyright (c) 2010, Linden Research, Inc. - license - mit - license_file - LICENSES/llbase-license.txt - name - llbase - platforms - - darwin64 - - archive - - hash - e18eeb0691af053b83bd46b76c6ee86a - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6299/21982/llbase-0.9.3.506286-darwin64-506286.tar.bz2 - - name - darwin64 - - windows - - archive - - hash - e6865670f9bca1c82fb8b91db3ea515c - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6301/21994/llbase-0.9.3.506286-windows-506286.tar.bz2 - - name - windows - - - version - 0.9.3.506286 - llca copyright @@ -2955,52 +2855,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 8.35.500898 - requests - - copyright - Copyright 2016 Kenneth Reitz - description - Python HTTP Library - license - Apache - license_file - LICENSES/requests.txt - name - requests - platforms - - darwin64 - - archive - - hash - b8d134a970261b445a3f376ba4e05ff7 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6693/23788/requests-2.18.1-darwin64-506681.tar.bz2 - - name - darwin64 - - linux64 - - archive - - hash - a92f2235991871c3d601a73cfef9b2af - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4105/11530/requests-1.0-linux64-504094.tar.bz2 - - name - linux64 - - - source - https://bitbucket.org/lindenlab/p64_python-requests - source_type - hg - version - 2.18.1 - slvoice copyright @@ -3211,36 +3065,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 0.8.0.1 - urllib3 - - copyright - Copyright 2008-2016 Andrey Petrov and contributors (see CONTRIBUTORS.txt) - description - Python HTTP Library - license - MIT - license_file - LICENSES/urllib3.txt - name - urllib3 - platforms - - darwin64 - - archive - - hash - 22f64c7fbb6704d2e9519fd1cca8e49b - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6659/23560/urllib3-1.21.1-darwin64-506648.tar.bz2 - - name - darwin64 - - - version - 1.21.1 - viewer-manager copyright diff --git a/indra/cmake/LLBase.cmake b/indra/cmake/LLBase.cmake deleted file mode 100644 index 76e3c688a3..0000000000 --- a/indra/cmake/LLBase.cmake +++ /dev/null @@ -1,4 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -use_prebuilt_binary(llbase) diff --git a/indra/cmake/Requests.cmake b/indra/cmake/Requests.cmake deleted file mode 100644 index b9c729d697..0000000000 --- a/indra/cmake/Requests.cmake +++ /dev/null @@ -1,7 +0,0 @@ -if (DARWIN) - include (Prebuilt) - use_prebuilt_binary(requests) - use_prebuilt_binary(urllib3) - use_prebuilt_binary(chardet) - use_prebuilt_binary(idna) -endif (DARWIN) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 212677717e..e7111ebe54 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -16,7 +16,6 @@ include(GLOD) include(Hunspell) include(JsonCpp) include(LLAppearance) -include(LLBase) include(LLAudio) include(LLCA) include(LLCharacter) @@ -44,7 +43,6 @@ include(OPENAL) include(OpenGL) include(OpenSSL) include(PNG) -include(Requests) include(TemplateCheck) include(UI) include(UnixInstall) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 4f0f4b17d9..57da87a3ee 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -502,11 +502,6 @@ class WindowsManifest(ViewerManifest): self.path("*.png") self.path("*.gif") - #before, we only needed llbase at build time. With VMP, we need it at run time. - with self.prefix(src=os.path.join(pkgdir, "lib", "python", "llbase"), dst="llbase"): - self.path("*.py") - self.path("_cllsd.so") - # Plugin host application self.path2basename(os.path.join(os.pardir, 'llplugin', 'slplugin', self.args['configuration']), @@ -1386,9 +1381,6 @@ class LinuxManifest(ViewerManifest): #this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323 with self.prefix(src="../viewer_components/manager", dst=""): self.path("*.py") - with self.prefix(src=os.path.join("lib", "python", "llbase"), dst="llbase"): - self.path("*.py") - self.path("_cllsd.so") # recurses, packaged again self.path("res-sdl") From cc376f86e8496e9e924fd596064c13ee6aa0133e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 25 Sep 2018 11:21:34 -0400 Subject: [PATCH 25/59] DRTVWR-474: Update to viewer-manager build 519951 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 29066d7c49..7f18ab9abf 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 952c2e32e37ef67115ba3074892961c3 + 904caf508ec1718e1fc9cd321ad95715 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24508/190821/viewer_manager-2.0.519640-darwin64-519640.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24994/196128/viewer_manager-2.0.519951-darwin64-519951.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 7c8b210c1687a100f0b295d60ffac2c5 + e7f7ed2d40c1e554d038276fef690639 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24507/190827/viewer_manager-2.0.519640-windows-519640.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24996/196136/viewer_manager-2.0.519951-windows-519951.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.519640 + 2.0.519951 vlc-bin From 267e7d7554a4c11e8d745be3657eed923fa65876 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 26 Sep 2018 16:37:14 -0400 Subject: [PATCH 26/59] DRTVWR-474: Finish pulling in new viewer-release. --- autobuild.xml | 188 ++------------------------------------------------ 1 file changed, 6 insertions(+), 182 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 3107d77548..7f18ab9abf 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -225,36 +225,6 @@ version 1.57 - chardet - - copyright - Contributors to charset (see https://github.com/chardet/chardet) - description - Python Character Encoding Library - license - LGPL - license_file - LICENSES/chardet.txt - name - chardet - platforms - - darwin64 - - archive - - hash - 0124862b6a1b88455c78a68f8b823d21 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6662/23578/chardet-3.0.4-darwin64-506651.tar.bz2 - - name - darwin64 - - - version - 3.0.4 - colladadom copyright @@ -1465,36 +1435,6 @@ version 2012.1-2 - idna - - copyright - Copyright (c) 2013-2017, Kim Davies. All rights reserved. - description - Python Internationalized Domain Names in Applications (IDNA) Library - license - see idna.rst - license_file - LICENSES/idna.rst - name - idna - platforms - - darwin64 - - archive - - hash - 7dfe9fc4023d7d4f511dd9fac7258266 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6663/23584/idna-2.5-darwin64-506652.tar.bz2 - - name - darwin64 - - - version - 2.5 - jpeglib copyright @@ -2173,46 +2113,6 @@ version 0.0.1 - llbase - - copyright - Copyright (c) 2010, Linden Research, Inc. - license - mit - license_file - LICENSES/llbase-license.txt - name - llbase - platforms - - darwin64 - - archive - - hash - e18eeb0691af053b83bd46b76c6ee86a - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6299/21982/llbase-0.9.3.506286-darwin64-506286.tar.bz2 - - name - darwin64 - - windows - - archive - - hash - e6865670f9bca1c82fb8b91db3ea515c - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6301/21994/llbase-0.9.3.506286-windows-506286.tar.bz2 - - name - windows - - - version - 0.9.3.506286 - llca copyright @@ -2955,52 +2855,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 8.35.500898 - requests - - copyright - Copyright 2016 Kenneth Reitz - description - Python HTTP Library - license - Apache - license_file - LICENSES/requests.txt - name - requests - platforms - - darwin64 - - archive - - hash - b8d134a970261b445a3f376ba4e05ff7 - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6693/23788/requests-2.18.1-darwin64-506681.tar.bz2 - - name - darwin64 - - linux64 - - archive - - hash - a92f2235991871c3d601a73cfef9b2af - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4105/11530/requests-1.0-linux64-504094.tar.bz2 - - name - linux64 - - - source - https://bitbucket.org/lindenlab/p64_python-requests - source_type - hg - version - 2.18.1 - slvoice copyright @@ -3211,36 +3065,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 0.8.0.1 - urllib3 - - copyright - Copyright 2008-2016 Andrey Petrov and contributors (see CONTRIBUTORS.txt) - description - Python HTTP Library - license - MIT - license_file - LICENSES/urllib3.txt - name - urllib3 - platforms - - darwin64 - - archive - - hash - 22f64c7fbb6704d2e9519fd1cca8e49b - url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6659/23560/urllib3-1.21.1-darwin64-506648.tar.bz2 - - name - darwin64 - - - version - 1.21.1 - viewer-manager copyright @@ -3248,7 +3072,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors description Linden Lab Viewer Management Process suite. license - Proprietary + viewerlgpl license_file LICENSE name @@ -3260,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - ce95944fb842849108102263a25fc794 + 904caf508ec1718e1fc9cd321ad95715 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/23237/178332/viewer_manager-1.0.518840-darwin64-518840.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24994/196128/viewer_manager-2.0.519951-darwin64-519951.tar.bz2 name darwin64 @@ -3284,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 642f847a9ac45551af65a55826974334 + e7f7ed2d40c1e554d038276fef690639 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/23236/178338/viewer_manager-1.0.518840-windows-518840.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24996/196136/viewer_manager-2.0.519951-windows-519951.tar.bz2 name windows @@ -3297,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 1.0.518840 + 2.0.519951 vlc-bin From 0497b8a537f6549e287c789d661728b850763c79 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 26 Sep 2018 20:43:37 -0400 Subject: [PATCH 27/59] DRTVWR-447: Update to viewer-manager build 520046 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f615a52ba8..4c97752da1 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3314,9 +3314,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - ce95944fb842849108102263a25fc794 + 4785e25bde1503e99cb4c2fe344b3d4e url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/23237/178332/viewer_manager-1.0.518840-darwin64-518840.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25165/197744/viewer_manager-1.0.520046-darwin64-520046.tar.bz2 name darwin64 @@ -3338,9 +3338,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 642f847a9ac45551af65a55826974334 + b03866283b2cf3d8a79a93a07cbec9d6 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/23236/178338/viewer_manager-1.0.518840-windows-518840.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25166/197758/viewer_manager-1.0.520046-windows-520046.tar.bz2 name windows @@ -3351,7 +3351,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 1.0.518840 + 1.0.520046 vlc-bin From e1826d508c7bb5edc3917e090ad087b0b3a754cb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 26 Sep 2018 20:45:03 -0400 Subject: [PATCH 28/59] DRTVWR-474: Update to viewer-manager build 520047 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 7f18ab9abf..7f7cf02073 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 904caf508ec1718e1fc9cd321ad95715 + 0a1471744de42317b9462f0d9ddcc691 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24994/196128/viewer_manager-2.0.519951-darwin64-519951.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25167/197752/viewer_manager-2.0.520047-darwin64-520047.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - e7f7ed2d40c1e554d038276fef690639 + 278eb5ff960846ae69626880a2afa05a url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24996/196136/viewer_manager-2.0.519951-windows-519951.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25168/197765/viewer_manager-2.0.520047-windows-520047.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.519951 + 2.0.520047 vlc-bin From ec6487f3a70a5067f6d8fc601437160bb4fa753f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 27 Sep 2018 14:57:03 -0400 Subject: [PATCH 29/59] DRTVWR-474: Make LLEventMailDrop pass all saved events to listener. Previously, LLEventMailDrop would send only the first queued event to a newly-connected listener. If you wanted to flush all queued events, you'd have to "pump" the queue by repeatedly disconnecting and reconnecting -- with no good way to know when you'd caught up. The new behavior makes LLEventMailDrop resemble a multi-valued future: a rendezvous between producer and consumer that, once connected, pushes values rather than requiring them to be pulled (as with a simple queue) -- regardless of the relative order in which post() and listen() are called. --- indra/llcommon/llevents.cpp | 23 +++++++++++++++-------- indra/llcommon/llevents.h | 20 +++++++++++++------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index dce97b5411..eedd8c92b5 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -545,10 +545,8 @@ bool LLEventStream::post(const LLSD& event) *****************************************************************************/ bool LLEventMailDrop::post(const LLSD& event) { - bool posted = false; - - if (!mSignal->empty()) - posted = LLEventStream::post(event); + // forward the call to our base class + bool posted = LLEventStream::post(event); if (!posted) { // if the event was not handled we will save it for later so that it can @@ -564,16 +562,25 @@ LLBoundListener LLEventMailDrop::listen_impl(const std::string& name, const NameList& after, const NameList& before) { - if (!mEventHistory.empty()) + // Before actually connecting this listener for subsequent post() calls, + // first feed each of the saved events, in order, to the new listener. + // Remove any that this listener consumes -- Effective STL, Item 9. + for (auto hi(mEventHistory.begin()), hend(mEventHistory.end()); hi != hend; ) { - if (listener(mEventHistory.front())) + if (listener(*hi)) { - mEventHistory.pop_front(); + // new listener consumed this event, erase it + hi = mEventHistory.erase(hi); + } + else + { + // listener did not consume this event, just move along + ++hi; } } + // let base class perform the actual connection return LLEventStream::listen_impl(name, listener, after, before); - } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 1d51c660ed..5d60c63810 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -650,15 +650,21 @@ public: * LLEventMailDrop *****************************************************************************/ /** - * LLEventMailDrop is a specialization of LLEventStream. Events are posted normally, - * however if no listeners return that they have handled the event it is placed in - * a queue. Subsequent attaching listeners will receive stored events from the queue - * until a listener indicates that the event has been handled. In order to receive - * multiple events from a mail drop the listener must disconnect and reconnect. + * LLEventMailDrop is a specialization of LLEventStream. Events are posted + * normally, however if no listener returns that it has handled the event + * (returns true), it is placed in a queue. Subsequent attaching listeners + * will receive stored events from the queue until some listener indicates + * that the event has been handled. + * + * LLEventMailDrop completely decouples the timing of post() calls from + * listen() calls: every event posted to an LLEventMailDrop is eventually seen + * by all listeners, until some listener consumes it. The caveat is that each + * event *must* eventually reach a listener that will consume it, else the + * queue will grow to arbitrary length. * * @NOTE: When using an LLEventMailDrop (or LLEventQueue) with a LLEventTimeout or - * LLEventFilter attaching the filter downstream using Timeout's constructor will - * cause the MailDrop to discharge any of it's stored events. The timeout should + * LLEventFilter attaching the filter downstream, using Timeout's constructor will + * cause the MailDrop to discharge any of its stored events. The timeout should * instead be connected upstream using its listen() method. * See llcoro::suspendUntilEventOnWithTimeout() for an example. */ From 371a412a28377527b9aede016e9b482df95ea901 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 27 Sep 2018 17:40:10 -0400 Subject: [PATCH 30/59] DRTVWR-474: Update to viewer-manager build 520085 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 7f7cf02073..243954a9ba 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 0a1471744de42317b9462f0d9ddcc691 + 0a254644186f5523b0261d9427bf3e31 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25167/197752/viewer_manager-2.0.520047-darwin64-520047.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25233/198295/viewer_manager-2.0.520085-darwin64-520085.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 278eb5ff960846ae69626880a2afa05a + fee2780a7172732633cd115fdc7925ff url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25168/197765/viewer_manager-2.0.520047-windows-520047.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25234/198302/viewer_manager-2.0.520085-windows-520085.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520047 + 2.0.520085 vlc-bin From 182a091ad961fb296aafc974509746a4dff54421 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 27 Sep 2018 17:41:26 -0400 Subject: [PATCH 31/59] DRTVWR-474: Pass the leap updater the parameters it requires. --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llappviewer.cpp | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8e8cce5787..26572a7917 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4316,6 +4316,17 @@ Value 96.0 + ForceAddressSize + + Comment + Force Windows update to 32-bit or 64-bit viewer. + Persist + 1 + Type + U32 + Value + 0 + ForceAssetFail Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5a374755f7..776fc85a2d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1130,21 +1130,29 @@ bool LLAppViewer::init() gGLActive = FALSE; -#if LL_WINDOWS std::vector updater +#if LL_WINDOWS { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe") }; #elif LL_DARWIN // explicitly run the system Python interpreter on updater.py - std::vector updater { "python", gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py") }; #else - std::vector updater { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater") }; #endif // add LEAP mode command-line argument to whichever of these we selected updater.push_back("leap"); + // UpdaterServiceSettings + updater.push_back(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); + // channel + updater.push_back(LLVersionInfo::getChannel()); + // testok + updater.push_back(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); + // UpdaterServiceURL + updater.push_back(gSavedSettings.getString("UpdaterServiceURL")); + // ForceAddressSize + updater.push_back(stringize(gSavedSettings.getU32("ForceAddressSize"))); - // Run the updater. An exception from the updater should bother us. + // Run the updater. An exception from launching the updater should bother us. LLLeap::create("updater process", updater, true); // Iterate over --leap command-line options. But this is a bit tricky: if From b6e58b3b3af60c90a283949060f5532856d3198e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 28 Sep 2018 17:16:14 -0400 Subject: [PATCH 32/59] DRTVWR-474: Update to viewer-manager build 520110 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 243954a9ba..f92492ec1e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 0a254644186f5523b0261d9427bf3e31 + 1cb4af868486605d788ca75ffc786d2d url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25233/198295/viewer_manager-2.0.520085-darwin64-520085.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25263/198729/viewer_manager-2.0.520110-darwin64-520110.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - fee2780a7172732633cd115fdc7925ff + f4e68dcae8439c4e08cdb2843812e224 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25234/198302/viewer_manager-2.0.520085-windows-520085.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25264/198736/viewer_manager-2.0.520110-windows-520110.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520085 + 2.0.520110 vlc-bin From 6e1b2e137e2b6c6d92d14f478b6908c0c2f1e231 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 28 Sep 2018 17:16:49 -0400 Subject: [PATCH 33/59] DRTVWR-474: Make SkipBenchmark a Persistent setting --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 26572a7917..ca13c60768 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16183,7 +16183,7 @@ if true, disables running the GPU benchmark at startup (default to class 1) Persist - 0 + 1 Type Boolean Value From b1955d4247a4d28a3a4c259036390ff632e80008 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 3 Oct 2018 14:00:05 -0400 Subject: [PATCH 34/59] DRTVWR-474: Do NOT autokill updater process on viewer termination. The updater is required to survive beyond termination of the viewer that launched it so it can launch the next installer, or a replacement viewer. Having the old viewer forcibly terminate it on shutdown would be counter- productive. Introduce a third LLLeap::create() overload taking LLProcess::Params, which gives access to autokill, cwd and other options previously unsupported by LLLeap. Reimplement the existing create() overloads in terms of this new one, since LLLeapImpl::LLLeapImpl() is already based on LLProcess::Params anyway. Use LLProcess::Params in LLAppViewer::init() to specify the updater process, setting autokill=false. Refactoring LLLeapImpl() apparently involved engaging an LLInitParam::Block feature never before used: had to drag operator() into Multiple from its base class TypedParam (as has been done in other TypedParam subclasses). --- indra/llcommon/llinitparam.h | 3 +++ indra/llcommon/llleap.cpp | 51 ++++++++++++++++++++++------------- indra/llcommon/llleap.h | 14 ++++++++++ indra/newview/llappviewer.cpp | 33 +++++++++++------------ 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index f1f4226c40..7f5b9b4ac2 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -2115,6 +2115,9 @@ namespace LLInitParam typedef typename super_t::iterator iterator; typedef typename super_t::const_iterator const_iterator; + using super_t::operator(); + using super_t::operator const container_t&; + explicit Multiple(const char* name = "") : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) {} diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index c87d2a3e58..cf8f8cc6a5 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -47,9 +47,9 @@ class LLLeapImpl: public LLLeap LOG_CLASS(LLLeap); public: // Called only by LLLeap::create() - LLLeapImpl(const std::string& desc, const std::vector& plugin): + LLLeapImpl(const LLProcess::Params& cparams): // We might reassign mDesc in the constructor body if it's empty here. - mDesc(desc), + mDesc(cparams.desc), // We expect multiple LLLeapImpl instances. Definitely tweak // mDonePump's name for uniqueness. mDonePump("LLLeap", true), @@ -67,17 +67,17 @@ public: // this class or method name. mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2))) { - // Rule out empty vector - if (plugin.empty()) + // Rule out unpopulated Params block + if (! cparams.executable.isProvided()) { LLTHROW(Error("no plugin command")); } // Don't leave desc empty either, but in this case, if we weren't // given one, we'll fake one. - if (desc.empty()) + if (mDesc.empty()) { - mDesc = LLProcess::basename(plugin[0]); + mDesc = LLProcess::basename(cparams.executable); // how about a toLower() variant that returns the transformed string?! std::string desclower(mDesc); LLStringUtil::toLower(desclower); @@ -87,9 +87,9 @@ public: // notice Python specially: we provide Python LLSD serialization // support, so there's a pretty good reason to implement plugins // in that language. - if (plugin.size() >= 2 && (desclower == "python" || desclower == "python.exe")) + if (cparams.args.size() && (desclower == "python" || desclower == "python.exe")) { - mDesc = LLProcess::basename(plugin[1]); + mDesc = LLProcess::basename(cparams.args()[0]); } } @@ -97,14 +97,10 @@ public: mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::bad_launch, this, _1)); // Okay, launch child. - LLProcess::Params params; + // Get a modifiable copy of params block to set files and postend. + LLProcess::Params params(cparams); + // copy our deduced mDesc back into the params block params.desc = mDesc; - std::vector::const_iterator pi(plugin.begin()), pend(plugin.end()); - params.executable = *pi++; - for ( ; pi != pend; ++pi) - { - params.args.add(*pi); - } params.files.add(LLProcess::FileParam("pipe")); // stdin params.files.add(LLProcess::FileParam("pipe")); // stdout params.files.add(LLProcess::FileParam("pipe")); // stderr @@ -429,17 +425,17 @@ private: boost::scoped_ptr mListener; }; -// This must follow the declaration of LLLeapImpl, so it may as well be last. -LLLeap* LLLeap::create(const std::string& desc, const std::vector& plugin, bool exc) +// These must follow the declaration of LLLeapImpl, so they may as well be last. +LLLeap* LLLeap::create(const LLProcess::Params& params, bool exc) { // If caller is willing to permit exceptions, just instantiate. if (exc) - return new LLLeapImpl(desc, plugin); + return new LLLeapImpl(params); // Caller insists on suppressing LLLeap::Error. Very well, catch it. try { - return new LLLeapImpl(desc, plugin); + return new LLLeapImpl(params); } catch (const LLLeap::Error&) { @@ -447,6 +443,23 @@ LLLeap* LLLeap::create(const std::string& desc, const std::vector& } } +LLLeap* LLLeap::create(const std::string& desc, const std::vector& plugin, bool exc) +{ + LLProcess::Params params; + params.desc = desc; + std::vector::const_iterator pi(plugin.begin()), pend(plugin.end()); + // could validate here, but let's rely on LLLeapImpl's constructor + if (pi != pend) + { + params.executable = *pi++; + } + for ( ; pi != pend; ++pi) + { + params.args.add(*pi); + } + return create(params, exc); +} + LLLeap* LLLeap::create(const std::string& desc, const std::string& plugin, bool exc) { // Use LLStringUtil::getTokens() to parse the command line diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index 8aac8a64c5..7cecdf2f8f 100644 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h @@ -14,6 +14,7 @@ #include "llinstancetracker.h" #include "llexception.h" +#include "llprocess.h" #include #include @@ -61,6 +62,19 @@ public: static LLLeap* create(const std::string& desc, const std::string& plugin, bool exc=true); + /** + * Pass an LLProcess::Params instance to specify desc, executable, args et al. + * + * Note that files and postend are set implicitly; any values you set in + * those fields will be disregarded. + * + * Pass exc=false to suppress LLLeap::Error exception. Obviously in that + * case the caller cannot discover the nature of the error, merely that an + * error of some kind occurred (because create() returned NULL). Either + * way, the error is logged. + */ + static LLLeap* create(const LLProcess::Params& params, bool exc=true); + /** * Exception thrown for invalid create() arguments, e.g. no plugin * program. This is more resiliant than an LL_ERRS failure, because the diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 776fc85a2d..bc4ce19f77 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1130,30 +1130,35 @@ bool LLAppViewer::init() gGLActive = FALSE; - std::vector updater + LLProcess::Params updater; + updater.desc = "updater process"; + // Because it's the updater, it MUST persist beyond the lifespan of the + // viewer itself. + updater.autokill = false; #if LL_WINDOWS - { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe") }; + updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe"); #elif LL_DARWIN // explicitly run the system Python interpreter on updater.py - { "python", gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py") }; + updater.executable = "python"; + updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py")); #else - { gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater") }; + updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater"); #endif // add LEAP mode command-line argument to whichever of these we selected - updater.push_back("leap"); + updater.args.add("leap"); // UpdaterServiceSettings - updater.push_back(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); + updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting"))); // channel - updater.push_back(LLVersionInfo::getChannel()); + updater.args.add(LLVersionInfo::getChannel()); // testok - updater.push_back(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); + updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest"))); // UpdaterServiceURL - updater.push_back(gSavedSettings.getString("UpdaterServiceURL")); + updater.args.add(gSavedSettings.getString("UpdaterServiceURL")); // ForceAddressSize - updater.push_back(stringize(gSavedSettings.getU32("ForceAddressSize"))); + updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize"))); // Run the updater. An exception from launching the updater should bother us. - LLLeap::create("updater process", updater, true); + LLLeap::create(updater, true); // Iterate over --leap command-line options. But this is a bit tricky: if // there's only one, it won't be an array at all. @@ -3923,12 +3928,6 @@ void LLAppViewer::requestQuit() gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent. } - // Try to send last batch of avatar rez metrics. - if (!gDisconnected && isAgentAvatarValid()) - { - gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent. - } - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); effectp->setPositionGlobal(gAgent.getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); From 05068186c349294caf4fef3c970f9d75a9f30460 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 4 Oct 2018 16:35:38 -0400 Subject: [PATCH 35/59] DRTVWR-474: Make login coroutine sync with updater process on failure. Specifically, introduce an LLEventMailDrop("LoginSync"). When the updater detects that an update is required, it will post to that rendezvous point. When login.cgi responds with login failure, make the login coroutine wait (a few seconds) for that ping from the updater. If we receive that ping and if it contains a "reply" key, make the fail.login listener respond to the updater with an indication of whether to proceed with update. If both login.cgi and the updater concur that an update is required, produce a new confirmation message for the user and then (once user responds) tell the updater to proceed. Otherwise, produce the usual login-failure message and tell the updater never mind. Introduce LLCoro::OverrideConsuming to provide temporary save/restore of the set_consuming() / get_consuming() flag. It's a good idea to set the consuming flag when retrieving data from an LLEventMailDrop. --- indra/llcommon/llcoros.h | 20 ++++++ indra/newview/lllogininstance.cpp | 63 ++++++++++++++++--- indra/newview/lllogininstance.h | 6 +- .../skins/default/xui/en/notifications.xml | 13 +++- indra/viewer_components/login/lllogin.cpp | 56 +++++++++++++++-- 5 files changed, 142 insertions(+), 16 deletions(-) diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 8fb27af6a4..c551413811 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -169,6 +169,26 @@ public: static void set_consuming(bool consuming); static bool get_consuming(); + /** + * RAII control of the consuming flag + */ + class OverrideConsuming + { + public: + OverrideConsuming(bool consuming): + mPrevConsuming(get_consuming()) + { + set_consuming(consuming); + } + ~OverrideConsuming() + { + set_consuming(mPrevConsuming); + } + + private: + bool mPrevConsuming; + }; + /** * Please do NOT directly use boost::dcoroutines::future! It is essential * to maintain the "current" coroutine at every context switch. This diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index bc93fa2c20..126c6be388 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -253,14 +253,12 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event) mLoginState = event["state"].asString(); mResponseData = event["data"]; - + if(event.has("transfer_rate")) { mTransferRate = event["transfer_rate"].asReal(); } - - // Call the method registered in constructor, if any, for more specific // handling mDispatcher.try_call(event); @@ -276,6 +274,14 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) // Login has failed. // Figure out why and respond... LLSD response = event["data"]; + LLSD updater = response["updater"]; + + // Always provide a response to the updater, if in fact the updater + // contacted us, if in fact the ping contains a 'reply' key. Most code + // paths tell it not to proceed with updating. + ResponsePtr resp(std::make_shared + (LLSDMap("update", false), updater)); + std::string reason_response = response["reason"].asString(); std::string message_response = response["message"].asString(); LL_DEBUGS("LLLogin") << "reason " << reason_response @@ -328,17 +334,44 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) } else if(reason_response == "update") { - // This shouldn't happen - the viewer manager should have forced an update; - // possibly the user ran the viewer directly and bypassed the update check + // This can happen if the user clicked Login quickly, before we heard + // back from the Viewer Version Manager, but login failed because + // login.cgi is insisting on a required update. We were called with an + // event that bundles both the login.cgi 'response' and the + // synchronization event from the 'updater'. std::string required_version = response["message_args"]["VERSION"]; LL_WARNS("LLLogin") << "Login failed because an update to version " << required_version << " is required." << LL_ENDL; if (gViewerWindow) gViewerWindow->setShowProgress(FALSE); - LLSD data(LLSD::emptyMap()); - data["VERSION"] = required_version; - LLNotificationsUtil::add("RequiredUpdate", data, LLSD::emptyMap(), boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2)); + LLSD args(LLSDMap("VERSION", required_version)); + if (updater.isUndefined()) + { + // If the updater failed to shake hands, better advise the user to + // download the update him/herself. + LLNotificationsUtil::add( + "RequiredUpdate", + args, + updater, + boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2)); + } + else + { + // If we've heard from the updater that an update is required, + // then display the prompt that assures the user we'll take care + // of it. This is the one case in which we bind 'resp': + // instead of destroying our Response object (and thus sending a + // negative reply to the updater) as soon as we exit this + // function, bind our shared_ptr so it gets passed into + // syncWithUpdater. That ensures that the response is delayed + // until the user has responded to the notification. + LLNotificationsUtil::add( + "PauseForUpdate", + args, + updater, + boost::bind(&LLLoginInstance::syncWithUpdater, this, resp, _1, _2)); + } } else if( reason_response == "key" || reason_response == "presence" @@ -361,6 +394,19 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) } } +void LLLoginInstance::syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response) +{ + LL_INFOS("LLLogin") << "LLLoginInstance::syncWithUpdater" << LL_ENDL; + // 'resp' points to an instance of LLEventAPI::Response that will be + // destroyed as soon as we return and the notification response functor is + // unregistered. Modify it so that it tells the updater to go ahead and + // perform the update. Naturally, if we allowed the user a choice as to + // whether to proceed or not, this assignment would reflect the user's + // selection. + (*resp)["update"] = true; + attemptComplete(); +} + void LLLoginInstance::handleLoginDisallowed(const LLSD& notification, const LLSD& response) { attemptComplete(); @@ -420,7 +466,6 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) return true; } - std::string construct_start_string() { std::string start; diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 651ad10afb..b759b43474 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -28,8 +28,10 @@ #define LL_LLLOGININSTANCE_H #include "lleventdispatcher.h" +#include "lleventapi.h" #include #include +#include // std::shared_ptr #include "llsecapi.h" class LLLogin; class LLEventStream; @@ -68,6 +70,7 @@ public: LLNotificationsInterface& getNotificationsInterface() const { return *mNotifications; } private: + typedef std::shared_ptr ResponsePtr; void constructAuthParams(LLPointer user_credentials); void updateApp(bool mandatory, const std::string& message); bool updateDialogCallback(const LLSD& notification, const LLSD& response); @@ -77,7 +80,8 @@ private: void handleLoginSuccess(const LLSD& event); void handleDisconnect(const LLSD& event); void handleIndeterminate(const LLSD& event); - void handleLoginDisallowed(const LLSD& notification, const LLSD& response); + void handleLoginDisallowed(const LLSD& notification, const LLSD& response); + void syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response); bool handleTOSResponse(bool v, const std::string& key); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 9eaa5330c3..5f9b8adc89 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3841,7 +3841,6 @@ Finished download of raw terrain file to: name="RequiredUpdate" type="alertmodal"> Version [VERSION] is required for login. -This should have been updated for you but apparently was not. Please download from https://secondlife.com/support/downloads/ confirm + +Version [VERSION] is required for login. +Click OK to download and install. + confirm + + + Date: Thu, 4 Oct 2018 17:18:08 -0400 Subject: [PATCH 36/59] DRTVWR-474: Make "LLNotifications" "requestAdd" propagate "reqid" from request to response to help with request/response matching protocol. --- indra/llui/llnotificationslistener.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index b6a32a0e78..be26416cbb 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -90,9 +90,12 @@ void LLNotificationsListener::requestAdd(const LLSD& event_data) const { if(event_data.has("reply")) { + LLSD payload(event_data["payload"]); + // copy reqid, if provided, to link response with request + payload["reqid"] = event_data["reqid"]; mNotifications.add(event_data["name"], event_data["substitutions"], - event_data["payload"], + payload, boost::bind(&LLNotificationsListener::NotificationResponder, this, event_data["reply"].asString(), @@ -112,10 +115,12 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum const LLSD& notification, const LLSD& response) const { - LLSD reponse_event; - reponse_event["notification"] = notification; - reponse_event["response"] = response; - LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); + LLSD response_event; + response_event["notification"] = notification; + response_event["response"] = response; + // surface reqid at top level of response for request/response protocol + response_event["reqid"] = notification["payload"]["reqid"]; + LLEventPumps::getInstance()->obtain(reply_pump).post(response_event); } void LLNotificationsListener::listChannels(const LLSD& params) const From a3e569c90d7cc45d0e2bef77d36d4fea8924af6d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 5 Oct 2018 14:38:25 -0400 Subject: [PATCH 37/59] DRTVWR-474: Add OptionaUpdateReady, PromptOptionalUpdate notifications. --- .../skins/default/xui/en/notifications.xml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 5f9b8adc89..e2859603e0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3860,6 +3860,32 @@ Click OK to download and install. yestext="OK"/> + +Version [VERSION] has been downloaded and is ready to install. +Click OK to install. + confirm + + + + +Version [VERSION] has been downloaded and is ready to install. +Proceed? + confirm + + + Date: Fri, 5 Oct 2018 15:29:08 -0400 Subject: [PATCH 38/59] DRTVWR-474: Update to viewer-manager build 520325 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f92492ec1e..10dcc5c2a0 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 1cb4af868486605d788ca75ffc786d2d + be69b65c9372562ce1aeb884802fdf1e url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25263/198729/viewer_manager-2.0.520110-darwin64-520110.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25619/201842/viewer_manager-2.0.520325-darwin64-520325.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - f4e68dcae8439c4e08cdb2843812e224 + 5934273cf5272982926f553baf5505b8 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25264/198736/viewer_manager-2.0.520110-windows-520110.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25623/201856/viewer_manager-2.0.520325-windows-520325.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520110 + 2.0.520325 vlc-bin From d87cc1859f3f96b98a627fdc674e297e78438681 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 11 Oct 2018 14:17:52 -0400 Subject: [PATCH 39/59] Modify logging so that the in-viewer console and stderr do not escape line breaks Improve the implementation so that escaping is computed only once --- indra/llcommon/llerror.cpp | 149 ++++++++++++++-------- indra/llcommon/llerrorcontrol.h | 19 ++- indra/llcommon/tests/llerror_test.cpp | 68 +++++----- indra/newview/app_settings/logcontrol.xml | 1 - indra/newview/app_settings/settings.xml | 11 -- indra/newview/llappviewer.cpp | 7 +- indra/newview/llviewerwindow.cpp | 3 + indra/test/test.cpp | 1 - 8 files changed, 152 insertions(+), 107 deletions(-) diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 6dfb4bf028..668ea1f7d2 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -119,8 +119,6 @@ namespace { { LL_INFOS() << "Error setting log file to " << filename << LL_ENDL; } - mWantsTime = true; - mWantsTags = true; } ~RecordToFile() @@ -146,7 +144,7 @@ namespace { public: RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE) { - mWantsTime = timestamp; + this->showMultiline(true); } virtual void recordMessage(LLError::ELevel level, @@ -207,7 +205,13 @@ namespace { class RecordToFixedBuffer : public LLError::Recorder { public: - RecordToFixedBuffer(LLLineBuffer* buffer) : mBuffer(buffer) { } + RecordToFixedBuffer(LLLineBuffer* buffer) + : mBuffer(buffer) + { + this->showMultiline(true); + this->showTags(false); + this->showLocation(false); + } virtual void recordMessage(LLError::ELevel level, const std::string& message) @@ -224,7 +228,11 @@ namespace { { public: RecordToWinDebug() - {} + { + this->showMultiline(true); + this->showTags(false); + this->showLocation(false); + } virtual void recordMessage(LLError::ELevel level, const std::string& message) @@ -411,8 +419,6 @@ namespace LLError public: virtual ~SettingsConfig(); - bool mPrintLocation; - LLError::ELevel mDefaultLevel; LevelMap mFunctionLevelMap; @@ -453,7 +459,6 @@ namespace LLError SettingsConfig::SettingsConfig() : LLRefCount(), - mPrintLocation(false), mDefaultLevel(LLError::LEVEL_DEBUG), mFunctionLevelMap(), mClassLevelMap(), @@ -655,12 +660,6 @@ namespace LLError commonInit(user_dir, app_dir, log_to_stderr); } - void setPrintLocation(bool print) - { - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - s->mPrintLocation = print; - } - void setFatalFunction(const FatalFunction& f) { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); @@ -775,7 +774,6 @@ namespace LLError s->mTagLevelMap.clear(); s->mUniqueLogMessages.clear(); - setPrintLocation(config["print-location"]); setDefaultLevel(decodeLevel(config["default-level"])); LLSD sets = config["settings"]; @@ -798,11 +796,12 @@ namespace LLError namespace LLError { Recorder::Recorder() - : mWantsTime(false), - mWantsTags(false), - mWantsLevel(true), - mWantsLocation(false), - mWantsFunctionName(true) + : mWantsTime(true) + , mWantsTags(true) + , mWantsLevel(true) + , mWantsLocation(true) + , mWantsFunctionName(true) + , mWantsMultiline(false) { } @@ -839,6 +838,42 @@ namespace LLError return mWantsFunctionName; } + // virtual + bool Recorder::wantsMultiline() + { + return mWantsMultiline; + } + + void Recorder::showTime(bool show) + { + mWantsTime = show; + } + + void Recorder::showTags(bool show) + { + mWantsTags = show; + } + + void Recorder::showLevel(bool show) + { + mWantsLevel = show; + } + + void Recorder::showLocation(bool show) + { + mWantsLocation = show; + } + + void Recorder::showFunctionName(bool show) + { + mWantsFunctionName = show; + } + + void Recorder::showMultiline(bool show) + { + mWantsMultiline = show; + } + void addRecorder(RecorderPtr recorder) { if (!recorder) @@ -871,17 +906,15 @@ namespace LLError s->mFileRecorder.reset(); s->mFileRecorderFileName.clear(); - if (file_name.empty()) + if (!file_name.empty()) { - return; - } - - RecorderPtr recordToFile(new RecordToFile(file_name)); - if (boost::dynamic_pointer_cast(recordToFile)->okay()) - { - s->mFileRecorderFileName = file_name; - s->mFileRecorder = recordToFile; - addRecorder(recordToFile); + RecorderPtr recordToFile(new RecordToFile(file_name)); + if (boost::dynamic_pointer_cast(recordToFile)->okay()) + { + s->mFileRecorderFileName = file_name; + s->mFileRecorder = recordToFile; + addRecorder(recordToFile); + } } } @@ -892,14 +925,12 @@ namespace LLError removeRecorder(s->mFixedBufferRecorder); s->mFixedBufferRecorder.reset(); - if (!fixedBuffer) + if (fixedBuffer) { - return; - } - - RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer)); - s->mFixedBufferRecorder = recordToFixedBuffer; - addRecorder(recordToFixedBuffer); + RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer)); + s->mFixedBufferRecorder = recordToFixedBuffer; + addRecorder(recordToFixedBuffer); + } } std::string logFileName() @@ -911,8 +942,9 @@ namespace LLError namespace { - void addEscapedMessage(std::ostream& out, const std::string& message) + std::string escapedMessageLines(const std::string& message) { + std::ostringstream out; size_t written_out = 0; size_t all_content = message.length(); size_t escape_char_index; // always relative to start of message @@ -948,13 +980,16 @@ namespace // write whatever was left out << message.substr(written_out, std::string::npos); } + return out.str(); } - void writeToRecorders(const LLError::CallSite& site, const std::string& escaped_message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true) + void writeToRecorders(const LLError::CallSite& site, const std::string& message) { LLError::ELevel level = site.mLevel; LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); - + + std::string escaped_message; + for (Recorders::const_iterator i = s->mRecorders.begin(); i != s->mRecorders.end(); ++i) @@ -969,7 +1004,7 @@ namespace } message_stream << " "; - if (show_level && r->wantsLevel()) + if (r->wantsLevel()) { message_stream << site.mLevelString; } @@ -981,19 +1016,30 @@ namespace } message_stream << " "; - if (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation) + if (r->wantsLocation() || level == LLError::LEVEL_ERROR) { message_stream << site.mLocationString; } message_stream << " "; - if (show_function && r->wantsFunctionName()) + if (r->wantsFunctionName()) { message_stream << site.mFunctionString; } message_stream << " : "; - message_stream << escaped_message; + if (r->wantsMultiline()) + { + message_stream << message; + } + else + { + if (escaped_message.empty()) + { + escaped_message = escapedMessageLines(message); + } + message_stream << escaped_message; + } r->recordMessage(level, message_stream.str()); } @@ -1236,10 +1282,11 @@ namespace LLError delete out; } - std::ostringstream message_stream; if (site.mPrintOnce) { + std::ostringstream message_stream; + std::map::iterator messageIter = s->mUniqueLogMessages.find(message); if (messageIter != s->mUniqueLogMessages.end()) { @@ -1259,19 +1306,18 @@ namespace LLError message_stream << "ONCE: "; s->mUniqueLogMessages[message] = 1; } + message_stream << message; + message = message_stream.str(); } - addEscapedMessage(message_stream, message); - std::string message_line(message_stream.str()); - - writeToRecorders(site, message_line); + writeToRecorders(site, message); if (site.mLevel == LEVEL_ERROR) { - g->mFatalMessage = message_line; + g->mFatalMessage = message; if (s->mCrashFunction) { - s->mCrashFunction(message_line); + s->mCrashFunction(message); } } } @@ -1579,3 +1625,4 @@ bool debugLoggingEnabled(const std::string& tag) } + diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index ddbcdc94a0..a6278b3e50 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -148,13 +148,22 @@ namespace LLError bool wantsLevel(); bool wantsLocation(); bool wantsFunctionName(); + bool wantsMultiline(); + + void showTime(bool show); + void showTags(bool show); + void showLevel(bool show); + void showLocation(bool show); + void showFunctionName(bool show); + void showMultiline(bool show); protected: - bool mWantsTime, - mWantsTags, - mWantsLevel, - mWantsLocation, - mWantsFunctionName; + bool mWantsTime; + bool mWantsTags; + bool mWantsLevel; + bool mWantsLocation; + bool mWantsFunctionName; + bool mWantsMultiline; }; typedef boost::shared_ptr RecorderPtr; diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index ce0dbce075..bd0357e4bf 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -78,8 +78,12 @@ namespace tut class TestRecorder : public LLError::Recorder { public: - TestRecorder() { mWantsTime = false; mWantsTags = true; } - virtual ~TestRecorder() { } + TestRecorder() + { + showTime(false); + } + virtual ~TestRecorder() + {} virtual void recordMessage(LLError::ELevel level, const std::string& message) @@ -90,8 +94,6 @@ namespace tut int countMessages() { return (int) mMessages.size(); } void clearMessages() { mMessages.clear(); } - void setWantsTime(bool t) { mWantsTime = t; } - std::string message(int n) { std::ostringstream test_name; @@ -139,9 +141,14 @@ namespace tut } void setWantsTime(bool t) - { - boost::dynamic_pointer_cast(mRecorder)->setWantsTime(t); - } + { + boost::dynamic_pointer_cast(mRecorder)->showTime(t); + } + + void setWantsMultiline(bool t) + { + boost::dynamic_pointer_cast(mRecorder)->showMultiline(t); + } std::string message(int n) { @@ -378,27 +385,6 @@ namespace } } -namespace tut -{ - template<> template<> - void ErrorTestObject::test<5>() - // file and line information in log messages - { - std::string location = writeReturningLocation(); - // expecting default to not print location information - - LLError::setPrintLocation(true); - writeReturningLocation(); - - LLError::setPrintLocation(false); - writeReturningLocation(); - - ensure_message_does_not_contain(0, location); - ensure_message_field_equals(1, LOCATION_FIELD, location); - ensure_message_does_not_contain(2, location); - } -} - /* The following helper functions and class members all log a simple message from some particular function scope. Each function takes a bool argument that indicates if it should log its own name or not (in the manner that @@ -583,7 +569,6 @@ namespace tut // special handling of LL_ERRS() calls void ErrorTestObject::test<8>() { - LLError::setPrintLocation(false); std::string location = errorReturningLocation(); ensure_message_field_equals(0, LOCATION_FIELD, location); @@ -630,15 +615,15 @@ namespace tut // output order void ErrorTestObject::test<10>() { - LLError::setPrintLocation(true); LLError::setTimeFunction(roswell); setWantsTime(true); + std::string location, function; writeReturningLocationAndFunction(location, function); ensure_equals("order is time level tags location function message", - message(0), + message(0), roswell() + " INFO " + "# " /* no tag */ + location + " " + function + " : " + "apple"); } @@ -658,7 +643,7 @@ namespace tut LLError::setTimeFunction(roswell); LLError::RecorderPtr anotherRecorder(new TestRecorder()); - boost::dynamic_pointer_cast(anotherRecorder)->setWantsTime(true); + boost::dynamic_pointer_cast(anotherRecorder)->showTime(true); LLError::addRecorder(anotherRecorder); LL_INFOS() << "baz" << LL_ENDL; @@ -896,6 +881,25 @@ namespace tut } } +namespace tut +{ + template<> template<> + void ErrorTestObject::test<19>() + // backslash, return, and newline are not escaped with backslashes + { + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + setWantsMultiline(true); + writeMsgNeedsEscaping(); // but should not be now + ensure_message_field_equals(0, MSG_FIELD, "backslash\\"); + ensure_message_field_equals(1, MSG_FIELD, "newline\nafternewline"); + ensure_message_field_equals(2, MSG_FIELD, "return\rafterreturn"); + ensure_message_field_equals(3, MSG_FIELD, "backslash\\backslash\\"); + ensure_message_field_equals(4, MSG_FIELD, "backslash\\newline\nanothernewline\nafternewline"); + ensure_message_field_equals(5, MSG_FIELD, "backslash\\returnnewline\r\n\\afterbackslash"); + ensure_message_count(6); + } +} + /* Tests left: handling of classes without LOG_CLASS diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 71445ea541..8ced81fdb3 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -2,7 +2,6 @@ default-level INFO - print-location true settings diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8e8cce5787..44aa22b387 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13980,17 +13980,6 @@ Value 1 - VerboseLogs - - Comment - Display source file and line number for each log item for debugging purposes - Persist - 1 - Type - Boolean - Value - 0 - VertexShaderEnable Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index dd82aa735f..b3f09a73a2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -885,11 +885,6 @@ bool LLAppViewer::init() mNumSessions++; gSavedSettings.setS32("NumSessions", mNumSessions); - if (gSavedSettings.getBOOL("VerboseLogs")) - { - LLError::setPrintLocation(true); - } - // LLKeyboard relies on LLUI to know what some accelerator keys are called. LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); @@ -1702,7 +1697,7 @@ bool LLAppViewer::cleanup() release_start_screen(); // just in case - LLError::logToFixedBuffer(NULL); + LLError::logToFixedBuffer(NULL); // stop the fixed buffer recorder LL_INFOS() << "Cleaning Up" << LL_ENDL; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 01ec703fe6..873d011acc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -306,6 +306,9 @@ private: RecordToChatConsole::RecordToChatConsole(): mRecorder(new RecordToChatConsoleRecorder()) { + mRecorder->showTags(false); + mRecorder->showLocation(false); + mRecorder->showMultiline(true); } //////////////////////////////////////////////////////////////////////////// diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 80c84d9bea..9d6e9539cb 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -535,7 +535,6 @@ int main(int argc, char **argv) LLError::setDefaultLevel(LLError::LEVEL_DEBUG); } LLError::setFatalFunction(wouldHaveCrashed); - LLError::setPrintLocation(true); std::string test_app_name(argv[0]); std::string test_log = test_app_name + ".log"; LLFile::remove(test_log); From f960db28b72b9a1390e9e5e60f135806bfb9ced5 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 11 Oct 2018 20:52:01 -0400 Subject: [PATCH 40/59] DRTVWR-474: Update to viewer-manager build 520566 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 10dcc5c2a0..e9bd57b4e0 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - be69b65c9372562ce1aeb884802fdf1e + 55535daa041b922c22902b9d9e5d2b60 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25619/201842/viewer_manager-2.0.520325-darwin64-520325.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25997/204690/viewer_manager-2.0.520566-darwin64-520566.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 5934273cf5272982926f553baf5505b8 + 23e95f315f0adf957585af3f4eb42e88 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25623/201856/viewer_manager-2.0.520325-windows-520325.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25999/204773/viewer_manager-2.0.520566-windows-520566.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520325 + 2.0.520566 vlc-bin From 3abc0095c9e39faf8976ef815b0da656423c4905 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 12 Oct 2018 14:08:59 -0400 Subject: [PATCH 41/59] DRTVWR-474: Update to viewer-manager build 520576 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index e9bd57b4e0..f0358eb8ba 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3084,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 55535daa041b922c22902b9d9e5d2b60 + eeeb18f7396de3147c6d958dfbc1a2e5 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25997/204690/viewer_manager-2.0.520566-darwin64-520566.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26016/204885/viewer_manager-2.0.520576-darwin64-520576.tar.bz2 name darwin64 @@ -3108,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 23e95f315f0adf957585af3f4eb42e88 + 2832c40449a8a8230e9072ceac5120af url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25999/204773/viewer_manager-2.0.520566-windows-520566.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26017/204891/viewer_manager-2.0.520576-windows-520576.tar.bz2 name windows @@ -3121,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520566 + 2.0.520576 vlc-bin From 72c0845a243ebdf0293bf7665474cfc652492bc7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 16 Oct 2018 11:29:32 -0400 Subject: [PATCH 42/59] DRTVWR-447: Update to bugsplat build 520674 --- autobuild.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 4c97752da1..160f1d7d59 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -244,9 +244,9 @@ archive hash - 7a7bd828233e8a2b0e9c022f6219e6e7 + 436b124bce8cf57b18dbf10f5e6ebcd4 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/23730/182106/bugsplat-1.0.6.519145-darwin64-519145.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26151/206132/bugsplat-1.0.7.520674-darwin64-520674.tar.bz2 name darwin64 @@ -256,9 +256,9 @@ archive hash - a3938332a11215e6909d67d1b9be5259 + 5d19acddc51ee7c802297dd176194362 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/23732/182120/bugsplat-3.6.0.4.519145-windows-519145.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26153/206145/bugsplat-3.6.0.4.520674-windows-520674.tar.bz2 name windows @@ -268,16 +268,16 @@ archive hash - 453d624d87a80779f59cfb1880613d90 + 78f5688b694e04c052fb0a1165c98bb5 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/23731/182115/bugsplat-3.6.0.4.519145-windows64-519145.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26152/206142/bugsplat-3.6.0.4.520674-windows64-520674.tar.bz2 name windows64 version - 1.0.6.519145 + 1.0.7.520674 chardet From 00a839d66590de1204af5fa295f66abcff87e477 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 16 Oct 2018 16:18:31 -0400 Subject: [PATCH 43/59] renumber the new test to replace the one that was removed --- indra/llcommon/tests/llerror_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index bd0357e4bf..e7084fffc6 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -884,7 +884,7 @@ namespace tut namespace tut { template<> template<> - void ErrorTestObject::test<19>() + void ErrorTestObject::test<5>() // backslash, return, and newline are not escaped with backslashes { LLError::setDefaultLevel(LLError::LEVEL_DEBUG); From 9cdcef4d501f4a7fec3b1c7051037df9db082278 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 16 Oct 2018 16:53:06 -0400 Subject: [PATCH 44/59] DRTVWR-447: Use new attachmentsForBugsplatStartupManager SDK method to attach user settings file and static debug info file to Mac crash reports, as well as SecondLife.log, just like Windows crash reports. --- indra/newview/llappdelegate-objc.mm | 72 +++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index f55304f30b..1d55537427 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -26,6 +26,8 @@ #import "llappdelegate-objc.h" #if defined(LL_BUGSPLAT) +#include +#include @import BugsplatMac; // derived from BugsplatMac's BugsplatTester/AppDelegate.m @interface LLAppDelegate () @@ -271,25 +273,59 @@ infos("bugsplatStartupManagerWillSendCrashReport"); } -- (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { - std::string logfile = CrashMetadata_instance().logFilePathname; - // Still to do: - // userSettingsPathname - // staticDebugPathname - // but the BugsplatMac version 1.0.5 BugsplatStartupManagerDelegate API - // doesn't yet provide a way to attach more than one file. - NSString *ns_logfile = [NSString stringWithCString:logfile.c_str() - encoding:NSUTF8StringEncoding]; - NSData *data = [NSData dataWithContentsOfFile:ns_logfile]; +struct AttachmentInfo +{ + AttachmentInfo(const std::string& path, const std::string& type): + pathname(path), + basename(boost::filesystem::path(path).filename().string()), + mimetype(type) + {} - // Apologies for the hard-coded log-file basename, but I do not know the - // incantation for "$(basename "$logfile")" in this language. - BugsplatAttachment *attachment = - [[BugsplatAttachment alloc] initWithFilename:@"SecondLife.log" - attachmentData:data - contentType:@"text/plain"]; - infos("attachmentForBugsplatStartupManager attaching " + logfile); - return attachment; + std::string pathname, basename, mimetype; +}; + +- (NSArray *)attachmentsForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager +{ + const CrashMetadata& metadata(CrashMetadata_instance()); + + // Since we must do very similar processing for each of several file + // pathnames, start by collecting them into a vector so we can iterate + // instead of spelling out the logic for each. + std::vector info{ + AttachmentInfo(metadata.logFilePathname, "text/plain"), + AttachmentInfo(metadata.userSettingsPathname, "text/xml"), + AttachmentInfo(metadata.staticDebugPathname, "text/xml") + }; + + // We "happen to know" that info[0].basename is "SecondLife.old" -- due to + // the fact that BugsplatMac only notices a crash during the viewer run + // following the crash. Replace .old with .log to reduce confusion. + info[0].basename = + boost::filesystem::path(info[0].pathname).stem().string() + ".log"; + + NSMutableArray *attachments = [[NSMutableArray alloc] init]; + + // Iterate over each AttachmentInfo in info vector + for (const AttachmentInfo& attach : info) + { + NSString *nspathname = [NSString stringWithCString:attach.pathname.c_str() + encoding:NSUTF8StringEncoding]; + NSString *nsbasename = [NSString stringWithCString:attach.basename.c_str() + encoding:NSUTF8StringEncoding]; + NSString *nsmimetype = [NSString stringWithCString:attach.mimetype.c_str() + encoding:NSUTF8StringEncoding]; + NSData *nsdata = [NSData dataWithContentsOfFile:nspathname]; + + BugsplatAttachment *attachment = + [[BugsplatAttachment alloc] initWithFilename:nsbasename + attachmentData:nsdata + contentType:nsmimetype]; + + [attachments addObject:attachment]; + infos("attachmentsForBugsplatStartupManager attaching " + attach.pathname); + } + + return attachments; } - (void)bugsplatStartupManagerDidFinishSendingCrashReport:(BugsplatStartupManager *)bugsplatStartupManager From bffe112cf5a1b9dd8acf5146c733a0fe186f6e89 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 10:30:24 -0400 Subject: [PATCH 45/59] Last rev before Poseidon merge --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 06d289325d..ea43dd32fc 100755 --- a/.hgtags +++ b/.hgtags @@ -541,3 +541,4 @@ ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release ac3b1332ad4f55b7182a8cbcc1254535a0069f75 5.1.7-release 23ea0fe36fadf009a60c080392ce80e4bf8af8d9 5.1.8-release 52422540bfe54b71155aa455360bee6e3ef1fd96 5.1.9-release +1cfa567caf5088ae299271be08cc2d9f0801ff6a pre-Poseidon From d81863d23d49f3a71fb477d7e5c9d149b14da9f2 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 10:56:43 -0400 Subject: [PATCH 46/59] DRTVWR-447: Finish merging Poseidon into BugSplat --- autobuild.xml | 54 +++++ indra/newview/CMakeLists.txt | 339 ++++++++++++++++++++++--------- indra/newview/viewer_manifest.py | 304 ++++++++++++++------------- 3 files changed, 459 insertions(+), 238 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index f0358eb8ba..b1f4597a70 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -225,6 +225,60 @@ version 1.57 + bugsplat + + copyright + Copyright 2003-2017, BugSplat + description + Bugsplat crash reporting package + license + Proprietary + license_file + LICENSES/BUGSPLAT_LICENSE.txt + name + bugsplat + platforms + + darwin64 + + archive + + hash + 436b124bce8cf57b18dbf10f5e6ebcd4 + url + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26151/206132/bugsplat-1.0.7.520674-darwin64-520674.tar.bz2 + + name + darwin64 + + windows + + archive + + hash + 5d19acddc51ee7c802297dd176194362 + url + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26153/206145/bugsplat-3.6.0.4.520674-windows-520674.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 78f5688b694e04c052fb0a1165c98bb5 + url + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26152/206142/bugsplat-3.6.0.4.520674-windows64-520674.tar.bz2 + + name + windows64 + + + version + 1.0.7.520674 + colladadom copyright diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e7111ebe54..5c918fc3b2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -3,7 +3,14 @@ project(viewer) include(00-Common) +# DON'T move Linking.cmake to its place in the alphabetized list below: it +# sets variables on which the 3p .cmake files depend. +include(Linking) + include(Boost) +if (BUGSPLAT_DB) + include(bugsplat) +endif (BUGSPLAT_DB) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -36,7 +43,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(Linking) include(NDOF) include(NVAPI) include(OPENAL) @@ -91,6 +97,12 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) +if (BUGSPLAT_DB) + include_directories( + ${BUGSPLAT_INCLUDE_DIR} + ) +endif (BUGSPLAT_DB) + include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLXML_SYSTEM_INCLUDE_DIRS} @@ -1354,6 +1366,14 @@ if (DARWIN) # This should be compiled with the viewer. LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm) + set_source_files_properties( + llappdelegate-objc.mm + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + # BugsplatMac is a module, imported with @import. That language feature + # demands these switches. + COMPILE_FLAGS "-fmodules -fcxx-modules" + ) find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) @@ -1368,6 +1388,12 @@ if (DARWIN) ${COREAUDIO_LIBRARY} ) + if (BUGSPLAT_DB) + list(APPEND viewer_LIBRARIES + ${BUGSPLAT_LIBRARIES} + ) + endif (BUGSPLAT_DB) + # Add resource files to the project. set(viewer_RESOURCE_FILES secondlife.icns @@ -1393,6 +1419,11 @@ endif (DARWIN) if (LINUX) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp) + set_source_files_properties( + llappviewerlinux.cpp + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + ) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") @@ -1409,6 +1440,11 @@ if (WINDOWS) llappviewerwin32.cpp llwindebug.cpp ) + set_source_files_properties( + llappviewerwin32.cpp + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + ) list(APPEND viewer_HEADER_FILES llappviewerwin32.h @@ -1691,6 +1727,11 @@ if (SDL_FOUND) ) endif (SDL_FOUND) +if (BUGSPLAT_DB) + set_property(TARGET ${VIEWER_BINARY_NAME} + PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (BUGSPLAT_DB) + # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) @@ -1789,7 +1830,7 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll ) endif (FMODEX) - + add_custom_command( OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat COMMAND ${PYTHON_EXECUTABLE} @@ -1798,15 +1839,16 @@ if (WINDOWS) --actions=copy --arch=${ARCH} --artwork=${ARTWORK_DIR} + "--bugsplat=${BUGSPLAT_DB}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} + "--channel=${VIEWER_CHANNEL}" --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} --grid=${GRID} - "--channel=${VIEWER_CHANNEL}" - --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py stage_third_party_libs @@ -1824,24 +1866,9 @@ if (WINDOWS) add_dependencies(${VIEWER_BINARY_NAME} SLPlugin - windows-crash-logger + windows-crash-logger ) - # sets the 'working directory' for debugging from visual studio. - if (NOT UNATTENDED) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe - ARGS - --solution - ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln - --workingdir - ${VIEWER_BINARY_NAME} - "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging." - ) - endif (NOT UNATTENDED) - if (PACKAGE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2 @@ -1864,15 +1891,16 @@ if (WINDOWS) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --arch=${ARCH} --artwork=${ARTWORK_DIR} + "--bugsplat=${BUGSPLAT_DB}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" - --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} --grid=${GRID} --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py @@ -1903,8 +1931,8 @@ else (WINDOWS) endif (WINDOWS) # *NOTE: - this list is very sensitive to ordering, test carefully on all -# platforms if you change the releative order of the entries here. -# In particular, cmake 2.6.4 (when buidling with linux/makefile generators) +# platforms if you change the relative order of the entries here. +# In particular, cmake 2.6.4 (when building with linux/makefile generators) # appears to sometimes de-duplicate redundantly listed dependencies improperly. # To work around this, higher level modules should be listed before the modules # that they depend upon. -brad @@ -1979,6 +2007,12 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLAPPEARANCE_LIBRARIES} ) +if (BUGSPLAT_DB) + target_link_libraries(${VIEWER_BINARY_NAME} + ${BUGSPLAT_LIBRARIES} + ) +endif (BUGSPLAT_DB) + set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Path to artwork files.") @@ -2002,15 +2036,16 @@ if (LINUX) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --arch=${ARCH} --artwork=${ARTWORK_DIR} + "--bugsplat=${BUGSPLAT_DB}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" - --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --grid=${GRID} --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ${COPY_INPUT_DEPENDENCIES} @@ -2024,17 +2059,18 @@ if (LINUX) COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - --arch=${ARCH} --actions=copy + --arch=${ARCH} --artwork=${ARTWORK_DIR} + "--bugsplat=${BUGSPLAT_DB}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} + "--channel=${VIEWER_CHANNEL}" --configuration=${CMAKE_CFG_INTDIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --grid=${GRID} - "--channel=${VIEWER_CHANNEL}" - --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --source=${CMAKE_CURRENT_SOURCE_DIR} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ${COPY_INPUT_DEPENDENCIES} @@ -2052,31 +2088,45 @@ if (LINUX) endif (LINUX) if (DARWIN) - # These all get set with PROPERTIES - set(product "Second Life") - set(MACOSX_EXECUTABLE_NAME "Second Life") - set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer") + # These all get set with PROPERTIES. It's not that the property names are + # magically known to CMake -- it's that these names are referenced in the + # Info-SecondLife.plist file in the configure_file() directive below. + set(product "${VIEWER_CHANNEL}") + set(MACOSX_BUNDLE_INFO_STRING "${VIEWER_CHANNEL}") set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns") set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer") set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife") - set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}") + set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}") set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007") set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication") + + # https://blog.kitware.com/upcoming-in-cmake-2-8-12-osx-rpath-support/ + set(CMAKE_MACOSX_RPATH 1) set_target_properties( ${VIEWER_BINARY_NAME} PROPERTIES OUTPUT_NAME "${product}" + # From Contents/MacOS/SecondLife, look in Contents/Frameworks + INSTALL_RPATH "@loader_path/../Frameworks" + # SIGH, as of 2018-05-24 (cmake 3.11.1) the INSTALL_RPATH property simply + # does not work. Try this: + LINK_FLAGS "-rpath @loader_path/../Frameworks" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" ) + set(VIEWER_APP_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") + set(VIEWER_APP_EXE "${VIEWER_APP_BUNDLE}/Contents/MacOS/${product}") + set(VIEWER_APP_DSYM "${VIEWER_APP_EXE}.dSYM") + set(VIEWER_APP_XCARCHIVE "${VIEWER_APP_BUNDLE}/../${product}.xcarchive.zip") + configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" - "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app/Contents/Info.plist" + "${VIEWER_APP_BUNDLE}/Contents/Info.plist" ) add_custom_command( @@ -2087,15 +2137,16 @@ if (DARWIN) --actions=copy --arch=${ARCH} --artwork=${ARTWORK_DIR} + "--bugsplat=${BUGSPLAT_DB}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} - --configuration=${CMAKE_CFG_INTDIR} - --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app - --grid=${GRID} - "--channel=${VIEWER_CHANNEL}" - --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt --bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER} + "--channel=${VIEWER_CHANNEL}" + --configuration=${CMAKE_CFG_INTDIR} + --dest=${VIEWER_APP_BUNDLE} + --grid=${GRID} --source=${CMAKE_CURRENT_SOURCE_DIR} + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py @@ -2120,15 +2171,16 @@ if (DARWIN) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py --arch=${ARCH} --artwork=${ARTWORK_DIR} + "--bugsplat=${BUGSPLAT_DB}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} - --configuration=${CMAKE_CFG_INTDIR} - --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app - --grid=${GRID} "--channel=${VIEWER_CHANNEL}" - --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt + --configuration=${CMAKE_CFG_INTDIR} + --dest=${VIEWER_APP_BUNDLE} + --grid=${GRID} --source=${CMAKE_CURRENT_SOURCE_DIR} --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt ${SIGNING_SETTING} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py @@ -2140,67 +2192,152 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) -if (PACKAGE) - set(SYMBOL_SEARCH_DIRS "") - # Note that the path to VIEWER_SYMBOL_FILE must match that in ../../build.sh - if (WINDOWS) - list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows-$ENV{AUTOBUILD_ADDRSIZE}.tar.bz2") - # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad - # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") - set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}") - set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") - set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) - endif (WINDOWS) - if (DARWIN) - list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") - # *TODO: Generate these search dirs in the cmake files related to each binary. - list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}") - list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}") - list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin-$ENV{AUTOBUILD_ADDRSIZE}.tar.bz2") - set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-crash-logger") - set(VIEWER_EXE_GLOBS "'Second Life' mac-crash-logger") - set(VIEWER_LIB_GLOB "*.dylib") - endif (DARWIN) - if (LINUX) - list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged") - set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux-$ENV{AUTOBUILD_ADDRSIZE}.tar.bz2") - set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") - set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin") - set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") - set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) - endif (LINUX) +# Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh +if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE) + if (NOT BUGSPLAT_DB) + # Breakpad symbol-file generation + set(SYMBOL_SEARCH_DIRS "") + if (WINDOWS) + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad + # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") + set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) + endif (WINDOWS) + if (DARWIN) + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + # *TODO: Generate these search dirs in the cmake files related to each binary. + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}") + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}") + set(VIEWER_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger") + set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger") + set(VIEWER_LIB_GLOB "*.dylib") + endif (DARWIN) + if (LINUX) + list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged") + set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") + set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") + set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) + endif (LINUX) - if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) - if(CMAKE_CFG_INTDIR STREQUAL ".") - set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) - else(CMAKE_CFG_INTDIR STREQUAL ".") - # set LLBUILD_CONFIG to be a shell variable evaluated at build time - # reflecting the configuration we are currently building. - set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) - endif(CMAKE_CFG_INTDIR STREQUAL ".") - add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" - COMMAND "${PYTHON_EXECUTABLE}" - ARGS - "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" - "${LLBUILD_CONFIG}" - "${SYMBOL_SEARCH_DIRS}" - "${VIEWER_EXE_GLOBS}" - "${VIEWER_LIB_GLOB}" - "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms" - "${VIEWER_SYMBOL_FILE}" - DEPENDS generate_breakpad_symbols.py - VERBATIM) + if(CMAKE_CFG_INTDIR STREQUAL ".") + set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) + else(CMAKE_CFG_INTDIR STREQUAL ".") + # set LLBUILD_CONFIG to be a shell variable evaluated at build time + # reflecting the configuration we are currently building. + set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) + endif(CMAKE_CFG_INTDIR STREQUAL ".") + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${LLBUILD_CONFIG}" + "${SYMBOL_SEARCH_DIRS}" + "${VIEWER_EXE_GLOBS}" + "${VIEWER_LIB_GLOB}" + "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms" + "${VIEWER_SYMBOL_FILE}" + DEPENDS generate_breakpad_symbols.py + VERBATIM) - add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") - add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}") - if (WINDOWS OR LINUX) - add_dependencies(generate_breakpad_symbols "${VIEWER_COPY_MANIFEST}") - endif (WINDOWS OR LINUX) - add_dependencies(llpackage generate_breakpad_symbols) - endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) -endif (PACKAGE) + add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME} "${VIEWER_COPY_MANIFEST}") + add_dependencies(generate_symbols ${VIEWER_BINARY_NAME}) + if (WINDOWS OR LINUX) + add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}") + endif (WINDOWS OR LINUX) + + else (NOT BUGSPLAT_DB) + # BugSplat symbol-file generation + if (WINDOWS) + # Just pack up a tarball containing only the .pdb file for the + # executable. Because we intend to use cygwin tar, we must render + # VIEWER_SYMBOL_FILE in cygwin path syntax. + execute_process(COMMAND "cygpath" "-u" "${VIEWER_SYMBOL_FILE}" + OUTPUT_VARIABLE VIEWER_SYMBOL_FILE_CYGWIN + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND "cygpath" "-u" "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" + OUTPUT_VARIABLE PARENT_DIRECTORY_CYGWIN + OUTPUT_STRIP_TRAILING_WHITESPACE) + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + # Use of 'tar ...j' here assumes VIEWER_SYMBOL_FILE endswith .tar.bz2; + # testing a string suffix is painful enough in CMake language that + # we'll continue assuming it until forced to generalize. + COMMAND "tar" + ARGS + "cjf" + "${VIEWER_SYMBOL_FILE_CYGWIN}" + "-C" + "${PARENT_DIRECTORY_CYGWIN}" + "secondlife-bin.pdb" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-bin.pdb" + COMMENT "Packing viewer PDB into ${VIEWER_SYMBOL_FILE_CYGWIN}" + ) + add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME}) + add_dependencies(generate_symbols ${VIEWER_BINARY_NAME}) + endif (WINDOWS) + if (DARWIN) + # Have to run dsymutil first, then pack up the resulting .dSYM directory + add_custom_command(OUTPUT "${VIEWER_APP_DSYM}" + COMMAND "dsymutil" + ARGS + ${VIEWER_APP_EXE} + COMMENT "Generating ${VIEWER_APP_DSYM}" + ) + add_custom_target(dsym_generate DEPENDS "${VIEWER_APP_DSYM}") + add_dependencies(dsym_generate ${VIEWER_BINARY_NAME}) + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + # See above comments about "tar ...j" + COMMAND "tar" + ARGS + "cjf" + "${VIEWER_SYMBOL_FILE}" + "-C" + "${VIEWER_APP_DSYM}/.." + "${product}.dSYM" + DEPENDS "${VIEWER_APP_DSYM}" + COMMENT "Packing dSYM into ${VIEWER_SYMBOL_FILE}" + ) + add_custom_target(dsym_tarball DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(dsym_tarball dsym_generate) + add_custom_command(OUTPUT "${VIEWER_APP_XCARCHIVE}" + COMMAND "zip" + ARGS + "-r" + "${VIEWER_APP_XCARCHIVE}" + "." + WORKING_DIRECTORY "${VIEWER_APP_DSYM}/.." + DEPENDS "${VIEWER_APP_DSYM}" + COMMENT "Generating xcarchive.zip for upload to BugSplat" + ) + add_custom_target(dsym_xcarchive DEPENDS "${VIEWER_APP_XCARCHIVE}") + add_dependencies(dsym_xcarchive dsym_generate) + # Have to create a stamp file, and depend on it, to force CMake to run + # the cleanup step. + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp" + COMMAND rm -rf "${VIEWER_APP_DSYM}" + COMMAND touch "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp" + DEPENDS "${VIEWER_SYMBOL_FILE}" "${VIEWER_APP_XCARCHIVE}" + COMMENT "Cleaning up dSYM" + ) + add_custom_target(generate_symbols DEPENDS + "${VIEWER_APP_DSYM}" + "${VIEWER_SYMBOL_FILE}" + "${VIEWER_APP_XCARCHIVE}" + "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp" + ) + add_dependencies(generate_symbols dsym_tarball dsym_xcarchive) + endif (DARWIN) + if (LINUX) + # TBD + endif (LINUX) + endif (NOT BUGSPLAT_DB) + + # for both BUGSPLAT_DB and Breakpad + add_dependencies(llpackage generate_symbols) +endif () if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 57da87a3ee..5dd4d13a3a 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -26,19 +26,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ -import sys -import os -import os.path -import shutil import errno import json +import os +import os.path import plistlib import random import re +import shutil import stat import subprocess +import sys import tarfile import time +import zipfile viewer_dir = os.path.dirname(__file__) # Add indra/lib/python to our path so we don't have to muck with PYTHONPATH. @@ -63,7 +64,7 @@ class ViewerManifest(LLManifest): self.path(src="../../etc/message.xml", dst="app_settings/message.xml") if self.is_packaging_viewer(): - with self.prefix(src="app_settings"): + with self.prefix(src_dst="app_settings"): self.exclude("logcontrol.xml") self.exclude("logcontrol-dev.xml") self.path("*.ini") @@ -85,7 +86,7 @@ class ViewerManifest(LLManifest): # ... and the included spell checking dictionaries pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') - with self.prefix(src=pkgdir,dst=""): + with self.prefix(src=pkgdir): self.path("dictionaries") # include the extracted packages information (see BuildPackagesInfo.cmake) @@ -107,17 +108,18 @@ class ViewerManifest(LLManifest): Type='String', Value='')) settings_install = {} - if 'sourceid' in self.args and self.args['sourceid']: + sourceid = self.args.get('sourceid') + if sourceid: settings_install['sourceid'] = settings_template['sourceid'].copy() - settings_install['sourceid']['Value'] = self.args['sourceid'] - print "Set sourceid in settings_install.xml to '%s'" % self.args['sourceid'] + settings_install['sourceid']['Value'] = sourceid + print "Set sourceid in settings_install.xml to '%s'" % sourceid - if 'channel_suffix' in self.args and self.args['channel_suffix']: + if self.args.get('channel_suffix'): settings_install['CmdLineChannel'] = settings_template['CmdLineChannel'].copy() settings_install['CmdLineChannel']['Value'] = self.channel_with_pkg_suffix() print "Set CmdLineChannel in settings_install.xml to '%s'" % self.channel_with_pkg_suffix() - if 'grid' in self.args and self.args['grid']: + if self.args.get('grid'): settings_install['CmdLineGridChoice'] = settings_template['CmdLineGridChoice'].copy() settings_install['CmdLineGridChoice']['Value'] = self.grid() print "Set CmdLineGridChoice in settings_install.xml to '%s'" % self.grid() @@ -129,20 +131,20 @@ class ViewerManifest(LLManifest): src="environment") - with self.prefix(src="character"): + with self.prefix(src_dst="character"): self.path("*.llm") self.path("*.xml") self.path("*.tga") # Include our fonts - with self.prefix(src="fonts"): + with self.prefix(src_dst="fonts"): self.path("*.ttf") self.path("*.txt") # skins - with self.prefix(src="skins"): + with self.prefix(src_dst="skins"): # include the entire textures directory recursively - with self.prefix(src="*/textures"): + with self.prefix(src_dst="*/textures"): self.path("*/*.tga") self.path("*/*.j2c") self.path("*/*.jpg") @@ -170,7 +172,7 @@ class ViewerManifest(LLManifest): # local_assets dir (for pre-cached textures) - with self.prefix(src="local_assets"): + with self.prefix(src_dst="local_assets"): self.path("*.j2c") self.path("*.tga") @@ -186,6 +188,10 @@ class ViewerManifest(LLManifest): "Address Size":self.address_size, "Update Service":"https://update.secondlife.com/update", } + # Only store this if it's both present and non-empty + bugsplat_db = self.args.get('bugsplat') + if bugsplat_db: + build_data_dict["BugSplat DB"] = bugsplat_db build_data_dict = self.finish_build_data_dict(build_data_dict) with open(os.path.join(os.pardir,'build_data.json'), 'w') as build_data_handle: json.dump(build_data_dict,build_data_handle) @@ -206,8 +212,9 @@ class ViewerManifest(LLManifest): def channel_with_pkg_suffix(self): fullchannel=self.channel() - if 'channel_suffix' in self.args and self.args['channel_suffix']: - fullchannel+=' '+self.args['channel_suffix'] + channel_suffix = self.args.get('channel_suffix') + if channel_suffix: + fullchannel+=' '+channel_suffix return fullchannel def channel_variant(self): @@ -215,8 +222,7 @@ class ViewerManifest(LLManifest): return self.channel().replace(CHANNEL_VENDOR_BASE, "").strip() def channel_type(self): # returns 'release', 'beta', 'project', or 'test' - global CHANNEL_VENDOR_BASE - channel_qualifier=self.channel().replace(CHANNEL_VENDOR_BASE, "").lower().strip() + channel_qualifier=self.channel_variant().lower() if channel_qualifier.startswith('release'): channel_type='release' elif channel_qualifier.startswith('beta'): @@ -234,11 +240,12 @@ class ViewerManifest(LLManifest): if self.channel_type() == 'release': suffix=suffix.replace('Release', '').strip() # for the base release viewer, suffix will now be null - for any other, append what remains - if len(suffix) > 0: - suffix = "_"+ ("_".join(suffix.split())) + if suffix: + suffix = "_".join([''] + suffix.split()) # the additional_packages mechanism adds more to the installer name (but not to the app name itself) - if 'channel_suffix' in self.args and self.args['channel_suffix']: - suffix+='_'+("_".join(self.args['channel_suffix'].split())) + # ''.split() produces empty list, so suffix only changes if + # channel_suffix is non-empty + suffix = "_".join([suffix] + self.args.get('channel_suffix', '').split()) return suffix def installer_base_name(self): @@ -488,19 +495,19 @@ class WindowsManifest(ViewerManifest): # 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()) - with self.prefix(src=os.path.join(pkgdir, "VMP"), dst=""): + with self.prefix(src=os.path.join(pkgdir, "VMP")): # include the compiled launcher scripts so that it gets included in the file_list self.path('updater.exe') #IUM is not normally executed directly, just imported. No exe needed. self.path("InstallerUserMessage.py") - with self.prefix(src=self.icon_path(), dst="vmp_icons"): - self.path("secondlife.ico") - - #VMP Tkinter icons - with self.prefix("vmp_icons"): - self.path("*.png") - self.path("*.gif") + with self.prefix(dst="vmp_icons"): + with self.prefix(src=self.icon_path()): + self.path("secondlife.ico") + #VMP Tkinter icons + with self.prefix(src="vmp_icons"): + self.path("*.png") + self.path("*.gif") # Plugin host application self.path2basename(os.path.join(os.pardir, @@ -508,8 +515,8 @@ class WindowsManifest(ViewerManifest): "slplugin.exe") # Get shared libs from the shared libs staging directory - with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']), - dst=""): + with self.prefix(src=os.path.join(self.args['build'], os.pardir, + 'sharedlibs', self.args['configuration'])): # Get llcommon and deps. If missing assume static linkage and continue. try: @@ -575,6 +582,17 @@ class WindowsManifest(ViewerManifest): # Hunspell self.path("libhunspell.dll") + # BugSplat + if self.args.get('bugsplat'): + if(self.address_size == 64): + self.path("BsSndRpt64.exe") + self.path("BugSplat64.dll") + self.path("BugSplatRc64.dll") + else: + self.path("BsSndRpt.exe") + self.path("BugSplat.dll") + self.path("BugSplatRc.dll") + # For google-perftools tcmalloc allocator. try: if self.args['configuration'].lower() == 'debug': @@ -584,114 +602,116 @@ class WindowsManifest(ViewerManifest): except: print "Skipping libtcmalloc_minimal.dll" - self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") - with self.prefix(src=pkgdir,dst=""): + with self.prefix(src=pkgdir): self.path("ca-bundle.crt") # Media plugins - CEF - with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_cef.dll") + with self.prefix(dst="llplugin"): + with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins')): + with self.prefix(src=os.path.join('cef', self.args['configuration'])): + self.path("media_plugin_cef.dll") - # Media plugins - LibVLC - with self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_libvlc.dll") + # Media plugins - LibVLC + with self.prefix(src=os.path.join('libvlc', self.args['configuration'])): + self.path("media_plugin_libvlc.dll") - # Media plugins - Example (useful for debugging - not shipped with release viewer) - if self.channel_type() != 'release': - with self.prefix(src='../media_plugins/example/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_example.dll") + # Media plugins - Example (useful for debugging - not shipped with release viewer) + if self.channel_type() != 'release': + with self.prefix(src=os.path.join('example', self.args['configuration'])): + self.path("media_plugin_example.dll") - # CEF runtime files - debug - # CEF runtime files - not debug (release, relwithdebinfo etc.) - config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release' - with self.prefix(src=os.path.join(pkgdir, 'bin', config), dst="llplugin"): - self.path("chrome_elf.dll") - self.path("d3dcompiler_43.dll") - self.path("d3dcompiler_47.dll") - self.path("libcef.dll") - self.path("libEGL.dll") - self.path("libGLESv2.dll") - self.path("dullahan_host.exe") - self.path("natives_blob.bin") - self.path("snapshot_blob.bin") - self.path("widevinecdmadapter.dll") + # CEF runtime files - debug + # CEF runtime files - not debug (release, relwithdebinfo etc.) + config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release' + with self.prefix(src=os.path.join(pkgdir, 'bin', config)): + self.path("chrome_elf.dll") + self.path("d3dcompiler_43.dll") + self.path("d3dcompiler_47.dll") + self.path("libcef.dll") + self.path("libEGL.dll") + self.path("libGLESv2.dll") + self.path("dullahan_host.exe") + self.path("natives_blob.bin") + self.path("snapshot_blob.bin") + self.path("widevinecdmadapter.dll") - # MSVC DLLs needed for CEF and have to be in same directory as plugin - with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', 'Release'), dst="llplugin"): - self.path("msvcp120.dll") - self.path("msvcr120.dll") + # MSVC DLLs needed for CEF and have to be in same directory as plugin + with self.prefix(src=os.path.join(self.args['build'], os.pardir, + 'sharedlibs', 'Release')): + self.path("msvcp120.dll") + self.path("msvcr120.dll") - # CEF files common to all configurations - with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="llplugin"): - self.path("cef.pak") - self.path("cef_100_percent.pak") - self.path("cef_200_percent.pak") - self.path("cef_extensions.pak") - self.path("devtools_resources.pak") - self.path("icudtl.dat") + # CEF files common to all configurations + with self.prefix(src=os.path.join(pkgdir, 'resources')): + self.path("cef.pak") + self.path("cef_100_percent.pak") + self.path("cef_200_percent.pak") + self.path("cef_extensions.pak") + self.path("devtools_resources.pak") + self.path("icudtl.dat") - with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst=os.path.join('llplugin', 'locales')): - self.path("am.pak") - self.path("ar.pak") - self.path("bg.pak") - self.path("bn.pak") - self.path("ca.pak") - self.path("cs.pak") - self.path("da.pak") - self.path("de.pak") - self.path("el.pak") - self.path("en-GB.pak") - self.path("en-US.pak") - self.path("es-419.pak") - self.path("es.pak") - self.path("et.pak") - self.path("fa.pak") - self.path("fi.pak") - self.path("fil.pak") - self.path("fr.pak") - self.path("gu.pak") - self.path("he.pak") - self.path("hi.pak") - self.path("hr.pak") - self.path("hu.pak") - self.path("id.pak") - self.path("it.pak") - self.path("ja.pak") - self.path("kn.pak") - self.path("ko.pak") - self.path("lt.pak") - self.path("lv.pak") - self.path("ml.pak") - self.path("mr.pak") - self.path("ms.pak") - self.path("nb.pak") - self.path("nl.pak") - self.path("pl.pak") - self.path("pt-BR.pak") - self.path("pt-PT.pak") - self.path("ro.pak") - self.path("ru.pak") - self.path("sk.pak") - self.path("sl.pak") - self.path("sr.pak") - self.path("sv.pak") - self.path("sw.pak") - self.path("ta.pak") - self.path("te.pak") - self.path("th.pak") - self.path("tr.pak") - self.path("uk.pak") - self.path("vi.pak") - self.path("zh-CN.pak") - self.path("zh-TW.pak") + with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst='locales'): + self.path("am.pak") + self.path("ar.pak") + self.path("bg.pak") + self.path("bn.pak") + self.path("ca.pak") + self.path("cs.pak") + self.path("da.pak") + self.path("de.pak") + self.path("el.pak") + self.path("en-GB.pak") + self.path("en-US.pak") + self.path("es-419.pak") + self.path("es.pak") + self.path("et.pak") + self.path("fa.pak") + self.path("fi.pak") + self.path("fil.pak") + self.path("fr.pak") + self.path("gu.pak") + self.path("he.pak") + self.path("hi.pak") + self.path("hr.pak") + self.path("hu.pak") + self.path("id.pak") + self.path("it.pak") + self.path("ja.pak") + self.path("kn.pak") + self.path("ko.pak") + self.path("lt.pak") + self.path("lv.pak") + self.path("ml.pak") + self.path("mr.pak") + self.path("ms.pak") + self.path("nb.pak") + self.path("nl.pak") + self.path("pl.pak") + self.path("pt-BR.pak") + self.path("pt-PT.pak") + self.path("ro.pak") + self.path("ru.pak") + self.path("sk.pak") + self.path("sl.pak") + self.path("sr.pak") + self.path("sv.pak") + self.path("sw.pak") + self.path("ta.pak") + self.path("te.pak") + self.path("th.pak") + self.path("tr.pak") + self.path("uk.pak") + self.path("vi.pak") + self.path("zh-CN.pak") + self.path("zh-TW.pak") - with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="llplugin"): - self.path("libvlc.dll") - self.path("libvlccore.dll") - self.path("plugins/") + with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')): + self.path("libvlc.dll") + self.path("libvlccore.dll") + self.path("plugins/") # pull in the crash logger and updater from other projects # tag:"crash-logger" here as a cue to the exporter @@ -874,6 +894,12 @@ class DarwinManifest(ViewerManifest): # darwin requires full app bundle packaging even for debugging. return True + def is_rearranging(self): + # That said, some stuff should still only be performed once. + # Are either of these actions in 'actions'? Is the set intersection + # non-empty? + return bool(set(["package", "unpacked"]).intersection(self.args['actions'])) + def construct(self): # copy over the build result (this is a no-op if run within the xcode script) self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") @@ -1362,19 +1388,19 @@ class LinuxManifest(ViewerManifest): debpkgdir = os.path.join(pkgdir, "lib", "debug") self.path("licenses-linux.txt","licenses.txt") - with self.prefix("linux_tools", dst=""): + with self.prefix("linux_tools"): self.path("client-readme.txt","README-linux.txt") self.path("client-readme-voice.txt","README-linux-voice.txt") self.path("client-readme-joystick.txt","README-linux-joystick.txt") self.path("wrapper.sh","secondlife") - with self.prefix(src="", dst="etc"): + with self.prefix(dst="etc"): self.path("handle_secondlifeprotocol.sh") self.path("register_secondlifeprotocol.sh") self.path("refresh_desktop_app_entry.sh") self.path("launch_url.sh") self.path("install.sh") - with self.prefix(src="", dst="bin"): + with self.prefix(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") @@ -1388,9 +1414,9 @@ class LinuxManifest(ViewerManifest): # Get the icons based on the channel type icon_path = self.icon_path() print "DEBUG: icon_path '%s'" % icon_path - with self.prefix(src=icon_path, dst="") : + with self.prefix(src=icon_path) : self.path("secondlife_256.png","secondlife_icon.png") - with self.prefix(src="",dst="res-sdl") : + with self.prefix(dst="res-sdl") : self.path("secondlife_256.BMP","ll_icon.BMP") # plugins @@ -1412,7 +1438,7 @@ class LinuxManifest(ViewerManifest): self.path("featuretable_linux.txt") - with self.prefix(src=pkgdir,dst=""): + with self.prefix(src=pkgdir): self.path("ca-bundle.crt") def package_finish(self): @@ -1468,7 +1494,7 @@ class Linux_i686_Manifest(LinuxManifest): relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") - with self.prefix(relpkgdir, dst="lib"): + with self.prefix(src=relpkgdir, dst="lib"): self.path("libapr-1.so") self.path("libapr-1.so.0") self.path("libapr-1.so.0.4.5") @@ -1554,4 +1580,8 @@ class Linux_x86_64_Manifest(LinuxManifest): ################################################################ if __name__ == "__main__": - main() + extra_arguments = [ + dict(name='bugsplat', description="""BugSplat database to which to post crashes, + if BugSplat crash reporting is desired""", default=''), + ] + main(extra=extra_arguments) From 01c6fe141e64b742bb33782238faa4a0a5ca6816 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 11:35:01 -0400 Subject: [PATCH 47/59] DRTVWR-447: Update to viewer-manager build 520737 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index b1f4597a70..5b0817cbf8 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - eeeb18f7396de3147c6d958dfbc1a2e5 + 021b56ca0b1e34f40fa5fca713072c40 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26016/204885/viewer_manager-2.0.520576-darwin64-520576.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26246/206828/viewer_manager-2.0.520737-darwin64-520737.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 2832c40449a8a8230e9072ceac5120af + be91869780e39f58eaf1cd8c85b3b951 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26017/204891/viewer_manager-2.0.520576-windows-520576.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26247/206835/viewer_manager-2.0.520737-windows-520737.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520576 + 2.0.520737 vlc-bin From 3c4d63c6a1b0f5567c24d457b820022cf4de45cf Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 13:04:32 -0400 Subject: [PATCH 48/59] DRTVWR-447: Update to viewer-manager build 520750 --- autobuild.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 5b0817cbf8..6ce20e45ab 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 021b56ca0b1e34f40fa5fca713072c40 + 1d801a03cb87a248b6573f8550603286 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26246/206828/viewer_manager-2.0.520737-darwin64-520737.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26264/206909/viewer_manager-2.0.520750-darwin64-520750.tar.bz2 name darwin64 @@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - be91869780e39f58eaf1cd8c85b3b951 + 65e20bc630033178f3f7e4890c0b85f7 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26247/206835/viewer_manager-2.0.520737-windows-520737.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26265/206915/viewer_manager-2.0.520750-windows-520750.tar.bz2 name windows @@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 2.0.520737 + 2.0.520750 vlc-bin From 2c5d7199f69984ddba602ac50f8f55c6fd73fc9d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 13:53:37 -0400 Subject: [PATCH 49/59] DRTVWR-447: Restore channel-name sensitivity of Mac BugSplat viewer. --- indra/newview/viewer_manifest.py | 34 ++------------------------------ 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 5dd4d13a3a..0aea31d563 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -902,7 +902,7 @@ class DarwinManifest(ViewerManifest): def construct(self): # copy over the build result (this is a no-op if run within the xcode script) - self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="") + self.path(os.path.join(self.args['configuration'], self.channel()+".app"), dst="") pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') relpkgdir = os.path.join(pkgdir, "lib", "release") @@ -926,7 +926,7 @@ class DarwinManifest(ViewerManifest): if ("package" in self.args['actions'] or "unpacked" in self.args['actions']): self.run_command( - ['strip', '-S', self.dst_path_of('Second Life')]) + ['strip', '-S', self.dst_path_of(self.channel())]) with self.prefix(dst="Resources"): # defer cross-platform file copies until we're in the @@ -960,8 +960,6 @@ class DarwinManifest(ViewerManifest): with self.prefix(src=pkgdir,dst=""): self.path("ca-bundle.crt") - self.path("SecondLife.nib") - # Translations self.path("English.lproj/language.txt") self.replace_in(src="English.lproj/InfoPlist.strings", @@ -1321,34 +1319,6 @@ class DarwinManifest(ViewerManifest): else: print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" raise - print 72*'=' - import stat - print app_in_dmg - # Second Life.app - for sub0 in os.listdir(app_in_dmg): - print '--{}'.format(sub0) - path0 = os.path.join(app_in_dmg, sub0) - if os.path.isfile(path0): - # shouldn't be any file here - with open(path0) as inf: - for line in inf: - print ' {}'.format(line.rstrip()) - elif os.path.isdir(path0): - # Contents - for sub1 in os.listdir(path0): - print '----{}'.format(sub1) - path1 = os.path.join(path0, sub1) - if os.path.isfile(path1): - # Info.plist, PkgInfo - with open(path1) as inf: - for line in inf: - print ' {}'.format(line.rstrip()) - elif os.path.isdir(path1): - # Frameworks, MacOS, Resources - for sub2 in os.listdir(path1): - path2 = os.path.join(path1, sub2) - print ' {:04o} {}'.format(stat.S_IMODE(os.stat(path2).st_mode), sub2) - print 72*'=' self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg]) finally: From cd9d051b9024e4e0fc16a4aca28601d2a88a4045 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 16:42:59 -0400 Subject: [PATCH 50/59] DRTVWR-447: Move test<5> and writeMsgNeedsEscaping() into sequence. --- indra/llcommon/tests/llerror_test.cpp | 66 +++++++++++++-------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index e7084fffc6..8e1f4c14ac 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -498,6 +498,39 @@ namespace } } +namespace +{ + void writeMsgNeedsEscaping() + { + LL_DEBUGS("WriteTag") << "backslash\\" << LL_ENDL; + LL_INFOS("WriteTag") << "newline\nafternewline" << LL_ENDL; + LL_WARNS("WriteTag") << "return\rafterreturn" << LL_ENDL; + + LL_DEBUGS("WriteTag") << "backslash\\backslash\\" << LL_ENDL; + LL_INFOS("WriteTag") << "backslash\\newline\nanothernewline\nafternewline" << LL_ENDL; + LL_WARNS("WriteTag") << "backslash\\returnnewline\r\n\\afterbackslash" << LL_ENDL; + } +}; + +namespace tut +{ + template<> template<> + void ErrorTestObject::test<5>() + // backslash, return, and newline are not escaped with backslashes + { + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + setWantsMultiline(true); + writeMsgNeedsEscaping(); // but should not be now + ensure_message_field_equals(0, MSG_FIELD, "backslash\\"); + ensure_message_field_equals(1, MSG_FIELD, "newline\nafternewline"); + ensure_message_field_equals(2, MSG_FIELD, "return\rafterreturn"); + ensure_message_field_equals(3, MSG_FIELD, "backslash\\backslash\\"); + ensure_message_field_equals(4, MSG_FIELD, "backslash\\newline\nanothernewline\nafternewline"); + ensure_message_field_equals(5, MSG_FIELD, "backslash\\returnnewline\r\n\\afterbackslash"); + ensure_message_count(6); + } +} + namespace tut { template<> template<> @@ -820,20 +853,6 @@ namespace tut } } -namespace -{ - void writeMsgNeedsEscaping() - { - LL_DEBUGS("WriteTag") << "backslash\\" << LL_ENDL; - LL_INFOS("WriteTag") << "newline\nafternewline" << LL_ENDL; - LL_WARNS("WriteTag") << "return\rafterreturn" << LL_ENDL; - - LL_DEBUGS("WriteTag") << "backslash\\backslash\\" << LL_ENDL; - LL_INFOS("WriteTag") << "backslash\\newline\nanothernewline\nafternewline" << LL_ENDL; - LL_WARNS("WriteTag") << "backslash\\returnnewline\r\n\\afterbackslash" << LL_ENDL; - } -}; - namespace tut { template<> template<> @@ -881,25 +900,6 @@ namespace tut } } -namespace tut -{ - template<> template<> - void ErrorTestObject::test<5>() - // backslash, return, and newline are not escaped with backslashes - { - LLError::setDefaultLevel(LLError::LEVEL_DEBUG); - setWantsMultiline(true); - writeMsgNeedsEscaping(); // but should not be now - ensure_message_field_equals(0, MSG_FIELD, "backslash\\"); - ensure_message_field_equals(1, MSG_FIELD, "newline\nafternewline"); - ensure_message_field_equals(2, MSG_FIELD, "return\rafterreturn"); - ensure_message_field_equals(3, MSG_FIELD, "backslash\\backslash\\"); - ensure_message_field_equals(4, MSG_FIELD, "backslash\\newline\nanothernewline\nafternewline"); - ensure_message_field_equals(5, MSG_FIELD, "backslash\\returnnewline\r\n\\afterbackslash"); - ensure_message_count(6); - } -} - /* Tests left: handling of classes without LOG_CLASS From a3ca2c9ac830f58dbd6fa49090a936134f5cbf19 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 16:47:05 -0400 Subject: [PATCH 51/59] DRTVWR-447: Restore diagnostic output to Mac app bundle packaging. --- indra/newview/viewer_manifest.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 0aea31d563..40fa6cacf3 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1319,6 +1319,34 @@ class DarwinManifest(ViewerManifest): else: print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" raise + print 72*'=' + import stat + print app_in_dmg + # Second Life.app + for sub0 in os.listdir(app_in_dmg): + print '--{}'.format(sub0) + path0 = os.path.join(app_in_dmg, sub0) + if os.path.isfile(path0): + # shouldn't be any file here + with open(path0) as inf: + for line in inf: + print ' {}'.format(line.rstrip()) + elif os.path.isdir(path0): + # Contents + for sub1 in os.listdir(path0): + print '----{}'.format(sub1) + path1 = os.path.join(path0, sub1) + if os.path.isfile(path1): + # Info.plist, PkgInfo + with open(path1) as inf: + for line in inf: + print ' {}'.format(line.rstrip()) + elif os.path.isdir(path1): + # Frameworks, MacOS, Resources + for sub2 in os.listdir(path1): + path2 = os.path.join(path1, sub2) + print ' {:04o} {}'.format(stat.S_IMODE(os.stat(path2).st_mode), sub2) + print 72*'=' self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg]) finally: From d86b311b2cdc2f58ef53aa2f7a8d180fe4a61353 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Oct 2018 22:34:58 -0400 Subject: [PATCH 52/59] DRTVWR-447: Restore MACOSX_EXECUTABLE_NAME, used for Info.plist. --- indra/newview/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5c918fc3b2..1b19497354 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2092,6 +2092,7 @@ if (DARWIN) # magically known to CMake -- it's that these names are referenced in the # Info-SecondLife.plist file in the configure_file() directive below. set(product "${VIEWER_CHANNEL}") + set(MACOSX_EXECUTABLE_NAME "${VIEWER_CHANNEL}") set(MACOSX_BUNDLE_INFO_STRING "${VIEWER_CHANNEL}") set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns") set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer") From fa5350db7be671b9b935383e5925dcc64d440952 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 18 Oct 2018 11:44:56 -0400 Subject: [PATCH 53/59] DRTVWR-447: Update to bugsplat build 520784 --- autobuild.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 6ce20e45ab..08d4694942 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -244,9 +244,9 @@ archive hash - 436b124bce8cf57b18dbf10f5e6ebcd4 + 492f182607d6096ebc5620779fa6121d url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26151/206132/bugsplat-1.0.7.520674-darwin64-520674.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26319/207508/bugsplat-1.0.7.520784-darwin64-520784.tar.bz2 name darwin64 @@ -256,9 +256,9 @@ archive hash - 5d19acddc51ee7c802297dd176194362 + dfbc7f3c1fd88adc8015e9c2c21b2435 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26153/206145/bugsplat-3.6.0.4.520674-windows-520674.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26321/207522/bugsplat-3.6.0.4.520784-windows-520784.tar.bz2 name windows @@ -268,16 +268,16 @@ archive hash - 78f5688b694e04c052fb0a1165c98bb5 + 131db9b0775375386023f454cce9b803 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26152/206142/bugsplat-3.6.0.4.520674-windows64-520674.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26320/207516/bugsplat-3.6.0.4.520784-windows64-520784.tar.bz2 name windows64 version - 1.0.7.520674 + 1.0.7.520784 colladadom From b4bc7f7c0c1c8804ad9688e1759cc86629193a37 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 18 Oct 2018 13:55:55 -0400 Subject: [PATCH 54/59] DRTVWR-447: Update bugsplat to codeticket version 520791. --- autobuild.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 08d4694942..76c33d0005 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -244,9 +244,9 @@ archive hash - 492f182607d6096ebc5620779fa6121d + c3b5e8c57bd1c92bc9e0956586908b99 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26319/207508/bugsplat-1.0.7.520784-darwin64-520784.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26330/207568/bugsplat-1.0.7.520791-darwin64-520791.tar.bz2 name darwin64 @@ -256,9 +256,9 @@ archive hash - dfbc7f3c1fd88adc8015e9c2c21b2435 + 766dfde65a5b42ea5691d41df79c43e0 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26321/207522/bugsplat-3.6.0.4.520784-windows-520784.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26332/207582/bugsplat-3.6.0.4.520791-windows-520791.tar.bz2 name windows @@ -268,16 +268,16 @@ archive hash - 131db9b0775375386023f454cce9b803 + afd01285e22f27d473fac6f88fac9a3b url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26320/207516/bugsplat-3.6.0.4.520784-windows64-520784.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26331/207576/bugsplat-3.6.0.4.520791-windows64-520791.tar.bz2 name windows64 version - 1.0.7.520784 + 1.0.7.520791 colladadom From c532e3075c7857f3f3f0097890d93bd90ff82db0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 18 Oct 2018 15:31:44 -0400 Subject: [PATCH 55/59] DRTVWR-447: Re-inject BugsplatServerURL into Mac's Info.plist. --- indra/newview/viewer_manifest.py | 41 ++++++++++---------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 40fa6cacf3..fb132732a5 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -909,6 +909,19 @@ class DarwinManifest(ViewerManifest): debpkgdir = os.path.join(pkgdir, "lib", "debug") with self.prefix(src="", dst="Contents"): # everything goes in Contents + bugsplat_db = self.args.get('bugsplat') + if bugsplat_db: + # Inject BugsplatServerURL into Info.plist if provided. + Info_plist = self.dst_path_of("Info.plist") + Info = plistlib.readPlist(Info_plist) + # https://www.bugsplat.com/docs/platforms/os-x#configuration + Info["BugsplatServerURL"] = \ + "https://{}.bugsplat.com/".format(bugsplat_db) + self.put_in_file( + plistlib.writePlistToString(Info), + os.path.basename(Info_plist), + "Info.plist") + # CEF framework goes inside Contents/Frameworks. # Remember where we parked this car. with self.prefix(src="", dst="Frameworks"): @@ -1319,34 +1332,6 @@ class DarwinManifest(ViewerManifest): else: print >> sys.stderr, "Maximum codesign attempts exceeded; giving up" raise - print 72*'=' - import stat - print app_in_dmg - # Second Life.app - for sub0 in os.listdir(app_in_dmg): - print '--{}'.format(sub0) - path0 = os.path.join(app_in_dmg, sub0) - if os.path.isfile(path0): - # shouldn't be any file here - with open(path0) as inf: - for line in inf: - print ' {}'.format(line.rstrip()) - elif os.path.isdir(path0): - # Contents - for sub1 in os.listdir(path0): - print '----{}'.format(sub1) - path1 = os.path.join(path0, sub1) - if os.path.isfile(path1): - # Info.plist, PkgInfo - with open(path1) as inf: - for line in inf: - print ' {}'.format(line.rstrip()) - elif os.path.isdir(path1): - # Frameworks, MacOS, Resources - for sub2 in os.listdir(path1): - path2 = os.path.join(path1, sub2) - print ' {:04o} {}'.format(stat.S_IMODE(os.stat(path2).st_mode), sub2) - print 72*'=' self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg]) finally: From f55d3071e16f06c7afc0940928fa2e9a620556d9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 22 Oct 2018 14:21:35 -0400 Subject: [PATCH 56/59] DRTVWR-447: Restore copying BugsplatMac.framework into Mac package. --- indra/newview/viewer_manifest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index fb132732a5..ed9b5a35fd 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -929,6 +929,9 @@ class DarwinManifest(ViewerManifest): self.path2basename(relpkgdir, CEF_framework) CEF_framework = self.dst_path_of(CEF_framework) + if self.args.get('bugsplat'): + self.path2basename(relpkgdir, "BugsplatMac.framework") + with self.prefix(dst="MacOS"): # NOTE: the -S argument to strip causes it to keep # enough info for annotated backtraces (i.e. function From 279073dbb3eb03fbe1f897bd142a53d7c4c5bc7d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 22 Oct 2018 19:59:07 -0400 Subject: [PATCH 57/59] DRTVWR-447: Introduce LLManifest.process_either(). process_directory() and process_file() are reached both from the top-level caller (try_path(), a local function within LLManifest.path()) and recursively from process_directory(). Both places tested os.path.isdir(source), and if so called process_directory(), else process_file(). Both places were wrong, as it turns out. os.path.isdir(symlink_to_directory) returns True. That meant that despite explicit logic in ccopymumble() to recreate symlinks in the destination area, we were consistently recopying the contents of symlinked directories. The downside to this -- in addition to inflating the size of the installer! -- is that macOS is very particular about the structure of a Framework bundle. It *must* include a Versions/Current symlink identifying which of the other Versions subdirectories is, in fact, current. If Current is itself a subdirectory, codesign can't figure out how to sign the framework, and fails. The logic for deciding between process_directory() and process_file() must explicitly check for os.path.islink(source). Rather than replicating that change in both places, introduce process_either() which decides how to forward the call, and call it both from try_path() and from process_directory(). --- indra/lib/python/indra/util/llmanifest.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 9569014a47..2e6cf53912 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -615,6 +615,14 @@ class LLManifest(object): # *TODO is this gonna be useful? print "Cleaning up " + c + def process_either(self, src, dst): + # If it's a real directory, recurse through it -- + # but not a symlink! Handle those like files. + if os.path.isdir(src) and not os.path.islink(src): + return self.process_directory(src, dst) + else: + return self.process_file(src, dst) + def process_file(self, src, dst): if self.includes(src, dst): for action in self.actions: @@ -641,10 +649,7 @@ class LLManifest(object): for name in names: srcname = os.path.join(src, name) dstname = os.path.join(dst, name) - if os.path.isdir(srcname): - count += self.process_directory(srcname, dstname) - else: - count += self.process_file(srcname, dstname) + count += self.process_either(srcname, dstname) return count def includes(self, src, dst): @@ -816,11 +821,7 @@ class LLManifest(object): # if we're specifying a single path (not a glob), # we should error out if it doesn't exist self.check_file_exists(src) - # if it's a directory, recurse through it - if os.path.isdir(src): - count += self.process_directory(src, dst) - else: - count += self.process_file(src, dst) + count += self.process_either(src, dst) return count try_prefixes = [self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix()] From 32e30386d8cef58533610d31eaba3d3ac976ab76 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 23 Oct 2018 10:52:06 -0400 Subject: [PATCH 58/59] DRTVWR-447: Try to defeat scary Mac Gatekeeper popups by replacing the viewer's baked-in BugsplatMac.framework @rpath path with one based on @executable_path. --- indra/newview/viewer_manifest.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index ed9b5a35fd..508c5cb043 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -933,6 +933,34 @@ class DarwinManifest(ViewerManifest): self.path2basename(relpkgdir, "BugsplatMac.framework") with self.prefix(dst="MacOS"): + executable = self.dst_path_of(self.channel()) + if self.args.get('bugsplat'): + # According to Apple Technical Note TN2206: + # https://developer.apple.com/library/archive/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG207 + # "If an app uses @rpath or an absolute path to link to a + # dynamic library outside of the app, the app will be + # rejected by Gatekeeper. ... Neither the codesign nor the + # spctl tool will show the error." + # (Thanks, Apple. Maybe fix spctl to warn?) + # The BugsplatMac framework embeds @rpath, which is + # causing scary Gatekeeper popups at viewer start. Work + # around this by changing the reference baked into our + # viewer. The install_name_tool -change option needs the + # previous value. Instead of guessing -- which might + # silently be defeated by a BugSplat SDK update that + # changes their baked-in @rpath -- ask for the path + # stamped into the framework. + # Let exception, if any, propagate -- if this doesn't + # work, we need the build to noisily fail! + oldpath = subprocess.check_output( + ['objdump', '-macho', '-dylib-id', '-non-verbose', + os.path.join(relpkgdir, "BugsplatMac.framework", "BugsplatMac")] + ).splitlines()[-1] # take the last line of output + self.run_command( + ['install_name_tool', '-change', oldpath, + '@executable_path/../Frameworks/BugsplatMac.framework/BugsplatMac', + executable]) + # NOTE: the -S argument to strip causes it to keep # enough info for annotated backtraces (i.e. function # names in the crash log). 'strip' with no arguments @@ -942,7 +970,7 @@ class DarwinManifest(ViewerManifest): if ("package" in self.args['actions'] or "unpacked" in self.args['actions']): self.run_command( - ['strip', '-S', self.dst_path_of(self.channel())]) + ['strip', '-S', executable]) with self.prefix(dst="Resources"): # defer cross-platform file copies until we're in the From 9b5b44314acdef260ab515855a72c707e8f3f5fc Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 26 Oct 2018 14:55:13 -0400 Subject: [PATCH 59/59] DRTVWR-447: For some reason the Windows viewer exe wasn't signed. viewer_manifest.py was signing updater.exe within the package, and then signing the installer executable itself, but not the actual viewer executable. Add that. --- indra/newview/viewer_manifest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 508c5cb043..f2b0fe6a32 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -827,6 +827,7 @@ class WindowsManifest(ViewerManifest): # note that the enclosing setup exe is signed later, after the makensis makes it. # Unlike the viewer binary, the VMP filenames are invariant with respect to version, os, etc. for exe in ( + self.final_exe(), "updater.exe", ): self.sign(exe)