summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autobuild.xml242
-rw-r--r--indra/cmake/LLBase.cmake4
-rw-r--r--indra/cmake/Requests.cmake7
-rw-r--r--indra/llcommon/llcoros.h20
-rw-r--r--indra/llcommon/llevents.cpp23
-rw-r--r--indra/llcommon/llevents.h20
-rw-r--r--indra/llcommon/llinitparam.h3
-rw-r--r--indra/llcommon/llleap.cpp51
-rw-r--r--indra/llcommon/llleap.h14
-rw-r--r--indra/llui/llnotificationslistener.cpp15
-rw-r--r--indra/llvfs/lldir_mac.cpp4
-rw-r--r--indra/llwindow/llwindowmacosx.cpp10
-rw-r--r--indra/newview/CMakeLists.txt348
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/app_settings/settings.xml13
-rw-r--r--indra/newview/installers/windows/installer_template.nsi41
-rw-r--r--indra/newview/llappviewer.cpp56
-rw-r--r--indra/newview/lllogininstance.cpp63
-rw-r--r--indra/newview/lllogininstance.h6
-rw-r--r--indra/newview/llstartup.cpp3
-rw-r--r--indra/newview/llvoicevivox.cpp9
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml39
-rwxr-xr-xindra/newview/viewer_manifest.py1044
-rw-r--r--indra/viewer_components/login/lllogin.cpp56
24 files changed, 885 insertions, 1208 deletions
diff --git a/autobuild.xml b/autobuild.xml
index 160f1d7d59..f0358eb8ba 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -225,90 +225,6 @@
<key>version</key>
<string>1.57</string>
</map>
- <key>bugsplat</key>
- <map>
- <key>copyright</key>
- <string>Copyright 2003-2017, BugSplat</string>
- <key>description</key>
- <string>Bugsplat crash reporting package</string>
- <key>license</key>
- <string>Proprietary</string>
- <key>license_file</key>
- <string>LICENSES/BUGSPLAT_LICENSE.txt</string>
- <key>name</key>
- <string>bugsplat</string>
- <key>platforms</key>
- <map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>436b124bce8cf57b18dbf10f5e6ebcd4</string>
- <key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26151/206132/bugsplat-1.0.7.520674-darwin64-520674.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- <key>windows</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>5d19acddc51ee7c802297dd176194362</string>
- <key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26153/206145/bugsplat-3.6.0.4.520674-windows-520674.tar.bz2</string>
- </map>
- <key>name</key>
- <string>windows</string>
- </map>
- <key>windows64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>78f5688b694e04c052fb0a1165c98bb5</string>
- <key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/26152/206142/bugsplat-3.6.0.4.520674-windows64-520674.tar.bz2</string>
- </map>
- <key>name</key>
- <string>windows64</string>
- </map>
- </map>
- <key>version</key>
- <string>1.0.7.520674</string>
- </map>
- <key>chardet</key>
- <map>
- <key>copyright</key>
- <string>Contributors to charset (see https://github.com/chardet/chardet)</string>
- <key>description</key>
- <string>Python Character Encoding Library</string>
- <key>license</key>
- <string>LGPL</string>
- <key>license_file</key>
- <string>LICENSES/chardet.txt</string>
- <key>name</key>
- <string>chardet</string>
- <key>platforms</key>
- <map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>0124862b6a1b88455c78a68f8b823d21</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6662/23578/chardet-3.0.4-darwin64-506651.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- </map>
- <key>version</key>
- <string>3.0.4</string>
- </map>
<key>colladadom</key>
<map>
<key>copyright</key>
@@ -1519,36 +1435,6 @@
<key>version</key>
<string>2012.1-2</string>
</map>
- <key>idna</key>
- <map>
- <key>copyright</key>
- <string>Copyright (c) 2013-2017, Kim Davies. All rights reserved.</string>
- <key>description</key>
- <string>Python Internationalized Domain Names in Applications (IDNA) Library</string>
- <key>license</key>
- <string>see idna.rst</string>
- <key>license_file</key>
- <string>LICENSES/idna.rst</string>
- <key>name</key>
- <string>idna</string>
- <key>platforms</key>
- <map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>7dfe9fc4023d7d4f511dd9fac7258266</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6663/23584/idna-2.5-darwin64-506652.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- </map>
- <key>version</key>
- <string>2.5</string>
- </map>
<key>jpeglib</key>
<map>
<key>copyright</key>
@@ -2227,46 +2113,6 @@
<key>version</key>
<string>0.0.1</string>
</map>
- <key>llbase</key>
- <map>
- <key>copyright</key>
- <string>Copyright (c) 2010, Linden Research, Inc.</string>
- <key>license</key>
- <string>mit</string>
- <key>license_file</key>
- <string>LICENSES/llbase-license.txt</string>
- <key>name</key>
- <string>llbase</string>
- <key>platforms</key>
- <map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>e18eeb0691af053b83bd46b76c6ee86a</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6299/21982/llbase-0.9.3.506286-darwin64-506286.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- <key>windows</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>e6865670f9bca1c82fb8b91db3ea515c</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6301/21994/llbase-0.9.3.506286-windows-506286.tar.bz2</string>
- </map>
- <key>name</key>
- <string>windows</string>
- </map>
- </map>
- <key>version</key>
- <string>0.9.3.506286</string>
- </map>
<key>llca</key>
<map>
<key>copyright</key>
@@ -3009,52 +2855,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>8.35.500898</string>
</map>
- <key>requests</key>
- <map>
- <key>copyright</key>
- <string>Copyright 2016 Kenneth Reitz</string>
- <key>description</key>
- <string>Python HTTP Library</string>
- <key>license</key>
- <string>Apache</string>
- <key>license_file</key>
- <string>LICENSES/requests.txt</string>
- <key>name</key>
- <string>requests</string>
- <key>platforms</key>
- <map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>b8d134a970261b445a3f376ba4e05ff7</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6693/23788/requests-2.18.1-darwin64-506681.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- <key>linux64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>a92f2235991871c3d601a73cfef9b2af</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4105/11530/requests-1.0-linux64-504094.tar.bz2</string>
- </map>
- <key>name</key>
- <string>linux64</string>
- </map>
- </map>
- <key>source</key>
- <string>https://bitbucket.org/lindenlab/p64_python-requests</string>
- <key>source_type</key>
- <string>hg</string>
- <key>version</key>
- <string>2.18.1</string>
- </map>
<key>slvoice</key>
<map>
<key>copyright</key>
@@ -3265,36 +3065,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>0.8.0.1</string>
</map>
- <key>urllib3</key>
- <map>
- <key>copyright</key>
- <string>Copyright 2008-2016 Andrey Petrov and contributors (see CONTRIBUTORS.txt)</string>
- <key>description</key>
- <string>Python HTTP Library</string>
- <key>license</key>
- <string>MIT</string>
- <key>license_file</key>
- <string>LICENSES/urllib3.txt</string>
- <key>name</key>
- <string>urllib3</string>
- <key>platforms</key>
- <map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>22f64c7fbb6704d2e9519fd1cca8e49b</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6659/23560/urllib3-1.21.1-darwin64-506648.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- </map>
- <key>version</key>
- <string>1.21.1</string>
- </map>
<key>viewer-manager</key>
<map>
<key>copyright</key>
@@ -3302,7 +3072,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>description</key>
<string>Linden Lab Viewer Management Process suite.</string>
<key>license</key>
- <string>Proprietary</string>
+ <string>viewerlgpl</string>
<key>license_file</key>
<string>LICENSE</string>
<key>name</key>
@@ -3314,9 +3084,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>4785e25bde1503e99cb4c2fe344b3d4e</string>
+ <string>eeeb18f7396de3147c6d958dfbc1a2e5</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25165/197744/viewer_manager-1.0.520046-darwin64-520046.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26016/204885/viewer_manager-2.0.520576-darwin64-520576.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -3338,9 +3108,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>b03866283b2cf3d8a79a93a07cbec9d6</string>
+ <string>2832c40449a8a8230e9072ceac5120af</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/25166/197758/viewer_manager-1.0.520046-windows-520046.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/26017/204891/viewer_manager-2.0.520576-windows-520576.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -3351,7 +3121,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key>
<string>hg</string>
<key>version</key>
- <string>1.0.520046</string>
+ <string>2.0.520576</string>
</map>
<key>vlc-bin</key>
<map>
diff --git a/indra/cmake/LLBase.cmake b/indra/cmake/LLBase.cmake
deleted file mode 100644
index 76e3c688a3..0000000000
--- a/indra/cmake/LLBase.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-# -*- cmake -*-
-include(Prebuilt)
-
-use_prebuilt_binary(llbase)
diff --git a/indra/cmake/Requests.cmake b/indra/cmake/Requests.cmake
deleted file mode 100644
index b9c729d697..0000000000
--- a/indra/cmake/Requests.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-if (DARWIN)
- include (Prebuilt)
- use_prebuilt_binary(requests)
- use_prebuilt_binary(urllib3)
- use_prebuilt_binary(chardet)
- use_prebuilt_binary(idna)
-endif (DARWIN)
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 8fb27af6a4..c551413811 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -170,6 +170,26 @@ public:
static bool get_consuming();
/**
+ * RAII control of the consuming flag
+ */
+ class OverrideConsuming
+ {
+ public:
+ OverrideConsuming(bool consuming):
+ mPrevConsuming(get_consuming())
+ {
+ set_consuming(consuming);
+ }
+ ~OverrideConsuming()
+ {
+ set_consuming(mPrevConsuming);
+ }
+
+ private:
+ bool mPrevConsuming;
+ };
+
+ /**
* Please do NOT directly use boost::dcoroutines::future! It is essential
* to maintain the "current" coroutine at every context switch. This
* Future wraps the essential boost::dcoroutines::future functionality
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index dce97b5411..eedd8c92b5 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -545,10 +545,8 @@ bool LLEventStream::post(const LLSD& event)
*****************************************************************************/
bool LLEventMailDrop::post(const LLSD& event)
{
- bool posted = false;
-
- if (!mSignal->empty())
- posted = LLEventStream::post(event);
+ // forward the call to our base class
+ bool posted = LLEventStream::post(event);
if (!posted)
{ // if the event was not handled we will save it for later so that it can
@@ -564,16 +562,25 @@ LLBoundListener LLEventMailDrop::listen_impl(const std::string& name,
const NameList& after,
const NameList& before)
{
- if (!mEventHistory.empty())
+ // Before actually connecting this listener for subsequent post() calls,
+ // first feed each of the saved events, in order, to the new listener.
+ // Remove any that this listener consumes -- Effective STL, Item 9.
+ for (auto hi(mEventHistory.begin()), hend(mEventHistory.end()); hi != hend; )
{
- if (listener(mEventHistory.front()))
+ if (listener(*hi))
{
- mEventHistory.pop_front();
+ // new listener consumed this event, erase it
+ hi = mEventHistory.erase(hi);
+ }
+ else
+ {
+ // listener did not consume this event, just move along
+ ++hi;
}
}
+ // let base class perform the actual connection
return LLEventStream::listen_impl(name, listener, after, before);
-
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 1d51c660ed..5d60c63810 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -650,15 +650,21 @@ public:
* LLEventMailDrop
*****************************************************************************/
/**
- * LLEventMailDrop is a specialization of LLEventStream. Events are posted normally,
- * however if no listeners return that they have handled the event it is placed in
- * a queue. Subsequent attaching listeners will receive stored events from the queue
- * until a listener indicates that the event has been handled. In order to receive
- * multiple events from a mail drop the listener must disconnect and reconnect.
+ * LLEventMailDrop is a specialization of LLEventStream. Events are posted
+ * normally, however if no listener returns that it has handled the event
+ * (returns true), it is placed in a queue. Subsequent attaching listeners
+ * will receive stored events from the queue until some listener indicates
+ * that the event has been handled.
+ *
+ * LLEventMailDrop completely decouples the timing of post() calls from
+ * listen() calls: every event posted to an LLEventMailDrop is eventually seen
+ * by all listeners, until some listener consumes it. The caveat is that each
+ * event *must* eventually reach a listener that will consume it, else the
+ * queue will grow to arbitrary length.
*
* @NOTE: When using an LLEventMailDrop (or LLEventQueue) with a LLEventTimeout or
- * LLEventFilter attaching the filter downstream using Timeout's constructor will
- * cause the MailDrop to discharge any of it's stored events. The timeout should
+ * LLEventFilter attaching the filter downstream, using Timeout's constructor will
+ * cause the MailDrop to discharge any of its stored events. The timeout should
* instead be connected upstream using its listen() method.
* See llcoro::suspendUntilEventOnWithTimeout() for an example.
*/
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index f1f4226c40..7f5b9b4ac2 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -2115,6 +2115,9 @@ namespace LLInitParam
typedef typename super_t::iterator iterator;
typedef typename super_t::const_iterator const_iterator;
+ using super_t::operator();
+ using super_t::operator const container_t&;
+
explicit Multiple(const char* name = "")
: super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
{}
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index c87d2a3e58..cf8f8cc6a5 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -47,9 +47,9 @@ class LLLeapImpl: public LLLeap
LOG_CLASS(LLLeap);
public:
// Called only by LLLeap::create()
- LLLeapImpl(const std::string& desc, const std::vector<std::string>& plugin):
+ LLLeapImpl(const LLProcess::Params& cparams):
// We might reassign mDesc in the constructor body if it's empty here.
- mDesc(desc),
+ mDesc(cparams.desc),
// We expect multiple LLLeapImpl instances. Definitely tweak
// mDonePump's name for uniqueness.
mDonePump("LLLeap", true),
@@ -67,17 +67,17 @@ public:
// this class or method name.
mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2)))
{
- // Rule out empty vector
- if (plugin.empty())
+ // Rule out unpopulated Params block
+ if (! cparams.executable.isProvided())
{
LLTHROW(Error("no plugin command"));
}
// Don't leave desc empty either, but in this case, if we weren't
// given one, we'll fake one.
- if (desc.empty())
+ if (mDesc.empty())
{
- mDesc = LLProcess::basename(plugin[0]);
+ mDesc = LLProcess::basename(cparams.executable);
// how about a toLower() variant that returns the transformed string?!
std::string desclower(mDesc);
LLStringUtil::toLower(desclower);
@@ -87,9 +87,9 @@ public:
// notice Python specially: we provide Python LLSD serialization
// support, so there's a pretty good reason to implement plugins
// in that language.
- if (plugin.size() >= 2 && (desclower == "python" || desclower == "python.exe"))
+ if (cparams.args.size() && (desclower == "python" || desclower == "python.exe"))
{
- mDesc = LLProcess::basename(plugin[1]);
+ mDesc = LLProcess::basename(cparams.args()[0]);
}
}
@@ -97,14 +97,10 @@ public:
mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::bad_launch, this, _1));
// Okay, launch child.
- LLProcess::Params params;
+ // Get a modifiable copy of params block to set files and postend.
+ LLProcess::Params params(cparams);
+ // copy our deduced mDesc back into the params block
params.desc = mDesc;
- std::vector<std::string>::const_iterator pi(plugin.begin()), pend(plugin.end());
- params.executable = *pi++;
- for ( ; pi != pend; ++pi)
- {
- params.args.add(*pi);
- }
params.files.add(LLProcess::FileParam("pipe")); // stdin
params.files.add(LLProcess::FileParam("pipe")); // stdout
params.files.add(LLProcess::FileParam("pipe")); // stderr
@@ -429,17 +425,17 @@ private:
boost::scoped_ptr<LLLeapListener> mListener;
};
-// This must follow the declaration of LLLeapImpl, so it may as well be last.
-LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>& plugin, bool exc)
+// These must follow the declaration of LLLeapImpl, so they may as well be last.
+LLLeap* LLLeap::create(const LLProcess::Params& params, bool exc)
{
// If caller is willing to permit exceptions, just instantiate.
if (exc)
- return new LLLeapImpl(desc, plugin);
+ return new LLLeapImpl(params);
// Caller insists on suppressing LLLeap::Error. Very well, catch it.
try
{
- return new LLLeapImpl(desc, plugin);
+ return new LLLeapImpl(params);
}
catch (const LLLeap::Error&)
{
@@ -447,6 +443,23 @@ LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>&
}
}
+LLLeap* LLLeap::create(const std::string& desc, const std::vector<std::string>& plugin, bool exc)
+{
+ LLProcess::Params params;
+ params.desc = desc;
+ std::vector<std::string>::const_iterator pi(plugin.begin()), pend(plugin.end());
+ // could validate here, but let's rely on LLLeapImpl's constructor
+ if (pi != pend)
+ {
+ params.executable = *pi++;
+ }
+ for ( ; pi != pend; ++pi)
+ {
+ params.args.add(*pi);
+ }
+ return create(params, exc);
+}
+
LLLeap* LLLeap::create(const std::string& desc, const std::string& plugin, bool exc)
{
// Use LLStringUtil::getTokens() to parse the command line
diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h
index 8aac8a64c5..7cecdf2f8f 100644
--- a/indra/llcommon/llleap.h
+++ b/indra/llcommon/llleap.h
@@ -14,6 +14,7 @@
#include "llinstancetracker.h"
#include "llexception.h"
+#include "llprocess.h"
#include <string>
#include <vector>
@@ -62,6 +63,19 @@ public:
bool exc=true);
/**
+ * Pass an LLProcess::Params instance to specify desc, executable, args et al.
+ *
+ * Note that files and postend are set implicitly; any values you set in
+ * those fields will be disregarded.
+ *
+ * Pass exc=false to suppress LLLeap::Error exception. Obviously in that
+ * case the caller cannot discover the nature of the error, merely that an
+ * error of some kind occurred (because create() returned NULL). Either
+ * way, the error is logged.
+ */
+ static LLLeap* create(const LLProcess::Params& params, bool exc=true);
+
+ /**
* Exception thrown for invalid create() arguments, e.g. no plugin
* program. This is more resiliant than an LL_ERRS failure, because the
* string(s) passed to create() might come from an external source. This
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
index b6a32a0e78..be26416cbb 100644
--- a/indra/llui/llnotificationslistener.cpp
+++ b/indra/llui/llnotificationslistener.cpp
@@ -90,9 +90,12 @@ void LLNotificationsListener::requestAdd(const LLSD& event_data) const
{
if(event_data.has("reply"))
{
+ LLSD payload(event_data["payload"]);
+ // copy reqid, if provided, to link response with request
+ payload["reqid"] = event_data["reqid"];
mNotifications.add(event_data["name"],
event_data["substitutions"],
- event_data["payload"],
+ payload,
boost::bind(&LLNotificationsListener::NotificationResponder,
this,
event_data["reply"].asString(),
@@ -112,10 +115,12 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum
const LLSD& notification,
const LLSD& response) const
{
- LLSD reponse_event;
- reponse_event["notification"] = notification;
- reponse_event["response"] = response;
- LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
+ LLSD response_event;
+ response_event["notification"] = notification;
+ response_event["response"] = response;
+ // surface reqid at top level of response for request/response protocol
+ response_event["reqid"] = notification["payload"]["reqid"];
+ LLEventPumps::getInstance()->obtain(reply_pump).post(response_event);
}
void LLNotificationsListener::listChannels(const LLSD& params) const
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 79c4362747..87dc1b9795 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -171,9 +171,9 @@ void LLDir_Mac::initAppDirs(const std::string &app_name,
if (!app_read_only_data_dir.empty())
{
mAppRODataDir = app_read_only_data_dir;
- mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ mSkinBaseDir = add(mAppRODataDir, "skins");
}
- mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "../Resources", "ca-bundle.crt");
+ mCAFile = add(mAppRODataDir, "ca-bundle.crt");
}
std::string LLDir_Mac::getCurPath()
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 843294c239..d4afbb15df 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -1429,12 +1429,10 @@ static CursorRef gCursors[UI_CURSOR_COUNT];
static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY)
{
// cursors are in <Application Bundle>/Contents/Resources/cursors_mac/UI_CURSOR_FOO.tif
- std::string fullpath = gDirUtilp->getAppRODataDir();
- fullpath += gDirUtilp->getDirDelimiter();
- fullpath += "cursors_mac";
- fullpath += gDirUtilp->getDirDelimiter();
- fullpath += cursorIDToName(cursorid);
- fullpath += ".tif";
+ std::string fullpath = gDirUtilp->add(
+ gDirUtilp->getAppRODataDir(),
+ "cursors_mac",
+ cursorIDToName(cursorid) + std::string(".tif"));
gCursors[cursorid] = createImageCursor(fullpath.c_str(), hotspotX, hotspotY);
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e573b927d7..e7111ebe54 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -3,14 +3,7 @@
project(viewer)
include(00-Common)
-# DON'T move Linking.cmake to its place in the alphabetized list below: it
-# sets variables on which the 3p .cmake files depend.
-include(Linking)
-
include(Boost)
-if (BUGSPLAT_DB)
- include(bugsplat)
-endif (BUGSPLAT_DB)
include(BuildPackagesInfo)
include(BuildVersion)
include(CMakeCopyIfDifferent)
@@ -23,7 +16,6 @@ include(GLOD)
include(Hunspell)
include(JsonCpp)
include(LLAppearance)
-include(LLBase)
include(LLAudio)
include(LLCA)
include(LLCharacter)
@@ -44,13 +36,13 @@ include(LLUI)
include(LLVFS)
include(LLWindow)
include(LLXML)
+include(Linking)
include(NDOF)
include(NVAPI)
include(OPENAL)
include(OpenGL)
include(OpenSSL)
include(PNG)
-include(Requests)
include(TemplateCheck)
include(UI)
include(UnixInstall)
@@ -99,12 +91,6 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
-if (BUGSPLAT_DB)
- include_directories(
- ${BUGSPLAT_INCLUDE_DIR}
- )
-endif (BUGSPLAT_DB)
-
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
${LLXML_SYSTEM_INCLUDE_DIRS}
@@ -1368,14 +1354,6 @@ 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)
@@ -1390,12 +1368,6 @@ if (DARWIN)
${COREAUDIO_LIBRARY}
)
- if (BUGSPLAT_DB)
- list(APPEND viewer_LIBRARIES
- ${BUGSPLAT_LIBRARIES}
- )
- endif (BUGSPLAT_DB)
-
# Add resource files to the project.
set(viewer_RESOURCE_FILES
secondlife.icns
@@ -1421,11 +1393,6 @@ 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")
@@ -1442,11 +1409,6 @@ 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
@@ -1729,11 +1691,6 @@ if (SDL_FOUND)
)
endif (SDL_FOUND)
-if (BUGSPLAT_DB)
- set_property(TARGET ${VIEWER_BINARY_NAME}
- PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT")
-endif (BUGSPLAT_DB)
-
# add package files
file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py)
@@ -1832,7 +1789,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}
@@ -1841,16 +1798,15 @@ if (WINDOWS)
--actions=copy
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
- "--bugsplat=${BUGSPLAT_DB}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
- "--channel=${VIEWER_CHANNEL}"
--configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
--grid=${GRID}
+ "--channel=${VIEWER_CHANNEL}"
+ --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat
- --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
stage_third_party_libs
@@ -1868,9 +1824,24 @@ 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
@@ -1893,16 +1864,15 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
- "--bugsplat=${BUGSPLAT_DB}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
+ --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
--configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
--grid=${GRID}
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat
- --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
DEPENDS
${VIEWER_BINARY_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
@@ -1933,8 +1903,8 @@ else (WINDOWS)
endif (WINDOWS)
# *NOTE: - this list is very sensitive to ordering, test carefully on all
-# platforms if you change the relative order of the entries here.
-# In particular, cmake 2.6.4 (when building with linux/makefile generators)
+# platforms if you change the releative order of the entries here.
+# In particular, cmake 2.6.4 (when buidling 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
@@ -2009,12 +1979,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLAPPEARANCE_LIBRARIES}
)
-if (BUGSPLAT_DB)
- target_link_libraries(${VIEWER_BINARY_NAME}
- ${BUGSPLAT_LIBRARIES}
- )
-endif (BUGSPLAT_DB)
-
set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
"Path to artwork files.")
@@ -2038,16 +2002,15 @@ if (LINUX)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
- "--bugsplat=${BUGSPLAT_DB}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
+ --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
--configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/packaged
--grid=${GRID}
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
- --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
${COPY_INPUT_DEPENDENCIES}
@@ -2061,18 +2024,17 @@ if (LINUX)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --actions=copy
--arch=${ARCH}
+ --actions=copy
--artwork=${ARTWORK_DIR}
- "--bugsplat=${BUGSPLAT_DB}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
- "--channel=${VIEWER_CHANNEL}"
--configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/packaged
--grid=${GRID}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
+ "--channel=${VIEWER_CHANNEL}"
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
+ --source=${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
${COPY_INPUT_DEPENDENCIES}
@@ -2090,52 +2052,31 @@ if (LINUX)
endif (LINUX)
if (DARWIN)
- # 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")
- else (PACKAGE)
- # force the name of the actual executable to allow running it within Xcode for debugging
- set(MACOSX_WRAPPER_EXECUTABLE_NAME "../Resources/Second Life Viewer.app/Contents/MacOS/Second Life")
- endif (PACKAGE)
- set(MACOSX_BUNDLE_INFO_STRING "${VIEWER_CHANNEL}")
+ # These all get set with PROPERTIES
+ set(product "Second Life")
+ set(MACOSX_EXECUTABLE_NAME "Second Life")
+ set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer")
set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer")
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}.${VIEWER_VERSION_REVISION}")
+ set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007")
set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib")
set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication")
-
- # https://blog.kitware.com/upcoming-in-cmake-2-8-12-osx-rpath-support/
- set(CMAKE_MACOSX_RPATH 1)
set_target_properties(
${VIEWER_BINARY_NAME}
PROPERTIES
OUTPUT_NAME "${product}"
- # From Contents/MacOS/SecondLife, look in Contents/Frameworks
- INSTALL_RPATH "@loader_path/../Frameworks"
- # SIGH, as of 2018-05-24 (cmake 3.11.1) the INSTALL_RPATH property simply
- # does not work. Try this:
- LINK_FLAGS "-rpath @loader_path/../Frameworks"
MACOSX_BUNDLE_INFO_PLIST
"${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
)
- set(VIEWER_APP_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app")
- set(VIEWER_APP_EXE "${VIEWER_APP_BUNDLE}/Contents/MacOS/${product}")
- set(VIEWER_APP_DSYM "${VIEWER_APP_EXE}.dSYM")
- set(VIEWER_APP_XCARCHIVE "${VIEWER_APP_BUNDLE}/../${product}.xcarchive.zip")
-
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
- "${VIEWER_APP_BUNDLE}/Contents/Info.plist"
+ "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app/Contents/Info.plist"
)
add_custom_command(
@@ -2146,16 +2087,15 @@ if (DARWIN)
--actions=copy
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
- "--bugsplat=${BUGSPLAT_DB}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
- --bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER}
- "--channel=${VIEWER_CHANNEL}"
--configuration=${CMAKE_CFG_INTDIR}
- --dest=${VIEWER_APP_BUNDLE}
+ --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app
--grid=${GRID}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
+ "--channel=${VIEWER_CHANNEL}"
--versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
+ --bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER}
+ --source=${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
${VIEWER_BINARY_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
@@ -2180,16 +2120,15 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
- "--bugsplat=${BUGSPLAT_DB}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
- "--channel=${VIEWER_CHANNEL}"
--configuration=${CMAKE_CFG_INTDIR}
- --dest=${VIEWER_APP_BUNDLE}
+ --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app
--grid=${GRID}
+ "--channel=${VIEWER_CHANNEL}"
+ --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
- --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
${SIGNING_SETTING}
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
@@ -2201,152 +2140,67 @@ if (INSTALL)
include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)
endif (INSTALL)
-# Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh
-if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE)
- if (NOT BUGSPLAT_DB)
- # Breakpad symbol-file generation
- set(SYMBOL_SEARCH_DIRS "")
- if (WINDOWS)
- list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
- # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad
- # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe")
- set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
- set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}")
- set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest)
- endif (WINDOWS)
- if (DARWIN)
- list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
- # *TODO: Generate these search dirs in the cmake files related to each binary.
- list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
- list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
- list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
- set(VIEWER_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger")
- set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger")
- set(VIEWER_LIB_GLOB "*.dylib")
- endif (DARWIN)
- if (LINUX)
- list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged")
- set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
- set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin")
- set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*")
- set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
- endif (LINUX)
-
- if(CMAKE_CFG_INTDIR STREQUAL ".")
- set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
- else(CMAKE_CFG_INTDIR STREQUAL ".")
- # set LLBUILD_CONFIG to be a shell variable evaluated at build time
- # reflecting the configuration we are currently building.
- set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR})
- endif(CMAKE_CFG_INTDIR STREQUAL ".")
- add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
- COMMAND "${PYTHON_EXECUTABLE}"
- ARGS
- "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
- "${LLBUILD_CONFIG}"
- "${SYMBOL_SEARCH_DIRS}"
- "${VIEWER_EXE_GLOBS}"
- "${VIEWER_LIB_GLOB}"
- "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms"
- "${VIEWER_SYMBOL_FILE}"
- DEPENDS generate_breakpad_symbols.py
- VERBATIM)
-
- add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME} "${VIEWER_COPY_MANIFEST}")
- add_dependencies(generate_symbols ${VIEWER_BINARY_NAME})
- if (WINDOWS OR LINUX)
- add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}")
- endif (WINDOWS OR LINUX)
-
- else (NOT BUGSPLAT_DB)
- # BugSplat symbol-file generation
- if (WINDOWS)
- # Just pack up a tarball containing only the .pdb file for the
- # executable. Because we intend to use cygwin tar, we must render
- # VIEWER_SYMBOL_FILE in cygwin path syntax.
- execute_process(COMMAND "cygpath" "-u" "${VIEWER_SYMBOL_FILE}"
- OUTPUT_VARIABLE VIEWER_SYMBOL_FILE_CYGWIN
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- execute_process(COMMAND "cygpath" "-u" "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
- OUTPUT_VARIABLE PARENT_DIRECTORY_CYGWIN
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
- # Use of 'tar ...j' here assumes VIEWER_SYMBOL_FILE endswith .tar.bz2;
- # testing a string suffix is painful enough in CMake language that
- # we'll continue assuming it until forced to generalize.
- COMMAND "tar"
- ARGS
- "cjf"
- "${VIEWER_SYMBOL_FILE_CYGWIN}"
- "-C"
- "${PARENT_DIRECTORY_CYGWIN}"
- "secondlife-bin.pdb"
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-bin.pdb"
- COMMENT "Packing viewer PDB into ${VIEWER_SYMBOL_FILE_CYGWIN}"
- )
- add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME})
- add_dependencies(generate_symbols ${VIEWER_BINARY_NAME})
- endif (WINDOWS)
- if (DARWIN)
- # Have to run dsymutil first, then pack up the resulting .dSYM directory
- add_custom_command(OUTPUT "${VIEWER_APP_DSYM}"
- COMMAND "dsymutil"
- ARGS
- ${VIEWER_APP_EXE}
- COMMENT "Generating ${VIEWER_APP_DSYM}"
- )
- add_custom_target(dsym_generate DEPENDS "${VIEWER_APP_DSYM}")
- add_dependencies(dsym_generate ${VIEWER_BINARY_NAME})
- add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
- # See above comments about "tar ...j"
- COMMAND "tar"
- ARGS
- "cjf"
- "${VIEWER_SYMBOL_FILE}"
- "-C"
- "${VIEWER_APP_DSYM}/.."
- "${product}.dSYM"
- DEPENDS "${VIEWER_APP_DSYM}"
- COMMENT "Packing dSYM into ${VIEWER_SYMBOL_FILE}"
- )
- add_custom_target(dsym_tarball DEPENDS "${VIEWER_SYMBOL_FILE}")
- add_dependencies(dsym_tarball dsym_generate)
- add_custom_command(OUTPUT "${VIEWER_APP_XCARCHIVE}"
- COMMAND "zip"
- ARGS
- "-r"
- "${VIEWER_APP_XCARCHIVE}"
- "."
- WORKING_DIRECTORY "${VIEWER_APP_DSYM}/.."
- DEPENDS "${VIEWER_APP_DSYM}"
- COMMENT "Generating xcarchive.zip for upload to BugSplat"
- )
- add_custom_target(dsym_xcarchive DEPENDS "${VIEWER_APP_XCARCHIVE}")
- add_dependencies(dsym_xcarchive dsym_generate)
- # Have to create a stamp file, and depend on it, to force CMake to run
- # the cleanup step.
- add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp"
- COMMAND rm -rf "${VIEWER_APP_DSYM}"
- COMMAND touch "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp"
- DEPENDS "${VIEWER_SYMBOL_FILE}" "${VIEWER_APP_XCARCHIVE}"
- COMMENT "Cleaning up dSYM"
- )
- add_custom_target(generate_symbols DEPENDS
- "${VIEWER_APP_DSYM}"
- "${VIEWER_SYMBOL_FILE}"
- "${VIEWER_APP_XCARCHIVE}"
- "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp"
- )
- add_dependencies(generate_symbols dsym_tarball dsym_xcarchive)
- endif (DARWIN)
- if (LINUX)
- # TBD
- endif (LINUX)
- endif (NOT BUGSPLAT_DB)
-
- # for both BUGSPLAT_DB and Breakpad
- add_dependencies(llpackage generate_symbols)
-endif ()
+if (PACKAGE)
+ set(SYMBOL_SEARCH_DIRS "")
+ # Note that the path to VIEWER_SYMBOL_FILE must match that in ../../build.sh
+ if (WINDOWS)
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
+ set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows-$ENV{AUTOBUILD_ADDRSIZE}.tar.bz2")
+ # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad
+ # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe")
+ set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
+ set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}")
+ set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest)
+ endif (WINDOWS)
+ if (DARWIN)
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
+ # *TODO: Generate these search dirs in the cmake files related to each binary.
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
+ set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin-$ENV{AUTOBUILD_ADDRSIZE}.tar.bz2")
+ set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin mac-crash-logger")
+ set(VIEWER_EXE_GLOBS "'Second Life' mac-crash-logger")
+ set(VIEWER_LIB_GLOB "*.dylib")
+ endif (DARWIN)
+ if (LINUX)
+ list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged")
+ set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux-$ENV{AUTOBUILD_ADDRSIZE}.tar.bz2")
+ set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin")
+ set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin")
+ set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*")
+ set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
+ endif (LINUX)
+
+ if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
+ if(CMAKE_CFG_INTDIR STREQUAL ".")
+ set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
+ else(CMAKE_CFG_INTDIR STREQUAL ".")
+ # set LLBUILD_CONFIG to be a shell variable evaluated at build time
+ # reflecting the configuration we are currently building.
+ set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR})
+ endif(CMAKE_CFG_INTDIR STREQUAL ".")
+ add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
+ COMMAND "${PYTHON_EXECUTABLE}"
+ ARGS
+ "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
+ "${LLBUILD_CONFIG}"
+ "${SYMBOL_SEARCH_DIRS}"
+ "${VIEWER_EXE_GLOBS}"
+ "${VIEWER_LIB_GLOB}"
+ "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms"
+ "${VIEWER_SYMBOL_FILE}"
+ DEPENDS generate_breakpad_symbols.py
+ VERBATIM)
+
+ add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}")
+ add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}")
+ if (WINDOWS OR LINUX)
+ add_dependencies(generate_breakpad_symbols "${VIEWER_COPY_MANIFEST}")
+ endif (WINDOWS OR LINUX)
+ add_dependencies(llpackage generate_breakpad_symbols)
+ endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
+endif (PACKAGE)
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 8aabd6818b..9482f07524 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
- <string>${MACOSX_WRAPPER_EXECUTABLE_NAME}</string>
+ <string>${MACOSX_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 8e8cce5787..ca13c60768 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4316,6 +4316,17 @@
<key>Value</key>
<real>96.0</real>
</map>
+ <key>ForceAddressSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Force Windows update to 32-bit or 64-bit viewer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ForceAssetFail</key>
<map>
<key>Comment</key>
@@ -16172,7 +16183,7 @@
<string>if true, disables running the GPU benchmark at startup
(default to class 1)</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index 14c8dba39f..76187b49a5 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -299,7 +299,7 @@ StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"
CreateDirectory "$SMPROGRAMS\$INSTSHORTCUT"
SetOutPath "$INSTDIR"
CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \
- "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
+ "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \
@@ -317,9 +317,9 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \
# Other shortcuts
SetOutPath "$INSTDIR"
CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
- "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
+ "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \
- "$INSTDIR\$INSTEXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
+ "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
'"$INSTDIR\uninst.exe"' ''
@@ -327,7 +327,7 @@ CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" "$INSTDIR"
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" "${VERSION_LONG}"
WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" "$INSTSHORTCUT"
-WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$INSTEXE"
+WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$VIEWER_EXE"
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "Publisher" "Linden Research, Inc."
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "URLInfoAbout" "http://secondlife.com/whatis/"
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "URLUpdateInfo" "http://secondlife.com/support/downloads/"
@@ -338,10 +338,10 @@ WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninst
WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "EstimatedSize" "0x0001D500" # ~117 MB
# from FS:Ansariel
-WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayIcon" '"$INSTDIR\$INSTEXE"'
+WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayIcon" '"$INSTDIR\$VIEWER_EXE"'
# BUG-2707 Disable SEHOP for installed viewer.
-WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$INSTEXE" "DisableExceptionChainValidation" 1
+WriteRegDWORD HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$VIEWER_EXE" "DisableExceptionChainValidation" 1
# Write URL registry info
WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "(default)" "URL:Second Life"
@@ -358,9 +358,8 @@ WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$
# URL param must be last item passed to viewer, it ignores subsequent params to avoid parameter injection attacks.
WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$VIEWER_EXE" -url "%1"'
-# Only allow Launcher to be the icon
-WriteRegStr HKEY_CLASSES_ROOT "Applications\$INSTEXE" "IsHostApp" ""
-WriteRegStr HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" "NoStartPage" ""
+WriteRegStr HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "IsHostApp" ""
+##WriteRegStr HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" "NoStartPage" ""
# Write out uninstaller
WriteUninstaller "$INSTDIR\uninst.exe"
@@ -398,8 +397,8 @@ Call un.CloseSecondLife
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG"
DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG"
# BUG-2707 Remove entry that disabled SEHOP
-DeleteRegKey HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$INSTEXE"
-DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE"
+DeleteRegKey HKEY_LOCAL_MACHINE "Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$VIEWER_EXE"
+##DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE"
DeleteRegKey HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}"
# Clean up shortcuts
@@ -537,6 +536,7 @@ Function RemoveProgFilesOnInst
# Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
Delete "$INSTDIR\$INSTEXE"
+Delete "$INSTDIR\$VIEWER_EXE"
# Remove old shader files first so fallbacks will work. See DEV-5663
RMDir /r "$INSTDIR\app_settings\shaders"
@@ -673,7 +673,7 @@ FunctionEnd
;; After install completes, launch app
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function .onInstSuccess
-Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch.
+ Call CheckWindowsServPack # Warn if not on the latest SP before asking to launch.
Push $R0
Push $0
;; MAINT-7812: Only write nsis.winstall file with /marker switch
@@ -694,8 +694,21 @@ Call CheckWindowsServPack # Warn if not on the latest SP before asking to launc
Pop $R0
Push $R0 # Option value, unused#
StrCmp $SKIP_AUTORUN "true" +2;
-# Assumes SetOutPath $INSTDIR
- Exec '"$WINDIR\explorer.exe" "$INSTDIR\$INSTSHORTCUT.lnk"'
+ # Assumes SetOutPath $INSTDIR
+ # Run INSTEXE (our updater), passing VIEWER_EXE plus the command-line
+ # arguments built into our shortcuts. This gives the updater a chance
+ # to verify that the viewer we just installed is appropriate for the
+ # running system -- or, if not, to download and install a different
+ # viewer. For instance, if a user running 32-bit Windows installs a
+ # 64-bit viewer, it cannot run on this system. But since the updater
+ # is a 32-bit executable even in the 64-bit viewer package, the
+ # updater can detect the problem and adapt accordingly.
+ # Once everything is in order, the updater will run the specified
+ # viewer with the specified params.
+ # Quote the updater executable and the viewer executable because each
+ # must be a distinct command-line token, but DO NOT quote the language
+ # string because it must decompose into separate command-line tokens.
+ Exec '"$INSTDIR\$INSTEXE" precheck "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM'
Pop $R0
#
FunctionEnd
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index dd82aa735f..56e79bed74 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1092,26 +1092,6 @@ bool LLAppViewer::init()
}
}
-// don't nag developers who need to run the executable directly
-#if LL_RELEASE_FOR_DOWNLOAD
- // MAINT-8305: If we're processing a SLURL, skip the launcher check.
- if (gSavedSettings.getString("CmdLineLoginLocation").empty())
- {
- const char* PARENT = getenv("PARENT");
- if (! (PARENT && std::string(PARENT) == "SL_Launcher"))
- {
- // Don't directly run this executable. Please run the launcher, which
- // will run the viewer itself.
- // Naturally we do not consider this bulletproof. The point is to
- // gently remind a user who *inadvertently* finds him/herself in this
- // situation to do things the Right Way. Anyone who intentionally
- // bypasses this mechanism needs no reminder that s/he's shooting
- // him/herself in the foot.
- LLNotificationsUtil::add("RunLauncher");
- }
- }
-#endif
-
#if LL_WINDOWS
if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
{
@@ -1159,6 +1139,36 @@ bool LLAppViewer::init()
gGLActive = FALSE;
+ LLProcess::Params updater;
+ updater.desc = "updater process";
+ // Because it's the updater, it MUST persist beyond the lifespan of the
+ // viewer itself.
+ updater.autokill = false;
+#if LL_WINDOWS
+ updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater.exe");
+#elif LL_DARWIN
+ // explicitly run the system Python interpreter on updater.py
+ updater.executable = "python";
+ updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "updater.py"));
+#else
+ updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "updater");
+#endif
+ // add LEAP mode command-line argument to whichever of these we selected
+ updater.args.add("leap");
+ // UpdaterServiceSettings
+ updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
+ // channel
+ updater.args.add(LLVersionInfo::getChannel());
+ // testok
+ updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
+ // UpdaterServiceURL
+ updater.args.add(gSavedSettings.getString("UpdaterServiceURL"));
+ // ForceAddressSize
+ updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
+
+ // Run the updater. An exception from launching the updater should bother us.
+ LLLeap::create(updater, true);
+
// Iterate over --leap command-line options. But this is a bit tricky: if
// there's only one, it won't be an array at all.
LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand"));
@@ -3930,12 +3940,6 @@ void LLAppViewer::requestQuit()
gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
}
- // Try to send last batch of avatar rez metrics.
- if (!gDisconnected && isAgentAvatarValid())
- {
- gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
- }
-
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
effectp->setPositionGlobal(gAgent.getPositionGlobal());
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index bc93fa2c20..126c6be388 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -253,14 +253,12 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
mLoginState = event["state"].asString();
mResponseData = event["data"];
-
+
if(event.has("transfer_rate"))
{
mTransferRate = event["transfer_rate"].asReal();
}
-
-
// Call the method registered in constructor, if any, for more specific
// handling
mDispatcher.try_call(event);
@@ -276,6 +274,14 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
// Login has failed.
// Figure out why and respond...
LLSD response = event["data"];
+ LLSD updater = response["updater"];
+
+ // Always provide a response to the updater, if in fact the updater
+ // contacted us, if in fact the ping contains a 'reply' key. Most code
+ // paths tell it not to proceed with updating.
+ ResponsePtr resp(std::make_shared<LLEventAPI::Response>
+ (LLSDMap("update", false), updater));
+
std::string reason_response = response["reason"].asString();
std::string message_response = response["message"].asString();
LL_DEBUGS("LLLogin") << "reason " << reason_response
@@ -328,17 +334,44 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
}
else if(reason_response == "update")
{
- // This shouldn't happen - the viewer manager should have forced an update;
- // possibly the user ran the viewer directly and bypassed the update check
+ // This can happen if the user clicked Login quickly, before we heard
+ // back from the Viewer Version Manager, but login failed because
+ // login.cgi is insisting on a required update. We were called with an
+ // event that bundles both the login.cgi 'response' and the
+ // synchronization event from the 'updater'.
std::string required_version = response["message_args"]["VERSION"];
LL_WARNS("LLLogin") << "Login failed because an update to version " << required_version << " is required." << LL_ENDL;
if (gViewerWindow)
gViewerWindow->setShowProgress(FALSE);
- LLSD data(LLSD::emptyMap());
- data["VERSION"] = required_version;
- LLNotificationsUtil::add("RequiredUpdate", data, LLSD::emptyMap(), boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2));
+ LLSD args(LLSDMap("VERSION", required_version));
+ if (updater.isUndefined())
+ {
+ // If the updater failed to shake hands, better advise the user to
+ // download the update him/herself.
+ LLNotificationsUtil::add(
+ "RequiredUpdate",
+ args,
+ updater,
+ boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2));
+ }
+ else
+ {
+ // If we've heard from the updater that an update is required,
+ // then display the prompt that assures the user we'll take care
+ // of it. This is the one case in which we bind 'resp':
+ // instead of destroying our Response object (and thus sending a
+ // negative reply to the updater) as soon as we exit this
+ // function, bind our shared_ptr so it gets passed into
+ // syncWithUpdater. That ensures that the response is delayed
+ // until the user has responded to the notification.
+ LLNotificationsUtil::add(
+ "PauseForUpdate",
+ args,
+ updater,
+ boost::bind(&LLLoginInstance::syncWithUpdater, this, resp, _1, _2));
+ }
}
else if( reason_response == "key"
|| reason_response == "presence"
@@ -361,6 +394,19 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
}
}
+void LLLoginInstance::syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response)
+{
+ LL_INFOS("LLLogin") << "LLLoginInstance::syncWithUpdater" << LL_ENDL;
+ // 'resp' points to an instance of LLEventAPI::Response that will be
+ // destroyed as soon as we return and the notification response functor is
+ // unregistered. Modify it so that it tells the updater to go ahead and
+ // perform the update. Naturally, if we allowed the user a choice as to
+ // whether to proceed or not, this assignment would reflect the user's
+ // selection.
+ (*resp)["update"] = true;
+ attemptComplete();
+}
+
void LLLoginInstance::handleLoginDisallowed(const LLSD& notification, const LLSD& response)
{
attemptComplete();
@@ -420,7 +466,6 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
return true;
}
-
std::string construct_start_string()
{
std::string start;
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 651ad10afb..b759b43474 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -28,8 +28,10 @@
#define LL_LLLOGININSTANCE_H
#include "lleventdispatcher.h"
+#include "lleventapi.h"
#include <boost/scoped_ptr.hpp>
#include <boost/function.hpp>
+#include <memory> // std::shared_ptr
#include "llsecapi.h"
class LLLogin;
class LLEventStream;
@@ -68,6 +70,7 @@ public:
LLNotificationsInterface& getNotificationsInterface() const { return *mNotifications; }
private:
+ typedef std::shared_ptr<LLEventAPI::Response> ResponsePtr;
void constructAuthParams(LLPointer<LLCredential> user_credentials);
void updateApp(bool mandatory, const std::string& message);
bool updateDialogCallback(const LLSD& notification, const LLSD& response);
@@ -77,7 +80,8 @@ private:
void handleLoginSuccess(const LLSD& event);
void handleDisconnect(const LLSD& event);
void handleIndeterminate(const LLSD& event);
- void handleLoginDisallowed(const LLSD& notification, const LLSD& response);
+ void handleLoginDisallowed(const LLSD& notification, const LLSD& response);
+ void syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response);
bool handleTOSResponse(bool v, const std::string& key);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index cc02642203..b44d996558 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -480,8 +480,7 @@ bool idle_startup()
if (!found_template)
{
message_template_path =
- gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE,
- "../Resources/app_settings",
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
"message_template.msg");
found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
}
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index b039afa734..dd35ed4c71 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -770,14 +770,13 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
{
#ifndef VIVOXDAEMON_REMOTEHOST
// Launch the voice daemon
- std::string exe_path = gDirUtilp->getExecutableDir();
- exe_path += gDirUtilp->getDirDelimiter();
+ std::string exe_path = gDirUtilp->getAppRODataDir();
#if LL_WINDOWS
- exe_path += "SLVoice.exe";
+ gDirUtilp->append(exe_path, "SLVoice.exe");
#elif LL_DARWIN
- exe_path += "../Resources/SLVoice";
+ gDirUtilp->append(exe_path, "SLVoice");
#else
- exe_path += "SLVoice";
+ gDirUtilp->append(exe_path, "SLVoice");
#endif
// See if the vivox executable exists
llstat s;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 9eaa5330c3..e2859603e0 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3841,7 +3841,6 @@ Finished download of raw terrain file to:
name="RequiredUpdate"
type="alertmodal">
Version [VERSION] is required for login.
-This should have been updated for you but apparently was not.
Please download from https://secondlife.com/support/downloads/
<tag>confirm</tag>
<usetemplate
@@ -3851,6 +3850,44 @@ Please download from https://secondlife.com/support/downloads/
<notification
icon="alertmodal.tga"
+ name="PauseForUpdate"
+ type="alertmodal">
+Version [VERSION] is required for login.
+Click OK to download and install.
+ <tag>confirm</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OptionalUpdateReady"
+ type="alertmodal">
+Version [VERSION] has been downloaded and is ready to install.
+Click OK to install.
+ <tag>confirm</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PromptOptionalUpdate"
+ type="alertmodal">
+Version [VERSION] has been downloaded and is ready to install.
+Proceed?
+ <tag>confirm</tag>
+ <usetemplate
+ canceltext="Not Now"
+ name="yesnocancelbuttons"
+ notext="Skip"
+ yestext="Install"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="LoginFailedUnknown"
type="alertmodal">
Sorry, login failed for an unrecognized reason.
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 464f7aa3e9..57da87a3ee 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -26,20 +26,19 @@ 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 errno
-import json
+import sys
import os
import os.path
+import shutil
+import errno
+import json
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.
@@ -64,7 +63,7 @@ class ViewerManifest(LLManifest):
self.path(src="../../etc/message.xml", dst="app_settings/message.xml")
if self.is_packaging_viewer():
- with self.prefix(src_dst="app_settings"):
+ with self.prefix(src="app_settings"):
self.exclude("logcontrol.xml")
self.exclude("logcontrol-dev.xml")
self.path("*.ini")
@@ -86,7 +85,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):
+ with self.prefix(src=pkgdir,dst=""):
self.path("dictionaries")
# include the extracted packages information (see BuildPackagesInfo.cmake)
@@ -108,18 +107,17 @@ class ViewerManifest(LLManifest):
Type='String',
Value=''))
settings_install = {}
- sourceid = self.args.get('sourceid')
- if sourceid:
+ if 'sourceid' in self.args and self.args['sourceid']:
settings_install['sourceid'] = settings_template['sourceid'].copy()
- settings_install['sourceid']['Value'] = sourceid
- print "Set sourceid in settings_install.xml to '%s'" % sourceid
+ settings_install['sourceid']['Value'] = self.args['sourceid']
+ print "Set sourceid in settings_install.xml to '%s'" % self.args['sourceid']
- if self.args.get('channel_suffix'):
+ if 'channel_suffix' in self.args and self.args['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 self.args.get('grid'):
+ if 'grid' in self.args and self.args['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()
@@ -131,20 +129,20 @@ class ViewerManifest(LLManifest):
src="environment")
- with self.prefix(src_dst="character"):
+ with self.prefix(src="character"):
self.path("*.llm")
self.path("*.xml")
self.path("*.tga")
# Include our fonts
- with self.prefix(src_dst="fonts"):
+ with self.prefix(src="fonts"):
self.path("*.ttf")
self.path("*.txt")
# skins
- with self.prefix(src_dst="skins"):
+ with self.prefix(src="skins"):
# include the entire textures directory recursively
- with self.prefix(src_dst="*/textures"):
+ with self.prefix(src="*/textures"):
self.path("*/*.tga")
self.path("*/*.j2c")
self.path("*/*.jpg")
@@ -172,7 +170,7 @@ class ViewerManifest(LLManifest):
# local_assets dir (for pre-cached textures)
- with self.prefix(src_dst="local_assets"):
+ with self.prefix(src="local_assets"):
self.path("*.j2c")
self.path("*.tga")
@@ -188,10 +186,6 @@ class ViewerManifest(LLManifest):
"Address Size":self.address_size,
"Update Service":"https://update.secondlife.com/update",
}
- # Only store this if it's both present and non-empty
- bugsplat_db = self.args.get('bugsplat')
- if bugsplat_db:
- build_data_dict["BugSplat DB"] = bugsplat_db
build_data_dict = self.finish_build_data_dict(build_data_dict)
with open(os.path.join(os.pardir,'build_data.json'), 'w') as build_data_handle:
json.dump(build_data_dict,build_data_handle)
@@ -212,9 +206,8 @@ class ViewerManifest(LLManifest):
def channel_with_pkg_suffix(self):
fullchannel=self.channel()
- channel_suffix = self.args.get('channel_suffix')
- if channel_suffix:
- fullchannel+=' '+channel_suffix
+ if 'channel_suffix' in self.args and self.args['channel_suffix']:
+ fullchannel+=' '+self.args['channel_suffix']
return fullchannel
def channel_variant(self):
@@ -222,7 +215,8 @@ class ViewerManifest(LLManifest):
return self.channel().replace(CHANNEL_VENDOR_BASE, "").strip()
def channel_type(self): # returns 'release', 'beta', 'project', or 'test'
- channel_qualifier=self.channel_variant().lower()
+ global CHANNEL_VENDOR_BASE
+ channel_qualifier=self.channel().replace(CHANNEL_VENDOR_BASE, "").lower().strip()
if channel_qualifier.startswith('release'):
channel_type='release'
elif channel_qualifier.startswith('beta'):
@@ -240,12 +234,11 @@ 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 suffix:
- suffix = "_".join([''] + suffix.split())
+ if len(suffix) > 0:
+ suffix = "_"+ ("_".join(suffix.split()))
# the additional_packages mechanism adds more to the installer name (but not to the app name itself)
- # ''.split() produces empty list, so suffix only changes if
- # channel_suffix is non-empty
- suffix = "_".join([suffix] + self.args.get('channel_suffix', '').split())
+ if 'channel_suffix' in self.args and self.args['channel_suffix']:
+ suffix+='_'+("_".join(self.args['channel_suffix'].split()))
return suffix
def installer_base_name(self):
@@ -477,7 +470,7 @@ class WindowsManifest(ViewerManifest):
pass
except NoMatchingAssemblyException as err:
pass
-
+
self.ccopy(src,dst)
else:
raise Exception("Directories are not supported by test_CRT_and_copy_action()")
@@ -495,24 +488,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")):
+ with self.prefix(src=os.path.join(pkgdir, "VMP"), dst=""):
# include the compiled launcher scripts so that it gets included in the file_list
- self.path('SL_Launcher.exe')
+ self.path('updater.exe')
#IUM is not normally executed directly, just imported. No exe needed.
self.path("InstallerUserMessage.py")
- 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")
+ with self.prefix(src=self.icon_path(), dst="vmp_icons"):
+ self.path("secondlife.ico")
- #before, we only needed llbase at build time. With VMP, we need it at run time.
- with self.prefix(src=os.path.join(pkgdir, "lib", "python", "llbase"), dst="llbase"):
- self.path("*.py")
- self.path("_cllsd.so")
+ #VMP Tkinter icons
+ with self.prefix("vmp_icons"):
+ self.path("*.png")
+ self.path("*.gif")
# Plugin host application
self.path2basename(os.path.join(os.pardir,
@@ -520,8 +508,8 @@ class WindowsManifest(ViewerManifest):
"slplugin.exe")
# Get shared libs from the shared libs staging directory
- with self.prefix(src=os.path.join(self.args['build'], os.pardir,
- 'sharedlibs', self.args['configuration'])):
+ with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']),
+ dst=""):
# Get llcommon and deps. If missing assume static linkage and continue.
try:
@@ -587,17 +575,6 @@ class WindowsManifest(ViewerManifest):
# Hunspell
self.path("libhunspell.dll")
- # BugSplat
- if self.args.get('bugsplat'):
- if(self.address_size == 64):
- self.path("BsSndRpt64.exe")
- self.path("BugSplat64.dll")
- self.path("BugSplatRc64.dll")
- else:
- self.path("BsSndRpt.exe")
- self.path("BugSplat.dll")
- self.path("BugSplatRc.dll")
-
# For google-perftools tcmalloc allocator.
try:
if self.args['configuration'].lower() == 'debug':
@@ -607,116 +584,114 @@ class WindowsManifest(ViewerManifest):
except:
print "Skipping libtcmalloc_minimal.dll"
+
self.path(src="licenses-win32.txt", dst="licenses.txt")
self.path("featuretable.txt")
- with self.prefix(src=pkgdir):
+ with self.prefix(src=pkgdir,dst=""):
self.path("ca-bundle.crt")
# Media plugins - CEF
- with self.prefix(dst="llplugin"):
- with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins')):
- with self.prefix(src=os.path.join('cef', self.args['configuration'])):
- self.path("media_plugin_cef.dll")
-
- # Media plugins - LibVLC
- with self.prefix(src=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=os.path.join('example', self.args['configuration'])):
- self.path("media_plugin_example.dll")
-
- # CEF runtime files - debug
- # CEF runtime files - not debug (release, relwithdebinfo etc.)
- config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release'
- with self.prefix(src=os.path.join(pkgdir, 'bin', config)):
- 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(self.args['build'], os.pardir,
- 'sharedlibs', 'Release')):
- self.path("msvcp120.dll")
- self.path("msvcr120.dll")
-
- # CEF files common to all configurations
- with self.prefix(src=os.path.join(pkgdir, 'resources')):
- 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/")
+ 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"):
+ self.path("libvlc.dll")
+ self.path("libvlccore.dll")
+ self.path("plugins/")
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
@@ -788,7 +763,7 @@ class WindowsManifest(ViewerManifest):
substitution_strings['installer_file'] = installer_file
version_vars = """
- !define INSTEXE "SL_Launcher.exe"
+ !define INSTEXE "updater.exe"
!define VERSION "%(version_short)s"
!define VERSION_LONG "%(version)s"
!define VERSION_DASHES "%(version_dashes)s"
@@ -832,7 +807,7 @@ class WindowsManifest(ViewerManifest):
# note that the enclosing setup exe is signed later, after the makensis makes it.
# Unlike the viewer binary, the VMP filenames are invariant with respect to version, os, etc.
for exe in (
- "SL_Launcher.exe",
+ "updater.exe",
):
self.sign(exe)
@@ -899,431 +874,279 @@ class DarwinManifest(ViewerManifest):
# darwin requires full app bundle packaging even for debugging.
return True
- def is_rearranging(self):
- # That said, some stuff should still only be performed once.
- # Are either of these actions in 'actions'? Is the set intersection
- # non-empty?
- return bool(set(["package", "unpacked"]).intersection(self.args['actions']))
-
def construct(self):
- # These are the names of the top-level application and the embedded
- # applications for the VMP and for the actual viewer, respectively.
- # These names, without the .app suffix, determine the flyover text for
- # their corresponding Dock icons.
- toplevel_app = self.channel()+".app"
- toplevel_icon = "secondlife.icns"
- 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="")
+ self.path(os.path.join(self.args['configuration'], "Second Life.app"), dst="")
pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
relpkgdir = os.path.join(pkgdir, "lib", "release")
debpkgdir = os.path.join(pkgdir, "lib", "debug")
- # -------------------- top-level Second Life.app ---------------------
- # top-level Second Life application is only a container
- with self.prefix(dst="Contents"): # everything goes in Contents
- # top-level Info.plist is as generated by CMake
- Info_plist = self.dst_path_of("Info.plist")
-
- toplevel_MacOS = self.dst_path_of("MacOS")
- # the one file in top-level MacOS directory is the trampoline to
- # our nested launcher_app
- if not self.is_rearranging():
- trampoline = ""
- else:
- with self.prefix(dst="MacOS"):
- trampoline = self.put_in_file("""\
-#!/bin/bash
-open "%s" --args "$@"
-""" %
- # up one directory from MacOS to its sibling Resources directory
- os.path.join('$(dirname "$0")', os.pardir, 'Resources', launcher_app),
- "SL_Launcher", # write this file
- "trampoline") # flag to add to list of copied files
- # Script must be executable
- self.run_command(["chmod", "+x", trampoline])
-
- # Make a symlink to a nested app Frameworks directory that doesn't
- # yet exist. We shouldn't need this; the only things that need
- # Frameworks are nested apps under viewer_app, and they should
- # simply find its Contents/Frameworks by relative pathnames. But
- # empirically, we do: if we omit this symlink, CEF doesn't work --
- # the login splash screen doesn't even display. SIIIIGH.
- # We're passing a path that's already relative, hence symlinkf()
- # rather than relsymlinkf().
- self.symlinkf(os.path.join("Resources", viewer_app, "Contents", "Frameworks"))
+ with self.prefix(src="", dst="Contents"): # everything goes in Contents
+ # CEF framework goes inside Contents/Frameworks.
+ # Remember where we parked this car.
+ with self.prefix(src="", dst="Frameworks"):
+ CEF_framework = "Chromium Embedded Framework.framework"
+ self.path2basename(relpkgdir, CEF_framework)
+ CEF_framework = self.dst_path_of(CEF_framework)
+
+ with self.prefix(dst="MacOS"):
+ # NOTE: the -S argument to strip causes it to keep
+ # enough info for annotated backtraces (i.e. function
+ # names in the crash log). 'strip' with no arguments
+ # yields a slightly smaller binary but makes crash
+ # logs mostly useless. This may be desirable for the
+ # final release. Or not.
+ if ("package" in self.args['actions'] or
+ "unpacked" in self.args['actions']):
+ self.run_command(
+ ['strip', '-S', self.dst_path_of('Second Life')])
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()) :
- self.path(toplevel_icon)
-
- # ------------------- nested launcher_app --------------------
- with self.prefix(dst=os.path.join(launcher_app, "Contents")):
- # Info.plist is just like top-level one...
- Info = plistlib.readPlist(Info_plist)
- # except for these replacements:
- Info["CFBundleExecutable"] = "SL_Launcher"
- Info["CFBundleIconFile"] = launcher_icon
- self.put_in_file(
- plistlib.writePlistToString(Info),
- os.path.basename(Info_plist),
- "Info.plist")
-
- # copy VMP libs to MacOS
- with self.prefix(dst="MacOS"):
- #this copies over the python wrapper script,
- #associated utilities and required libraries, see
- #SL-321, SL-322, SL-323
- with self.prefix(src=os.path.join(pkgdir, "VMP")):
- 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")):
- # llbase provides our llrest service layer and llsd decoding
- 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")
- self.path("_cllsd.so")
- #requests module needed by llbase/llrest.py
- #this is only needed on POSIX, because in Windows
- #we compile it into the EXE
- for pypkg in "chardet", "idna", "requests", "urllib3":
- self.path(pypkg)
-
- # launcher_app/Contents/Resources
- with self.prefix(dst="Resources"):
- 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(src_dst="vmp_icons"):
- self.path("*.png")
- self.path("*.gif")
-
- # -------------------- nested viewer_app ---------------------
- with self.prefix(dst=os.path.join(viewer_app, "Contents")):
- # 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
- # Life.app. Move it here.
- here = self.get_dst_prefix()
- relbase = os.path.realpath(os.path.dirname(Info_plist))
- self.cmakedirs(here)
- for f in os.listdir(toplevel_MacOS):
- if f == os.path.basename(trampoline):
- # don't move the trampoline script we just made!
- continue
- fromwhere = os.path.join(toplevel_MacOS, f)
- towhere = self.dst_path_of(f)
- fromrel = self.relpath(fromwhere, relbase)
- torel = self.relpath(towhere, relbase)
- if not self.is_rearranging():
- print "Not yet moving {} => {}".format(fromrel, torel)
- else:
- print "Moving {} => {}".format(fromrel, torel)
- # now do it, only without relativizing paths
- os.rename(fromwhere, towhere)
-
- # If we haven't yet moved executables, find our viewer
- # executable where it was linked, in toplevel_MacOS.
- # If we have, find it here.
- whichdir = here if self.is_rearranging() else toplevel_MacOS
- # 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(whichdir, name))
- for name in os.listdir(whichdir)))[-1]
-
- if self.is_rearranging():
- # 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', 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
- bugsplat_db = self.args.get('bugsplat')
- if bugsplat_db:
- # https://www.bugsplat.com/docs/platforms/os-x#configuration
- Info["BugsplatServerURL"] = \
- "https://{}.bugsplat.com/".format(bugsplat_db)
- self.put_in_file(
- plistlib.writePlistToString(Info),
- os.path.basename(Info_plist),
- "Info.plist")
-
- with self.prefix(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)
-
- if self.args.get('bugsplat'):
- self.path2basename(relpkgdir, "BugsplatMac.framework")
-
- with self.prefix(dst="Resources"):
- # defer cross-platform file copies until we're in the right
- # nested Resources directory
- super(DarwinManifest, self).construct()
-
- with self.prefix(src=self.icon_path()) :
- self.path(viewer_icon)
-
- with self.prefix(src=relpkgdir):
- self.path("libndofdev.dylib")
- self.path("libhunspell-1.3.0.dylib")
-
- 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):
- self.path("ca-bundle.crt")
-
- self.path("SecondLife.nib")
-
- # Translations
- self.path("English.lproj/language.txt")
- self.replace_in(src="English.lproj/InfoPlist.strings",
- dst="English.lproj/InfoPlist.strings",
- searchdict={'%%VERSION%%':'.'.join(self.args['version'])}
- )
- self.path("German.lproj")
- self.path("Japanese.lproj")
- self.path("Korean.lproj")
- self.path("da.lproj")
- self.path("es.lproj")
- self.path("fr.lproj")
- self.path("hu.lproj")
- self.path("it.lproj")
- self.path("nl.lproj")
- self.path("pl.lproj")
- self.path("pt.lproj")
- self.path("ru.lproj")
- self.path("tr.lproj")
- self.path("uk.lproj")
- self.path("zh-Hans.lproj")
-
- def path_optional(src, dst):
- """
- For a number of our self.path() calls, not only do we want
- to deal with the absence of src, we also want to remember
- which were present. Return either an empty list (absent)
- or a list containing dst (present). Concatenate these
- return values to get a list of all libs that are present.
- """
- # This was simple before we started needing to pass
- # wildcards. Fortunately, self.path() ends up appending a
- # (source, dest) pair to self.file_list for every expanded
- # file processed. Remember its size before the call.
- oldlen = len(self.file_list)
- self.path(src, dst)
- # The dest appended to self.file_list has been prepended
- # with self.get_dst_prefix(). Strip it off again.
- added = [os.path.relpath(d, self.get_dst_prefix())
- for s, d in self.file_list[oldlen:]]
- if not added:
- print "Skipping %s" % dst
- return added
-
- # dylibs is a list of all the .dylib files we expect to need
- # in our bundled sub-apps. For each of these we'll create a
- # symlink from sub-app/Contents/Resources to the real .dylib.
- # Need to get the llcommon dll from any of the build directories as well.
- libfile_parent = self.get_dst_prefix()
- libfile = "libllcommon.dylib"
- dylibs = path_optional(self.find_existing_file(os.path.join(os.pardir,
- "llcommon",
- self.args['configuration'],
- libfile),
- os.path.join(relpkgdir, libfile)),
- dst=libfile)
-
- for libfile in (
- "libapr-1.0.dylib",
- "libaprutil-1.0.dylib",
- "libcollada14dom.dylib",
- "libexpat.1.dylib",
- "libexception_handler.dylib",
- "libGLOD.dylib",
- # libnghttp2.dylib is a symlink to
- # libnghttp2.major.dylib, which is a symlink to
- # libnghttp2.version.dylib. Get all of them.
- "libnghttp2.*dylib",
- ):
- dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
-
- # SLVoice and vivox lols, no symlinks needed
- for libfile in (
- 'libortp.dylib',
- 'libsndfile.dylib',
- 'libvivoxoal.dylib',
- 'libvivoxsdk.dylib',
- 'libvivoxplatform.dylib',
- 'SLVoice',
- ):
- self.path2basename(relpkgdir, libfile)
-
- # dylibs that vary based on configuration
- if self.args['configuration'].lower() == 'debug':
- for libfile in (
- "libfmodexL.dylib",
- ):
- dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile)
- else:
- for libfile in (
- "libfmodex.dylib",
- ):
- dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
-
- # our apps
- executable_path = {}
- for app_bld_dir, app in (
- ("mac_crash_logger", "mac-crash-logger.app"),
- # plugin launcher
- (os.path.join("llplugin", "slplugin"), "SLPlugin.app"),
- ):
- self.path2basename(
- os.path.join(os.pardir, app_bld_dir, self.args['configuration']),
- app)
- executable_path[app] = \
- self.dst_path_of(os.path.join(app, "Contents", "MacOS"))
-
- # our apps dependencies on shared libs
- # for each app, for each dylib we collected in dylibs,
- # create a symlink to the real copy of the dylib.
- with self.prefix(dst=os.path.join(app, "Contents", "Resources")):
- for libfile in dylibs:
- self.relsymlinkf(os.path.join(libfile_parent, libfile))
-
- # Dullahan helper apps go inside SLPlugin.app
- with self.prefix(dst=os.path.join(
- "SLPlugin.app", "Contents", "Frameworks")):
-
- frameworkname = 'Chromium Embedded Framework'
-
- # This code constructs a relative symlink from the
- # target framework folder back to the real CEF framework.
- # It needs to be relative so that the symlink still works when
- # (as is normal) the user moves the app bundle out of the DMG
- # and into the /Applications folder. Note we pass catch=False,
- # letting the uncaught exception terminate the process, since
- # without this symlink, Second Life web media can't possibly work.
-
- # It might seem simpler just to symlink Frameworks back to
- # the parent of Chromimum Embedded Framework.framework. But
- # that would create a symlink cycle, which breaks our
- # packaging step. So make a symlink from Chromium Embedded
- # Framework.framework to the directory of the same name, which
- # is NOT an ancestor of the symlink.
-
- # from SLPlugin.app/Contents/Frameworks/Chromium Embedded
- # Framework.framework back to
- # $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework
- SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False)
-
- # copy DullahanHelper.app
- self.path2basename(relpkgdir, 'DullahanHelper.app')
-
- # and fix that up with a Frameworks/CEF symlink too
- with self.prefix(dst=os.path.join(
- 'DullahanHelper.app', 'Contents', 'Frameworks')):
- # from Dullahan Helper.app/Contents/Frameworks/Chromium Embedded
- # Framework.framework back to
- # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework
- # Since SLPlugin_framework is itself a
- # symlink, don't let relsymlinkf() resolve --
- # explicitly call relpath(symlink=True) and
- # create that symlink here.
- DullahanHelper_framework = \
- self.symlinkf(self.relpath(SLPlugin_framework, symlink=True),
- catch=False)
-
- # change_command includes install_name_tool, the
- # -change subcommand and the old framework rpath
- # stamped into the executable. To use it with
- # run_command(), we must still append the new
- # framework path and the pathname of the
- # executable to change.
- change_command = [
- 'install_name_tool', '-change',
- '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework']
-
- with self.prefix(dst=os.path.join(
- 'DullahanHelper.app', 'Contents', 'MacOS')):
- # Now self.get_dst_prefix() is, at runtime,
- # @executable_path. Locate the helper app
- # framework (which is a symlink) from here.
- newpath = os.path.join(
- '@executable_path',
- self.relpath(DullahanHelper_framework, symlink=True),
- frameworkname)
- # and restamp the DullahanHelper executable
- self.run_command(
- change_command +
- [newpath, self.dst_path_of('DullahanHelper')])
-
- # SLPlugin plugins
- with self.prefix(dst="llplugin"):
- dylibexecutable = 'media_plugin_cef.dylib'
- self.path2basename("../media_plugins/cef/" + self.args['configuration'],
- dylibexecutable)
-
- # Do this install_name_tool *after* media plugin is copied over.
- # Locate the framework lib executable -- relative to
- # SLPlugin.app/Contents/MacOS, which will be our
- # @executable_path at runtime!
- newpath = os.path.join(
- '@executable_path',
- self.relpath(SLPlugin_framework, executable_path["SLPlugin.app"],
- symlink=True),
- frameworkname)
- # restamp media_plugin_cef.dylib
- self.run_command(
- change_command +
- [newpath, self.dst_path_of(dylibexecutable)])
-
- # copy LibVLC plugin itself
- self.path2basename("../media_plugins/libvlc/" + self.args['configuration'],
- "media_plugin_libvlc.dylib")
-
- # copy LibVLC dynamic libraries
- with self.prefix(src=relpkgdir, dst="lib"):
- self.path( "libvlc*.dylib*" )
- # copy LibVLC plugins folder
- with self.prefix(src='plugins'):
- self.path( "*.dylib" )
- self.path( "plugins.dat" )
+ # defer cross-platform file copies until we're in the
+ # nested Resources directory
+ super(DarwinManifest, self).construct()
+
+ # need .icns file referenced by Info.plist
+ with self.prefix(src=self.icon_path(), dst="") :
+ self.path("secondlife.icns")
+
+ # Copy in the updater script and helper modules
+ self.path(src=os.path.join(pkgdir, 'VMP'), dst="updater")
+
+ with self.prefix(src="", dst=os.path.join("updater", "icons")):
+ self.path2basename(self.icon_path(), "secondlife.ico")
+ with self.prefix(src="vmp_icons", dst=""):
+ self.path("*.png")
+ self.path("*.gif")
+
+ with self.prefix(src=relpkgdir, dst=""):
+ self.path("libndofdev.dylib")
+ self.path("libhunspell-1.3.0.dylib")
+
+ with self.prefix("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=""):
+ self.path("ca-bundle.crt")
+
+ self.path("SecondLife.nib")
+
+ # Translations
+ self.path("English.lproj/language.txt")
+ self.replace_in(src="English.lproj/InfoPlist.strings",
+ dst="English.lproj/InfoPlist.strings",
+ searchdict={'%%VERSION%%':'.'.join(self.args['version'])}
+ )
+ self.path("German.lproj")
+ self.path("Japanese.lproj")
+ self.path("Korean.lproj")
+ self.path("da.lproj")
+ self.path("es.lproj")
+ self.path("fr.lproj")
+ self.path("hu.lproj")
+ self.path("it.lproj")
+ self.path("nl.lproj")
+ self.path("pl.lproj")
+ self.path("pt.lproj")
+ self.path("ru.lproj")
+ self.path("tr.lproj")
+ self.path("uk.lproj")
+ self.path("zh-Hans.lproj")
+
+ def path_optional(src, dst):
+ """
+ For a number of our self.path() calls, not only do we want
+ to deal with the absence of src, we also want to remember
+ which were present. Return either an empty list (absent)
+ or a list containing dst (present). Concatenate these
+ return values to get a list of all libs that are present.
+ """
+ # This was simple before we started needing to pass
+ # wildcards. Fortunately, self.path() ends up appending a
+ # (source, dest) pair to self.file_list for every expanded
+ # file processed. Remember its size before the call.
+ oldlen = len(self.file_list)
+ self.path(src, dst)
+ # The dest appended to self.file_list has been prepended
+ # with self.get_dst_prefix(). Strip it off again.
+ added = [os.path.relpath(d, self.get_dst_prefix())
+ for s, d in self.file_list[oldlen:]]
+ if not added:
+ print "Skipping %s" % dst
+ return added
+
+ # dylibs is a list of all the .dylib files we expect to need
+ # in our bundled sub-apps. For each of these we'll create a
+ # symlink from sub-app/Contents/Resources to the real .dylib.
+ # Need to get the llcommon dll from any of the build directories as well.
+ libfile_parent = self.get_dst_prefix()
+ libfile = "libllcommon.dylib"
+ dylibs = path_optional(self.find_existing_file(os.path.join(os.pardir,
+ "llcommon",
+ self.args['configuration'],
+ libfile),
+ os.path.join(relpkgdir, libfile)),
+ dst=libfile)
+
+ for libfile in (
+ "libapr-1.0.dylib",
+ "libaprutil-1.0.dylib",
+ "libcollada14dom.dylib",
+ "libexpat.1.dylib",
+ "libexception_handler.dylib",
+ "libGLOD.dylib",
+ # libnghttp2.dylib is a symlink to
+ # libnghttp2.major.dylib, which is a symlink to
+ # libnghttp2.version.dylib. Get all of them.
+ "libnghttp2.*dylib",
+ ):
+ dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
+
+ # SLVoice and vivox lols, no symlinks needed
+ for libfile in (
+ 'libortp.dylib',
+ 'libsndfile.dylib',
+ 'libvivoxoal.dylib',
+ 'libvivoxsdk.dylib',
+ 'libvivoxplatform.dylib',
+ 'SLVoice',
+ ):
+ self.path2basename(relpkgdir, libfile)
+
+ # dylibs that vary based on configuration
+ if self.args['configuration'].lower() == 'debug':
+ for libfile in (
+ "libfmodexL.dylib",
+ ):
+ dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile)
+ else:
+ for libfile in (
+ "libfmodex.dylib",
+ ):
+ dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile)
+
+ # our apps
+ executable_path = {}
+ for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),
+ # plugin launcher
+ (os.path.join("llplugin", "slplugin"), "SLPlugin.app"),
+ ):
+ self.path2basename(os.path.join(os.pardir,
+ app_bld_dir, self.args['configuration']),
+ app)
+ executable_path[app] = \
+ self.dst_path_of(os.path.join(app, "Contents", "MacOS"))
+
+ # our apps dependencies on shared libs
+ # for each app, for each dylib we collected in dylibs,
+ # create a symlink to the real copy of the dylib.
+ with self.prefix(dst=os.path.join(app, "Contents", "Resources")):
+ for libfile in dylibs:
+ self.relsymlinkf(os.path.join(libfile_parent, libfile))
+
+ # Dullahan helper apps go inside SLPlugin.app
+ with self.prefix(dst=os.path.join(
+ "SLPlugin.app", "Contents", "Frameworks")):
+
+ frameworkname = 'Chromium Embedded Framework'
+
+ # This code constructs a relative symlink from the
+ # target framework folder back to the real CEF framework.
+ # It needs to be relative so that the symlink still works when
+ # (as is normal) the user moves the app bundle out of the DMG
+ # and into the /Applications folder. Note we pass catch=False,
+ # letting the uncaught exception terminate the process, since
+ # without this symlink, Second Life web media can't possibly work.
+
+ # It might seem simpler just to symlink Frameworks back to
+ # the parent of Chromimum Embedded Framework.framework. But
+ # that would create a symlink cycle, which breaks our
+ # packaging step. So make a symlink from Chromium Embedded
+ # Framework.framework to the directory of the same name, which
+ # is NOT an ancestor of the symlink.
+
+ # from SLPlugin.app/Contents/Frameworks/Chromium Embedded
+ # Framework.framework back to
+ # $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework
+ SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False)
+
+ # copy DullahanHelper.app
+ self.path2basename(relpkgdir, 'DullahanHelper.app')
+
+ # and fix that up with a Frameworks/CEF symlink too
+ with self.prefix(dst=os.path.join(
+ 'DullahanHelper.app', 'Contents', 'Frameworks')):
+ # from Dullahan Helper.app/Contents/Frameworks/Chromium Embedded
+ # Framework.framework back to
+ # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework
+ # Since SLPlugin_framework is itself a
+ # symlink, don't let relsymlinkf() resolve --
+ # explicitly call relpath(symlink=True) and
+ # create that symlink here.
+ DullahanHelper_framework = \
+ self.symlinkf(self.relpath(SLPlugin_framework, symlink=True),
+ catch=False)
+
+ # change_command includes install_name_tool, the
+ # -change subcommand and the old framework rpath
+ # stamped into the executable. To use it with
+ # run_command(), we must still append the new
+ # framework path and the pathname of the
+ # executable to change.
+ change_command = [
+ 'install_name_tool', '-change',
+ '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework']
+
+ with self.prefix(dst=os.path.join(
+ 'DullahanHelper.app', 'Contents', 'MacOS')):
+ # Now self.get_dst_prefix() is, at runtime,
+ # @executable_path. Locate the helper app
+ # framework (which is a symlink) from here.
+ newpath = os.path.join(
+ '@executable_path',
+ self.relpath(DullahanHelper_framework, symlink=True),
+ frameworkname)
+ # and restamp the DullahanHelper executable
+ self.run_command(
+ change_command +
+ [newpath, self.dst_path_of('DullahanHelper')])
+
+ # SLPlugin plugins
+ with self.prefix(dst="llplugin"):
+ dylibexecutable = 'media_plugin_cef.dylib'
+ self.path2basename("../media_plugins/cef/" + self.args['configuration'],
+ dylibexecutable)
+
+ # Do this install_name_tool *after* media plugin is copied over.
+ # Locate the framework lib executable -- relative to
+ # SLPlugin.app/Contents/MacOS, which will be our
+ # @executable_path at runtime!
+ newpath = os.path.join(
+ '@executable_path',
+ self.relpath(SLPlugin_framework, executable_path["SLPlugin.app"],
+ symlink=True),
+ frameworkname)
+ # restamp media_plugin_cef.dylib
+ self.run_command(
+ change_command +
+ [newpath, self.dst_path_of(dylibexecutable)])
+
+ # copy LibVLC plugin itself
+ self.path2basename("../media_plugins/libvlc/" + self.args['configuration'],
+ "media_plugin_libvlc.dylib")
+
+ # copy LibVLC dynamic libraries
+ with self.prefix(src=relpkgdir, dst="lib"):
+ self.path( "libvlc*.dylib*" )
+ # copy LibVLC plugins folder
+ with self.prefix(src='plugins', dst=""):
+ self.path( "*.dylib" )
+ self.path( "plugins.dat" )
def package_finish(self):
global CHANNEL_VENDOR_BASE
@@ -1472,10 +1295,35 @@ open "%s" --args "$@"
else:
print >> sys.stderr, "Maximum codesign attempts exceeded; giving up"
raise
- self.run_command(['spctl', '-a', '-texec', '-vv', app_in_dmg])
-
- imagename="SecondLife_" + '_'.join(self.args['version'])
-
+ print 72*'='
+ import stat
+ print app_in_dmg
+ # Second Life.app
+ for sub0 in os.listdir(app_in_dmg):
+ print '--{}'.format(sub0)
+ path0 = os.path.join(app_in_dmg, sub0)
+ if os.path.isfile(path0):
+ # shouldn't be any file here
+ with open(path0) as inf:
+ for line in inf:
+ print ' {}'.format(line.rstrip())
+ elif os.path.isdir(path0):
+ # Contents
+ for sub1 in os.listdir(path0):
+ print '----{}'.format(sub1)
+ path1 = os.path.join(path0, sub1)
+ if os.path.isfile(path1):
+ # Info.plist, PkgInfo
+ with open(path1) as inf:
+ for line in inf:
+ print ' {}'.format(line.rstrip())
+ elif os.path.isdir(path1):
+ # Frameworks, MacOS, Resources
+ for sub2 in os.listdir(path1):
+ path2 = os.path.join(path1, sub2)
+ print ' {:04o} {}'.format(stat.S_IMODE(os.stat(path2).st_mode), sub2)
+ print 72*'='
+ self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg])
finally:
# Unmount the image even if exceptions from any of the above
@@ -1514,29 +1362,25 @@ class LinuxManifest(ViewerManifest):
debpkgdir = os.path.join(pkgdir, "lib", "debug")
self.path("licenses-linux.txt","licenses.txt")
- with self.prefix("linux_tools"):
+ with self.prefix("linux_tools", dst=""):
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(dst="etc"):
+ with self.prefix(src="", 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(dst="bin"):
+ with self.prefix(src="", dst="bin"):
self.path("secondlife-bin","do-not-directly-run-secondlife-bin")
self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
self.path2basename("../llplugin/slplugin", "SLPlugin")
#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"):
- self.path("SL_Launcher")
+ with self.prefix(src="../viewer_components/manager", dst=""):
self.path("*.py")
- with self.prefix(src=os.path.join("lib", "python", "llbase"), dst="llbase"):
- self.path("*.py")
- self.path("_cllsd.so")
# recurses, packaged again
self.path("res-sdl")
@@ -1544,9 +1388,9 @@ class LinuxManifest(ViewerManifest):
# Get the icons based on the channel type
icon_path = self.icon_path()
print "DEBUG: icon_path '%s'" % icon_path
- with self.prefix(src=icon_path) :
+ with self.prefix(src=icon_path, dst="") :
self.path("secondlife_256.png","secondlife_icon.png")
- with self.prefix(dst="res-sdl") :
+ with self.prefix(src="",dst="res-sdl") :
self.path("secondlife_256.BMP","ll_icon.BMP")
# plugins
@@ -1568,7 +1412,7 @@ class LinuxManifest(ViewerManifest):
self.path("featuretable_linux.txt")
- with self.prefix(src=pkgdir):
+ with self.prefix(src=pkgdir,dst=""):
self.path("ca-bundle.crt")
def package_finish(self):
@@ -1611,7 +1455,7 @@ class LinuxManifest(ViewerManifest):
self.run_command(
["find"] +
[os.path.join(self.get_dst_prefix(), dir) for dir in ('bin', 'lib')] +
- ['-type', 'f', '!', '-name', '*.py', '!', '-name', 'SL_Launcher',
+ ['-type', 'f', '!', '-name', '*.py',
'!', '-name', 'update_install', '-exec', 'strip', '-S', '{}', ';'])
class Linux_i686_Manifest(LinuxManifest):
@@ -1624,7 +1468,7 @@ class Linux_i686_Manifest(LinuxManifest):
relpkgdir = os.path.join(pkgdir, "lib", "release")
debpkgdir = os.path.join(pkgdir, "lib", "debug")
- with self.prefix(src=relpkgdir, dst="lib"):
+ with self.prefix(relpkgdir, dst="lib"):
self.path("libapr-1.so")
self.path("libapr-1.so.0")
self.path("libapr-1.so.0.4.5")
@@ -1710,8 +1554,4 @@ class Linux_x86_64_Manifest(LinuxManifest):
################################################################
if __name__ == "__main__":
- extra_arguments = [
- dict(name='bugsplat', description="""BugSplat database to which to post crashes,
- if BugSplat crash reporting is desired""", default=''),
- ]
- main(extra=extra_arguments)
+ main()
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index c767d52c7b..9193d32b49 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -128,6 +128,15 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL;
}
+namespace {
+// Instantiate this rendezvous point at namespace scope so it's already
+// present no matter how early the updater might post to it.
+// Use an LLEventMailDrop, which has future-like semantics: regardless of the
+// relative order in which post() or listen() are called, it delivers each
+// post() event to its listener(s) until one of them consumes that event.
+static LLEventMailDrop sSyncPoint("LoginSync");
+}
+
void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
{
LLSD printable_params = login_params;
@@ -219,7 +228,44 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
}
else
{
- sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+ // Synchronize here with the updater. We synchronize here rather
+ // than in the fail.login handler, which actually examines the
+ // response from login.cgi, because here we are definitely in a
+ // coroutine and can definitely use suspendUntilBlah(). Whoever's
+ // listening for fail.login might not be.
+
+ // If the reason for login failure is that we must install a
+ // required update, we definitely want to pass control to the
+ // updater to manage that for us. We'll handle any other login
+ // failure ourselves, as usual. We figure that no matter where you
+ // are in the world, or what kind of network you're on, we can
+ // reasonably expect the Viewer Version Manager to respond more or
+ // less as quickly as login.cgi. This synchronization is only
+ // intended to smooth out minor races between the two services.
+ // But what if the updater crashes? Use a timeout so that
+ // eventually we'll tire of waiting for it and carry on as usual.
+ // Given the above, it can be a fairly short timeout, at least
+ // from a human point of view.
+
+ // Since sSyncPoint is an LLEventMailDrop, we DEFINITELY want to
+ // consume the posted event.
+ LLCoros::OverrideConsuming oc(true);
+ // Timeout should produce the isUndefined() object passed here.
+ LL_DEBUGS("LLLogin") << "Login failure, waiting for sync from updater" << LL_ENDL;
+ LLSD updater = llcoro::suspendUntilEventOnWithTimeout(sSyncPoint, 10, LLSD());
+ if (updater.isUndefined())
+ {
+ LL_WARNS("LLLogin") << "Failed to hear from updater, proceeding with fail.login"
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("LLLogin") << "Got responses from updater and login.cgi" << LL_ENDL;
+ }
+ // Let the fail.login handler deal with empty updater response.
+ LLSD responses(mAuthResponse["responses"]);
+ responses["updater"] = updater;
+ sendProgressEvent("offline", "fail.login", responses);
}
return; // Done!
}
@@ -249,10 +295,10 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
// llsd with no "responses" node. To make the output from an incomplete login symmetrical
// to success, add a data/message and data/reason fields.
- LLSD error_response;
- error_response["reason"] = mAuthResponse["status"];
- error_response["errorcode"] = mAuthResponse["errorcode"];
- error_response["message"] = mAuthResponse["error"];
+ LLSD error_response(LLSDMap
+ ("reason", mAuthResponse["status"])
+ ("errorcode", mAuthResponse["errorcode"])
+ ("message", mAuthResponse["error"]));
if(mAuthResponse.has("certificate"))
{
error_response["certificate"] = mAuthResponse["certificate"];