Decouple strutil from C++ lite library for a further 23k reduction.
diff --git a/src/Makefile.am b/src/Makefile.am
index 2bc2aad..cd832b2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,10 +83,6 @@
   google/protobuf/stubs/map-util.h                             \
   google/protobuf/stubs/stl_util-inl.cc                        \
   google/protobuf/stubs/stl_util-inl.h                         \
-  google/protobuf/stubs/strutil.cc                             \
-  google/protobuf/stubs/strutil.h                              \
-  google/protobuf/stubs/substitute.cc                          \
-  google/protobuf/stubs/substitute.h                           \
   google/protobuf/extension_set.cc                             \
   google/protobuf/generated_message_util.cc                    \
   google/protobuf/message_lite.cc                              \
@@ -100,6 +96,10 @@
 libprotobuf_la_LDFLAGS = -version-info 3:0:0
 libprotobuf_la_SOURCES =                                       \
   $(libprotobuf_lite_la_SOURCES)                               \
+  google/protobuf/stubs/strutil.cc                             \
+  google/protobuf/stubs/strutil.h                              \
+  google/protobuf/stubs/substitute.cc                          \
+  google/protobuf/stubs/substitute.h                           \
   google/protobuf/stubs/structurally_valid.cc                  \
   google/protobuf/descriptor.cc                                \
   google/protobuf/descriptor.pb.cc                             \
@@ -311,6 +311,7 @@
 protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include    \
                                          -I$(top_builddir)/gtest/include  \
                                          -DPROTOBUF_TEST_NO_DESCRIPTORS
+protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
 protobuf_lazy_descriptor_test_SOURCES =                        \
   google/protobuf/compiler/cpp/cpp_unittest.cc                 \
   $(COMMON_TEST_SOURCES)
@@ -318,6 +319,7 @@
 
 # Build lite_unittest separately, since it doesn't use gtest.
 protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la
+protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
 protobuf_lite_test_SOURCES =                                           \
   google/protobuf/lite_unittest.cc                                     \
   google/protobuf/test_util_lite.cc                                    \
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 5e156f2..a53740a 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -39,7 +39,6 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <google/protobuf/stubs/stl_util-inl.h>
 
 namespace google {
@@ -55,11 +54,23 @@
 
 string InitializationErrorMessage(const char* action,
                                   const MessageLite& message) {
-  return strings::Substitute(
-    "Can't $0 message of type \"$1\" because it is missing required "
-    "fields: $2",
-    action, message.GetTypeName(),
-    message.InitializationErrorString());
+  // Note:  We want to avoid depending on strutil in the lite library, otherwise
+  //   we'd use:
+  //
+  // return strings::Substitute(
+  //   "Can't $0 message of type \"$1\" because it is missing required "
+  //   "fields: $2",
+  //   action, message.GetTypeName(),
+  //   message.InitializationErrorString());
+
+  string result;
+  result += "Can't ";
+  result += action;
+  result += " message of type \"";
+  result += message.GetTypeName();
+  result += "\" because it is missing required fields: ";
+  result += message.InitializationErrorString();
+  return result;
 }
 
 // Several of the Parse methods below just do one thing and then call another
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index 302be7a..1e2d68d 100644
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -32,8 +32,6 @@
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
 #include <stdio.h>
 #include <errno.h>
 #include <vector>
@@ -43,6 +41,7 @@
 #ifdef _WIN32
 #define WIN32_LEAN_AND_MEAN  // We only need minimal includes
 #include <windows.h>
+#define snprintf _snprintf    // see comment in strutil.cc
 #elif defined(HAVE_PTHREAD)
 #include <pthread.h>
 #else
@@ -87,7 +86,15 @@
   int minor = (version / 1000) % 1000;
   int micro = version % 1000;
 
-  return strings::Substitute("$0.$1.$2", major, minor, micro);
+  // 128 bytes should always be enough, but we use snprintf() anyway to be
+  // safe.
+  char buffer[128];
+  snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro);
+
+  // Guard against broken MSVC snprintf().
+  buffer[sizeof(buffer)-1] = '\0';
+
+  return buffer;
 }
 
 }  // namespace internal
@@ -131,23 +138,39 @@
   GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount);
 }
 
-static string SimpleCtoa(char c) { return string(1, c); }
+LogMessage& LogMessage::operator<<(const string& value) {
+  message_ += value;
+  return *this;
+}
 
+LogMessage& LogMessage::operator<<(const char* value) {
+  message_ += value;
+  return *this;
+}
+
+// Since this is just for logging, we don't care if the current locale changes
+// the results -- in fact, we probably prefer that.  So we use snprintf()
+// instead of Simple*toa().
 #undef DECLARE_STREAM_OPERATOR
-#define DECLARE_STREAM_OPERATOR(TYPE, TOSTRING)                     \
+#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT)                       \
   LogMessage& LogMessage::operator<<(TYPE value) {                  \
-    message_ += TOSTRING(value);                                    \
+    /* 128 bytes should be big enough for any of the primitive */   \
+    /* values which we print with this, but well use snprintf() */  \
+    /* anyway to be extra safe. */                                  \
+    char buffer[128];                                               \
+    snprintf(buffer, sizeof(buffer), FORMAT, value);                \
+    /* Guard against broken MSVC snprintf(). */                     \
+    buffer[sizeof(buffer)-1] = '\0';                                \
+    message_ += buffer;                                             \
     return *this;                                                   \
   }
 
-DECLARE_STREAM_OPERATOR(const string&, )
-DECLARE_STREAM_OPERATOR(const char*  , )
-DECLARE_STREAM_OPERATOR(char         , SimpleCtoa)
-DECLARE_STREAM_OPERATOR(int          , SimpleItoa)
-DECLARE_STREAM_OPERATOR(uint         , SimpleItoa)
-DECLARE_STREAM_OPERATOR(long         , SimpleItoa)
-DECLARE_STREAM_OPERATOR(unsigned long, SimpleItoa)
-DECLARE_STREAM_OPERATOR(double       , SimpleDtoa)
+DECLARE_STREAM_OPERATOR(char         , "%c" )
+DECLARE_STREAM_OPERATOR(int          , "%d" )
+DECLARE_STREAM_OPERATOR(uint         , "%u" )
+DECLARE_STREAM_OPERATOR(long         , "%ld")
+DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
+DECLARE_STREAM_OPERATOR(double       , "%g" )
 #undef DECLARE_STREAM_OPERATOR
 
 LogMessage::LogMessage(LogLevel level, const char* filename, int line)