diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 57788f60992e8fc834c7c0d9f98d4ea0031e93b4..4bc70b2ca4106c67fde86440317e9fa406dd45bc 100755
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -27,6 +27,7 @@
 $/LicenseInfo$
 """
 
+from collections import namedtuple, defaultdict
 import commands
 import errno
 import filecmp
@@ -312,6 +313,8 @@ def __init__(cls, name, bases, dct):
         if match:
            cls.manifests[match.group(1).lower()] = cls
 
+MissingFile = namedtuple("MissingFile", ("pattern", "tried"))
+
 class LLManifest(object):
     __metaclass__ = LLManifestRegistry
     manifests = {}
@@ -333,7 +336,8 @@ def __init__(self, args):
         self.dst_prefix = [args['dest']]
         self.created_paths = []
         self.package_name = "Unknown"
-        
+        self.missing = []
+
     def default_channel(self):
         return self.args.get('channel', None) == RELEASE_CHANNEL
 
@@ -592,6 +596,40 @@ def copy_action(self, src, dst):
     def package_action(self, src, dst):
         pass
 
+    def finish(self):
+        """
+        generic finish, always called before the ${action}_finish() methods
+        """
+        # Collecting MissingFile instances in self.missing, and checking that
+        # here, is intended to minimize the number of (potentially lengthy)
+        # build cycles a developer must run in order to fix missing-files
+        # errors. The manifest processing is necessarily the last step in a
+        # build, and if we only caught a single missing file error per run,
+        # the developer would need to run a build for each additional missing-
+        # file error until all were resolved. This way permits the developer
+        # to resolve them all at once.
+        if self.missing:
+            print '*' * 72
+            print "Missing files:"
+            # Instead of just dumping each missing file and all the places we
+            # looked for it, group by common sets of places we looked. Use a
+            # set to store the 'tried' directories, to avoid mismatches due to
+            # reordering -- but since we intend to use the set of 'tried'
+            # directories as a dict key, it must be a frozenset.
+            organize = defaultdict(set)
+            for missingfile in self.missing:
+                organize[frozenset(missingfile.tried)].add(missingfile.pattern)
+            # Now dump all the patterns sought in each group of 'tried'
+            # directories.
+            for tried, patterns in organize.items():
+                print "  Could not find in:"
+                for dir in sorted(tried):
+                    print "    %s" % dir
+                for pattern in sorted(patterns):
+                    print "      %s" % pattern
+            print '*' * 72
+            raise MissingError('%s patterns could not be found' % len(self.missing))
+
     def copy_finish(self):
         pass
 
@@ -825,18 +863,23 @@ def try_path(src):
             return count
 
         try_prefixes = [self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix()]
-        tried=[]
-        count=0
-        while not count and try_prefixes: 
-            pfx = try_prefixes.pop(0)
+        for pfx in try_prefixes:
             try:
                 count = try_path(os.path.join(pfx, src))
             except MissingError:
-                tried.append(pfx)
-                if not try_prefixes:
-                    # no more prefixes left to try
-                    raise MissingError("unable to find '%s'; looked in:\n  %s" % (src, '\n  '.join(tried)))
-                    
+                # if we produce MissingError, just try the next prefix
+                continue
+            # If we actually found nonzero files, stop looking
+            if count:
+                break
+        else:
+            # no more prefixes left to try
+            print("\nunable to find '%s'; looked in:\n  %s" % (src, '\n  '.join(try_prefixes)))
+            self.missing.append(MissingFile(pattern=src, tried=try_prefixes))
+            # At this point 'count' might never have been successfully
+            # assigned! Even if it was, though, we can be sure it is 0.
+            return 0
+
         print "%d files" % count
 
         # Let caller check whether we processed as many files as expected. In
@@ -847,6 +890,8 @@ def do(self, *actions):
         self.actions = actions
         self.construct()
         # perform finish actions
+        # generic finish first
+        self.finish()
         for action in self.actions:
             methodname = action + "_finish"
             method = getattr(self, methodname, None)
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 3f6a7124a405f83dcafe22fcf395cd7b91995ee9..9976c49ca51c482656c3cd8c8ecc0e7c987d9cd0 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -145,13 +145,10 @@ def construct(self):
             with self.prefix(src_dst="skins"):
                     # include the entire textures directory recursively
                     with self.prefix(src_dst="*/textures"):
-                            self.path("*/*.tga")
-                            self.path("*/*.j2c")
                             self.path("*/*.jpg")
                             self.path("*/*.png")
                             self.path("*.tga")
                             self.path("*.j2c")
-                            self.path("*.jpg")
                             self.path("*.png")
                             self.path("textures.xml")
                     self.path("*/xui/*/*.xml")
@@ -171,11 +168,6 @@ def construct(self):
                             self.path("*/*/*.gif")
 
 
-            # local_assets dir (for pre-cached textures)
-            with self.prefix(src_dst="local_assets"):
-                self.path("*.j2c")
-                self.path("*.tga")
-
             #build_data.json.  Standard with exception handling is fine.  If we can't open a new file for writing, we have worse problems
             #platform is computed above with other arg parsing
             build_data_dict = {"Type":"viewer","Version":'.'.join(self.args['version']),
@@ -514,17 +506,6 @@ def construct(self):
         with self.prefix(src=os.path.join(self.args['build'], os.pardir,
                                           'sharedlibs', self.args['configuration'])):
 
-            # Get llcommon and deps. If missing assume static linkage and continue.
-            try:
-                self.path('llcommon.dll')
-                self.path('libapr-1.dll')
-                self.path('libaprutil-1.dll')
-                self.path('libapriconv-1.dll')
-                
-            except MissingError as err:
-                print err.message
-                print "Skipping llcommon.dll (assuming llcommon was linked statically)"
-
             # Mesh 3rd party libs needed for auto LOD and collada reading
             try:
                 self.path("glod.dll")
@@ -549,13 +530,9 @@ def construct(self):
             if self.args['configuration'].lower() == 'debug':
                 self.path("msvcr120d.dll")
                 self.path("msvcp120d.dll")
-                self.path("msvcr100d.dll")
-                self.path("msvcp100d.dll")
             else:
                 self.path("msvcr120.dll")
                 self.path("msvcp120.dll")
-                self.path("msvcr100.dll")
-                self.path("msvcp100.dll")
 
             # Vivox runtimes
             self.path("SLVoice.exe")
@@ -565,8 +542,6 @@ def construct(self):
             else:
                 self.path("vivoxsdk.dll")
                 self.path("ortp.dll")
-            self.path("libsndfile-1.dll")
-            self.path("vivoxoal.dll")
             
             # Security
             self.path("ssleay32.dll")
@@ -589,15 +564,6 @@ def construct(self):
                     self.path("BugSplat.dll")
                     self.path("BugSplatRc.dll")
 
-            # For google-perftools tcmalloc allocator.
-            try:
-                if self.args['configuration'].lower() == 'debug':
-                    self.path('libtcmalloc_minimal-debug.dll')
-                else:
-                    self.path('libtcmalloc_minimal.dll')
-            except:
-                print "Skipping libtcmalloc_minimal.dll"
-
         self.path(src="licenses-win32.txt", dst="licenses.txt")
         self.path("featuretable.txt")