diff --git a/Makefile b/Makefile
index 3272f6bfe039922453fa5c9a679814eae1bc29dd..53d0eb17f85c3dcf7632f5fa17191fa448278d40 100644
--- a/Makefile
+++ b/Makefile
@@ -9,30 +9,21 @@ PREFIX ?= /usr
 
 def: compile_library
 
-compile_library:
-	$(CXX) $(CXXFLAGS) -c libr.cc -I . -o libr.o
-	$(AR) $(ARFLAGS) libr.a libr.o
-
 install_header:
 	[ ! -d $(PREFIX)/include/rlib ] || rm -rf $(PREFIX)/include/rlib
 	cp -r . $(PREFIX)/include/rlib
 	rm -rf $(PREFIX)/include/rlib/test $(PREFIX)/include/rlib/.git
 
-install_library: compile_library
-	cp libr.a $(PREFIX)/lib/
-
 install_cmake: install_library
 	[ ! -d $(PREFIX)/lib/cmake/rlib ] || rm -rf $(PREFIX)/lib/cmake/rlib
 	[ ! -d $(PREFIX)/lib/cmake ] || cp -r cmake $(PREFIX)/lib/cmake/rlib
 
-install: install_header install_library install_cmake
+install: install_header install_cmake
 
 uninstall:
 	rm -rf $(PREFIX)/include/rlib $(PREFIX)/lib/cmake/rlib
-	rm -f $(PREFIX)/lib/libr.a
 
 clean:
-	rm *.o *.a
 
 .PHONY: test
 
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 129368e5fd783b0215c6ed962049b4f1c601d545..a5e83076586f217a294a42e30d83b596fd43df5f 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -14,6 +14,5 @@ if(MSYS OR MINGW)
     add_definitions(-DRLIB_MINGW_DISABLE_TLS)
 endif()
 
-add_library(r STATIC ../libr.cc)
 include_directories(..)
 
diff --git a/cmake/rlib-config.cmake b/cmake/rlib-config.cmake
index 18a57587445ae34fa310bf8a741689e3712cbcb3..0cc3a3ce2ba6e2832668adefed8d4685db3bdab0 100644
--- a/cmake/rlib-config.cmake
+++ b/cmake/rlib-config.cmake
@@ -1,7 +1,6 @@
 # use this file if you want to install rlib
 
 set(rlib_INCLUDE_DIRS ${PREFIX}/include)
-set(rlib_LIBRARIES ${PREFIX}/lib/libr.a)
 
 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
     # using clang
