From 803b75a718833ccf236f00b425faff4eaf0f29cb Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 18 Oct 2017 18:36:10 -0700 Subject: First version that builds with a dummy BugSplay call in llapp.cpp --- indra/cmake/Copy3rdPartyLibs.cmake | 3 +++ indra/cmake/bugsplat.cmake | 20 ++++++++++++++++++++ indra/llcommon/CMakeLists.txt | 3 +++ indra/llcommon/llapp.cpp | 12 ++++++++++++ indra/newview/viewer_manifest.py | 19 ++++++++++++++----- 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 indra/cmake/bugsplat.cmake (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 5ccbe7d1d8..9238d232b8 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -39,6 +39,9 @@ if(WINDOWS) libeay32.dll glod.dll libhunspell.dll + BugSplat64.dll + BugSplatRc64.dll + BsSndRpt64.exe ) if (FMODEX) diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake new file mode 100644 index 0000000000..6805465023 --- /dev/null +++ b/indra/cmake/bugsplat.cmake @@ -0,0 +1,20 @@ +include(Prebuilt) + +set(BUGSPLAT_FIND_QUIETLY ON) +set(BUGSPLAT_FIND_REQUIRED ON) + +if (USESYSTEMLIBS) + include(FindBUGSPLAT) +else (USESYSTEMLIBS) + use_prebuilt_binary(bugsplat) + if (WINDOWS) + set(BUGSPLAT_LIBRARIES + ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat64.lib + ) + elseif (DARWIN) + + else (WINDOWS) + + endif (WINDOWS) + set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) +endif (USESYSTEMLIBS) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d9eb13d65a..50e262ae7a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,6 +13,7 @@ include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) +include(BUGSPLAT) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -21,6 +22,7 @@ include_directories( ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} ${URIPARSER_INCLUDE_DIRS} + ${BUGSPLAT_INCLUDE_DIR} ) # add_executable(lltreeiterators lltreeiterators.cpp) @@ -291,6 +293,7 @@ target_link_libraries( ${BOOST_SYSTEM_LIBRARY} ${GOOGLE_PERFTOOLS_LIBRARIES} ${URIPARSER_LIBRARIES} + ${BUGSPLAT_LIBRARIES} ) if (DARWIN) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6cc9e804d4..9dd9fc3c70 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -50,6 +50,10 @@ #include "stringize.h" #include "llcleanup.h" +#include "BugSplat.h" + +MiniDmpSender *mpSender; + // // Signal handling // @@ -151,6 +155,14 @@ void LLApp::commonCtor() // (this is used to avoid allocating memory in the crash handler) memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH); mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; + + + static const wchar_t *bugdb_name = L"second_life_callum_test"; + static const wchar_t *app_name = L"SecondLifeViewer"; + static const wchar_t *app_version = L"1.0.0"; + mpSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); + + } LLApp::LLApp(LLErrorThread *error_thread) : diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 71e348db3f..7292f715b7 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -448,6 +448,11 @@ class WindowsManifest(ViewerManifest): # Hunspell self.path("libhunspell.dll") + # BugSplat + self.path("BsSndRpt64.exe") + self.path("BugSplat64.dll") + self.path("BugSplatRc64.dll") + # For google-perftools tcmalloc allocator. try: if self.args['configuration'].lower() == 'debug': @@ -457,7 +462,6 @@ class WindowsManifest(ViewerManifest): except: print "Skipping libtcmalloc_minimal.dll" - self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") self.path("ca-bundle.crt") @@ -571,10 +575,15 @@ class WindowsManifest(ViewerManifest): self.path("zh-CN.pak") self.path("zh-TW.pak") - with self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"): - self.path("libvlc.dll") - self.path("libvlccore.dll") - self.path("plugins/") + with self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"): + self.path("libvlc.dll") + self.path("libvlccore.dll") + self.path("plugins/") + + with self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'release'), dst=""): + self.path("BsSndRpt64.exe") + self.path("BugSplat64.dll") + self.path("BugSplatRc64.dll") # pull in the crash logger and updater from other projects # tag:"crash-logger" here as a cue to the exporter -- cgit v1.2.3 From e75b16f3584b76df706a470395383abf680eb87f Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 19 Oct 2017 11:34:36 -0700 Subject: First pass at adding BugSplat code to viewer and turning off existing (Google Breakpad) exception handling --- indra/llcommon/llapp.cpp | 76 +++++++++++++++++++++++++++++++++++++++--------- indra/llcommon/llapp.h | 10 ++++++- 2 files changed, 72 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 9dd9fc3c70..ea4a0fb59c 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -49,10 +49,20 @@ #include "google_breakpad/exception_handler.h" #include "stringize.h" #include "llcleanup.h" - #include "BugSplat.h" -MiniDmpSender *mpSender; +// TESTING ONLY - REMOVE FOR PRODUCTION +// (Want to only invoke BugSplat crash reporting in the same way we did for Breakpad - for Release viewers +// but need to test here in a ReleaseWithDebugInfo environment) +#if BUGSPLAT_ENABLED +#define LL_SEND_CRASH_REPORTS 1 +#endif + +// BugSplat crash reporting tool - http://bugsplat.com +#if BUGSPLAT_ENABLED +bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2); +MiniDmpSender *gBugSplatSender; +#endif // // Signal handling @@ -155,14 +165,6 @@ void LLApp::commonCtor() // (this is used to avoid allocating memory in the crash handler) memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH); mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; - - - static const wchar_t *bugdb_name = L"second_life_callum_test"; - static const wchar_t *app_name = L"SecondLifeViewer"; - static const wchar_t *app_version = L"1.0.0"; - mpSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); - - } LLApp::LLApp(LLErrorThread *error_thread) : @@ -397,6 +399,42 @@ void EnableCrashingOnCrashes() } #endif +#if BUGSPLAT_ENABLED +bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2) +{ + switch (nCode) + { + case MDSCB_EXCEPTIONCODE: + { + EXCEPTION_RECORD *p = (EXCEPTION_RECORD *)lpVal1; + DWORD code = p ? p->ExceptionCode : 0; + + // create some files in the %temp% directory and attach them + wchar_t cmdString[2 * MAX_PATH]; + wchar_t filePath[MAX_PATH]; + wchar_t tempPath[MAX_PATH]; + GetTempPathW(MAX_PATH, tempPath); + + wsprintf(filePath, L"%sfile1.txt", tempPath); + wsprintf(cmdString, L"echo Exception Code = 0x%08x > %s", code, filePath); + _wsystem(cmdString); + gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); + + wsprintf(filePath, L"%sfile2.txt", tempPath); + wchar_t buf[_MAX_PATH]; + gBugSplatSender->getMinidumpPath((__wchar_t *)buf, _MAX_PATH); + + wsprintf(cmdString, L"echo Crash reporting is so clutch! minidump path = %s > %s", buf, filePath); + _wsystem(cmdString); + gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); + } + break; + } + + return false; +} +#endif + void LLApp::setupErrorHandling(bool second_instance) { // Error handling is done by starting up an error handling thread, which just sleeps and @@ -405,6 +443,17 @@ void LLApp::setupErrorHandling(bool second_instance) #if LL_WINDOWS #if LL_SEND_CRASH_REPORTS + +#if BUGSPLAT_ENABLED + // TODOCP: populate these fields correctly + static const wchar_t *bugdb_name = L"second_life_callum_test"; + static const wchar_t *app_name = L"SecondLifeViewer"; + static const wchar_t *app_version = L"1.0.0"; + gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); + + gBugSplatSender->setCallback(BugSplatExceptionCallback); +#else + EnableCrashingOnCrashes(); // This sets a callback to handle w32 signals to the console window. @@ -466,8 +515,9 @@ void LLApp::setupErrorHandling(bool second_instance) mExceptionHandler->set_handle_debug_exceptions(true); } } -#endif -#else +#endif // BUGSPLAT_ENABLED +#endif // LL_SEND_CRASH_REPORTS +#else // not LL_WINDOWS // // Start up signal handling. // @@ -528,7 +578,7 @@ void LLApp::setupErrorHandling(bool second_instance) } #endif -#endif +#endif // LL_WINDOWS startErrorThread(); } diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index acd829d864..5a4b7f13df 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -30,6 +30,7 @@ #include #include "llrun.h" #include "llsd.h" + // Forward declarations template class LLAtomic32; typedef LLAtomic32 LLAtomicU32; @@ -39,6 +40,14 @@ class LLLiveFile; #include #endif +// first version of Bugsplat (http://bugsplat.com) crash reporting tool +// is only supported on Windows - macOS to follow. +#define BUGSPLAT_ENABLED LL_WINDOWS + +#if BUGSPLAT_ENABLED +class __declspec(dllexport) MiniDmpSender; +#endif + typedef void (*LLAppErrorHandler)(); #if !LL_WINDOWS @@ -316,7 +325,6 @@ private: google_breakpad::ExceptionHandler * mExceptionHandler; - #if !LL_WINDOWS friend void default_unix_signal_handler(int signum, siginfo_t *info, void *); #endif -- cgit v1.2.3 From 6cbb00fe85df8cb01c3a979dbdf2c0354e7bfa4d Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 19 Oct 2017 18:35:00 -0700 Subject: Differentiate between 32/64 bit windows builds for build systewm (BugsSplat enforces specifc names that vary across bitness) --- indra/cmake/bugsplat.cmake | 2 +- indra/newview/viewer_manifest.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index 6805465023..e993979902 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -9,7 +9,7 @@ else (USESYSTEMLIBS) use_prebuilt_binary(bugsplat) if (WINDOWS) set(BUGSPLAT_LIBRARIES - ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat64.lib + ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib ) elseif (DARWIN) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 7292f715b7..4e69597b61 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -449,9 +449,14 @@ class WindowsManifest(ViewerManifest): self.path("libhunspell.dll") # BugSplat - self.path("BsSndRpt64.exe") - self.path("BugSplat64.dll") - self.path("BugSplatRc64.dll") + 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: @@ -580,11 +585,6 @@ class WindowsManifest(ViewerManifest): self.path("libvlccore.dll") self.path("plugins/") - with self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'release'), dst=""): - self.path("BsSndRpt64.exe") - self.path("BugSplat64.dll") - self.path("BugSplatRc64.dll") - # pull in the crash logger and updater from other projects # tag:"crash-logger" here as a cue to the exporter self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], -- cgit v1.2.3 From 0ee774c39f3c689f998dae19d04af11981abd684 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Mon, 23 Oct 2017 11:37:06 -0700 Subject: Missed a place in the Copy3rdPartyLibs.cmake file (thank Windows Find) that needs to differentiate between 32 and 64 bit Windows builds --- indra/cmake/Copy3rdPartyLibs.cmake | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 9238d232b8..eaf1e31fce 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -39,11 +39,20 @@ if(WINDOWS) libeay32.dll glod.dll libhunspell.dll - BugSplat64.dll - BugSplatRc64.dll - BsSndRpt64.exe ) + # Filenames are different for 32/64 bit BugSplat file and we don't + # have any control over them so need to branch. + if(ADDRESS_SIZE EQUAL 32) + set(release_files ${release_files} BugSplat.dll) + set(release_files ${release_files} BugSplatRc.dll) + set(release_files ${release_files} BsSndRpt.exe) + else(ADDRESS_SIZE EQUAL 32) + set(release_files ${release_files} BugSplat64.dll) + set(release_files ${release_files} BugSplatRc64.dll) + set(release_files ${release_files} BsSndRpt64.exe) + endif(ADDRESS_SIZE EQUAL 32) + if (FMODEX) if(ADDRESS_SIZE EQUAL 32) -- cgit v1.2.3 From d359dca06518d778c0f115afec8c759ca026de47 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 24 Oct 2017 14:28:43 -0700 Subject: painfully add in the path to the second life log file that we also send - painful because of string <--> wstring issues --- indra/llcommon/llapp.cpp | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index ea4a0fb59c..6ea1700ea8 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -406,27 +406,11 @@ bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2) { case MDSCB_EXCEPTIONCODE: { - EXCEPTION_RECORD *p = (EXCEPTION_RECORD *)lpVal1; - DWORD code = p ? p->ExceptionCode : 0; - - // create some files in the %temp% directory and attach them - wchar_t cmdString[2 * MAX_PATH]; - wchar_t filePath[MAX_PATH]; - wchar_t tempPath[MAX_PATH]; - GetTempPathW(MAX_PATH, tempPath); - - wsprintf(filePath, L"%sfile1.txt", tempPath); - wsprintf(cmdString, L"echo Exception Code = 0x%08x > %s", code, filePath); - _wsystem(cmdString); - gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); - - wsprintf(filePath, L"%sfile2.txt", tempPath); - wchar_t buf[_MAX_PATH]; - gBugSplatSender->getMinidumpPath((__wchar_t *)buf, _MAX_PATH); - - wsprintf(cmdString, L"echo Crash reporting is so clutch! minidump path = %s > %s", buf, filePath); - _wsystem(cmdString); - gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); + // send the main viewer log file (Clearly a temporary hack since we don't have access to the gDir*** set of functions in newview + const std::string appdata = std::string(getenv("APPDATA")); + const std::string logfile = appdata + "\\SecondLife\\logs\\Secondlife.log"; + const std::wstring wide_logfile(logfile.begin(), logfile.end()); + gBugSplatSender->sendAdditionalFile((const __wchar_t *)wide_logfile.c_str()); } break; } -- cgit v1.2.3 From 2e3c5ac88a434ee437bc3e68b321d5bd0bcd7cc9 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 24 Oct 2017 16:13:23 -0700 Subject: Add in real SL viewer name and version --- indra/llcommon/CMakeLists.txt | 10 +++++++++- indra/llcommon/llapp.cpp | 14 +++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 50e262ae7a..9c5481a977 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -14,6 +14,7 @@ include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) include(BUGSPLAT) +include(BuildVersion) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -255,7 +256,14 @@ set(llcommon_HEADER_FILES ) set_source_files_properties(${llcommon_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) + PROPERTIES HEADER_FILE_ONLY TRUE + ) + +# bring in version information for BugSplat crash reporting +set_source_files_properties(${llcommon_SOURCE_FILES} + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6ea1700ea8..3e652dbdb5 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -431,9 +431,17 @@ void LLApp::setupErrorHandling(bool second_instance) #if BUGSPLAT_ENABLED // TODOCP: populate these fields correctly static const wchar_t *bugdb_name = L"second_life_callum_test"; - static const wchar_t *app_name = L"SecondLifeViewer"; - static const wchar_t *app_version = L"1.0.0"; - gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); + + // build (painfully) the app/channel name + #define stringize_inner(x) L#x + #define stringize_outer(x) stringize_inner(x) + std::wstring app_name(stringize_outer(LL_VIEWER_CHANNEL)); + + // build in real app version now we leveraged CMake to build in BuildVersion.cmake into LLCommon + wchar_t version_string[MAX_STRING]; + wsprintf(version_string, L"%d.%d.%d.%d", LL_VIEWER_VERSION_MAJOR, LL_VIEWER_VERSION_MINOR, LL_VIEWER_VERSION_PATCH, LL_VIEWER_VERSION_BUILD); + + gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name.c_str(), (const __wchar_t *)version_string, NULL); gBugSplatSender->setCallback(BugSplatExceptionCallback); #else -- cgit v1.2.3 From 508e754eb4501b9c3fbfbfde52ca7ae8ed0f06b7 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 14 Dec 2017 18:12:22 -0500 Subject: fix tab character coding style violation --- indra/llcommon/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 9c5481a977..c8e44d7ba4 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -257,13 +257,13 @@ set(llcommon_HEADER_FILES set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE - ) + ) # bring in version information for BugSplat crash reporting set_source_files_properties(${llcommon_SOURCE_FILES} PROPERTIES - COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake - ) + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) -- cgit v1.2.3 From 3de5bab17459ed5bf0494d7bd2a531c473e20b7e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 11 May 2018 16:00:20 -0400 Subject: SL-821: Move BugSplat includes/libs from llcommon to newview. No C++ source in llcommon references any of the BugSplat code. --- indra/llcommon/CMakeLists.txt | 3 --- indra/newview/CMakeLists.txt | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index c8e44d7ba4..4eba1d5451 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,7 +13,6 @@ include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) -include(BUGSPLAT) include(BuildVersion) include_directories( @@ -23,7 +22,6 @@ include_directories( ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} ${URIPARSER_INCLUDE_DIRS} - ${BUGSPLAT_INCLUDE_DIR} ) # add_executable(lltreeiterators lltreeiterators.cpp) @@ -301,7 +299,6 @@ target_link_libraries( ${BOOST_SYSTEM_LIBRARY} ${GOOGLE_PERFTOOLS_LIBRARIES} ${URIPARSER_LIBRARIES} - ${BUGSPLAT_LIBRARIES} ) if (DARWIN) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6b16713add..1fd0af0558 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -4,6 +4,7 @@ project(viewer) include(00-Common) include(Boost) +include(bugsplat) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -91,6 +92,7 @@ include_directories( ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLAPPEARANCE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ${BUGSPLAT_INCLUDE_DIR} ) include_directories(SYSTEM @@ -1976,6 +1978,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + ${BUGSPLAT_LIBRARIES} ) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH -- cgit v1.2.3 From 78b8a0c3e44d7ae0931da7ea6064a12bd3d77b8c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 11 May 2018 17:04:24 -0400 Subject: SL-821: Use one self.path() call for everything under "llplugin". --- indra/newview/viewer_manifest.py | 195 ++++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 97 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 437769726d..3375d4e071 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -605,103 +605,104 @@ class WindowsManifest(ViewerManifest): 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") - - # Media plugins - LibVLC - with self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"): - 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") - - # 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") - - # 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") - - # 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") - - 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, 'bin', 'release'), dst="llplugin"): + with self.prefix(dst="llplugin"): + with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration']): + self.path("media_plugin_cef.dll") + + # Media plugins - LibVLC + with self.prefix(src='../media_plugins/libvlc/%s' % 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']): + 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)): + 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')): + self.path("msvcp120.dll") + self.path("msvcr120.dll") + + # 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='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')): self.path("libvlc.dll") self.path("libvlccore.dll") self.path("plugins/") -- cgit v1.2.3 From ed891c60de4169fa8ef4cc19e953e389cc4df60e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 05:33:14 -0400 Subject: SL-821: Add LL_TO_WSTRING() macro to llpreprocessor.h. Also use existing LL_TO_STRING() macro to stringize LL_VIEWER_CHANNEL in llversioninfo.cpp and its tests. --- indra/llcommon/llpreprocessor.h | 2 ++ indra/newview/llversioninfo.cpp | 7 ++----- indra/newview/tests/llversioninfo_test.cpp | 6 ++---- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 2879038c36..ef015fdce4 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -198,6 +198,8 @@ #define LL_TO_STRING_HELPER(x) #x #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x) +#define LL_TO_WSTRING_HELPER(x) L#x +#define LL_TO_WSTRING(x) LL_TO_WSTRING_HELPER(x) #define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg #define LL_GLUE_IMPL(x, y) x##y #define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y) diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index 375dce485d..4e07223784 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -101,14 +101,11 @@ namespace { // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The // macro expands to the string name of the channel, but without quotes. We - // need to turn it into a quoted string. This macro trick does that. -#define stringize_inner(x) #x -#define stringize_outer(x) stringize_inner(x) - + // need to turn it into a quoted string. LL_TO_STRING() does that. /// Storage of the channel name the viewer is using. // The channel name is set by hardcoded constant, // or by calling LLVersionInfo::resetChannel() - std::string sWorkingChannelName(stringize_outer(LL_VIEWER_CHANNEL)); + std::string sWorkingChannelName(LL_TO_STRING(LL_VIEWER_CHANNEL)); // Storage for the "version and channel" string. // This will get reset too. diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp index 2f7a4e9601..58f0469552 100644 --- a/indra/newview/tests/llversioninfo_test.cpp +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -33,10 +33,8 @@ // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The // macro expands to the string name of the channel, but without quotes. We -// need to turn it into a quoted string. This macro trick does that. -#define stringize_inner(x) #x -#define stringize_outer(x) stringize_inner(x) -#define ll_viewer_channel stringize_outer(LL_VIEWER_CHANNEL) +// need to turn it into a quoted string. LL_TO_STRING() does that. +#define ll_viewer_channel LL_TO_STRING(LL_VIEWER_CHANNEL) namespace tut { -- cgit v1.2.3 From c09d9c12e79fde83a87b2394c88b32e568271eda Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 05:45:36 -0400 Subject: SL-821: Add WSTRINGIZE() and DEWSTRINGIZE() macros for wide strings. Streamline convenience overload stringize(std::wstring); make convenience overload wstringize(std::string) symmetrically convert from UTF-8 string. Also eliminate STRINGIZE() et al. dependency on Boost.Phoenix: use lambdas instead. Using lambdas instead of template expansion necessitates reordering some code in wrapllerrs.h. --- indra/llcommon/stringize.h | 52 ++++++++++++++++++++++----------------- indra/llcommon/tests/wrapllerrs.h | 14 +++++------ 2 files changed, 36 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index a5a90d7297..38dd198ad3 100644 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h @@ -30,7 +30,6 @@ #define LL_STRINGIZE_H #include -#include #include /** @@ -53,12 +52,7 @@ std::basic_string gstringize(const T& item) */ inline std::string stringize(const std::wstring& item) { - LL_WARNS() << "WARNING: Possible narrowing" << LL_ENDL; - - std::string s; - - s = wstring_to_utf8str(item); - return gstringize(s); + return wstring_to_utf8str(item); } /** @@ -76,7 +70,10 @@ std::string stringize(const T& item) */ inline std::wstring wstringize(const std::string& item) { - return gstringize(item.c_str()); + // utf8str_to_wstring() returns LLWString, which isn't necessarily the + // same as std::wstring + LLWString s(utf8str_to_wstring(item)); + return std::wstring(s.begin(), s.end()); } /** @@ -91,10 +88,10 @@ std::wstring wstringize(const T& item) /** * stringize_f(functor) */ -template -std::string stringize_f(Functor const & f) +template +std::basic_string stringize_f(Functor const & f) { - std::ostringstream out; + std::basic_ostringstream out; f(out); return out.str(); } @@ -108,31 +105,37 @@ std::string stringize_f(Functor const & f) * return out.str(); * @endcode */ -#define STRINGIZE(EXPRESSION) (stringize_f(boost::phoenix::placeholders::arg1 << EXPRESSION)) +#define STRINGIZE(EXPRESSION) (stringize_f([&](std::ostream& out){ out << EXPRESSION; })) +/** + * WSTRINGIZE() is the wstring equivalent of STRINGIZE() + */ +#define WSTRINGIZE(EXPRESSION) (stringize_f([&](std::wostream& out){ out << EXPRESSION; })) /** * destringize(str) * defined for symmetry with stringize - * *NOTE - this has distinct behavior from boost::lexical_cast regarding + * @NOTE - this has distinct behavior from boost::lexical_cast regarding * leading/trailing whitespace and handling of bad_lexical_cast exceptions + * @NOTE - no need for dewstringize(), since passing std::wstring will Do The + * Right Thing */ -template -T destringize(std::string const & str) +template +T destringize(std::basic_string const & str) { - T val; - std::istringstream in(str); - in >> val; + T val; + std::basic_istringstream in(str); + in >> val; return val; } /** * destringize_f(str, functor) */ -template -void destringize_f(std::string const & str, Functor const & f) +template +void destringize_f(std::basic_string const & str, Functor const & f) { - std::istringstream in(str); + std::basic_istringstream in(str); f(in); } @@ -143,8 +146,11 @@ void destringize_f(std::string const & str, Functor const & f) * std::istringstream in(str); * in >> item1 >> item2 >> item3 ... ; * @endcode + * @NOTE - once we get generic lambdas, we shouldn't need DEWSTRINGIZE() any + * more since DESTRINGIZE() should do the right thing with a std::wstring. But + * until then, the lambda we pass must accept the right std::basic_istream. */ -#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::phoenix::placeholders::arg1 >> EXPRESSION))) - +#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::istream& in){in >> EXPRESSION;})) +#define DEWSTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::wistream& in){in >> EXPRESSION;})) #endif /* ! defined(LL_STRINGIZE_H) */ diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 9a4bbbd630..08fbf19b1c 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -109,6 +109,12 @@ public: mMessages.push_back(message); } + friend inline + std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) + { + return log.streamto(out); + } + /// Don't assume the message we want is necessarily the LAST log message /// emitted by the underlying code; search backwards through all messages /// for the sought string. @@ -126,7 +132,7 @@ public: throw tut::failure(STRINGIZE("failed to find '" << search << "' in captured log messages:\n" - << boost::ref(*this))); + << *this)); } std::ostream& streamto(std::ostream& out) const @@ -200,10 +206,4 @@ private: LLError::RecorderPtr mRecorder; }; -inline -std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) -{ - return log.streamto(out); -} - #endif /* ! defined(LL_WRAPLLERRS_H) */ -- cgit v1.2.3 From c5f618d096f05bdff91a5d384c46e26840f5a771 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 06:53:42 -0400 Subject: SL-821: Move Windows BugSplat engagement from llcommon to newview. Use WSTRINGIZE(), LL_TO_WSTRING(), wstringize() to produce required wide strings. Use a lambda for callback that sends log file; use LLDir, if set, to find the log file. Introduce BUGSPLAT CMake variable to allow suppressing BugSplat. Make BUGSPLAT CMake variable set LL_BUGSPLAT for C++ compilations. Set viewer version macros on llappviewerwin32.cpp, llappviewerlinux.cpp and llappdelegate-objc.mm -- because BugSplat needs the viewer version data, and because the macOS BugSplat hook is engaged in an Objective-C++ function we override in the app delegate. --- indra/cmake/CMakeLists.txt | 1 + indra/cmake/bugsplat.cmake | 46 +++++++++++++++++------------ indra/llcommon/CMakeLists.txt | 10 +------ indra/llcommon/llapp.cpp | 60 ++------------------------------------ indra/llcommon/llapp.h | 10 +------ indra/newview/CMakeLists.txt | 23 ++++++++++++++- indra/newview/llappviewerwin32.cpp | 49 ++++++++++++++++++++++++++++--- 7 files changed, 101 insertions(+), 98 deletions(-) (limited to 'indra') diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 4a3ebe4835..84e1c5d6fd 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -12,6 +12,7 @@ set(cmake_SOURCE_FILES Audio.cmake BerkeleyDB.cmake Boost.cmake + bugsplat.cmake BuildVersion.cmake CEFPlugin.cmake CEFPlugin.cmake diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index e993979902..a7f4194905 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -1,20 +1,30 @@ -include(Prebuilt) +# BUGSPLAT can be set when launching the make using the argument -DBUGSPLAT:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with BUGSPLAT. +# Open source devs should use the -DBUGSPLAT:BOOL=ON then if they want to +# build with BugSplat, whether they are using USESYSTEMLIBS or not. +if (INSTALL_PROPRIETARY) + set(BUGSPLAT ON CACHE BOOL "Using BugSplat crash reporting library.") +endif (INSTALL_PROPRIETARY) -set(BUGSPLAT_FIND_QUIETLY ON) -set(BUGSPLAT_FIND_REQUIRED ON) +if (BUGSPLAT) + if (USESYSTEMLIBS) + set(BUGSPLAT_FIND_QUIETLY ON) + set(BUGSPLAT_FIND_REQUIRED ON) + include(FindBUGSPLAT) + else (USESYSTEMLIBS) + include(Prebuilt) + use_prebuilt_binary(bugsplat) + if (WINDOWS) + set(BUGSPLAT_LIBRARIES + ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib + ) + elseif (DARWIN) + find_library(BUGSPLAT_LIBRARIES BugsplatMac + PATHS "${ARCH_PREBUILT_DIRS_RELEASE}") + else (WINDOWS) -if (USESYSTEMLIBS) - include(FindBUGSPLAT) -else (USESYSTEMLIBS) - use_prebuilt_binary(bugsplat) - if (WINDOWS) - set(BUGSPLAT_LIBRARIES - ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib - ) - elseif (DARWIN) - - else (WINDOWS) - - endif (WINDOWS) - set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) -endif (USESYSTEMLIBS) + endif (WINDOWS) + set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) + endif (USESYSTEMLIBS) +endif (BUGSPLAT) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 4eba1d5451..d9eb13d65a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,7 +13,6 @@ include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) -include(BuildVersion) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -254,14 +253,7 @@ set(llcommon_HEADER_FILES ) set_source_files_properties(${llcommon_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE - ) - -# bring in version information for BugSplat crash reporting -set_source_files_properties(${llcommon_SOURCE_FILES} - PROPERTIES - COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake - ) + PROPERTIES HEADER_FILE_ONLY TRUE) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 3e652dbdb5..6cc9e804d4 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -49,20 +49,6 @@ #include "google_breakpad/exception_handler.h" #include "stringize.h" #include "llcleanup.h" -#include "BugSplat.h" - -// TESTING ONLY - REMOVE FOR PRODUCTION -// (Want to only invoke BugSplat crash reporting in the same way we did for Breakpad - for Release viewers -// but need to test here in a ReleaseWithDebugInfo environment) -#if BUGSPLAT_ENABLED -#define LL_SEND_CRASH_REPORTS 1 -#endif - -// BugSplat crash reporting tool - http://bugsplat.com -#if BUGSPLAT_ENABLED -bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2); -MiniDmpSender *gBugSplatSender; -#endif // // Signal handling @@ -399,26 +385,6 @@ void EnableCrashingOnCrashes() } #endif -#if BUGSPLAT_ENABLED -bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2) -{ - switch (nCode) - { - case MDSCB_EXCEPTIONCODE: - { - // send the main viewer log file (Clearly a temporary hack since we don't have access to the gDir*** set of functions in newview - const std::string appdata = std::string(getenv("APPDATA")); - const std::string logfile = appdata + "\\SecondLife\\logs\\Secondlife.log"; - const std::wstring wide_logfile(logfile.begin(), logfile.end()); - gBugSplatSender->sendAdditionalFile((const __wchar_t *)wide_logfile.c_str()); - } - break; - } - - return false; -} -#endif - void LLApp::setupErrorHandling(bool second_instance) { // Error handling is done by starting up an error handling thread, which just sleeps and @@ -427,25 +393,6 @@ void LLApp::setupErrorHandling(bool second_instance) #if LL_WINDOWS #if LL_SEND_CRASH_REPORTS - -#if BUGSPLAT_ENABLED - // TODOCP: populate these fields correctly - static const wchar_t *bugdb_name = L"second_life_callum_test"; - - // build (painfully) the app/channel name - #define stringize_inner(x) L#x - #define stringize_outer(x) stringize_inner(x) - std::wstring app_name(stringize_outer(LL_VIEWER_CHANNEL)); - - // build in real app version now we leveraged CMake to build in BuildVersion.cmake into LLCommon - wchar_t version_string[MAX_STRING]; - wsprintf(version_string, L"%d.%d.%d.%d", LL_VIEWER_VERSION_MAJOR, LL_VIEWER_VERSION_MINOR, LL_VIEWER_VERSION_PATCH, LL_VIEWER_VERSION_BUILD); - - gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name.c_str(), (const __wchar_t *)version_string, NULL); - - gBugSplatSender->setCallback(BugSplatExceptionCallback); -#else - EnableCrashingOnCrashes(); // This sets a callback to handle w32 signals to the console window. @@ -507,9 +454,8 @@ void LLApp::setupErrorHandling(bool second_instance) mExceptionHandler->set_handle_debug_exceptions(true); } } -#endif // BUGSPLAT_ENABLED -#endif // LL_SEND_CRASH_REPORTS -#else // not LL_WINDOWS +#endif +#else // // Start up signal handling. // @@ -570,7 +516,7 @@ void LLApp::setupErrorHandling(bool second_instance) } #endif -#endif // LL_WINDOWS +#endif startErrorThread(); } diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 5a4b7f13df..acd829d864 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -30,7 +30,6 @@ #include #include "llrun.h" #include "llsd.h" - // Forward declarations template class LLAtomic32; typedef LLAtomic32 LLAtomicU32; @@ -40,14 +39,6 @@ class LLLiveFile; #include #endif -// first version of Bugsplat (http://bugsplat.com) crash reporting tool -// is only supported on Windows - macOS to follow. -#define BUGSPLAT_ENABLED LL_WINDOWS - -#if BUGSPLAT_ENABLED -class __declspec(dllexport) MiniDmpSender; -#endif - typedef void (*LLAppErrorHandler)(); #if !LL_WINDOWS @@ -325,6 +316,7 @@ private: google_breakpad::ExceptionHandler * mExceptionHandler; + #if !LL_WINDOWS friend void default_unix_signal_handler(int signum, siginfo_t *info, void *); #endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1fd0af0558..2592b532c4 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1354,6 +1354,11 @@ 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}" + ) find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) @@ -1366,6 +1371,7 @@ if (DARWIN) ${AGL_LIBRARY} ${IOKIT_LIBRARY} ${COREAUDIO_LIBRARY} + ${BUGSPLAT_LIBRARIES} ) # Add resource files to the project. @@ -1393,6 +1399,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 +1420,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 @@ -1692,6 +1708,11 @@ if (SDL_FOUND) ) endif (SDL_FOUND) +if (BUGSPLAT) + set_property(TARGET ${VIEWER_BINARY_NAME} + PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (BUGSPLAT) + # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) @@ -1790,7 +1811,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} diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 48b3a1c485..8a014c55d7 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -66,8 +66,18 @@ #endif #include "stringize.h" +#include "lldir.h" #include + +// Bugsplat (http://bugsplat.com) crash reporting tool +#ifdef LL_BUGSPLAT +#include "BugSplat.h" + +// FIXME: need a production BugSplat database name +static const wchar_t *bugdb_name = L"second_life_callum_test"; +#endif + namespace { void (*gOldTerminateHandler)() = NULL; @@ -495,15 +505,46 @@ bool LLAppViewerWin32::init() LLWinDebug::instance(); #endif -#if LL_WINDOWS #if LL_SEND_CRASH_REPORTS - +#if ! defined(LL_BUGSPLAT) LLAppViewer* pApp = LLAppViewer::instance(); pApp->initCrashReporting(); -#endif -#endif +#else // LL_BUGSPLAT + + std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << + LL_VIEWER_VERSION_MINOR << '.' << + LL_VIEWER_VERSION_PATCH << '.' << + LL_VIEWER_VERSION_BUILD)); + + auto sender = new MiniDmpSender( + bugdb_name, LL_TO_WSTRING(LL_VIEWER_CHANNEL), version_string.c_str(), nullptr); + sender->setCallback( + [sender](unsigned int nCode, void* lpVal1, void* lpVal2) + { + // If we haven't yet initialized LLDir, don't bother trying to + // find our log file. + // Alternatively -- if we might encounter trouble trying to query + // LLDir during crash cleanup -- consider making gDirUtilp an + // LLPounceable, and attach a callback that stores the pathname to + // the log file here. + if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) + { + // send the main viewer log file + // widen to wstring, then pass c_str() + sender->sendAdditionalFile( + wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); + } + + return false; + }); + + LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) + << version_string << ')' << LL_ENDL; + +#endif // LL_BUGSPLAT +#endif // LL_SEND_CRASH_REPORTS bool success = LLAppViewer::init(); -- cgit v1.2.3 From cd21556aef547dbb031e363d3a9b9f1893be4d08 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 10:58:59 -0400 Subject: SL-821: Convert wstrings to strings of __wchar_t for BugSplat API. --- indra/newview/llappviewerwin32.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 8a014c55d7..91c6f08000 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -76,7 +76,14 @@ // FIXME: need a production BugSplat database name static const wchar_t *bugdb_name = L"second_life_callum_test"; -#endif + +// MiniDmpSender's constructor is defined to accept __wchar_t* instead of +// plain wchar_t*. +inline std::basic_string<__wchar_t> wunder(const std::wstring& str) +{ + return { str.begin(), str.end() }; +} +#endif // LL_BUGSPLAT namespace { @@ -518,8 +525,12 @@ bool LLAppViewerWin32::init() LL_VIEWER_VERSION_PATCH << '.' << LL_VIEWER_VERSION_BUILD)); + // have to convert normal wide strings to strings of __wchar_t auto sender = new MiniDmpSender( - bugdb_name, LL_TO_WSTRING(LL_VIEWER_CHANNEL), version_string.c_str(), nullptr); + wunder(bugdb_name).c_str(), + wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), + wunder(version_string).c_str(), + nullptr); sender->setCallback( [sender](unsigned int nCode, void* lpVal1, void* lpVal2) { @@ -532,16 +543,17 @@ bool LLAppViewerWin32::init() if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) { // send the main viewer log file - // widen to wstring, then pass c_str() + // widen to wstring, convert to __wchar_t, then pass c_str() sender->sendAdditionalFile( - wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); + wunder(wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))).c_str()); } return false; }); + // engage stringize() overload that converts from wstring LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) - << version_string << ')' << LL_ENDL; + << stringize(version_string) << ')' << LL_ENDL; #endif // LL_BUGSPLAT #endif // LL_SEND_CRASH_REPORTS -- cgit v1.2.3 From 800b47ec230d1d2a6781dce5ba9816d10a37e91e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 15:02:26 -0400 Subject: SL-821: Use classic-C BugSplat callback and static dumb pointer. BugSplat has no business introducing a new C++ API based on classic-C function pointers without even a generic pass-through user data pointer! --- indra/newview/llappviewerwin32.cpp | 65 ++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 91c6f08000..5f3bf14bc2 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -74,14 +74,43 @@ #ifdef LL_BUGSPLAT #include "BugSplat.h" -// FIXME: need a production BugSplat database name -static const wchar_t *bugdb_name = L"second_life_callum_test"; - -// MiniDmpSender's constructor is defined to accept __wchar_t* instead of -// plain wchar_t*. -inline std::basic_string<__wchar_t> wunder(const std::wstring& str) +namespace { - return { str.begin(), str.end() }; + // FIXME: need a production BugSplat database name + static const wchar_t *bugdb_name = L"second_life_callum_test"; + + // MiniDmpSender's constructor is defined to accept __wchar_t* instead of + // plain wchar_t*. + inline std::basic_string<__wchar_t> wunder(const std::wstring& str) + { + return { str.begin(), str.end() }; + } + + // Irritatingly, MiniDmpSender::setCallback() is defined to accept a + // classic-C function pointer instead of an arbitrary C++ callable. In the + // latter case, we could pass a lambda that binds our MiniDmpSender + // pointer. As things stand, we must define an actual function and store + // the pointer statically. + static MiniDmpSender *sBugSplatSender = nullptr; + + bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) + { + // If we haven't yet initialized LLDir, don't bother trying to + // find our log file. + // Alternatively -- if we might encounter trouble trying to query + // LLDir during crash cleanup -- consider making gDirUtilp an + // LLPounceable, and attach a callback that stores the pathname to + // the log file here. + if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) + { + // send the main viewer log file + // widen to wstring, convert to __wchar_t, then pass c_str() + sBugSplatSender->sendAdditionalFile( + wunder(wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))).c_str()); + } + + return false; + } } #endif // LL_BUGSPLAT @@ -526,30 +555,12 @@ bool LLAppViewerWin32::init() LL_VIEWER_VERSION_BUILD)); // have to convert normal wide strings to strings of __wchar_t - auto sender = new MiniDmpSender( + sBugSplatSender = new MiniDmpSender( wunder(bugdb_name).c_str(), wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), wunder(version_string).c_str(), nullptr); - sender->setCallback( - [sender](unsigned int nCode, void* lpVal1, void* lpVal2) - { - // If we haven't yet initialized LLDir, don't bother trying to - // find our log file. - // Alternatively -- if we might encounter trouble trying to query - // LLDir during crash cleanup -- consider making gDirUtilp an - // LLPounceable, and attach a callback that stores the pathname to - // the log file here. - if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) - { - // send the main viewer log file - // widen to wstring, convert to __wchar_t, then pass c_str() - sender->sendAdditionalFile( - wunder(wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))).c_str()); - } - - return false; - }); + sBugSplatSender->setCallback(bugsplatSendLog); // engage stringize() overload that converts from wstring LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) -- cgit v1.2.3 From 4562773abcfe14425478889e2fea02da205013e1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 21 May 2018 13:03:43 -0400 Subject: SL-821: Reorder CMakeLists.txt includes to resolve interdependencies. --- indra/newview/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2592b532c4..d28791485c 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -3,6 +3,10 @@ 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) include(bugsplat) include(BuildPackagesInfo) @@ -38,7 +42,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(Linking) include(NDOF) include(NVAPI) include(OPENAL) -- cgit v1.2.3 From 881bdec4b356ede32b0d0896334f7d6addac6c54 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 21 May 2018 13:07:44 -0400 Subject: SL-821: Introduce macOS BugSplat initialization. --- indra/newview/llappdelegate-objc.mm | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index aebae4c434..2fa8319260 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -25,6 +25,9 @@ */ #import "llappdelegate-objc.h" +#if defined(LL_BUGSPLAT) +#import BugsplatMac; +#endif #include "llwindowmacosx-objc.h" #include // Used for Text Input Services ("Safe" API - it's supported) @@ -64,6 +67,11 @@ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil]; // [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; + +#if defined(LL_BUGSPLAT) + // https://www.bugsplat.com/docs/platforms/os-x#initialization + [[BugsplatStartupManager sharedManager] start]; +#endif } - (void) handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { -- cgit v1.2.3 From 3a885e9cb7bb86e82036b217e2aaf2d96106be43 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 21 May 2018 13:29:16 -0400 Subject: SL-821: Use @import, not #import. --- indra/newview/llappdelegate-objc.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 2fa8319260..e8b4272e51 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -26,7 +26,7 @@ #import "llappdelegate-objc.h" #if defined(LL_BUGSPLAT) -#import BugsplatMac; +@import BugsplatMac; #endif #include "llwindowmacosx-objc.h" #include // Used for Text Input Services ("Safe" API - it's supported) -- cgit v1.2.3 From 6f878571ec65d15f9e06af39375cc0251e4d1e2d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 21 May 2018 13:54:39 -0400 Subject: SL-821: Add -fmodules to llappdelegate-objc.mm compile switches. The BugsplatMac package is built as a module requiring @import. Using @import requires Objective-C++ module support, which requires the -fmodules switch. --- indra/newview/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d28791485c..3501fdf800 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1361,6 +1361,7 @@ if (DARWIN) llappdelegate-objc.mm PROPERTIES COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + COMPILE_FLAGS "-fmodules" ) find_library(AGL_LIBRARY AGL) -- cgit v1.2.3 From 170d5201ff97b4110fa9cc2a9a80234de53e12d8 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 21 May 2018 14:13:11 -0400 Subject: SL-821: Need -fcxx-modules for C++ module support, vs. classic C. --- indra/newview/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3501fdf800..7638a74bc1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1361,7 +1361,7 @@ if (DARWIN) llappdelegate-objc.mm PROPERTIES COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" - COMPILE_FLAGS "-fmodules" + COMPILE_FLAGS "-fmodules -fcxx-modules" ) find_library(AGL_LIBRARY AGL) -- cgit v1.2.3 From 199c688e211125ae1b404425d9a8bd3bc036ea50 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 22 May 2018 11:52:00 -0400 Subject: SL-821: Copy BugsplatMac.framework into target application bundle. --- indra/newview/viewer_manifest.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 3375d4e071..d1a56c2230 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1005,13 +1005,15 @@ open "%s" --args "$@" os.path.basename(Info_plist), "Info.plist") - # CEF framework goes inside viewer_app/Contents/Frameworks. - # Remember where we parked this car. with self.prefix(src="", dst="Frameworks"): + # CEF framework goes inside viewer_app/Contents/Frameworks. CEF_framework = "Chromium Embedded Framework.framework" self.path2basename(relpkgdir, CEF_framework) + # Remember where we parked this car. CEF_framework = self.dst_path_of(CEF_framework) + self.path2basename(relpkgdir, "BugsplatMac.framework") + with self.prefix(dst="MacOS"): # CMake constructs the Second Life executable in the # MacOS directory belonging to the top-level Second -- cgit v1.2.3 From 48534c1badcd2f63dee2ee0106a109b93604827c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 22 May 2018 12:00:20 -0400 Subject: SL-821: Add macOS rpath to Mac viewer executable for BugsplatMac. The BugsplatMac framework is stamped with @rpath/BugsplatMac.framework/etc., so that's the dependency stamped into our viewer executable. To support that lookup, direct CMake to add an appropriate RPATH to the executable. --- indra/newview/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7638a74bc1..954d5ce9ed 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1361,9 +1361,16 @@ if (DARWIN) 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" ) + # from https://stackoverflow.com/a/43551534 + set(CMAKE_MACOSX_RPATH 1) + # From Contents/MacOS/SecondLife, look in Contents/Frameworks + set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") + find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) find_library(COCOA_LIBRARY Cocoa) -- cgit v1.2.3 From 43716d580049bb026904133f0804e8c8d1f519aa Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 23 May 2018 15:48:58 -0400 Subject: SL-821: Try again to add -rpath to Mac executable for BugSplat. --- indra/newview/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6065a08524..9e8a68224b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1368,11 +1368,6 @@ if (DARWIN) COMPILE_FLAGS "-fmodules -fcxx-modules" ) - # from https://stackoverflow.com/a/43551534 - set(CMAKE_MACOSX_RPATH 1) - # From Contents/MacOS/SecondLife, look in Contents/Frameworks - set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") - find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) find_library(COCOA_LIBRARY Cocoa) @@ -1937,8 +1932,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 @@ -2101,11 +2096,16 @@ if (DARWIN) 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" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" ) -- cgit v1.2.3 From b247c4e42434715459df93b5cbf6adb15d3c4cc4 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 24 May 2018 08:48:00 -0400 Subject: SL-821: Force the Mac -rpath linker switch using LINK_FLAGS property instead of the INSTALL_RPATH CMake property, which _should_ have worked. --- indra/newview/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9e8a68224b..c67f365767 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2106,6 +2106,9 @@ if (DARWIN) 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" ) -- cgit v1.2.3 From 63fe7d802aad177107ef8e3bc0c9b7ea5118ad61 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 25 May 2018 12:09:50 -0400 Subject: SL-821, SL-826: Use BUGSPLAT_DB from environment on Windows and Mac. On TeamCity, set BUGSPLAT_DB from build-secrets. Use the presence of $BUGSPLAT_DB, rather than a new CMake BUGSPLAT option, to control whether CMake searches for BugSplat -- and passes LL_BUGSPLAT into C++. When BUGSPLAT_DB is present, make viewer_manifest.py set "BugSplat DB" in build_data.json, and "BugsplatServerURL" in Mac Info.plist. Make llappviewerwin32.cpp read "BugSplat DB" from build_data.json. Add placeholders for Mac hooks to suppress BugSplat prompt and send SecondLife.log. --- indra/cmake/bugsplat.cmake | 16 +++---- indra/newview/CMakeLists.txt | 4 +- indra/newview/llappdelegate-objc.mm | 19 ++++++++ indra/newview/llappviewerwin32.cpp | 87 +++++++++++++++++++++++++++---------- indra/newview/viewer_manifest.py | 12 +++++ 5 files changed, 101 insertions(+), 37 deletions(-) (limited to 'indra') diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index a7f4194905..4db9068b49 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -1,13 +1,7 @@ -# BUGSPLAT can be set when launching the make using the argument -DBUGSPLAT:BOOL=ON -# When building using proprietary binaries though (i.e. having access to LL private servers), -# we always build with BUGSPLAT. -# Open source devs should use the -DBUGSPLAT:BOOL=ON then if they want to -# build with BugSplat, whether they are using USESYSTEMLIBS or not. -if (INSTALL_PROPRIETARY) - set(BUGSPLAT ON CACHE BOOL "Using BugSplat crash reporting library.") -endif (INSTALL_PROPRIETARY) - -if (BUGSPLAT) +# BugSplat is engaged by setting environment variable BUGSPLAT_DB to the +# target BugSplat database name prior to running CMake (and during autobuild +# build). +if (DEFINED ENV{BUGSPLAT_DB}) if (USESYSTEMLIBS) set(BUGSPLAT_FIND_QUIETLY ON) set(BUGSPLAT_FIND_REQUIRED ON) @@ -27,4 +21,4 @@ if (BUGSPLAT) endif (WINDOWS) set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) endif (USESYSTEMLIBS) -endif (BUGSPLAT) +endif (DEFINED ENV{BUGSPLAT_DB}) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c67f365767..cf275ef4b5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1715,10 +1715,10 @@ if (SDL_FOUND) ) endif (SDL_FOUND) -if (BUGSPLAT) +if (DEFINED ENV{BUGSPLAT_DB}) set_property(TARGET ${VIEWER_BINARY_NAME} PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") -endif (BUGSPLAT) +endif (DEFINED ENV{BUGSPLAT_DB}) # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index e8b4272e51..8e1ad169c9 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -70,6 +70,8 @@ #if defined(LL_BUGSPLAT) // https://www.bugsplat.com/docs/platforms/os-x#initialization +// [BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; +// [BugsplatStartupManager sharedManager].askUserDetails = NO; [[BugsplatStartupManager sharedManager] start]; #endif } @@ -187,4 +189,21 @@ return true; } +#if 0 // defined(LL_BUGSPLAT) + +@implementation BugsplatStartupManagerDelegate + +- (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { + NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"example" withExtension:@"json"]; + NSData *data = [NSData dataWithContentsOfURL:fileURL]; + + BugsplatAttachment *attachment = + [[BugsplatAttachment alloc] initWithFilename:@"example.json" + attachmentData:data + contentType:@"application/json"]; + return attachment; +} + +#endif // LL_BUGSPLAT + @end diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 5f3bf14bc2..f9df2b88ed 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -68,29 +68,30 @@ #include "stringize.h" #include "lldir.h" +#include #include // Bugsplat (http://bugsplat.com) crash reporting tool #ifdef LL_BUGSPLAT #include "BugSplat.h" +#include "reader.h" // JsonCpp namespace { - // FIXME: need a production BugSplat database name - static const wchar_t *bugdb_name = L"second_life_callum_test"; - // MiniDmpSender's constructor is defined to accept __wchar_t* instead of - // plain wchar_t*. + // plain wchar_t*. It would be nice if, when wchar_t is the same as + // __wchar_t, this whole function would optimize away. However, we use it + // only for the arguments to make exactly one call to initialize BugSplat. inline std::basic_string<__wchar_t> wunder(const std::wstring& str) { return { str.begin(), str.end() }; } // Irritatingly, MiniDmpSender::setCallback() is defined to accept a - // classic-C function pointer instead of an arbitrary C++ callable. In the - // latter case, we could pass a lambda that binds our MiniDmpSender - // pointer. As things stand, we must define an actual function and store - // the pointer statically. + // classic-C function pointer instead of an arbitrary C++ callable. If it + // did accept a modern callable, we could pass a lambda that binds our + // MiniDmpSender pointer. As things stand, though, we must define an + // actual function and store the pointer statically. static MiniDmpSender *sBugSplatSender = nullptr; bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) @@ -549,22 +550,60 @@ bool LLAppViewerWin32::init() #else // LL_BUGSPLAT - std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << - LL_VIEWER_VERSION_MINOR << '.' << - LL_VIEWER_VERSION_PATCH << '.' << - LL_VIEWER_VERSION_BUILD)); - - // have to convert normal wide strings to strings of __wchar_t - sBugSplatSender = new MiniDmpSender( - wunder(bugdb_name).c_str(), - wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), - wunder(version_string).c_str(), - nullptr); - sBugSplatSender->setCallback(bugsplatSendLog); - - // engage stringize() overload that converts from wstring - LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) - << stringize(version_string) << ')' << LL_ENDL; + if (gDirUtilp) + { + LL_WARNS() << "Can't initialize BugSplat, gDirUtilp not yet set" << LL_ENDL; + } + else + { + std::string build_data_fname( + gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); + std::ifstream inf(build_data_fname.c_str()); + if (! inf.open()) + { + LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname + << "'" << LL_ENDL; + } + else + { + Json::Reader reader; + Json::Value build_data; + if (! reader.parse(inf, build_data, false)) // don't collect comments + { + LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname + << "': " << reader.getFormattedErrorMessages() << LL_ENDL; + } + else + { + Json::Value BugSplat_DB = build_data["BugSplat DB"]; + if (! BugSplat_DB) + { + LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" + << build_data_fname "'" << LL_ENDL; + } + else + { + // Got BugSplat_DB, onward! + std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << + LL_VIEWER_VERSION_MINOR << '.' << + LL_VIEWER_VERSION_PATCH << '.' << + LL_VIEWER_VERSION_BUILD)); + + // have to convert normal wide strings to strings of __wchar_t + sBugSplatSender = new MiniDmpSender( + wunder(BugSplat_DB).c_str(), + wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), + wunder(version_string).c_str(), + nullptr); + sBugSplatSender->setCallback(bugsplatSendLog); + + // engage stringize() overload that converts from wstring + LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) + << stringize(version_string) << ')' << LL_ENDL; + } // got BugSplat_DB + } // parsed build_data.json + } // opened build_data.json + } // gDirUtilp set #endif // LL_BUGSPLAT #endif // LL_SEND_CRASH_REPORTS diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 1fa948f89e..68ad1db14d 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -186,6 +186,11 @@ class ViewerManifest(LLManifest): "Address Size":self.address_size, "Update Service":"https://update.secondlife.com/update", } + try: + build_data_dict["BugSplat DB"] = os.environ["BUGSPLAT_DB"] + except KeyError: + # skip the assignment if there's no BUGSPLAT_DB variable + pass 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) @@ -1001,6 +1006,13 @@ open "%s" --args "$@" # runs the executable, instead of launching the app) Info["CFBundleExecutable"] = "Second Life" Info["CFBundleIconFile"] = viewer_icon + try: + # https://www.bugsplat.com/docs/platforms/os-x#configuration + Info["BugsplatServerURL"] = \ + "https://{BUGSPLAT_DB}.bugsplatsoftware.com/".format(**os.environ) + except KeyError: + # skip the assignment if there's no BUGSPLAT_DB variable + pass self.put_in_file( plistlib.writePlistToString(Info), os.path.basename(Info_plist), -- cgit v1.2.3 From 8781b36d7ee5d6532fb6534caa595166ad00f04d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 25 May 2018 16:08:00 -0400 Subject: SL-821: export BUGSPLAT_DB when loaded so child processes can detect. Produce CMake message when BugSplat is engaged so we can detect in build log. Don't try to copy BugSplat DLLs when NOT engaged. --- indra/cmake/Copy3rdPartyLibs.cmake | 8 +++++--- indra/cmake/bugsplat.cmake | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 7f708bc27a..c9519b0e1d 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -51,15 +51,17 @@ if(WINDOWS) # Filenames are different for 32/64 bit BugSplat file and we don't # have any control over them so need to branch. - if(ADDRESS_SIZE EQUAL 32) + if (DEFINED ENV{BUGSPLAT_DB}) + if(ADDRESS_SIZE EQUAL 32) set(release_files ${release_files} BugSplat.dll) set(release_files ${release_files} BugSplatRc.dll) set(release_files ${release_files} BsSndRpt.exe) - else(ADDRESS_SIZE EQUAL 32) + else(ADDRESS_SIZE EQUAL 32) set(release_files ${release_files} BugSplat64.dll) set(release_files ${release_files} BugSplatRc64.dll) set(release_files ${release_files} BsSndRpt64.exe) - endif(ADDRESS_SIZE EQUAL 32) + endif(ADDRESS_SIZE EQUAL 32) + endif (DEFINED ENV{BUGSPLAT_DB}) if (FMODEX) diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index 4db9068b49..eb5808b1fb 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -3,10 +3,12 @@ # build). if (DEFINED ENV{BUGSPLAT_DB}) if (USESYSTEMLIBS) + message(STATUS "Looking for system BugSplat") set(BUGSPLAT_FIND_QUIETLY ON) set(BUGSPLAT_FIND_REQUIRED ON) include(FindBUGSPLAT) else (USESYSTEMLIBS) + message(STATUS "Engaging autobuild BugSplat") include(Prebuilt) use_prebuilt_binary(bugsplat) if (WINDOWS) -- cgit v1.2.3 From 3ca76065b0beeaf276078b4bc28b8e0c6295a4fc Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 25 May 2018 19:02:53 -0400 Subject: SL-823: Fix minor compile errors in code to read build_data.json. --- indra/newview/llappviewerwin32.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index f9df2b88ed..b7ad28448b 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -79,14 +79,29 @@ namespace { // MiniDmpSender's constructor is defined to accept __wchar_t* instead of - // plain wchar_t*. It would be nice if, when wchar_t is the same as - // __wchar_t, this whole function would optimize away. However, we use it - // only for the arguments to make exactly one call to initialize BugSplat. + // plain wchar_t*. That said, wunder() returns std::basic_string<__wchar_t>, + // NOT plain __wchar_t*, despite the apparent convenience. Calling + // wunder(something).c_str() as an argument expression is fine: that + // std::basic_string instance will survive until the function returns. + // Calling c_str() on a std::basic_string local to wunder() would be + // Undefined Behavior: we'd be left with a pointer into a destroyed + // std::basic_string instance. + + // It would be nice if, when wchar_t is the same as __wchar_t, this whole + // function would optimize away. However, we use it only for the arguments + // to make exactly one call to initialize BugSplat. inline std::basic_string<__wchar_t> wunder(const std::wstring& str) { return { str.begin(), str.end() }; } + // when what we have in hand is a std::string, convert from UTF-8 using + // specific wstringize() overload + inline std::basic_string<__wchar_t> wunder(const std::string& str) + { + return wunder(wstringize(str)); + } + // Irritatingly, MiniDmpSender::setCallback() is defined to accept a // classic-C function pointer instead of an arbitrary C++ callable. If it // did accept a modern callable, we could pass a lambda that binds our @@ -107,7 +122,7 @@ namespace // send the main viewer log file // widen to wstring, convert to __wchar_t, then pass c_str() sBugSplatSender->sendAdditionalFile( - wunder(wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))).c_str()); + wunder(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); } return false; @@ -559,7 +574,7 @@ bool LLAppViewerWin32::init() std::string build_data_fname( gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); std::ifstream inf(build_data_fname.c_str()); - if (! inf.open()) + if (! inf.is_open()) { LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname << "'" << LL_ENDL; @@ -570,8 +585,9 @@ bool LLAppViewerWin32::init() Json::Value build_data; if (! reader.parse(inf, build_data, false)) // don't collect comments { + // gah, the typo is baked into their API LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname - << "': " << reader.getFormattedErrorMessages() << LL_ENDL; + << "': " << reader.getFormatedErrorMessages() << LL_ENDL; } else { @@ -579,7 +595,7 @@ bool LLAppViewerWin32::init() if (! BugSplat_DB) { LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" - << build_data_fname "'" << LL_ENDL; + << build_data_fname << "'" << LL_ENDL; } else { @@ -591,7 +607,7 @@ bool LLAppViewerWin32::init() // have to convert normal wide strings to strings of __wchar_t sBugSplatSender = new MiniDmpSender( - wunder(BugSplat_DB).c_str(), + wunder(BugSplat_DB.asString()).c_str(), wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), wunder(version_string).c_str(), nullptr); -- cgit v1.2.3 From a5c17472fb3bbd2bc6fe188c450d2123963b5d6e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 26 May 2018 08:44:57 -0400 Subject: SL-823: Fix typo in code that sets up BugSplat. --- indra/newview/llappviewerwin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index f9df2b88ed..c2cbce493c 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -550,7 +550,7 @@ bool LLAppViewerWin32::init() #else // LL_BUGSPLAT - if (gDirUtilp) + if (! gDirUtilp) { LL_WARNS() << "Can't initialize BugSplat, gDirUtilp not yet set" << LL_ENDL; } -- cgit v1.2.3 From d2fa5a53e8b91bd0aba10ab3917c722dc360b610 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 30 May 2018 13:14:43 -0400 Subject: remove unused UNATTENDED cmake variable that generates warnings --- indra/cmake/Variables.cmake | 1 - indra/newview/CMakeLists.txt | 26 ++++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index bd69c49856..b913d6398e 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -209,7 +209,6 @@ set(SIGNING_IDENTITY "" CACHE STRING "Specifies the signing identity to use, if set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside") set(USESYSTEMLIBS OFF CACHE BOOL "Use libraries from your system rather than Linden-supplied prebuilt libraries.") -set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.") set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.") diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index cf275ef4b5..6b3db36efe 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1853,23 +1853,21 @@ 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) + 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." + ) if (PACKAGE) add_custom_command( -- cgit v1.2.3 From 5caeacb3f6cf677cbec265ee6de733697dbf30ec Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 10:55:38 -0400 Subject: SL-821: Create macOS symbol-file archive while packaging. --- indra/newview/viewer_manifest.py | 67 +++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 68ad1db14d..8f2d04e9b8 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. @@ -903,6 +904,9 @@ class DarwinManifest(ViewerManifest): launcher_app, launcher_icon = "Second Life Launcher.app", "secondlife.icns" viewer_app, viewer_icon = "Second Life Viewer.app", "secondlife.icns" + # capture the path to the directory containing toplevel_app + parentdir = os.path.join(self.get_dst_prefix(), os.pardir) + # 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="") @@ -914,10 +918,12 @@ class DarwinManifest(ViewerManifest): # 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) + Info_plist = self.dst_path_of("Info.plist") + # except we twiddle these entries + Info = plistlib.readPlist(Info_plist) + Info["CFBundleGetInfoString"] = self.channel() + Info["CFBundleShortVersionString"] = '.'.join(self.args['version']) + plistlib.writePlist(Info, Info_plist) # the one file in top-level MacOS directory is the trampoline to # our nested launcher_app @@ -1046,14 +1052,47 @@ open "%s" --args "$@" # now do it, only without relativizing paths os.rename(fromwhere, towhere) - # 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']): + # only if we're engaging BugSplat + if "BUGSPLAT_DB" in os.environ: + # Create a symbol archive BEFORE stripping the + # binary. + self.run_command(['dsymutil', os.path.join(here, 'Second Life')]) + # This should produce a Second Life.dSYM bundle directory. + try: + # Now pretend we're Xcode making a .xcarchive file. + # Put it as a sibling of the top-level .app. + # From "Dave" at BugSplat support: + # "More from our Mac lead: I think zipping + # a folder containing the binary and + # symbols would be sufficient. Assuming + # symbol files are created with CMake. I'm + # not sure if CMake strips symbols into + # separate files at build time, and if so + # they're in a supported format." + xcarchive = os.path.join(parentdir, + 'Second Life.xcarchive.zip') + with zipfile.ZipFile(xcarchive, 'w', + compression=zipfile.ZIP_DEFLATED) as zf: + print "Creating {}".format(xcarchive) + for base, dirs, files in os.walk(here): + for fn in files: + fullfn = os.path.join(base, fn) + relfn = os.path.relpath(fullfn, here) + print " {}".format(relfn) + zf.write(fullfn, relfn) + finally: + # Whether or not we were able to create the + # .xcarchive file, clean up the .dSYM bundle + shutil.rmtree(os.path.join(here, 'Second Life.dSYM')) + + # 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. self.run_command( ['strip', '-S', self.dst_path_of('Second Life')]) -- cgit v1.2.3 From ac2604a039bb9477cf9102dfccd77619a6061d7a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 11:31:17 -0400 Subject: SL-821: Avoid Breakpad (and signal handling in general) for BugSplat. Pass LL_BUGSPLAT into llapp.cpp compile to be able to detect that. --- indra/llcommon/CMakeLists.txt | 5 +++++ indra/llcommon/llapp.cpp | 23 ++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d9eb13d65a..8977acb873 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -255,6 +255,11 @@ set(llcommon_HEADER_FILES set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +if (DEFINED ENV{BUGSPLAT_DB}) + set_source_files_properties(llapp.cpp + PROPERTIES COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (DEFINED ENV{BUGSPLAT_DB}) + list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) if(LLCOMMON_LINK_SHARED) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6cc9e804d4..421af3006e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -392,7 +392,7 @@ void LLApp::setupErrorHandling(bool second_instance) #if LL_WINDOWS -#if LL_SEND_CRASH_REPORTS +#if LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT) EnableCrashingOnCrashes(); // This sets a callback to handle w32 signals to the console window. @@ -454,8 +454,15 @@ void LLApp::setupErrorHandling(bool second_instance) mExceptionHandler->set_handle_debug_exceptions(true); } } -#endif -#else +#endif // LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT) +#else // ! LL_WINDOWS + +#if defined(LL_BUGSPLAT) + // Don't install our own signal handlers -- BugSplat needs to hook them, + // or it's completely ineffectual. + bool installHandler = false; + +#else // ! LL_BUGSPLAT // // Start up signal handling. // @@ -463,9 +470,11 @@ void LLApp::setupErrorHandling(bool second_instance) // thread, asynchronous signals can be delivered to any thread (in theory) // setup_signals(); - + // Add google breakpad exception handler configured for Darwin/Linux. bool installHandler = true; +#endif // ! LL_BUGSPLAT + #if LL_DARWIN // For the special case of Darwin, we do not want to install the handler if // the process is being debugged as the app will exit with value ABRT (6) if @@ -498,7 +507,7 @@ void LLApp::setupErrorHandling(bool second_instance) // installing the handler. installHandler = true; } - #endif + #endif // ! LL_RELEASE_FOR_DOWNLOAD if(installHandler && (mExceptionHandler == 0)) { @@ -514,9 +523,9 @@ void LLApp::setupErrorHandling(bool second_instance) google_breakpad::MinidumpDescriptor desc(mDumpPath); mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1); } -#endif +#endif // LL_LINUX -#endif +#endif // ! LL_WINDOWS startErrorThread(); } -- cgit v1.2.3 From 6cda0ecc964e4bcc989c97df7b4bc61b78e91592 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 13:22:20 -0400 Subject: SL-821: Rename macOS Second Life executable to match the channel name. This requires fixing CFBundleExecutable as well. --- indra/newview/viewer_manifest.py | 90 +++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 38 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 8f2d04e9b8..4d6df04156 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1005,34 +1005,7 @@ open "%s" --args "$@" # -------------------- 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 - try: - # https://www.bugsplat.com/docs/platforms/os-x#configuration - Info["BugsplatServerURL"] = \ - "https://{BUGSPLAT_DB}.bugsplatsoftware.com/".format(**os.environ) - except KeyError: - # skip the assignment if there's no BUGSPLAT_DB variable - pass - self.put_in_file( - plistlib.writePlistToString(Info), - os.path.basename(Info_plist), - "Info.plist") - - with self.prefix(src="", dst="Frameworks"): - # CEF framework goes inside viewer_app/Contents/Frameworks. - CEF_framework = "Chromium Embedded Framework.framework" - self.path2basename(relpkgdir, CEF_framework) - # Remember where we parked this car. - CEF_framework = self.dst_path_of(CEF_framework) - - self.path2basename(relpkgdir, "BugsplatMac.framework") - + # defer Info.plist until after MacOS with self.prefix(dst="MacOS"): # CMake constructs the Second Life executable in the # MacOS directory belonging to the top-level Second @@ -1040,25 +1013,39 @@ open "%s" --args "$@" 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 + # don't move the trampoline script we just made! + executables = [f for f in os.listdir(toplevel_MacOS) + if f != os.path.basename(trampoline)] + if not executables: + raise ManifestError("Couldn't find viewer executable in {}!" + .format(toplevel_MacOS)) + for f in executables: fromwhere = os.path.join(toplevel_MacOS, f) - towhere = os.path.join(here, f) + towhere = self.dst_path_of(f) print "Moving %s => %s" % \ (self.relpath(fromwhere, relbase), self.relpath(towhere, relbase)) # now do it, only without relativizing paths os.rename(fromwhere, towhere) + # Pick the biggest of the executables as the real viewer. + # Make (size, filename) pairs; sort by size; pick the + # last pair; take the filename entry from that. + SecondLife = sorted((os.path.getsize(self.dst_path_of(f)), f) + for f in executables)[-1][1] + # now rename it to match the channel name + exename = self.channel() + exepath = self.dst_path_of(exename) + print "{} => {}".format(SecondLife, exename) + os.rename(self.dst_path_of(SecondLife), exepath) + if ("package" in self.args['actions'] or "unpacked" in self.args['actions']): # only if we're engaging BugSplat if "BUGSPLAT_DB" in os.environ: # Create a symbol archive BEFORE stripping the # binary. - self.run_command(['dsymutil', os.path.join(here, 'Second Life')]) + self.run_command(['dsymutil', exepath]) # This should produce a Second Life.dSYM bundle directory. try: # Now pretend we're Xcode making a .xcarchive file. @@ -1072,7 +1059,7 @@ open "%s" --args "$@" # separate files at build time, and if so # they're in a supported format." xcarchive = os.path.join(parentdir, - 'Second Life.xcarchive.zip') + exename + '.xcarchive.zip') with zipfile.ZipFile(xcarchive, 'w', compression=zipfile.ZIP_DEFLATED) as zf: print "Creating {}".format(xcarchive) @@ -1085,7 +1072,7 @@ open "%s" --args "$@" finally: # Whether or not we were able to create the # .xcarchive file, clean up the .dSYM bundle - shutil.rmtree(os.path.join(here, 'Second Life.dSYM')) + shutil.rmtree(self.dst_path_of(exename + '.dSYM')) # NOTE: the -S argument to strip causes it to keep # enough info for annotated backtraces (i.e. function @@ -1093,8 +1080,35 @@ open "%s" --args "$@" # yields a slightly smaller binary but makes crash # logs mostly useless. This may be desirable for the # final release. Or not. - self.run_command( - ['strip', '-S', self.dst_path_of('Second Life')]) + self.run_command(['strip', '-S', exepath]) + + # 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"] = exename + Info["CFBundleIconFile"] = viewer_icon + try: + # https://www.bugsplat.com/docs/platforms/os-x#configuration + Info["BugsplatServerURL"] = \ + "https://{BUGSPLAT_DB}.bugsplatsoftware.com/".format(**os.environ) + except KeyError: + # skip the assignment if there's no BUGSPLAT_DB variable + pass + self.put_in_file( + plistlib.writePlistToString(Info), + os.path.basename(Info_plist), + "Info.plist") + + with self.prefix(src="", dst="Frameworks"): + # CEF framework goes inside viewer_app/Contents/Frameworks. + CEF_framework = "Chromium Embedded Framework.framework" + self.path2basename(relpkgdir, CEF_framework) + # Remember where we parked this car. + CEF_framework = self.dst_path_of(CEF_framework) + + self.path2basename(relpkgdir, "BugsplatMac.framework") with self.prefix(dst="Resources"): # defer cross-platform file copies until we're in the right -- cgit v1.2.3 From 1378547bb6a077fbed594ae7b92289dac5942183 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 14:25:03 -0400 Subject: SL-821: Defend macOS packaging against multiple viewer_manifest runs --- indra/newview/viewer_manifest.py | 51 +++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 4d6df04156..80370be109 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -27,6 +27,7 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ import errno +import glob import json import os import os.path @@ -1016,28 +1017,34 @@ open "%s" --args "$@" # don't move the trampoline script we just made! executables = [f for f in os.listdir(toplevel_MacOS) if f != os.path.basename(trampoline)] - if not executables: - raise ManifestError("Couldn't find viewer executable in {}!" - .format(toplevel_MacOS)) - for f in executables: - fromwhere = os.path.join(toplevel_MacOS, f) - towhere = self.dst_path_of(f) - print "Moving %s => %s" % \ - (self.relpath(fromwhere, relbase), - self.relpath(towhere, relbase)) - # now do it, only without relativizing paths - os.rename(fromwhere, towhere) - - # Pick the biggest of the executables as the real viewer. - # Make (size, filename) pairs; sort by size; pick the - # last pair; take the filename entry from that. - SecondLife = sorted((os.path.getsize(self.dst_path_of(f)), f) - for f in executables)[-1][1] - # now rename it to match the channel name - exename = self.channel() - exepath = self.dst_path_of(exename) - print "{} => {}".format(SecondLife, exename) - os.rename(self.dst_path_of(SecondLife), exepath) + if executables: + # there are still executables in toplevel_MacOS + for f in executables: + fromwhere = os.path.join(toplevel_MacOS, f) + towhere = self.dst_path_of(f) + print "Moving %s => %s" % \ + (self.relpath(fromwhere, relbase), + self.relpath(towhere, relbase)) + # now do it, only without relativizing paths + os.rename(fromwhere, towhere) + + # Pick the biggest of the executables as the real viewer. + # Make (size, filename) pairs; sort by size; pick the + # last pair; take the filename entry from that. + SecondLife = sorted((os.path.getsize(self.dst_path_of(f)), f) + for f in executables)[-1][1] + # now rename it to match the channel name + exename = self.channel() + exepath = self.dst_path_of(exename) + print "{} => {}".format(SecondLife, exename) + os.rename(self.dst_path_of(SecondLife), exepath) + + else: + # executables already located 'here' -- pick the + # biggest, as above + exepath = sorted((os.path.getsize(f), f) + for f in glob.glob(os.path.join(here, '*')))[-1][1] + exename = os.path.basename(exepath) if ("package" in self.args['actions'] or "unpacked" in self.args['actions']): -- cgit v1.2.3 From 67f6625c56406604197507c842496f031eb0986f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 17:03:25 -0400 Subject: SL-821: Continue changing macOS executable to match channel name. Set our CMake 'product' variable to VIEWER_CHANNEL. This probably has far- reaching implications, but it seems the expedient way to keep everything self- consistent. Use ${product} in the DARWIN VIEWER_EXE_GLOBS used for Breakpad symbol dumping instead of hardcoding 'Second Life'. The Breakpad symbol dumping stanza was enclosed in nested (but not indented) conditions. To these we add another condition: don't bother if we're using BugSplat. Unify all three into a single horrendous outermost expression. Fix the MACOSX_BUNDLE_INFO_STRING, and hence CFBundleGetInfoString, to VIEWER_CHANNEL as well. Our CMake MACOSX_BUNDLE_SHORT_VERSION_STRING was never used before -- we were erroneously using MACOSX_BUNDLE_LONG_VERSION_STRING in the Info-SecondLife.plist template even for CFBundleShortVersionString. Looks like a classic copy/paste error. Fix that; also use four-part version number instead of three-part. With those two changes, we shouldn't need to patch the top-level Info.plist in viewer_manifest.py any more. viewer_manifest.py still needs to move the viewer executable(s) to the embedded viewer app bundle, but it no longer needs to rename the real executable to the channel name since we've already dealt with that in CMake land. This lets us unify the code that picks the biggest of those executables in the first and second viewer_manifest.py runs. --- indra/newview/CMakeLists.txt | 20 ++++++------- indra/newview/Info-SecondLife.plist | 2 +- indra/newview/viewer_manifest.py | 59 ++++++++++++++----------------------- 3 files changed, 33 insertions(+), 48 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ba261c8e91..5648e3eb02 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2082,16 +2082,18 @@ if (LINUX) endif (LINUX) if (DARWIN) - # These all get set with PROPERTIES - set(product "Second Life") + # 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}") # this is the setting for the Python wrapper, see SL-322 and WRAPPER line in Info-SecondLife.plist set(MACOSX_WRAPPER_EXECUTABLE_NAME "SL_Launcher") - set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer") + 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") @@ -2179,7 +2181,7 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) -if (PACKAGE) +if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND NOT DEFINED ENV{BUGSPLAT_DB}) set(SYMBOL_SEARCH_DIRS "") # Note that the path to VIEWER_SYMBOL_FILE must match that in ../../build.sh if (WINDOWS) @@ -2198,8 +2200,8 @@ if (PACKAGE) 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_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger") + set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger") set(VIEWER_LIB_GLOB "*.dylib") endif (DARWIN) if (LINUX) @@ -2211,7 +2213,6 @@ if (PACKAGE) 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 ".") @@ -2238,8 +2239,7 @@ if (PACKAGE) 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) +endif () if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index af4cf26ac6..8aabd6818b 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -21,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - ${MACOSX_BUNDLE_LONG_VERSION_STRING} + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} CFBundleSignature ???? CFBundleVersion diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 80370be109..49dc732457 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -27,7 +27,6 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ import errno -import glob import json import os import os.path @@ -920,11 +919,6 @@ class DarwinManifest(ViewerManifest): with self.prefix(src="", dst="Contents"): # everything goes in Contents # top-level Info.plist is as generated by CMake Info_plist = self.dst_path_of("Info.plist") - # except we twiddle these entries - Info = plistlib.readPlist(Info_plist) - Info["CFBundleGetInfoString"] = self.channel() - Info["CFBundleShortVersionString"] = '.'.join(self.args['version']) - plistlib.writePlist(Info, Info_plist) # the one file in top-level MacOS directory is the trampoline to # our nested launcher_app @@ -1014,37 +1008,28 @@ open "%s" --args "$@" here = self.get_dst_prefix() relbase = os.path.realpath(os.path.dirname(Info_plist)) self.cmakedirs(here) - # don't move the trampoline script we just made! - executables = [f for f in os.listdir(toplevel_MacOS) - if f != os.path.basename(trampoline)] - if executables: - # there are still executables in toplevel_MacOS - for f in executables: - fromwhere = os.path.join(toplevel_MacOS, f) - towhere = self.dst_path_of(f) - print "Moving %s => %s" % \ - (self.relpath(fromwhere, relbase), - self.relpath(towhere, relbase)) - # now do it, only without relativizing paths - os.rename(fromwhere, towhere) - - # Pick the biggest of the executables as the real viewer. - # Make (size, filename) pairs; sort by size; pick the - # last pair; take the filename entry from that. - SecondLife = sorted((os.path.getsize(self.dst_path_of(f)), f) - for f in executables)[-1][1] - # now rename it to match the channel name - exename = self.channel() - exepath = self.dst_path_of(exename) - print "{} => {}".format(SecondLife, exename) - os.rename(self.dst_path_of(SecondLife), exepath) - - else: - # executables already located 'here' -- pick the - # biggest, as above - exepath = sorted((os.path.getsize(f), f) - for f in glob.glob(os.path.join(here, '*')))[-1][1] - exename = os.path.basename(exepath) + 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 = self.dst_path_of(f) + print "Moving %s => %s" % \ + (self.relpath(fromwhere, relbase), + self.relpath(towhere, relbase)) + # now do it, only without relativizing paths + os.rename(fromwhere, towhere) + + # Pick the biggest of the executables as the real viewer. + # Make (basename, fullpath) pairs; for each pair, + # expand to (size, basename, fullpath) triples; sort + # by size; pick the last triple; take the basename and + # fullpath from that. + _, exename, exepath = \ + sorted((os.path.getsize(path), name, path) + for name, path in + ((name, os.path.join(here, name)) + for name in os.listdir(here)))[-1] if ("package" in self.args['actions'] or "unpacked" in self.args['actions']): -- cgit v1.2.3 From 9b7640d70ae820a954634ecf0dae43dfb33c0d3a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 18:19:54 -0400 Subject: SL-821: Remove VSTool invocation to unbreak Windows TeamCity builds. --- indra/newview/CMakeLists.txt | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 23337ddbfb..f7b30007c9 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1827,21 +1827,6 @@ if (WINDOWS) 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 -- cgit v1.2.3 From 16776975e708f881c4e806c8b9a82f0f270636a7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 18:25:17 -0400 Subject: SL-821: Merge removal of VSTool.exe invocation from CMake. --- indra/newview/CMakeLists.txt | 70 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f7b30007c9..ad65301d4d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -3,7 +3,12 @@ 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) +include(bugsplat) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -37,7 +42,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(Linking) include(NDOF) include(NVAPI) include(OPENAL) @@ -91,6 +95,7 @@ include_directories( ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLAPPEARANCE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ${BUGSPLAT_INCLUDE_DIR} ) include_directories(SYSTEM @@ -530,6 +535,7 @@ set(viewer_SOURCE_FILES llscriptfloater.cpp llscrollingpanelparam.cpp llscrollingpanelparambase.cpp + llsculptidsize.cpp llsearchcombobox.cpp llsearchhistory.cpp llsecapi.cpp @@ -1143,6 +1149,7 @@ set(viewer_HEADER_FILES llscriptruntimeperms.h llscrollingpanelparam.h llscrollingpanelparambase.h + llsculptidsize.h llsearchcombobox.h llsearchhistory.h llsecapi.h @@ -1354,6 +1361,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) @@ -1366,6 +1381,7 @@ if (DARWIN) ${AGL_LIBRARY} ${IOKIT_LIBRARY} ${COREAUDIO_LIBRARY} + ${BUGSPLAT_LIBRARIES} ) # Add resource files to the project. @@ -1393,6 +1409,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 +1430,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 +1717,11 @@ if (SDL_FOUND) ) endif (SDL_FOUND) +if (DEFINED ENV{BUGSPLAT_DB}) + set_property(TARGET ${VIEWER_BINARY_NAME} + PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (DEFINED ENV{BUGSPLAT_DB}) + # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) @@ -1789,7 +1820,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} @@ -1824,7 +1855,7 @@ if (WINDOWS) add_dependencies(${VIEWER_BINARY_NAME} SLPlugin - windows-crash-logger + windows-crash-logger ) if (PACKAGE) @@ -1888,8 +1919,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 @@ -1962,6 +1993,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + ${BUGSPLAT_LIBRARIES} ) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH @@ -2037,25 +2069,35 @@ if (LINUX) endif (LINUX) if (DARWIN) - # These all get set with PROPERTIES - set(product "Second Life") + # 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}") # this is the setting for the Python wrapper, see SL-322 and WRAPPER line in Info-SecondLife.plist set(MACOSX_WRAPPER_EXECUTABLE_NAME "SL_Launcher") - set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer") + 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" ) @@ -2126,7 +2168,7 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) -if (PACKAGE) +if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND NOT DEFINED ENV{BUGSPLAT_DB}) set(SYMBOL_SEARCH_DIRS "") # Note that the path to VIEWER_SYMBOL_FILE must match that in ../../build.sh if (WINDOWS) @@ -2145,8 +2187,8 @@ if (PACKAGE) 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_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger") + set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger") set(VIEWER_LIB_GLOB "*.dylib") endif (DARWIN) if (LINUX) @@ -2158,7 +2200,6 @@ if (PACKAGE) 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 ".") @@ -2185,8 +2226,7 @@ if (PACKAGE) 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) +endif () if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below -- cgit v1.2.3 From bb757b937c6cde205c59a80e83d8f970523edeeb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 15 Jun 2018 11:28:01 -0400 Subject: SL-820: gDirUtilp is never nullptr. It might point to an uninitialized LLDir, but that's a whole separate problem, one that wouldn't be detected by checking for nullptr. If we hit that, time to change to an LLSingleton. --- indra/newview/llappviewerwin32.cpp | 79 +++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 4701e7bbed..3efc94d7b5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -565,61 +565,54 @@ bool LLAppViewerWin32::init() #else // LL_BUGSPLAT - if (! gDirUtilp) + std::string build_data_fname( + gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); + std::ifstream inf(build_data_fname.c_str()); + if (! inf.is_open()) { - LL_WARNS() << "Can't initialize BugSplat, gDirUtilp not yet set" << LL_ENDL; + LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname + << "'" << LL_ENDL; } else { - std::string build_data_fname( - gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); - std::ifstream inf(build_data_fname.c_str()); - if (! inf.is_open()) + Json::Reader reader; + Json::Value build_data; + if (! reader.parse(inf, build_data, false)) // don't collect comments { - LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname - << "'" << LL_ENDL; + // gah, the typo is baked into their API + LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname + << "': " << reader.getFormatedErrorMessages() << LL_ENDL; } else { - Json::Reader reader; - Json::Value build_data; - if (! reader.parse(inf, build_data, false)) // don't collect comments + Json::Value BugSplat_DB = build_data["BugSplat DB"]; + if (! BugSplat_DB) { - // gah, the typo is baked into their API - LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname - << "': " << reader.getFormatedErrorMessages() << LL_ENDL; + LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" + << build_data_fname << "'" << LL_ENDL; } else { - Json::Value BugSplat_DB = build_data["BugSplat DB"]; - if (! BugSplat_DB) - { - LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" - << build_data_fname << "'" << LL_ENDL; - } - else - { - // Got BugSplat_DB, onward! - std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << - LL_VIEWER_VERSION_MINOR << '.' << - LL_VIEWER_VERSION_PATCH << '.' << - LL_VIEWER_VERSION_BUILD)); - - // have to convert normal wide strings to strings of __wchar_t - sBugSplatSender = new MiniDmpSender( - wunder(BugSplat_DB.asString()).c_str(), - wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), - wunder(version_string).c_str(), - nullptr); - sBugSplatSender->setCallback(bugsplatSendLog); - - // engage stringize() overload that converts from wstring - LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) - << stringize(version_string) << ')' << LL_ENDL; - } // got BugSplat_DB - } // parsed build_data.json - } // opened build_data.json - } // gDirUtilp set + // Got BugSplat_DB, onward! + std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << + LL_VIEWER_VERSION_MINOR << '.' << + LL_VIEWER_VERSION_PATCH << '.' << + LL_VIEWER_VERSION_BUILD)); + + // have to convert normal wide strings to strings of __wchar_t + sBugSplatSender = new MiniDmpSender( + wunder(BugSplat_DB.asString()).c_str(), + wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), + wunder(version_string).c_str(), + nullptr); + sBugSplatSender->setCallback(bugsplatSendLog); + + // engage stringize() overload that converts from wstring + LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) + << stringize(version_string) << ')' << LL_ENDL; + } // got BugSplat_DB + } // parsed build_data.json + } // opened build_data.json #endif // LL_BUGSPLAT #endif // LL_SEND_CRASH_REPORTS -- cgit v1.2.3 From f26ba0f0eccce2e6b66554dc1132ff29e6d0f3b1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 15 Jun 2018 11:45:03 -0400 Subject: SL-820: Make bugsplat.cmake and its symbols conditional. --- indra/newview/CMakeLists.txt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ad65301d4d..d9c267324b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -8,7 +8,9 @@ include(00-Common) include(Linking) include(Boost) -include(bugsplat) +if (DEFINED ENV{BUGSPLAT_DB}) + include(bugsplat) +endif (DEFINED ENV{BUGSPLAT_DB}) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -95,8 +97,13 @@ include_directories( ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLAPPEARANCE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ) + +if (DEFINED ENV{BUGSPLAT_DB}) + include_directories( ${BUGSPLAT_INCLUDE_DIR} ) +endif (DEFINED ENV{BUGSPLAT_DB}) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -1381,9 +1388,14 @@ if (DARWIN) ${AGL_LIBRARY} ${IOKIT_LIBRARY} ${COREAUDIO_LIBRARY} - ${BUGSPLAT_LIBRARIES} ) + if (DEFINED ENV{BUGSPLAT_DB}) + list(APPEND viewer_LIBRARIES + ${BUGSPLAT_LIBRARIES} + ) + endif (DEFINED ENV{BUGSPLAT_DB}) + # Add resource files to the project. set(viewer_RESOURCE_FILES secondlife.icns @@ -1993,8 +2005,13 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + ) + +if (DEFINED ENV{BUGSPLAT_DB}) + target_link_libraries(${VIEWER_BINARY_NAME} ${BUGSPLAT_LIBRARIES} ) +endif (DEFINED ENV{BUGSPLAT_DB}) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Path to artwork files.") -- cgit v1.2.3 From 448e82f39c472c82620bb52e0644e258b363d562 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 15 Jun 2018 16:48:20 -0400 Subject: SL-821: Try to add SecondLife.log file to Mac BugSplat crash report. Introduce new header file llappviewermacosx-for-objc.h to publish for llappdelegate-objc.mm and other Objective-C++ consumers the free functions in llappviewermacosx.cpp they consume. These were never before declared in any header file. Apparently, to date, we've been trusting to luck that Objective-C++ will infer the correct signature from calls -- and that the calls are correct with respect to the function definitions. :-P This gives us a place to introduce a new getLogFilePathname() function to query LLDir. (We don't simply #include "lldir.h" because of the pervasive use of BOOL in viewer headers; BOOL means something very different in Objective-C++.) --- indra/newview/llappdelegate-objc.mm | 17 +++++++++------ indra/newview/llappviewermacosx-for-objc.h | 34 ++++++++++++++++++++++++++++++ indra/newview/llappviewermacosx.cpp | 6 ++++++ 3 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 indra/newview/llappviewermacosx-for-objc.h (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 8e1ad169c9..ad5398721b 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -29,6 +29,7 @@ @import BugsplatMac; #endif #include "llwindowmacosx-objc.h" +#include "llappviewermacosx-for-objc.h" #include // Used for Text Input Services ("Safe" API - it's supported) @implementation LLAppDelegate @@ -189,18 +190,22 @@ return true; } -#if 0 // defined(LL_BUGSPLAT) +#if defined(LL_BUGSPLAT) @implementation BugsplatStartupManagerDelegate - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { - NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"example" withExtension:@"json"]; - NSData *data = [NSData dataWithContentsOfURL:fileURL]; - + std::string logfile = getLogFilePathname(); + NSString *ns_logfile = [NSString stringWithCString:logfile->c_str() + encoding:NSUTF8StringEncoding]; + NSData *data = [NSData dataWithContentsOfFile:ns_logfile]; + + // 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:@"example.json" + [[BugsplatAttachment alloc] initWithFilename:@"SecondLife.log" attachmentData:data - contentType:@"application/json"]; + contentType:@"text/plain"]; return attachment; } diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h new file mode 100644 index 0000000000..ef5d90bfef --- /dev/null +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -0,0 +1,34 @@ +/** + * @file llappviewermacosx-for-objc.h + * @author Nat Goodspeed + * @date 2018-06-15 + * @brief llappviewermacosx.h publishes the C++ API for + * llappviewermacosx.cpp, just as + * llappviewermacosx-objc.h publishes the Objective-C++ API for + * llappviewermacosx-objc.mm. + * + * This header is intended to publish for Objective-C++ consumers a + * subset of the C++ API presented by llappviewermacosx.cpp. It's a + * subset because, if an Objective-C++ consumer were to #include + * the full llappviewermacosx.h, we would almost surely run into + * trouble due to the discrepancy between Objective-C++'s BOOL versus + * classic Microsoft/Linden BOOL. + * + * $LicenseInfo:firstyear=2018&license=viewerlgpl$ + * Copyright (c) 2018, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) +#define LL_LLAPPVIEWERMACOSX_FOR_OBJC_H + +#include + +bool initViewer(); +void handleUrl(const char* url_utf8); +bool pumpMainLoop(); +void handleQuit(); +void cleanupViewer(); +std::string getLogFilePathname(); + +#endif /* ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) */ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index d472f8926b..cdbdb23d9a 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -36,6 +36,7 @@ #include "llappviewermacosx-objc.h" #include "llappviewermacosx.h" +#include "llappviewermacosx-for-objc.h" #include "llwindowmacosx-objc.h" #include "llcommandlineparser.h" @@ -147,6 +148,11 @@ void cleanupViewer() gViewerAppPtr = NULL; } +std::string getLogFilePathname() +{ + return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"); +} + int main( int argc, char **argv ) { // Store off the command line args for use later. -- cgit v1.2.3 From 1d7687efb2bb8785b6a2a2f620d05fe1cb84f922 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 15 Jun 2018 17:58:00 -0400 Subject: SL-821: Fix up Objective-C++ syntax errors. --- indra/newview/llappdelegate-objc.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index ad5398721b..008203fd32 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -190,13 +190,15 @@ return true; } +@end + #if defined(LL_BUGSPLAT) @implementation BugsplatStartupManagerDelegate - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { std::string logfile = getLogFilePathname(); - NSString *ns_logfile = [NSString stringWithCString:logfile->c_str() + NSString *ns_logfile = [NSString stringWithCString:logfile.c_str() encoding:NSUTF8StringEncoding]; NSData *data = [NSData dataWithContentsOfFile:ns_logfile]; @@ -209,6 +211,6 @@ return attachment; } -#endif // LL_BUGSPLAT - @end + +#endif // LL_BUGSPLAT -- cgit v1.2.3 From b889c15cddccdfa5dd164388a566e4c63bbdf6f3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 18 Jun 2018 12:57:12 -0400 Subject: SL-821: Fix BugSplat attachment method override per BugSplat support. The example code on the BugSplat documentation page https://www.bugsplat.com/docs/platforms/os-x#configuration omits certain essential Objective-C++ boilerplate incantations. Adding them at least compiles successfully. --- indra/newview/llappdelegate-objc.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 008203fd32..11a4b5d48e 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -194,7 +194,11 @@ #if defined(LL_BUGSPLAT) -@implementation BugsplatStartupManagerDelegate +// per Geoff at BugSplat support +@interface AppDelegate : NSObject +@end + +@implementation AppDelegate - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { std::string logfile = getLogFilePathname(); -- cgit v1.2.3 From 6e790fc27d22e80527789cf8e783be6c90a23505 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 18 Jun 2018 16:38:49 -0400 Subject: SL-821: Add logging in the macOS BugSplat attachment override. --- indra/newview/llappdelegate-objc.mm | 4 ++++ indra/newview/llappviewermacosx-for-objc.h | 1 + indra/newview/llappviewermacosx.cpp | 5 +++++ 3 files changed, 10 insertions(+) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 11a4b5d48e..2c2302ecfb 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -202,9 +202,12 @@ - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { std::string logfile = getLogFilePathname(); + infos("Reached attachmentForBugsplatStartupManager with:"); + infos(logfile); NSString *ns_logfile = [NSString stringWithCString:logfile.c_str() encoding:NSUTF8StringEncoding]; NSData *data = [NSData dataWithContentsOfFile:ns_logfile]; + infos("Read logfile"); // Apologies for the hard-coded log-file basename, but I do not know the // incantation for "$(basename "$logfile")" in this language. @@ -212,6 +215,7 @@ [[BugsplatAttachment alloc] initWithFilename:@"SecondLife.log" attachmentData:data contentType:@"text/plain"]; + infos("returning attachment"); return attachment; } diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h index ef5d90bfef..e45cb85861 100644 --- a/indra/newview/llappviewermacosx-for-objc.h +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -30,5 +30,6 @@ bool pumpMainLoop(); void handleQuit(); void cleanupViewer(); std::string getLogFilePathname(); +void infos(const std::string& message); #endif /* ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) */ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index cdbdb23d9a..562e7ebfde 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -153,6 +153,11 @@ std::string getLogFilePathname() return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"); } +void infos(const std::string& message) +{ + LL_INFOS() << message << LL_ENDL; +} + int main( int argc, char **argv ) { // Store off the command line args for use later. -- cgit v1.2.3 From c9898f1b69a53cd5d3e7bb49f77a764dde43772e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 19 Jun 2018 09:37:28 -0400 Subject: SL-821: Try again to override BugSplat Obj-C methods. --- indra/newview/llappdelegate-objc.mm | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 2c2302ecfb..68b803c367 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -27,6 +27,9 @@ #import "llappdelegate-objc.h" #if defined(LL_BUGSPLAT) @import BugsplatMac; +// derived from BugsplatMac's BugsplatTester/AppDelegate.m +@interface LLAppDelegate () +@end #endif #include "llwindowmacosx-objc.h" #include "llappviewermacosx-for-objc.h" @@ -190,15 +193,14 @@ return true; } -@end - #if defined(LL_BUGSPLAT) -// per Geoff at BugSplat support -@interface AppDelegate : NSObject -@end - -@implementation AppDelegate +- (NSString *)applicationLogForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager +{ +// return NSStringFromSelector(_cmd); + infos("Reached applicationLogForBugsplatStartupManager"); + return @"[contents of SecondLife.log]"; +} - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { std::string logfile = getLogFilePathname(); @@ -219,6 +221,6 @@ return attachment; } -@end - #endif // LL_BUGSPLAT + +@end -- cgit v1.2.3 From 3376b2acfbea2f6d2d8f79ecf890702e1ab60ae3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 19 Jun 2018 13:34:08 -0400 Subject: SL-821: Another Objective-C++ magic incantation from BugSplat support. --- indra/newview/llappdelegate-objc.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 68b803c367..2ee294e1e6 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -76,6 +76,7 @@ // https://www.bugsplat.com/docs/platforms/os-x#initialization // [BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; // [BugsplatStartupManager sharedManager].askUserDetails = NO; + [BugsplatStartupManager sharedManager].delegate = self; [[BugsplatStartupManager sharedManager] start]; #endif } -- cgit v1.2.3 From d26c931ae2c5d33adc5fc20842b7be838a2822b4 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 19 Jun 2018 15:08:56 -0400 Subject: SL-821: Send the SecondLife.log from the previous (crashed) run. Also clean up log messages. --- indra/newview/llappdelegate-objc.mm | 16 +++++++++++----- indra/newview/llappviewermacosx-for-objc.h | 2 +- indra/newview/llappviewermacosx.cpp | 4 ++-- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 2ee294e1e6..4510f4070f 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -196,21 +196,27 @@ #if defined(LL_BUGSPLAT) +#if 0 +// Apparently this override method only contributes the User Description field +// of BugSplat's All Crashes table. Despite the method name, it would seem to +// be a bad place to try to stuff all of SecondLife.log. - (NSString *)applicationLogForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { // return NSStringFromSelector(_cmd); infos("Reached applicationLogForBugsplatStartupManager"); return @"[contents of SecondLife.log]"; } +#endif - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { - std::string logfile = getLogFilePathname(); - infos("Reached attachmentForBugsplatStartupManager with:"); - infos(logfile); + // We get the *old* log file pathname (for SecondLife.old) because it's on + // the run *following* the crash that BugsplatStartupManager notices that + // the previous run crashed and calls this override. By that time, we've + // already renamed SecondLife.log to SecondLife.old. + std::string logfile = getOldLogFilePathname(); NSString *ns_logfile = [NSString stringWithCString:logfile.c_str() encoding:NSUTF8StringEncoding]; NSData *data = [NSData dataWithContentsOfFile:ns_logfile]; - infos("Read logfile"); // Apologies for the hard-coded log-file basename, but I do not know the // incantation for "$(basename "$logfile")" in this language. @@ -218,7 +224,7 @@ [[BugsplatAttachment alloc] initWithFilename:@"SecondLife.log" attachmentData:data contentType:@"text/plain"]; - infos("returning attachment"); + infos("attachmentForBugsplatStartupManager: attaching " + logfile); return attachment; } diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h index e45cb85861..c439297611 100644 --- a/indra/newview/llappviewermacosx-for-objc.h +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -29,7 +29,7 @@ void handleUrl(const char* url_utf8); bool pumpMainLoop(); void handleQuit(); void cleanupViewer(); -std::string getLogFilePathname(); +std::string getOldLogFilePathname(); void infos(const std::string& message); #endif /* ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) */ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 562e7ebfde..d014e992f9 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -148,9 +148,9 @@ void cleanupViewer() gViewerAppPtr = NULL; } -std::string getLogFilePathname() +std::string getOldLogFilePathname() { - return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"); + return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.old"); } void infos(const std::string& message) -- cgit v1.2.3 From f6e7893a6e34190e8080d289a5f89d7f9c47d583 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 28 Jun 2018 12:39:42 -0400 Subject: MAINT-8797: Resurrect BugSplat crash reporting on Windows. The Breakpad symbol-file upload in the viewer's build.sh was failing on BugSplat builds since we weren't generating Breakpad symbol files. That upload was conditional on RELEASE_CRASH_REPORTING, so my first approach was to set RELEASE_CRASH_REPORTING=OFF for BugSplat builds. Unfortunately that symbol also propagates down into C++ compiles, and in llappviewerwin32.cpp, both Breakpad and BugSplat crash reporting is conditional on it. So that change inadvertently turned off the C++ logic to engage BugSplat. Stop forcing RELEASE_CRASH_REPORTING=OFF for BugSplat builds. Instead, make the Breakpad symbol-file upload check the BUGSPLAT_DB variable as well. Add #pragma messages to llappviewerwin32.cpp so we can detect whether it's being built for Breakpad or BugSplat or neither. --- indra/newview/llappviewerwin32.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 3efc94d7b5..247b94db3e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -559,11 +559,13 @@ bool LLAppViewerWin32::init() #if LL_SEND_CRASH_REPORTS #if ! defined(LL_BUGSPLAT) +#pragma message("Building without BugSplat") LLAppViewer* pApp = LLAppViewer::instance(); pApp->initCrashReporting(); #else // LL_BUGSPLAT +#pragma message("Building with BugSplat") std::string build_data_fname( gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); @@ -579,7 +581,7 @@ bool LLAppViewerWin32::init() Json::Value build_data; if (! reader.parse(inf, build_data, false)) // don't collect comments { - // gah, the typo is baked into their API + // gah, the typo is baked into Json::Reader API LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname << "': " << reader.getFormatedErrorMessages() << LL_ENDL; } @@ -609,7 +611,7 @@ bool LLAppViewerWin32::init() // engage stringize() overload that converts from wstring LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) - << stringize(version_string) << ')' << LL_ENDL; + << ' ' << stringize(version_string) << ')' << LL_ENDL; } // got BugSplat_DB } // parsed build_data.json } // opened build_data.json -- cgit v1.2.3 From cd52724ef8f8a19ebe28c73f39a582b56fb58093 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 28 Jun 2018 21:49:07 -0400 Subject: DRTVWR-447: Suppress BugSplat UI; auto-fill certain BugSplat data. Direct BugSplat to send crash reports without prompting, on both Windows and Mac. Add a mechanism by which code called after LL_ERRS() can retrieve the fatal log message string. (How did the crash logger extract that for Linden crash logging?) Add that fatal message to crash reports on Windows. But as BugsplatMac is engaged only on the run _after_ the crash, we no longer have that message in memory. Also add user name and region location to Windows crash reports. On Mac, (a) we don't have the information from the previous run and (b) BugsplatMac doesn't provide an API to attach that information to the crash report. Add Mac logging to indicate the success or failure of sending the crash report. Add Windows logging to indicate we're about to send. --- indra/llcommon/llerror.cpp | 33 ++++++++++++------- indra/llcommon/llerrorcontrol.h | 3 ++ indra/newview/llappdelegate-objc.mm | 34 +++++++++++++------ indra/newview/llappviewermacosx-for-objc.h | 2 ++ indra/newview/llappviewermacosx.cpp | 12 +++++++ indra/newview/llappviewerwin32.cpp | 53 +++++++++++++++++++++--------- 6 files changed, 101 insertions(+), 36 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f31a054139..b5e7e81f21 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -377,6 +377,7 @@ namespace public: std::ostringstream messageStream; bool messageStreamInUse; + std::string mFatalMessage; void addCallSite(LLError::CallSite&); void invalidateCallSites(); @@ -670,11 +671,16 @@ namespace LLError s->mCrashFunction = f; } - FatalFunction getFatalFunction() - { + FatalFunction getFatalFunction() + { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - return s->mCrashFunction; - } + return s->mCrashFunction; + } + + std::string getFatalMessage() + { + return Globals::getInstance()->mFatalMessage; + } void setTimeFunction(TimeFunction f) { @@ -1194,7 +1200,7 @@ namespace LLError { writeToRecorders(site, "error", true, true, true, false, false); } - + std::ostringstream message_stream; if (site.mPrintOnce) @@ -1219,14 +1225,19 @@ namespace LLError s->mUniqueLogMessages[message] = 1; } } - + message_stream << message; - - writeToRecorders(site, message_stream.str()); - - if (site.mLevel == LEVEL_ERROR && s->mCrashFunction) + std::string message_line(message_stream.str()); + + writeToRecorders(site, message_line); + + if (site.mLevel == LEVEL_ERROR) { - s->mCrashFunction(message_stream.str()); + g->mFatalMessage = message_line; + if (s->mCrashFunction) + { + s->mCrashFunction(message_line); + } } } } diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index caf2ba72c2..ddbcdc94a0 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -102,6 +102,9 @@ namespace LLError LL_COMMON_API FatalFunction getFatalFunction(); // Retrieve the previously-set FatalFunction + LL_COMMON_API std::string getFatalMessage(); + // Retrieve the message last passed to FatalFunction, if any + /// temporarily override the FatalFunction for the duration of a /// particular scope, e.g. for unit tests class LL_COMMON_API OverrideFatalFunction diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 4510f4070f..82e49540a4 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -74,9 +74,9 @@ #if defined(LL_BUGSPLAT) // https://www.bugsplat.com/docs/platforms/os-x#initialization -// [BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; -// [BugsplatStartupManager sharedManager].askUserDetails = NO; - [BugsplatStartupManager sharedManager].delegate = self; + [BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; + [BugsplatStartupManager sharedManager].askUserDetails = NO; + [BugsplatStartupManager sharedManager].delegate = self; [[BugsplatStartupManager sharedManager] start]; #endif } @@ -196,17 +196,20 @@ #if defined(LL_BUGSPLAT) -#if 0 -// Apparently this override method only contributes the User Description field -// of BugSplat's All Crashes table. Despite the method name, it would seem to -// be a bad place to try to stuff all of SecondLife.log. - (NSString *)applicationLogForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { -// return NSStringFromSelector(_cmd); infos("Reached applicationLogForBugsplatStartupManager"); - return @"[contents of SecondLife.log]"; + // Apparently this override method only contributes the User Description + // field of BugSplat's All Crashes table. Despite the method name, it + // would seem to be a bad place to try to stuff all of SecondLife.log. + return [NSString stringWithCString:getFatalMessage().c_str() + encoding:NSUTF8StringEncoding]; +} + +- (void)bugsplatStartupManagerWillSendCrashReport:(BugsplatStartupManager *)bugsplatStartupManager +{ + infos("Reached bugsplatStartupManagerWillSendCrashReport"); } -#endif - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { // We get the *old* log file pathname (for SecondLife.old) because it's on @@ -228,6 +231,17 @@ return attachment; } +- (void)bugsplatStartupManagerDidFinishSendingCrashReport:(BugsplatStartupManager *)bugsplatStartupManager +{ + infos("Sent crash report to BugSplat"); +} + +- (void)bugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager didFailWithError:(NSError *)error +{ + // TODO: message string from NSError + infos("Could not send crash report to BugSplat"); +} + #endif // LL_BUGSPLAT @end diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h index c439297611..ac85d7e8c3 100644 --- a/indra/newview/llappviewermacosx-for-objc.h +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -30,6 +30,8 @@ bool pumpMainLoop(); void handleQuit(); void cleanupViewer(); std::string getOldLogFilePathname(); +std::string getFatalMessage(); +std::string getAgentFullname(); void infos(const std::string& message); #endif /* ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) */ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index d014e992f9..c3a3c3284a 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -45,6 +45,8 @@ #include "llmd5.h" #include "llfloaterworldmap.h" #include "llurldispatcher.h" +#include "llerrorcontrol.h" +#include "llvoavatarself.h" // for gAgentAvatarp->getFullname() #include #ifdef LL_CARBON_CRASH_HANDLER #include @@ -153,6 +155,16 @@ std::string getOldLogFilePathname() return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.old"); } +std::string getFatalMessage() +{ + return LLError::getFatalMessage(); +} + +std::string getAgentFullname() +{ + return gAgentAvatarp? gAgentAvatarp->getFullname() : std::string(); +} + void infos(const std::string& message) { LL_INFOS() << message << LL_ENDL; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 247b94db3e..1e135fa229 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -67,6 +67,7 @@ #include "stringize.h" #include "lldir.h" +#include "llerrorcontrol.h" #include #include @@ -74,7 +75,10 @@ // Bugsplat (http://bugsplat.com) crash reporting tool #ifdef LL_BUGSPLAT #include "BugSplat.h" -#include "reader.h" // JsonCpp +#include "reader.h" // JsonCpp +#include "llagent.h" // for agent location +#include "llviewerregion.h" +#include "llvoavatarself.h" // for agent name namespace { @@ -85,7 +89,8 @@ namespace // std::basic_string instance will survive until the function returns. // Calling c_str() on a std::basic_string local to wunder() would be // Undefined Behavior: we'd be left with a pointer into a destroyed - // std::basic_string instance. + // std::basic_string instance. But we can do that with a macro... + #define WCSTR(string) wunder(string).c_str() // It would be nice if, when wchar_t is the same as __wchar_t, this whole // function would optimize away. However, we use it only for the arguments @@ -111,19 +116,35 @@ namespace bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) { - // If we haven't yet initialized LLDir, don't bother trying to - // find our log file. - // Alternatively -- if we might encounter trouble trying to query - // LLDir during crash cleanup -- consider making gDirUtilp an - // LLPounceable, and attach a callback that stores the pathname to - // the log file here. - if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) + if (nCode == MDSCB_EXCEPTIONCODE) { // send the main viewer log file // widen to wstring, convert to __wchar_t, then pass c_str() sBugSplatSender->sendAdditionalFile( - wunder(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); - } + WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); + + if (gAgentAvatarp) + { + // user name, when we have it + sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname())); + } + + // LL_ERRS message, when there is one + sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage())); + + if (gAgent.getRegion()) + { + // region location, when we have it + LLVector3 loc = gAgent.getPositionAgent(); + sBugSplatSender->resetAppIdentifier( + WCSTR(STRINGIZE(gAgent.getRegion()->getName() + << '/' << loc.mV[0] + << '/' << loc.mV[1] + << '/' << loc.mV[2]))); + } + + LL_INFOS() << "Sending crash report to BugSplat." << LL_ENDL; + } // MDSCB_EXCEPTIONCODE return false; } @@ -603,10 +624,12 @@ bool LLAppViewerWin32::init() // have to convert normal wide strings to strings of __wchar_t sBugSplatSender = new MiniDmpSender( - wunder(BugSplat_DB.asString()).c_str(), - wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), - wunder(version_string).c_str(), - nullptr); + WCSTR(BugSplat_DB.asString()), + WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)), + WCSTR(version_string), + nullptr, // szAppIdentifier -- set later + MDSF_NONINTERACTIVE | // automatically submit report without prompting + MDSF_PREVENTHIJACKING); // disallow swiping Exception filter sBugSplatSender->setCallback(bugsplatSendLog); // engage stringize() overload that converts from wstring -- cgit v1.2.3 From 93ea0d7026dcb7a9aec3bd4f8615eb62da159a02 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 29 Jun 2018 17:08:48 -0400 Subject: MAINT-8822: Revamp the LLManifest.prefix() calling convention. The way prefix("path_fragment") or prefix(src="path_fragment") has always worked is that unless you explicitly specify dst="", it adds "path_fragment" to the source AND dest prefix stacks! The most recent refactoring of viewer_manifest.py failed to copy CEF because it involved prefix(src="../some lengthy path fragment") -- forgetting to specify dst="" -- which added "../some lengthy path fragment" to the dest prefix stack -- which put it outside the viewer install staging area altogether. Having been bitten too many times by forgetting to add prefix(dst=""), we remove the necessity. The prefix() src=, build= and dst= prefix stacks are now completely independent. Add src_dst= keyword argument for when you DO want to add the same path fragment to both the source and dest prefix stacks. ("Explicit is better than implicit.") Change all existing calls accordingly. Now that the build prefix stack no longer tracks the src prefix stack, we were failing to pick up some things from the build area because NOBODY ever used build=, relying entirely on src= to point both to stuff in the source tree and stuff in the build tree. Try to use build= appropriately. If that proves too confusing, we might eliminate the separate build and artwork (!) prefix stacks entirely, requiring callers to reset the src stack explicitly when switching back and forth. --- indra/lib/python/indra/util/llmanifest.py | 32 ++++++--- indra/newview/viewer_manifest.py | 107 +++++++++++++++--------------- 2 files changed, 77 insertions(+), 62 deletions(-) (limited to 'indra') diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 598261e3d7..4c3d3fc217 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -375,7 +375,7 @@ class LLManifest(object): in the file list by path().""" self.excludes.append(glob) - def prefix(self, src='', build=None, dst=None): + def prefix(self, src='', build='', dst='', src_dst=None): """ Usage: @@ -385,8 +385,21 @@ class LLManifest(object): For the duration of the 'with' block, pushes a prefix onto the stack. Within that block, all relevant method calls (esp. to path()) will prefix paths with the entire prefix stack. Source and destination - prefixes can be different, though if only one is provided they are - both equal. To specify a no-op, use an empty string, not None. + prefixes are independent; if omitted (or passed as the empty string), + the prefix has no effect. Thus: + + with self.prefix(src='foo'): + # no effect on dst + + with self.prefix(dst='bar'): + # no effect on src + + If you want to set both at once, use src_dst: + + with self.prefix(src_dst='subdir'): + # same as self.prefix(src='subdir', dst='subdir') + # Passing src_dst makes any src or dst argument in the same + # parameter list irrelevant. Also supports the older (pre-Python-2.5) syntax: @@ -400,10 +413,9 @@ class LLManifest(object): returned True specifically so that the caller could indent the relevant block of code with 'if', just for aesthetic purposes. """ - if dst is None: - dst = src - if build is None: - build = src + if src_dst is not None: + src = src_dst + dst = src_dst self.src_prefix.append(src) self.artwork_prefix.append(src) self.build_prefix.append(build) @@ -609,7 +621,6 @@ class LLManifest(object): def process_file(self, src, dst): if self.includes(src, dst): -# print src, "=>", dst for action in self.actions: methodname = action + "_action" method = getattr(self, methodname, None) @@ -677,7 +688,11 @@ class LLManifest(object): # Don't recopy file if it's up-to-date. # If we seem to be not not overwriting files that have been # updated, set the last arg to False, but it will take longer. +## reldst = (dst[len(self.dst_prefix[0]):] +## if dst.startswith(self.dst_prefix[0]) +## else dst).lstrip(r'\/') if os.path.exists(dst) and filecmp.cmp(src, dst, True): +## print "{} (skipping, {} exists)".format(src, reldst) return # only copy if it's not excluded if self.includes(src, dst): @@ -687,6 +702,7 @@ class LLManifest(object): if err.errno != errno.ENOENT: raise +## print "{} => {}".format(src, reldst) shutil.copy2(src, dst) def ccopytree(self, src, dst): diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 49dc732457..35cd7db161 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -64,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") @@ -86,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(build=pkgdir): self.path("dictionaries") # include the extracted packages information (see BuildPackagesInfo.cmake) @@ -130,20 +130,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") @@ -171,7 +171,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") @@ -494,19 +494,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(build=os.path.join(pkgdir, "VMP")): # include the compiled launcher scripts so that it gets included in the file_list self.path('SL_Launcher.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") #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"): @@ -519,8 +519,7 @@ 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(build=os.path.join(os.pardir, 'sharedlibs', self.args['configuration'])): # Get llcommon and deps. If missing assume static linkage and continue. try: @@ -608,27 +607,27 @@ class WindowsManifest(ViewerManifest): self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") - with self.prefix(src=pkgdir,dst=""): + with self.prefix(build=pkgdir): self.path("ca-bundle.crt") # Media plugins - CEF with self.prefix(dst="llplugin"): - with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration']): + with self.prefix(build='../media_plugins/cef/%s' % self.args['configuration']): self.path("media_plugin_cef.dll") # Media plugins - LibVLC - with self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration']): + with self.prefix(build='../media_plugins/libvlc/%s' % 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']): + with self.prefix(build='../media_plugins/example/%s' % 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)): + with self.prefix(build=os.path.join(pkgdir, 'bin', config)): self.path("chrome_elf.dll") self.path("d3dcompiler_43.dll") self.path("d3dcompiler_47.dll") @@ -641,12 +640,12 @@ class WindowsManifest(ViewerManifest): 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')): + with self.prefix(build=os.path.join(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')): + with self.prefix(build=os.path.join(pkgdir, 'resources')): self.path("cef.pak") self.path("cef_100_percent.pak") self.path("cef_200_percent.pak") @@ -654,7 +653,7 @@ class WindowsManifest(ViewerManifest): self.path("devtools_resources.pak") self.path("icudtl.dat") - with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst='locales'): + with self.prefix(build=os.path.join(pkgdir, 'resources', 'locales'), dst='locales'): self.path("am.pak") self.path("ar.pak") self.path("bg.pak") @@ -709,7 +708,7 @@ class WindowsManifest(ViewerManifest): self.path("zh-CN.pak") self.path("zh-TW.pak") - with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')): + with self.prefix(build=os.path.join(pkgdir, 'bin', 'release')): self.path("libvlc.dll") self.path("libvlccore.dll") self.path("plugins/") @@ -916,7 +915,7 @@ class DarwinManifest(ViewerManifest): # -------------------- top-level Second Life.app --------------------- # top-level Second Life application is only a container - with self.prefix(src="", dst="Contents"): # everything goes in Contents + with self.prefix(dst="Contents"): # everything goes in Contents # top-level Info.plist is as generated by CMake Info_plist = self.dst_path_of("Info.plist") @@ -945,10 +944,10 @@ open "%s" --args "$@" # rather than relsymlinkf(). self.symlinkf(os.path.join("Resources", viewer_app, "Contents", "Frameworks")) - with self.prefix(src="", dst="Resources"): + with self.prefix(dst="Resources"): # top-level Resources directory should be pretty sparse # need .icns file referenced by top-level Info.plist - with self.prefix(src=self.icon_path(), dst="") : + with self.prefix(src=self.icon_path()) : self.path(toplevel_icon) # ------------------- nested launcher_app -------------------- @@ -968,15 +967,15 @@ open "%s" --args "$@" #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=""): + with self.prefix(build=os.path.join(pkgdir, "VMP")): 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=""): + with self.prefix(build=os.path.join(pkgdir, "lib", "python")): # llbase provides our llrest service layer and llsd decoding - with self.prefix("llbase"): + with self.prefix(build="llbase", dst="llbase"): # (Why is llbase treated specially here? What # DON'T we want to copy out of lib/python/llbase?) self.path("*.py") @@ -989,12 +988,12 @@ open "%s" --args "$@" # launcher_app/Contents/Resources with self.prefix(dst="Resources"): - with self.prefix(src=self.icon_path(), dst="") : + with self.prefix(src=self.icon_path()) : self.path(launcher_icon) with self.prefix(dst="vmp_icons"): self.path("secondlife.ico") #VMP Tkinter icons - with self.prefix("vmp_icons"): + with self.prefix(src_dst="vmp_icons"): self.path("*.png") self.path("*.gif") @@ -1093,7 +1092,7 @@ open "%s" --args "$@" os.path.basename(Info_plist), "Info.plist") - with self.prefix(src="", dst="Frameworks"): + with self.prefix(dst="Frameworks"): # CEF framework goes inside viewer_app/Contents/Frameworks. CEF_framework = "Chromium Embedded Framework.framework" self.path2basename(relpkgdir, CEF_framework) @@ -1107,21 +1106,21 @@ open "%s" --args "$@" # nested Resources directory super(DarwinManifest, self).construct() - with self.prefix(src=self.icon_path(), dst="") : + with self.prefix(src=self.icon_path()) : self.path(viewer_icon) - with self.prefix(src=relpkgdir, dst=""): + with self.prefix(build=relpkgdir): self.path("libndofdev.dylib") self.path("libhunspell-1.3.0.dylib") - with self.prefix("cursors_mac"): + with self.prefix(src_dst="cursors_mac"): self.path("*.tif") self.path("licenses-mac.txt", dst="licenses.txt") self.path("featuretable_mac.txt") self.path("SecondLife.nib") - with self.prefix(src=pkgdir,dst=""): + with self.prefix(build=pkgdir): self.path("ca-bundle.crt") self.path("SecondLife.nib") @@ -1331,10 +1330,10 @@ open "%s" --args "$@" "media_plugin_libvlc.dylib") # copy LibVLC dynamic libraries - with self.prefix(src=relpkgdir, dst="lib"): + with self.prefix(build=relpkgdir, dst="lib"): self.path( "libvlc*.dylib*" ) # copy LibVLC plugins folder - with self.prefix(src='plugins', dst=""): + with self.prefix(build='plugins'): self.path( "*.dylib" ) self.path( "plugins.dat" ) @@ -1527,24 +1526,24 @@ 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") #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=""): + with self.prefix(src="../viewer_components/manager"): self.path("SL_Launcher") self.path("*.py") with self.prefix(src=os.path.join("lib", "python", "llbase"), dst="llbase"): @@ -1557,22 +1556,22 @@ 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 - with self.prefix(src="../media_plugins", dst="bin/llplugin"): + with self.prefix(build="../media_plugins", dst="bin/llplugin"): self.path("gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") self.path2basename("libvlc", "libmedia_plugin_libvlc.so") - with self.prefix(src=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): + with self.prefix(build=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): self.path( "plugins.dat" ) self.path( "*/*.so" ) - with self.prefix(src=os.path.join(pkgdir, 'lib' ), dst="lib"): + with self.prefix(build=os.path.join(pkgdir, 'lib' ), dst="lib"): self.path( "libvlc*.so*" ) # llcommon @@ -1581,7 +1580,7 @@ class LinuxManifest(ViewerManifest): self.path("featuretable_linux.txt") - with self.prefix(src=pkgdir,dst=""): + with self.prefix(build=pkgdir): self.path("ca-bundle.crt") def package_finish(self): @@ -1637,7 +1636,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(build=relpkgdir, dst="lib"): self.path("libapr-1.so") self.path("libapr-1.so.0") self.path("libapr-1.so.0.4.5") @@ -1699,9 +1698,9 @@ class Linux_i686_Manifest(LinuxManifest): # Vivox runtimes - with self.prefix(src=relpkgdir, dst="bin"): + with self.prefix(build=relpkgdir, dst="bin"): self.path("SLVoice") - with self.prefix(src=relpkgdir, dst="lib"): + with self.prefix(build=relpkgdir, dst="lib"): self.path("libortp.so") self.path("libsndfile.so.1") #self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OpenAL lib -- cgit v1.2.3 From bbadee86c104609cc47be20297470bd7abab8008 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 30 Jun 2018 10:01:11 -0400 Subject: MAINT-8822: Give LLManifest.prefix() (suppressed) debugging output. --- indra/lib/python/indra/util/llmanifest.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 4c3d3fc217..974ac18e34 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -421,25 +421,34 @@ class LLManifest(object): self.build_prefix.append(build) self.dst_prefix.append(dst) +## self.display_stacks() + # The above code is unchanged from the original implementation. What's # new is the return value. We're going to return an instance of # PrefixManager that binds this LLManifest instance and Does The Right # Thing on exit. return self.PrefixManager(self) + def display_stacks(self): + width = 1 + max(len(stack) for stack in self.PrefixManager.stacks) + for stack in self.PrefixManager.stacks: + print "{} {}".format((stack + ':').ljust(width), + os.path.join(*getattr(self, stack))) + class PrefixManager(object): + # stack attributes we manage in this LLManifest (sub)class + # instance + stacks = ("src_prefix", "artwork_prefix", "build_prefix", "dst_prefix") + def __init__(self, manifest): self.manifest = manifest - # stack attributes we manage in this LLManifest (sub)class - # instance - stacks = ("src_prefix", "artwork_prefix", "build_prefix", "dst_prefix") # If the caller wrote: # with self.prefix(...): # as intended, then bind the state of each prefix stack as it was # just BEFORE the call to prefix(). Since prefix() appended an # entry to each prefix stack, capture len()-1. self.prevlen = { stack: len(getattr(self.manifest, stack)) - 1 - for stack in stacks } + for stack in self.stacks } def __nonzero__(self): # If the caller wrote: @@ -472,6 +481,8 @@ class LLManifest(object): # truncate that list back to 'prevlen' del getattr(self.manifest, stack)[prevlen:] +## self.manifest.display_stacks() + def end_prefix(self, descr=None): """Pops a prefix off the stack. If given an argument, checks the argument against the top of the stack. If the argument -- cgit v1.2.3 From 3e66dc9f193e4641041dd9ac4da1cf7ff7440ec0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 30 Jun 2018 10:08:35 -0400 Subject: MAINT-8822: Revert viewer_manifest to using src= instead of build=. Turns out that having multiple (source, build, artwork) prefix stacks isn't such a good idea after all. Many of our LLManifest.path() directives use wildcards -- and if _any files_ match the specified wildcard from a prefix stack other than what you had in mind, viewer_manifest will silently, cheerfully do the Wrong Thing. There is a good reason why all existing LLManifest.prefix() calls exclusively used src= and/or dst= instead of build=. --- indra/newview/viewer_manifest.py | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 35cd7db161..e1374b0518 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -86,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(build=pkgdir): + with self.prefix(src=pkgdir): self.path("dictionaries") # include the extracted packages information (see BuildPackagesInfo.cmake) @@ -494,7 +494,7 @@ 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(build=os.path.join(pkgdir, "VMP")): + 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('SL_Launcher.exe') #IUM is not normally executed directly, just imported. No exe needed. @@ -519,7 +519,7 @@ class WindowsManifest(ViewerManifest): "slplugin.exe") # Get shared libs from the shared libs staging directory - with self.prefix(build=os.path.join(os.pardir, 'sharedlibs', self.args['configuration'])): + with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration'])): # Get llcommon and deps. If missing assume static linkage and continue. try: @@ -607,27 +607,27 @@ class WindowsManifest(ViewerManifest): self.path(src="licenses-win32.txt", dst="licenses.txt") self.path("featuretable.txt") - with self.prefix(build=pkgdir): + with self.prefix(src=pkgdir): self.path("ca-bundle.crt") # Media plugins - CEF with self.prefix(dst="llplugin"): - with self.prefix(build='../media_plugins/cef/%s' % self.args['configuration']): + with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration']): self.path("media_plugin_cef.dll") # Media plugins - LibVLC - with self.prefix(build='../media_plugins/libvlc/%s' % self.args['configuration']): + with self.prefix(src='../media_plugins/libvlc/%s' % 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(build='../media_plugins/example/%s' % self.args['configuration']): + with self.prefix(src='../media_plugins/example/%s' % 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(build=os.path.join(pkgdir, 'bin', config)): + 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") @@ -640,12 +640,12 @@ class WindowsManifest(ViewerManifest): self.path("widevinecdmadapter.dll") # MSVC DLLs needed for CEF and have to be in same directory as plugin - with self.prefix(build=os.path.join(os.pardir, 'sharedlibs', 'Release')): + with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', 'Release')): self.path("msvcp120.dll") self.path("msvcr120.dll") # CEF files common to all configurations - with self.prefix(build=os.path.join(pkgdir, 'resources')): + 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") @@ -653,7 +653,7 @@ class WindowsManifest(ViewerManifest): self.path("devtools_resources.pak") self.path("icudtl.dat") - with self.prefix(build=os.path.join(pkgdir, 'resources', 'locales'), dst='locales'): + with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst='locales'): self.path("am.pak") self.path("ar.pak") self.path("bg.pak") @@ -708,7 +708,7 @@ class WindowsManifest(ViewerManifest): self.path("zh-CN.pak") self.path("zh-TW.pak") - with self.prefix(build=os.path.join(pkgdir, 'bin', 'release')): + with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')): self.path("libvlc.dll") self.path("libvlccore.dll") self.path("plugins/") @@ -967,15 +967,15 @@ open "%s" --args "$@" #this copies over the python wrapper script, #associated utilities and required libraries, see #SL-321, SL-322, SL-323 - with self.prefix(build=os.path.join(pkgdir, "VMP")): + with self.prefix(src=os.path.join(pkgdir, "VMP")): 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(build=os.path.join(pkgdir, "lib", "python")): + with self.prefix(src=os.path.join(pkgdir, "lib", "python")): # llbase provides our llrest service layer and llsd decoding - with self.prefix(build="llbase", dst="llbase"): + with self.prefix(src="llbase", dst="llbase"): # (Why is llbase treated specially here? What # DON'T we want to copy out of lib/python/llbase?) self.path("*.py") @@ -1109,7 +1109,7 @@ open "%s" --args "$@" with self.prefix(src=self.icon_path()) : self.path(viewer_icon) - with self.prefix(build=relpkgdir): + with self.prefix(src=relpkgdir): self.path("libndofdev.dylib") self.path("libhunspell-1.3.0.dylib") @@ -1120,7 +1120,7 @@ open "%s" --args "$@" self.path("featuretable_mac.txt") self.path("SecondLife.nib") - with self.prefix(build=pkgdir): + with self.prefix(src=pkgdir): self.path("ca-bundle.crt") self.path("SecondLife.nib") @@ -1330,10 +1330,10 @@ open "%s" --args "$@" "media_plugin_libvlc.dylib") # copy LibVLC dynamic libraries - with self.prefix(build=relpkgdir, dst="lib"): + with self.prefix(src=relpkgdir, dst="lib"): self.path( "libvlc*.dylib*" ) # copy LibVLC plugins folder - with self.prefix(build='plugins'): + with self.prefix(src='plugins'): self.path( "*.dylib" ) self.path( "plugins.dat" ) @@ -1562,16 +1562,16 @@ class LinuxManifest(ViewerManifest): self.path("secondlife_256.BMP","ll_icon.BMP") # plugins - with self.prefix(build="../media_plugins", dst="bin/llplugin"): + with self.prefix(src="../media_plugins", dst="bin/llplugin"): self.path("gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") self.path2basename("libvlc", "libmedia_plugin_libvlc.so") - with self.prefix(build=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): + with self.prefix(src=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): self.path( "plugins.dat" ) self.path( "*/*.so" ) - with self.prefix(build=os.path.join(pkgdir, 'lib' ), dst="lib"): + with self.prefix(src=os.path.join(pkgdir, 'lib' ), dst="lib"): self.path( "libvlc*.so*" ) # llcommon @@ -1580,7 +1580,7 @@ class LinuxManifest(ViewerManifest): self.path("featuretable_linux.txt") - with self.prefix(build=pkgdir): + with self.prefix(src=pkgdir): self.path("ca-bundle.crt") def package_finish(self): @@ -1636,7 +1636,7 @@ class Linux_i686_Manifest(LinuxManifest): relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") - with self.prefix(build=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") @@ -1698,9 +1698,9 @@ class Linux_i686_Manifest(LinuxManifest): # Vivox runtimes - with self.prefix(build=relpkgdir, dst="bin"): + with self.prefix(src=relpkgdir, dst="bin"): self.path("SLVoice") - with self.prefix(build=relpkgdir, dst="lib"): + with self.prefix(src=relpkgdir, dst="lib"): self.path("libortp.so") self.path("libsndfile.so.1") #self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OpenAL lib -- cgit v1.2.3 From 07d7e48f4157929b607c4183929aa02b8391444c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 10 Jul 2018 14:01:19 -0400 Subject: DRTVWR-447: Use absolute path prefixes for CEF components. viewer_manifest.py had LLManifest.prefix() calls starting with '..' (or os.pardir, same thing) which failed with new prefix() calling conventions. Explicitly starting with os.path.join(self.args['build'], os.pardir, etc.) where applicable works much better. --- indra/newview/viewer_manifest.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index e1374b0518..ad6ba3ddff 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -221,8 +221,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'): @@ -519,7 +518,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'])): + 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: @@ -612,17 +612,18 @@ class WindowsManifest(ViewerManifest): # Media plugins - CEF with self.prefix(dst="llplugin"): - with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration']): - self.path("media_plugin_cef.dll") + 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']): - 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']): - 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.) @@ -640,7 +641,8 @@ class WindowsManifest(ViewerManifest): 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')): + with self.prefix(src=os.path.join(self.args['build'], os.pardir, + 'sharedlibs', 'Release')): self.path("msvcp120.dll") self.path("msvcr120.dll") -- cgit v1.2.3 From 62eecd87a5610aae41cff6dc6ebcc81e7bcb474f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 10 Jul 2018 17:47:00 -0400 Subject: SL-932: Attach user's settings.xml file to Windows crash reports. It is not obvious whether the BugsplatMac attachment API even supports multiple file attachments. I've contacted BugSplat support. --- indra/newview/llappviewerwin32.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 1e135fa229..adb3a2bbe2 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -123,6 +123,9 @@ namespace sBugSplatSender->sendAdditionalFile( WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); + sBugSplatSender->sendAdditionalFile( + WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); + if (gAgentAvatarp) { // user name, when we have it -- cgit v1.2.3 From 66d083967ec25b5c46424689624b2aa366a2ae6b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 11 Jul 2018 16:01:48 -0400 Subject: DRTVWR-447: Add more diagnostic logging to Windows BugSplat crash. --- indra/newview/llappviewerwin32.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index adb3a2bbe2..5c7cb5b9c6 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -116,24 +116,38 @@ namespace bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) { + // When BugSplat intercepts a crash, logging seems to stop?! + // Maybe because our test crashes use LL_ERROR(). Try writing a + // special log file "by hand." + std::ofstream log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "BugSplat.log"), + std::ios_base::app); + log << "Entered bugsplatSendLog() callback\n"; if (nCode == MDSCB_EXCEPTIONCODE) { // send the main viewer log file // widen to wstring, convert to __wchar_t, then pass c_str() sBugSplatSender->sendAdditionalFile( WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); + log << "Attached " << gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log") << '\n'; sBugSplatSender->sendAdditionalFile( WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); + log << "Attached " << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml") << '\n'; if (gAgentAvatarp) { // user name, when we have it sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname())); + log << "Set default user name to '" << gAgentAvatarp->getFullname() << "'\n"; + } + else + { + log << "gAgentAvatarp is nullptr\n"; } // LL_ERRS message, when there is one sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage())); + log << "Set default user description to '" << LLError::getFatalMessage() << "'\n"; if (gAgent.getRegion()) { @@ -144,10 +158,25 @@ namespace << '/' << loc.mV[0] << '/' << loc.mV[1] << '/' << loc.mV[2]))); + log << "Set app identifier to '" + << gAgent.getRegion()->getName() + << '/' << loc.mV[0] + << '/' << loc.mV[1] + << '/' << log.mV[2] + << "'\n"; + } + else + { + log "gAgent.getRegion() is nullptr\n"; } LL_INFOS() << "Sending crash report to BugSplat." << LL_ENDL; + log << "Sending crash report to BugSplat.\n"; } // MDSCB_EXCEPTIONCODE + else + { + log << "nCode != MDSCB_EXCEPTIONCODE\n"; + } return false; } -- cgit v1.2.3 From 869d2f1fb2ed59e65dd9cb8b75a9ea560dbeab2d Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 11 Jul 2018 18:26:27 -0400 Subject: DRTVWR-447: Fix silly typos --- indra/newview/llappviewerwin32.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 5c7cb5b9c6..43b25699ca 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -162,12 +162,12 @@ namespace << gAgent.getRegion()->getName() << '/' << loc.mV[0] << '/' << loc.mV[1] - << '/' << log.mV[2] + << '/' << loc.mV[2] << "'\n"; } else { - log "gAgent.getRegion() is nullptr\n"; + log << "gAgent.getRegion() is nullptr\n"; } LL_INFOS() << "Sending crash report to BugSplat." << LL_ENDL; -- cgit v1.2.3 From c7616af624f784e6226f530f6a21b3541ba730cc Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 11 Jul 2018 21:52:03 -0400 Subject: DRTVWR-447: Diagnostically try naively widening BugSplat metadata. --- indra/newview/llappviewerwin32.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 43b25699ca..b78d6bdc62 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -104,7 +104,11 @@ namespace // specific wstringize() overload inline std::basic_string<__wchar_t> wunder(const std::string& str) { - return wunder(wstringize(str)); +// return wunder(wstringize(str)); + // Is wstringize(const std::string&) doing the right thing? Try + // widening each character individually -- which works only for 8-bit + // characters, of course -- just diagnostically. + return { str.begin(), str.end() }; } // Irritatingly, MiniDmpSender::setCallback() is defined to accept a -- cgit v1.2.3 From b883ffaa750630ce15bd133c3ddd1f39896fee02 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 12 Jul 2018 14:45:14 -0400 Subject: DRTVWR-447: More diagnostic logging for BugSplat metadata strings. --- indra/newview/llappviewerwin32.cpp | 55 ++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index b78d6bdc62..43a61c3857 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -70,6 +70,7 @@ #include "llerrorcontrol.h" #include +#include #include // Bugsplat (http://bugsplat.com) crash reporting tool @@ -111,6 +112,38 @@ namespace return { str.begin(), str.end() }; } + // can only be used in a context in which 'log' is a valid std::ostream + #define WVCSTR(string) wview(log, WCSTR(string)) + + const __wchar_t* wview(std::ostream& out, const __wchar_t* wstr) + { + const size_t maxlen = 50; + char buffer[maxlen]; + size_t size; + // Classic-C loop to calculate size; also forcibly narrow each + // __wchar_t to plain char into 'buffer'. + for (size = 0; size < (maxlen - 1) && wstr[size]; ++size) + buffer[size] = char(wstr[size]); + buffer[size] = '\0'; + // Log the length, show the plain chars + out << "(length " << size << ") '" << buffer << "' "; + // Now dump the memory pointed to by wstr as raw bytes. + char oldfill = out.fill(); + out << std::hex << std::setfill('0') << std::setw(2); + unsigned char* bytes = reinterpret_cast(wstr); + // Increment by one __wchar_t so we display the final nul character; + // remember to multiply by the number of bytes in a __wchar_t. + for (size_t b = 0; b < ((size + 1) * sizeof(__wchar_t)); ++b) + { + // To display as hex, need to convert each byte to int -- if we engage + // the operator<<(ostream&, char) overload, we'll just get characters. + out << int(bytes[b]); + } + out << std::dec << std::setfill(oldfill) << std::setw(0); + out << '\n'; + return wstr; + } + // Irritatingly, MiniDmpSender::setCallback() is defined to accept a // classic-C function pointer instead of an arbitrary C++ callable. If it // did accept a modern callable, we could pass a lambda that binds our @@ -131,18 +164,18 @@ namespace // send the main viewer log file // widen to wstring, convert to __wchar_t, then pass c_str() sBugSplatSender->sendAdditionalFile( - WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); - log << "Attached " << gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log") << '\n'; + WVCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); + log << "sendAdditionalFile('" << gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log") << "')\n"; sBugSplatSender->sendAdditionalFile( - WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); - log << "Attached " << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml") << '\n'; + WVCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); + log << "sendAdditionalFile('" << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml") << "')\n"; if (gAgentAvatarp) { // user name, when we have it - sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname())); - log << "Set default user name to '" << gAgentAvatarp->getFullname() << "'\n"; + sBugSplatSender->setDefaultUserName(WVCSTR(gAgentAvatarp->getFullname())); + log << "setDefaultUserName('" << gAgentAvatarp->getFullname() << "')\n"; } else { @@ -150,24 +183,24 @@ namespace } // LL_ERRS message, when there is one - sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage())); - log << "Set default user description to '" << LLError::getFatalMessage() << "'\n"; + sBugSplatSender->setDefaultUserDescription(WVCSTR(LLError::getFatalMessage())); + log << "setDefaultUserDescription('" << LLError::getFatalMessage() << "')\n"; if (gAgent.getRegion()) { // region location, when we have it LLVector3 loc = gAgent.getPositionAgent(); sBugSplatSender->resetAppIdentifier( - WCSTR(STRINGIZE(gAgent.getRegion()->getName() + WVCSTR(STRINGIZE(gAgent.getRegion()->getName() << '/' << loc.mV[0] << '/' << loc.mV[1] << '/' << loc.mV[2]))); - log << "Set app identifier to '" + log << "resetAppIdentifier('" << gAgent.getRegion()->getName() << '/' << loc.mV[0] << '/' << loc.mV[1] << '/' << loc.mV[2] - << "'\n"; + << "')\n"; } else { -- cgit v1.2.3 From 3888d1862a79ab927d118087b2ce662f15e27f41 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 12 Jul 2018 16:07:06 -0400 Subject: DRTVWR-447: For want of a 'const', the build was lost. --- indra/newview/llappviewerwin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 43a61c3857..d2854c6b47 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -130,7 +130,7 @@ namespace // Now dump the memory pointed to by wstr as raw bytes. char oldfill = out.fill(); out << std::hex << std::setfill('0') << std::setw(2); - unsigned char* bytes = reinterpret_cast(wstr); + const unsigned char* bytes = reinterpret_cast(wstr); // Increment by one __wchar_t so we display the final nul character; // remember to multiply by the number of bytes in a __wchar_t. for (size_t b = 0; b < ((size + 1) * sizeof(__wchar_t)); ++b) -- cgit v1.2.3 From 234ca77f19e53de1c02f8a641530ba89c90f1298 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 14 Jul 2018 08:52:58 -0400 Subject: DRTVWR-447: Revert BugSplat diagnostic logging; add platform tag. --- indra/newview/llappviewerwin32.cpp | 86 +++++--------------------------------- 1 file changed, 11 insertions(+), 75 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index d2854c6b47..adb340d40e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -70,7 +70,6 @@ #include "llerrorcontrol.h" #include -#include #include // Bugsplat (http://bugsplat.com) crash reporting tool @@ -95,7 +94,7 @@ namespace // It would be nice if, when wchar_t is the same as __wchar_t, this whole // function would optimize away. However, we use it only for the arguments - // to make exactly one call to initialize BugSplat. + // to the BugSplat API -- a handful of calls. inline std::basic_string<__wchar_t> wunder(const std::wstring& str) { return { str.begin(), str.end() }; @@ -105,43 +104,7 @@ namespace // specific wstringize() overload inline std::basic_string<__wchar_t> wunder(const std::string& str) { -// return wunder(wstringize(str)); - // Is wstringize(const std::string&) doing the right thing? Try - // widening each character individually -- which works only for 8-bit - // characters, of course -- just diagnostically. - return { str.begin(), str.end() }; - } - - // can only be used in a context in which 'log' is a valid std::ostream - #define WVCSTR(string) wview(log, WCSTR(string)) - - const __wchar_t* wview(std::ostream& out, const __wchar_t* wstr) - { - const size_t maxlen = 50; - char buffer[maxlen]; - size_t size; - // Classic-C loop to calculate size; also forcibly narrow each - // __wchar_t to plain char into 'buffer'. - for (size = 0; size < (maxlen - 1) && wstr[size]; ++size) - buffer[size] = char(wstr[size]); - buffer[size] = '\0'; - // Log the length, show the plain chars - out << "(length " << size << ") '" << buffer << "' "; - // Now dump the memory pointed to by wstr as raw bytes. - char oldfill = out.fill(); - out << std::hex << std::setfill('0') << std::setw(2); - const unsigned char* bytes = reinterpret_cast(wstr); - // Increment by one __wchar_t so we display the final nul character; - // remember to multiply by the number of bytes in a __wchar_t. - for (size_t b = 0; b < ((size + 1) * sizeof(__wchar_t)); ++b) - { - // To display as hex, need to convert each byte to int -- if we engage - // the operator<<(ostream&, char) overload, we'll just get characters. - out << int(bytes[b]); - } - out << std::dec << std::setfill(oldfill) << std::setw(0); - out << '\n'; - return wstr; + return wunder(wstringize(str)); } // Irritatingly, MiniDmpSender::setCallback() is defined to accept a @@ -153,67 +116,40 @@ namespace bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) { - // When BugSplat intercepts a crash, logging seems to stop?! - // Maybe because our test crashes use LL_ERROR(). Try writing a - // special log file "by hand." - std::ofstream log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "BugSplat.log"), - std::ios_base::app); - log << "Entered bugsplatSendLog() callback\n"; if (nCode == MDSCB_EXCEPTIONCODE) { // send the main viewer log file // widen to wstring, convert to __wchar_t, then pass c_str() sBugSplatSender->sendAdditionalFile( - WVCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); - log << "sendAdditionalFile('" << gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log") << "')\n"; + WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); sBugSplatSender->sendAdditionalFile( - WVCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); - log << "sendAdditionalFile('" << gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml") << "')\n"; + WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml"))); + + // We don't have an email address for any user. Hijack this + // metadata field for the platform identifier. + sBugSplatSender->setDefaultUserEmail(WCSTR(STRINGIZE("Windows" << ADDRESS_SIZE))); if (gAgentAvatarp) { // user name, when we have it - sBugSplatSender->setDefaultUserName(WVCSTR(gAgentAvatarp->getFullname())); - log << "setDefaultUserName('" << gAgentAvatarp->getFullname() << "')\n"; - } - else - { - log << "gAgentAvatarp is nullptr\n"; + sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname())); } // LL_ERRS message, when there is one - sBugSplatSender->setDefaultUserDescription(WVCSTR(LLError::getFatalMessage())); - log << "setDefaultUserDescription('" << LLError::getFatalMessage() << "')\n"; + sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage())); if (gAgent.getRegion()) { // region location, when we have it LLVector3 loc = gAgent.getPositionAgent(); sBugSplatSender->resetAppIdentifier( - WVCSTR(STRINGIZE(gAgent.getRegion()->getName() + WCSTR(STRINGIZE(gAgent.getRegion()->getName() << '/' << loc.mV[0] << '/' << loc.mV[1] << '/' << loc.mV[2]))); - log << "resetAppIdentifier('" - << gAgent.getRegion()->getName() - << '/' << loc.mV[0] - << '/' << loc.mV[1] - << '/' << loc.mV[2] - << "')\n"; - } - else - { - log << "gAgent.getRegion() is nullptr\n"; } - - LL_INFOS() << "Sending crash report to BugSplat." << LL_ENDL; - log << "Sending crash report to BugSplat.\n"; } // MDSCB_EXCEPTIONCODE - else - { - log << "nCode != MDSCB_EXCEPTIONCODE\n"; - } return false; } -- cgit v1.2.3 From c11ecfddff7e8769ad9b0c0a6f039193c031b8a3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 17 Jul 2018 14:42:35 -0400 Subject: DRTVWR-447: Force rebuild with new BUGSPLAT_DB value. --- indra/llappearance/lllocaltextureobject.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index f49cf21512..3f564ec3de 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -210,4 +210,3 @@ void LLLocalTextureObject::setBakedReady(BOOL ready) { mIsBakedReady = ready; } - -- cgit v1.2.3 From 59d2bf0622ceb5f6e09e7f850606e0cbcb794cb8 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 2 Aug 2018 16:21:30 -0400 Subject: DRTVWR-447: Merge changesets from newly updated viewer-release. --- indra/newview/CMakeLists.txt | 100 ++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2fc722d4c3..31c4c02d99 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 (DEFINED ENV{BUGSPLAT_DB}) + include(bugsplat) +endif (DEFINED ENV{BUGSPLAT_DB}) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -37,7 +44,6 @@ include(LLUI) include(LLVFS) include(LLWindow) include(LLXML) -include(Linking) include(NDOF) include(NVAPI) include(OPENAL) @@ -93,6 +99,12 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) +if (DEFINED ENV{BUGSPLAT_DB}) + include_directories( + ${BUGSPLAT_INCLUDE_DIR} + ) +endif (DEFINED ENV{BUGSPLAT_DB}) + include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLXML_SYSTEM_INCLUDE_DIRS} @@ -1356,6 +1368,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) @@ -1370,6 +1390,12 @@ if (DARWIN) ${COREAUDIO_LIBRARY} ) + if (DEFINED ENV{BUGSPLAT_DB}) + list(APPEND viewer_LIBRARIES + ${BUGSPLAT_LIBRARIES} + ) + endif (DEFINED ENV{BUGSPLAT_DB}) + # Add resource files to the project. set(viewer_RESOURCE_FILES secondlife.icns @@ -1395,6 +1421,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") @@ -1411,6 +1442,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 @@ -1693,6 +1729,11 @@ if (SDL_FOUND) ) endif (SDL_FOUND) +if (DEFINED ENV{BUGSPLAT_DB}) + set_property(TARGET ${VIEWER_BINARY_NAME} + PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (DEFINED ENV{BUGSPLAT_DB}) + # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) @@ -1791,7 +1832,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} @@ -1826,24 +1867,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 @@ -1905,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 @@ -1981,6 +2007,12 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLAPPEARANCE_LIBRARIES} ) +if (DEFINED ENV{BUGSPLAT_DB}) + target_link_libraries(${VIEWER_BINARY_NAME} + ${BUGSPLAT_LIBRARIES} + ) +endif (DEFINED ENV{BUGSPLAT_DB}) + set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Path to artwork files.") @@ -2054,8 +2086,10 @@ if (LINUX) endif (LINUX) if (DARWIN) - # These all get set with PROPERTIES - set(product "Second Life") + # 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}") # 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") @@ -2063,21 +2097,29 @@ if (DARWIN) # 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_BUNDLE_INFO_STRING "Second Life Viewer") + 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" ) @@ -2148,7 +2190,7 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) -if (PACKAGE) +if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND NOT DEFINED ENV{BUGSPLAT_DB}) set(SYMBOL_SEARCH_DIRS "") # Note that the path to VIEWER_SYMBOL_FILE must match that in ../../build.sh if (WINDOWS) @@ -2167,8 +2209,8 @@ if (PACKAGE) 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_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger") + set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger") set(VIEWER_LIB_GLOB "*.dylib") endif (DARWIN) if (LINUX) @@ -2180,7 +2222,6 @@ if (PACKAGE) 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 ".") @@ -2207,8 +2248,7 @@ if (PACKAGE) 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) +endif () if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below -- cgit v1.2.3 From 1b2f52257aa84d43cdeec31f1b1424e7ad44fa7f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 15 Aug 2018 16:38:09 -0400 Subject: DRTVWR-447: Streamline some of the logic around extra packages. --- indra/lib/python/indra/util/llmanifest.py | 81 +++++++------------------------ 1 file changed, 17 insertions(+), 64 deletions(-) (limited to 'indra') diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 974ac18e34..c24e25ba89 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -232,16 +232,12 @@ def main(): print "Option:", opt, "=", args[opt] # pass in sourceid as an argument now instead of an environment variable - try: - args['sourceid'] = os.environ["sourceid"] - except KeyError: - args['sourceid'] = "" + args['sourceid'] = os.environ.get("sourceid", "") # Build base package. touch = args.get('touch') if touch: print 'Creating base package' - args['package_id'] = "" # base package has no package ID wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args) wm.do(*args['actions']) # Store package file for later if making touched file. @@ -251,64 +247,25 @@ def main(): base_package_file = "" + wm.package_file # handle multiple packages if set - try: - additional_packages = os.environ["additional_packages"] - except KeyError: - additional_packages = "" + # ''.split() produces empty list + additional_packages = os.environ.get("additional_packages", "").split() if additional_packages: # Determine destination prefix / suffix for additional packages. - base_dest_postfix = args['dest'] - base_dest_prefix = "" base_dest_parts = args['dest'].split(os.sep) - if len(base_dest_parts) > 1: - base_dest_postfix = base_dest_parts[len(base_dest_parts) - 1] - base_dest_prefix = base_dest_parts[0] - i = 1 - while i < len(base_dest_parts) - 1: - base_dest_prefix = base_dest_prefix + os.sep + base_dest_parts[i] - i = i + 1 + base_dest_parts.insert(-1, "{}") + base_dest_template = os.sep.join(base_dest_parts) # Determine touched prefix / suffix for additional packages. - base_touch_postfix = "" - base_touch_prefix = "" if touch: - base_touch_postfix = touch - base_touch_parts = touch.split('/') + base_touch_parts = touch.split(os.sep) if "arwin" in args['platform']: - if len(base_touch_parts) > 1: - base_touch_postfix = base_touch_parts[len(base_touch_parts) - 1] - base_touch_prefix = base_touch_parts[0] - i = 1 - while i < len(base_touch_parts) - 1: - base_touch_prefix = base_touch_prefix + '/' + base_touch_parts[i] - i = i + 1 + base_touch_parts.insert(-1, "{}") else: - if len(base_touch_parts) > 2: - base_touch_postfix = base_touch_parts[len(base_touch_parts) - 2] + '/' + base_touch_parts[len(base_touch_parts) - 1] - base_touch_prefix = base_touch_parts[0] - i = 1 - while i < len(base_touch_parts) - 2: - base_touch_prefix = base_touch_prefix + '/' + base_touch_parts[i] - i = i + 1 - # Store base channel name. - base_channel_name = args['channel'] - # Build each additional package. - package_id_list = additional_packages.split(" ") - args['channel'] = base_channel_name - for package_id in package_id_list: - try: - if package_id + "_viewer_channel_suffix" in os.environ: - args['channel_suffix'] = os.environ[package_id + "_viewer_channel_suffix"] - else: - args['channel_suffix'] = None - if package_id + "_sourceid" in os.environ: - args['sourceid'] = os.environ[package_id + "_sourceid"] - else: - args['sourceid'] = None - args['dest'] = base_dest_prefix + os.sep + package_id + os.sep + base_dest_postfix - except KeyError: - sys.stderr.write("Failed to create package for package_id: %s" % package_id) - sys.stderr.flush() - continue + base_touch_parts.insert(-2, "{}") + base_touch_template = os.sep.join(base_touch_parts) + for package_id in additional_packages: + args['channel_suffix'] = os.environ.get(package_id + "_viewer_channel_suffix") + args['sourceid'] = os.environ.get(package_id + "_sourceid") + args['dest'] = base_dest_template.format(package_id) if touch: print 'Creating additional package for "', package_id, '" in ', args['dest'] try: @@ -318,18 +275,14 @@ def main(): sys.exit(str(err)) if touch: print 'Created additional package ', wm.package_file, ' for ', package_id - faketouch = base_touch_prefix + '/' + package_id + '/' + base_touch_postfix - fp = open(faketouch, 'w') - fp.write('set package_file=%s\n' % wm.package_file) - fp.close() + with open(base_touch_template.format(package_id), 'w') as fp: + fp.write('set package_file=%s\n' % wm.package_file) # Write out the package file in this format, so that it can easily be called # and used in a .bat file - yeah, it sucks, but this is the simplest... - touch = args.get('touch') if touch: - fp = open(touch, 'w') - fp.write('set package_file=%s\n' % base_package_file) - fp.close() + with open(touch, 'w') as fp: + fp.write('set package_file=%s\n' % base_package_file) print 'touched', touch return 0 -- cgit v1.2.3 From bc5aeae202ba6683cdae363a91d054043dc09949 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 15 Aug 2018 16:41:19 -0400 Subject: DRTVWR-447: Simplify redundant if-key-in-dict-and-value-nonempty logic --- indra/newview/viewer_manifest.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index ad6ba3ddff..ea0b3625be 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -108,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() @@ -212,8 +213,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): @@ -239,11 +241,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): -- cgit v1.2.3 From 52fe35737024abc5712bda770801fdeb703881fc Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 17 Aug 2018 14:39:32 -0400 Subject: DRTVWR-447: Use os.path.split(path) instead of path.split(os.sep). On Windows, where 'path' might be separated either with '/' or '\', the latter breaks unless all path separators are in fact the os.sep character '\'. While it would be possible to code something fancy with os.sep and os.altsep, testing the latter for None, much simpler to let os.path.split() handle it. --- indra/lib/python/indra/util/llmanifest.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index c24e25ba89..611f72269e 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -251,17 +251,21 @@ def main(): additional_packages = os.environ.get("additional_packages", "").split() if additional_packages: # Determine destination prefix / suffix for additional packages. - base_dest_parts = args['dest'].split(os.sep) + base_dest_parts = list(os.path.split(args['dest'])) base_dest_parts.insert(-1, "{}") - base_dest_template = os.sep.join(base_dest_parts) + base_dest_template = os.path.join(*base_dest_parts) # Determine touched prefix / suffix for additional packages. if touch: - base_touch_parts = touch.split(os.sep) + base_touch_parts = list(os.path.split(touch)) + # Because of the special insert() logic below, we don't just want + # [dirpath, basename]; we want [dirpath, directory, basename]. + # Further split the dirpath and replace it in the list. + base_touch_parts[0:1] = os.path.split(base_touch_parts[0]) if "arwin" in args['platform']: base_touch_parts.insert(-1, "{}") else: base_touch_parts.insert(-2, "{}") - base_touch_template = os.sep.join(base_touch_parts) + base_touch_template = os.path.join(*base_touch_parts) for package_id in additional_packages: args['channel_suffix'] = os.environ.get(package_id + "_viewer_channel_suffix") args['sourceid'] = os.environ.get(package_id + "_sourceid") -- cgit v1.2.3