diff --git a/CMakeLists.txt b/CMakeLists.txt index 05f7dd5c..153c75d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,10 +126,11 @@ if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) endif() if (SPDLOG_BUILD_SHARED) - if(WIN32) - message(FATAL_ERROR "spdlog shared lib is not yet supported under windows") - endif() add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS}) + target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB) + if(WIN32) + target_compile_options(spdlog PUBLIC /wd4251 /wd4275) + endif() else() add_library(spdlog STATIC ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS}) endif() @@ -265,7 +266,10 @@ if (SPDLOG_INSTALL) # Include files #--------------------------------------------------------------------------------------- install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PATTERN "fmt/bundled" EXCLUDE) - install(TARGETS spdlog spdlog_header_only EXPORT spdlog DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install(TARGETS spdlog spdlog_header_only EXPORT spdlog + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO) install(DIRECTORY include/${PROJECT_NAME}/fmt/bundled/ diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 829c5acc..6f299672 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -30,7 +30,7 @@ namespace details { class thread_pool; } -class async_logger final : public std::enable_shared_from_this, public logger +class SPDLOG_API async_logger final : public std::enable_shared_from_this, public logger { friend class details::thread_pool; diff --git a/include/spdlog/cfg/helpers.h b/include/spdlog/cfg/helpers.h index cf5146c0..8d750824 100644 --- a/include/spdlog/cfg/helpers.h +++ b/include/spdlog/cfg/helpers.h @@ -17,7 +17,7 @@ namespace helpers { // turn off all logging except for logger1: "off,logger1=debug" // turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info" // -log_levels extract_levels(const std::string &txt); +SPDLOG_API log_levels extract_levels(const std::string &txt); } // namespace helpers } // namespace cfg diff --git a/include/spdlog/common.h b/include/spdlog/common.h index cb6355cf..aa94e794 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -17,8 +17,18 @@ #ifdef SPDLOG_COMPILED_LIB #undef SPDLOG_HEADER_ONLY -#define SPDLOG_INLINE +# if defined(_WIN32) && defined(SPDLOG_SHARED_LIB) +# ifdef spdlog_EXPORTS +# define SPDLOG_API __declspec(dllexport) +# else +# define SPDLOG_API __declspec(dllimport) +# endif +# else +# define SPDLOG_API +# endif +# define SPDLOG_INLINE #else +#define SPDLOG_API #define SPDLOG_HEADER_ONLY #define SPDLOG_INLINE inline #endif @@ -153,9 +163,9 @@ enum level_enum } #endif -string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; -const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; -spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT; +SPDLOG_API string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; +SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; +SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT; using level_hasher = std::hash; } // namespace level @@ -183,7 +193,7 @@ enum class pattern_time_type // // Log exception // -class spdlog_ex : public std::exception +class SPDLOG_API spdlog_ex : public std::exception { public: explicit spdlog_ex(std::string msg); diff --git a/include/spdlog/details/backtracer.h b/include/spdlog/details/backtracer.h index 0e779cab..b7476bc9 100644 --- a/include/spdlog/details/backtracer.h +++ b/include/spdlog/details/backtracer.h @@ -15,7 +15,7 @@ namespace spdlog { namespace details { -class backtracer +class SPDLOG_API backtracer { mutable std::mutex mutex_; std::atomic enabled_{false}; diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index 3228ce84..5395d9cb 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -13,7 +13,7 @@ namespace details { // When failing to open a file, retry several times(5) with a delay interval(10 ms). // Throw spdlog_ex exception on errors. -class file_helper +class SPDLOG_API file_helper { public: explicit file_helper() = default; diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 9ae473d4..03bdbaec 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -8,7 +8,7 @@ namespace spdlog { namespace details { -struct log_msg +struct SPDLOG_API log_msg { log_msg() = default; log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); diff --git a/include/spdlog/details/log_msg_buffer.h b/include/spdlog/details/log_msg_buffer.h index c20ae7b0..18075d67 100644 --- a/include/spdlog/details/log_msg_buffer.h +++ b/include/spdlog/details/log_msg_buffer.h @@ -11,7 +11,7 @@ namespace details { // Extend log_msg with internal buffer to store its payload. // THis is needed since log_msg holds string_views that points to stack data. -class log_msg_buffer : public log_msg +class SPDLOG_API log_msg_buffer : public log_msg { memory_buf_t buffer; void update_string_views(); diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index 70604cab..cd586e14 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -10,15 +10,15 @@ namespace spdlog { namespace details { namespace os { -spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; +SPDLOG_API spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT; -std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; +SPDLOG_API std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; -std::tm localtime() SPDLOG_NOEXCEPT; +SPDLOG_API std::tm localtime() SPDLOG_NOEXCEPT; -std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; +SPDLOG_API std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT; -std::tm gmtime() SPDLOG_NOEXCEPT; +SPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT; // eol definition #if !defined(SPDLOG_EOL) @@ -39,49 +39,49 @@ SPDLOG_CONSTEXPR static const char folder_sep = '/'; #endif // fopen_s on non windows for writing -bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); +SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode); // Remove filename. return 0 on success -int remove(const filename_t &filename) SPDLOG_NOEXCEPT; +SPDLOG_API int remove(const filename_t &filename) SPDLOG_NOEXCEPT; // Remove file if exists. return 0 on success // Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread) -int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; +SPDLOG_API int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT; -int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; +SPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT; // Return if file exists. -bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT; +SPDLOG_API bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT; // Return file size according to open FILE* object -size_t filesize(FILE *f); +SPDLOG_API size_t filesize(FILE *f); // Return utc offset in minutes or throw spdlog_ex on failure -int utc_minutes_offset(const std::tm &tm = details::os::localtime()); +SPDLOG_API int utc_minutes_offset(const std::tm &tm = details::os::localtime()); // Return current thread id as size_t // It exists because the std::this_thread::get_id() is much slower(especially // under VS 2013) -size_t _thread_id() SPDLOG_NOEXCEPT; +SPDLOG_API size_t _thread_id() SPDLOG_NOEXCEPT; // Return current thread id as size_t (from thread local storage) -size_t thread_id() SPDLOG_NOEXCEPT; +SPDLOG_API size_t thread_id() SPDLOG_NOEXCEPT; // This is avoid msvc issue in sleep_for that happens if the clock changes. // See https://github.com/gabime/spdlog/issues/609 -void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT; +SPDLOG_API void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT; -std::string filename_to_str(const filename_t &filename); +SPDLOG_API std::string filename_to_str(const filename_t &filename); -int pid() SPDLOG_NOEXCEPT; +SPDLOG_API int pid() SPDLOG_NOEXCEPT; // Determine if the terminal supports colors // Source: https://github.com/agauniyal/rang/ -bool is_color_terminal() SPDLOG_NOEXCEPT; +SPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT; // Determine if the terminal attached // Source: https://github.com/agauniyal/rang/ -bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; +SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; #if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32) void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); @@ -92,15 +92,15 @@ void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target); // "abc/" => "abc" // "abc" => "" // "abc///" => "abc//" -filename_t dir_name(filename_t path); +SPDLOG_API filename_t dir_name(filename_t path); // Create a dir from the given path. // Return true if succeeded or if this dir already exists. -bool create_dir(filename_t path); +SPDLOG_API bool create_dir(filename_t path); // non thread safe, cross platform getenv/getenv_s // return empty string if field not found -std::string getenv(const char *field); +SPDLOG_API std::string getenv(const char *field); } // namespace os } // namespace details diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index a5c035d1..820f55b5 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -62,7 +62,7 @@ protected: } // namespace details -class pattern_formatter final : public formatter +class SPDLOG_API pattern_formatter final : public formatter { public: explicit pattern_formatter( diff --git a/include/spdlog/details/periodic_worker.h b/include/spdlog/details/periodic_worker.h index d3b5c639..42373665 100644 --- a/include/spdlog/details/periodic_worker.h +++ b/include/spdlog/details/periodic_worker.h @@ -17,7 +17,7 @@ namespace spdlog { namespace details { -class periodic_worker +class SPDLOG_API periodic_worker { public: periodic_worker(const std::function &callback_fun, std::chrono::seconds interval); diff --git a/include/spdlog/details/registry-inl.h b/include/spdlog/details/registry-inl.h index 84e1c414..a6cfc54c 100644 --- a/include/spdlog/details/registry-inl.h +++ b/include/spdlog/details/registry-inl.h @@ -48,6 +48,9 @@ SPDLOG_INLINE registry::registry() #endif // SPDLOG_DISABLE_DEFAULT_LOGGER } + +SPDLOG_INLINE registry::~registry() = default; + SPDLOG_INLINE void registry::register_logger(std::shared_ptr new_logger) { std::lock_guard lock(logger_map_mutex_); diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index e7adb541..8be109ed 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -25,7 +25,7 @@ namespace details { class thread_pool; class periodic_worker; -class registry +class SPDLOG_API registry { public: registry(const registry &) = delete; @@ -86,7 +86,7 @@ public: private: registry(); - ~registry() = default; + ~registry(); void throw_if_exists_(const std::string &logger_name); void register_logger_(std::shared_ptr new_logger); diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index 12078044..733949ba 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -79,7 +79,7 @@ struct async_msg : log_msg_buffer {} }; -class thread_pool +class SPDLOG_API thread_pool { public: using item_type = async_msg; diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index b78d8544..aeb38564 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -39,7 +39,7 @@ namespace spdlog { -class logger +class SPDLOG_API logger { public: // Empty logger diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index b2ca4db1..be99744d 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -9,7 +9,7 @@ namespace spdlog { namespace sinks { -class sink +class SPDLOG_API sink { public: virtual ~sink() = default; diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 9ac04be0..55de6676 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -44,61 +44,61 @@ inline std::shared_ptr create(std::string logger_name, SinkArgs // Example: // auto mylogger = std::make_shared("mylogger", ...); // spdlog::initialize_logger(mylogger); -void initialize_logger(std::shared_ptr logger); +SPDLOG_API void initialize_logger(std::shared_ptr logger); // Return an existing logger or nullptr if a logger with such name doesn't // exist. // example: spdlog::get("my_logger")->info("hello {}", "world"); -std::shared_ptr get(const std::string &name); +SPDLOG_API std::shared_ptr get(const std::string &name); // Set global formatter. Each sink in each logger will get a clone of this object -void set_formatter(std::unique_ptr formatter); +SPDLOG_API void set_formatter(std::unique_ptr formatter); // Set global format string. // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); -void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); +SPDLOG_API void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); // enable global backtrace support -void enable_backtrace(size_t n_messages); +SPDLOG_API void enable_backtrace(size_t n_messages); // disable global backtrace support -void disable_backtrace(); +SPDLOG_API void disable_backtrace(); // call dump backtrace on default logger -void dump_backtrace(); +SPDLOG_API void dump_backtrace(); // Set global logging level -void set_level(level::level_enum log_level); +SPDLOG_API void set_level(level::level_enum log_level); // Set global flush level -void flush_on(level::level_enum log_level); +SPDLOG_API void flush_on(level::level_enum log_level); // Start/Restart a periodic flusher thread // Warning: Use only if all your loggers are thread safe! -void flush_every(std::chrono::seconds interval); +SPDLOG_API void flush_every(std::chrono::seconds interval); // Set global error handler -void set_error_handler(void (*handler)(const std::string &msg)); +SPDLOG_API void set_error_handler(void (*handler)(const std::string &msg)); // Register the given logger with the given name -void register_logger(std::shared_ptr logger); +SPDLOG_API void register_logger(std::shared_ptr logger); // Apply a user defined function on all registered loggers // Example: // spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); -void apply_all(const std::function)> &fun); +SPDLOG_API void apply_all(const std::function)> &fun); // Drop the reference to the given logger -void drop(const std::string &name); +SPDLOG_API void drop(const std::string &name); // Drop all references from the registry -void drop_all(); +SPDLOG_API void drop_all(); // stop any running threads started by spdlog and clean registry loggers -void shutdown(); +SPDLOG_API void shutdown(); // Automatic registration of loggers when using spdlog::create() or spdlog::create_async -void set_automatic_registration(bool automatic_registration); +SPDLOG_API void set_automatic_registration(bool automatic_registration); // API for using default logger (stdout_color_mt), // e.g: spdlog::info("Message {}", 1); @@ -115,11 +115,11 @@ void set_automatic_registration(bool automatic_registration); // set_default_logger() *should not* be used concurrently with the default API. // e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. -std::shared_ptr default_logger(); +SPDLOG_API std::shared_ptr default_logger(); -spdlog::logger *default_logger_raw(); +SPDLOG_API spdlog::logger *default_logger_raw(); -void set_default_logger(std::shared_ptr default_logger); +SPDLOG_API void set_default_logger(std::shared_ptr default_logger); template inline void log(source_loc source, level::level_enum lvl, string_view_t fmt, const Args &... args) diff --git a/src/async.cpp b/src/async.cpp index 106bd71f..d7ee8274 100644 --- a/src/async.cpp +++ b/src/async.cpp @@ -10,4 +10,4 @@ #include #include -template class spdlog::details::mpmc_blocking_queue; \ No newline at end of file +template class SPDLOG_API spdlog::details::mpmc_blocking_queue; \ No newline at end of file diff --git a/src/color_sinks.cpp b/src/color_sinks.cpp index 351b6bc7..4fc13820 100644 --- a/src/color_sinks.cpp +++ b/src/color_sinks.cpp @@ -14,12 +14,12 @@ // #ifdef _WIN32 #include -template class spdlog::sinks::wincolor_sink; -template class spdlog::sinks::wincolor_sink; -template class spdlog::sinks::wincolor_stdout_sink; -template class spdlog::sinks::wincolor_stdout_sink; -template class spdlog::sinks::wincolor_stderr_sink; -template class spdlog::sinks::wincolor_stderr_sink; +template class SPDLOG_API spdlog::sinks::wincolor_sink; +template class SPDLOG_API spdlog::sinks::wincolor_sink; +template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink; +template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink; +template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink; +template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink; #else #include "spdlog/sinks/ansicolor_sink-inl.h" template class spdlog::sinks::ansicolor_sink; @@ -32,16 +32,16 @@ template class spdlog::sinks::ansicolor_stderr_sink spdlog::stdout_color_mt( +template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stdout_color_st( +template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stderr_color_mt( +template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stderr_color_st( +template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stdout_color_mt(const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stdout_color_st(const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stderr_color_mt(const std::string &logger_name, color_mode mode); -template std::shared_ptr spdlog::stderr_color_st(const std::string &logger_name, color_mode mode); +template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt(const std::string &logger_name, color_mode mode); +template SPDLOG_API std::shared_ptr spdlog::stdout_color_st(const std::string &logger_name, color_mode mode); +template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt(const std::string &logger_name, color_mode mode); +template SPDLOG_API std::shared_ptr spdlog::stderr_color_st(const std::string &logger_name, color_mode mode); diff --git a/src/file_sinks.cpp b/src/file_sinks.cpp index e17e2296..5fd7e98a 100644 --- a/src/file_sinks.cpp +++ b/src/file_sinks.cpp @@ -8,12 +8,13 @@ #include #include #include +#include #include -template class spdlog::sinks::basic_file_sink; -template class spdlog::sinks::basic_file_sink; +template class SPDLOG_API spdlog::sinks::basic_file_sink; +template class SPDLOG_API spdlog::sinks::basic_file_sink; #include -template class spdlog::sinks::rotating_file_sink; -template class spdlog::sinks::rotating_file_sink; \ No newline at end of file +template class SPDLOG_API spdlog::sinks::rotating_file_sink; +template class SPDLOG_API spdlog::sinks::rotating_file_sink; \ No newline at end of file diff --git a/src/spdlog.cpp b/src/spdlog.cpp index 3c940a04..38047398 100644 --- a/src/spdlog.cpp +++ b/src/spdlog.cpp @@ -21,6 +21,6 @@ #include // template instantiate logger constructor with sinks init list -template spdlog::logger::logger(std::string name, sinks_init_list::iterator begin, sinks_init_list::iterator end); -template class spdlog::sinks::base_sink; -template class spdlog::sinks::base_sink; \ No newline at end of file +template SPDLOG_API spdlog::logger::logger(std::string name, sinks_init_list::iterator begin, sinks_init_list::iterator end); +template class SPDLOG_API spdlog::sinks::base_sink; +template class SPDLOG_API spdlog::sinks::base_sink; \ No newline at end of file diff --git a/src/stdout_sinks.cpp b/src/stdout_sinks.cpp index 493d3dec..9e86e061 100644 --- a/src/stdout_sinks.cpp +++ b/src/stdout_sinks.cpp @@ -11,19 +11,19 @@ #include #include -template class spdlog::sinks::stdout_sink_base; -template class spdlog::sinks::stdout_sink_base; -template class spdlog::sinks::stdout_sink; -template class spdlog::sinks::stdout_sink; -template class spdlog::sinks::stderr_sink; -template class spdlog::sinks::stderr_sink; +template class SPDLOG_API spdlog::sinks::stdout_sink_base; +template class SPDLOG_API spdlog::sinks::stdout_sink_base; +template class SPDLOG_API spdlog::sinks::stdout_sink; +template class SPDLOG_API spdlog::sinks::stdout_sink; +template class SPDLOG_API spdlog::sinks::stderr_sink; +template class SPDLOG_API spdlog::sinks::stderr_sink; -template std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); -template std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); -template std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); -template std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); -template std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); -template std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); -template std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); -template std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); \ No newline at end of file +template SPDLOG_API std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); +template SPDLOG_API std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); \ No newline at end of file