diff --git a/libr.cc b/libr.cc
deleted file mode 100644
index 006f5f3d5324d69d10523730594701e780058c29..0000000000000000000000000000000000000000
--- a/libr.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <rlib/log.hpp> //log_level_t
-#include <rlib/stream.hpp>
-#include <sstream>
-
-#if (RLIB_CXX_STD >= 2017) && (RLIB_COMPILER_ID != CC_MSVC)
-#warning library should not be compiled under C++17. Or The library wont work for c++14 users.
-#endif
-
-namespace rlib {
-    namespace impl {
-// If libr.cc is built under C++17, and other header files are included in C++14 project,
-// Then something wrong will happen. So DO NOT ignore the following definitions. NEVER.
-//#if RLIB_CXX_STD < 2017
-        bool enable_endl_flush = true;
-        int max_predefined_log_level = (int)log_level_t::DEBUG;
-        NullStreamBuf null_streambuf;
-//#endif
-//#ifndef RLIB_MINGW_DISABLE_TLS
-//#if RLIB_CXX_STD < 2017
-        thread_local std::stringstream _format_string_helper_ss;
-        thread_local std::stringstream to_string_by_sstream_ss;        
-//#endif
-//#endif
-    }
-//#if RLIB_CXX_STD < 2017
-    std::ostream null_stream(&impl::null_streambuf);
-//#endif
-}
diff --git a/log.hpp b/log.hpp
index b338b12d34326757b28fada9a86cf486fd145cac..10b6babb24621cecc986530e8851622480e14357 100644
--- a/log.hpp
+++ b/log.hpp
@@ -36,11 +36,10 @@ namespace rlib {
     // Allow extension.
     enum class log_level_t : int { FATAL = 1, ERROR, WARNING, INFO, VERBOSE, DEBUG };
     namespace impl {
-#if RLIB_CXX_STD < 2017
-        extern int max_predefined_log_level;
-#else
-        inline int max_predefined_log_level = (int)log_level_t::DEBUG;
-#endif
+        inline int &max_predefined_log_level() {
+            static int instance = (int)log_level_t::DEBUG;
+            return instance;
+        }
     }
     /*
     How to update log_level_t:
@@ -109,10 +108,10 @@ namespace rlib {
         }
         // Warning: this method is not thread-safe.
         log_level_t register_log_level(const std::string &name) {
-            if(impl::max_predefined_log_level == INT_MAX)
+            if(impl::max_predefined_log_level() == INT_MAX)
                 throw std::overflow_error("At most {}(INT_MAX) log_level is allowed."_format(INT_MAX));
-            ++ impl::max_predefined_log_level;
-            log_level_t new_level = (log_level_t)impl::max_predefined_log_level;
+            ++ impl::max_predefined_log_level();
+            log_level_t new_level = (log_level_t)impl::max_predefined_log_level();
             custom_log_level_names.push_back({new_level, name});
             return new_level;
         }
diff --git a/stdio.hpp b/stdio.hpp
index 54e05551bd47890297b227eead29f282cfb0e51c..80d6e6bfbb974b8812f3a7760ca50857fedc7ca8 100644
--- a/stdio.hpp
+++ b/stdio.hpp
@@ -96,25 +96,24 @@ namespace rlib {
     // implementations below --------------------------------
 
     namespace impl {
-#if RLIB_CXX_STD < 2017
-        extern bool enable_endl_flush;
-#else
-        inline bool enable_endl_flush = true;
-#endif
+        inline bool &enable_endl_flush() {
+            static bool instance = true;
+            return instance;
+        }
     }
 
     inline bool sync_with_stdio(bool sync = true) noexcept {
         return std::ios::sync_with_stdio(sync);
     }
     inline bool enable_endl_flush(bool enable = true) noexcept {
-        return impl::enable_endl_flush = enable;
+        return impl::enable_endl_flush() = enable;
     }
 
 // Implements.
     template < class CharT, class Traits >
     inline std::basic_ostream<CharT, Traits>& endl(std::basic_ostream<CharT, Traits>& os) {
         os << RLIB_IMPL_ENDLINE;
-        if(impl::enable_endl_flush)
+        if(impl::enable_endl_flush())
             os.flush();
         return os;
     }
diff --git a/stream.hpp b/stream.hpp
index a3bf36d07378167394c6ced68f60fab8f56bfde2..93f77c25b061ac57b64be56718c3273c534b5963 100644
--- a/stream.hpp
+++ b/stream.hpp
@@ -10,16 +10,15 @@ namespace rlib {
         public:
             int overflow(int c) { return c; }
         };
-#if RLIB_CXX_STD < 2017
-        extern NullStreamBuf null_streambuf;
-#else
-        inline NullStreamBuf null_streambuf;
-#endif
+
+        inline NullStreamBuf & null_streambuf() {
+            static NullStreamBuf instance;
+            return instance;
+        }
     }
     
-#if RLIB_CXX_STD < 2017
-    extern std::ostream null_stream;
-#else
-    inline std::ostream null_stream(&impl::null_streambuf);
-#endif
+    inline std::ostream &null_stream() {
+        static std::ostream instance(impl::null_streambuf());
+        return instance;
+    }
 }
diff --git a/string.hpp b/string.hpp
index 79d23b501f141be14b4a59dc93515f5a93805110..9fe79687a1eab5374f64b9f23f644786c421408e 100644
--- a/string.hpp
+++ b/string.hpp
@@ -24,6 +24,7 @@
 #include <sstream>
 #include <type_traits>
 
+// Intel C++ compiler has a pending bug for `thread_local inline` variable.
 #if RLIB_COMPILER_ID == CC_ICC
 #define RLIB_IMPL_SSTREAM_DISABLE_TLS
 #endif
@@ -36,14 +37,14 @@ namespace rlib {
     // literals::_format, format_string, string::format
     namespace impl {
 #ifndef RLIB_IMPL_SSTREAM_DISABLE_TLS
-#if RLIB_CXX_STD < 2017
-// Intel C++ compiler has a pending bug for `thread_local inline` variable.
-        thread_local extern std::stringstream to_string_by_sstream_ss;        
-        thread_local extern std::stringstream _format_string_helper_ss;
-#else
-        thread_local inline std::stringstream to_string_by_sstream_ss;        
-        thread_local inline std::stringstream _format_string_helper_ss;
-#endif
+        inline std::stringstream &to_string_by_sstream_ss() {
+            static thread_local std::stringstream instance;
+            return instance;
+        }
+        inline std::stringstream &_format_string_helper_ss() {
+            static thread_local std::stringstream instance;
+            return instance;
+        }
 #endif
         template <typename VarT>
         std::string to_string_by_sstream(VarT &thing) {
@@ -52,7 +53,7 @@ namespace rlib {
             // Also fix mingw bug. But much slower!
             std::stringstream ss;
 #else
-            auto &ss = to_string_by_sstream_ss;
+            auto &ss = to_string_by_sstream_ss();
             ss.str(std::string());
 #endif
             ss << thing;
@@ -65,7 +66,7 @@ namespace rlib {
             // Fix intel C++ bug https://software.intel.com/en-us/forums/intel-c-compiler/topic/784136
             std::stringstream ss;
 #else
-            auto &ss = _format_string_helper_ss; // cached stringstream is much quicker.
+            auto &ss = _format_string_helper_ss(); // cached stringstream is much quicker.
             ss.str(std::string());
 #endif
             size_t pos = 0, prev_pos = 0;
diff --git a/test/Makefile b/test/Makefile
index a81d86444a9921db0ae3e5244fe8c59c8f4a1ea0..edd67cbaeea2c5b9dfc1190853e50a7248be17fa 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -24,8 +24,8 @@ MODULES=string meta trait stdio sio scope_guard
 XTRA_FLAGS ?=
 CXXFLAGS=-I. -I../.. $(XTRA_FLAGS)
 STD ?= 14
-FLAGS11=-std=c++11 rlib/libr.a
-FLAGS14=-std=c++14 rlib/libr.a
+FLAGS11=-std=c++11
+FLAGS14=-std=c++14
 FLAGS17=-std=c++17
 
 ifeq ($(STD),11)