From c47318afa8303ef753f9a279b8f49969469ad803 Mon Sep 17 00:00:00 2001 From: Maciej Dems Date: Wed, 9 Dec 2015 14:52:09 +0100 Subject: [PATCH] Declarations for shared library in Windows. Added __declspec(dllimport) and __declspec(dllexport) declarations when compiled in Windows. --- CMakeLists.txt | 21 +++++++++++----- format.h | 58 +++++++++++++++++++++++++++------------------ test/CMakeLists.txt | 6 +++++ 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b005981d..d7a3bf5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,12 +94,17 @@ if (BIICODE) return() endif () -add_library(cppformat ${FMT_SOURCES}) -if (BUILD_SHARED_LIBS AND UNIX AND NOT APPLE) - # Fix rpmlint warning: - # unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6. - target_link_libraries(cppformat -Wl,--as-needed) -endif () +if (BUILD_SHARED_LIBS) + add_library(cppformat SHARED ${FMT_SOURCES}) + if (UNIX AND NOT APPLE) + # Fix rpmlint warning: + # unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6. + target_link_libraries(cppformat -Wl,--as-needed) + endif () +else () + add_library(cppformat ${FMT_SOURCES}) +endif() + if (FMT_PEDANTIC AND (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))) set(FMT_EXTRA_COMPILE_FLAGS "-Wall -Wextra -Wshadow -pedantic") @@ -114,6 +119,10 @@ if (CPP11_FLAG AND FMT_PEDANTIC) set(FMT_TEST_DEFAULT_FLAGS TRUE) endif () +if (BUILD_SHARED_LIBS) + set(FMT_EXTRA_COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS} -DFMT_EXPORT") +endif () + set_target_properties(cppformat PROPERTIES COMPILE_FLAGS "${FMT_EXTRA_COMPILE_FLAGS}") diff --git a/format.h b/format.h index 45d54283..1217291c 100644 --- a/format.h +++ b/format.h @@ -64,6 +64,18 @@ typedef long long intmax_t; # include #endif +#if !defined(FMT_HEADER_ONLY) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) +# ifdef FMT_EXPORT +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# else +# define FMT_API +# endif +#else +# define FMT_API +#endif + #ifdef _MSC_VER # include // _BitScanReverse, _BitScanReverse64 @@ -676,7 +688,7 @@ class FixedBuffer : public fmt::Buffer { FixedBuffer(Char *array, std::size_t size) : fmt::Buffer(array, size) {} protected: - void grow(std::size_t size); + FMT_API void grow(std::size_t size); }; template @@ -704,7 +716,7 @@ class CharTraits : public BasicCharTraits { // Formats a floating-point number. template - static int format_float(char *buffer, std::size_t size, + FMT_API static int format_float(char *buffer, std::size_t size, const char *format, unsigned width, int precision, T value); }; @@ -715,7 +727,7 @@ class CharTraits : public BasicCharTraits { static wchar_t convert(wchar_t value) { return value; } template - static int format_float(wchar_t *buffer, std::size_t size, + FMT_API static int format_float(wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, T value); }; @@ -769,12 +781,12 @@ FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned); FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long); FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong); -void report_unknown_type(char code, const char *type); +FMT_API void report_unknown_type(char code, const char *type); // Static data is placed in this class template to allow header-only // configuration. template -struct BasicData { +struct FMT_API BasicData { static const uint32_t POWERS_OF_10_32[]; static const uint64_t POWERS_OF_10_64[]; static const char DIGITS[]; @@ -863,7 +875,7 @@ class UTF8ToUTF16 { MemoryBuffer buffer_; public: - explicit UTF8ToUTF16(StringRef s); + FMT_API explicit UTF8ToUTF16(StringRef s); operator WStringRef() const { return WStringRef(&buffer_[0], size()); } size_t size() const { return buffer_.size() - 1; } const wchar_t *c_str() const { return &buffer_[0]; } @@ -878,7 +890,7 @@ class UTF16ToUTF8 { public: UTF16ToUTF8() {} - explicit UTF16ToUTF8(WStringRef s); + FMT_API explicit UTF16ToUTF8(WStringRef s); operator StringRef() const { return StringRef(&buffer_[0], size()); } size_t size() const { return buffer_.size() - 1; } const char *c_str() const { return &buffer_[0]; } @@ -887,15 +899,15 @@ class UTF16ToUTF8 { // Performs conversion returning a system error code instead of // throwing exception on conversion error. This method may still throw // in case of memory allocation error. - int convert(WStringRef s); + FMT_API int convert(WStringRef s); }; -void format_windows_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT; +FMT_API void format_windows_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT; #endif -void format_system_error(fmt::Writer &out, int error_code, - fmt::StringRef message) FMT_NOEXCEPT; +FMT_API void format_system_error(fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT; // A formatting argument value. struct Value { @@ -1638,7 +1650,7 @@ class ArgMap { MapType map_; public: - void init(const ArgList &args); + FMT_API void init(const ArgList &args); const internal::Arg* find(const fmt::BasicStringRef &name) const { typename MapType::const_iterator it = map_.find(name); @@ -1768,7 +1780,7 @@ class FormatterBase { int next_arg_index_; // Returns the argument with specified index. - Arg do_get_arg(unsigned arg_index, const char *&error); + FMT_API Arg do_get_arg(unsigned arg_index, const char *&error); protected: const ArgList &args() const { return args_; } @@ -1824,7 +1836,7 @@ class PrintfFormatter : private FormatterBase { public: explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {} - void format(BasicWriter &writer, BasicCStringRef format_str); + FMT_API void format(BasicWriter &writer, BasicCStringRef format_str); }; } // namespace internal @@ -2929,14 +2941,14 @@ void format(BasicFormatter &f, const Char *&format_str, const T &value) { // Reports a system error without throwing an exception. // Can be used to report errors from destructors. -void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT; +FMT_API void report_system_error(int error_code, StringRef message) FMT_NOEXCEPT; #if FMT_USE_WINDOWS_H /** A Windows error. */ class WindowsError : public SystemError { private: - void init(int error_code, CStringRef format_str, ArgList args); + FMT_API void init(int error_code, CStringRef format_str, ArgList args); public: /** @@ -2975,7 +2987,7 @@ class WindowsError : public SystemError { // Reports a Windows error without throwing an exception. // Can be used to report errors from destructors. -void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT; +FMT_API void report_windows_error(int error_code, StringRef message) FMT_NOEXCEPT; #endif @@ -2987,7 +2999,7 @@ enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; Example: print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23); */ -void print_colored(Color c, CStringRef format, ArgList args); +FMT_API void print_colored(Color c, CStringRef format, ArgList args); /** \rst @@ -3019,7 +3031,7 @@ inline std::wstring format(WCStringRef format_str, ArgList args) { print(stderr, "Don't {}!", "panic"); \endrst */ -void print(std::FILE *f, CStringRef format_str, ArgList args); +FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args); /** \rst @@ -3030,7 +3042,7 @@ void print(std::FILE *f, CStringRef format_str, ArgList args); print("Elapsed time: {0:.2f} seconds", 1.23); \endrst */ -void print(CStringRef format_str, ArgList args); +FMT_API void print(CStringRef format_str, ArgList args); template void printf(BasicWriter &w, BasicCStringRef format, ArgList args) { @@ -3067,7 +3079,7 @@ inline std::wstring sprintf(WCStringRef format, ArgList args) { fmt::fprintf(stderr, "Don't %s!", "panic"); \endrst */ -int fprintf(std::FILE *f, CStringRef format, ArgList args); +FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args); /** \rst @@ -3362,7 +3374,7 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) print(cerr, "Don't {}!", "panic"); \endrst */ -void print(std::ostream &os, CStringRef format_str, ArgList args); +FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); FMT_VARIADIC(void, print, std::ostream &, CStringRef) #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d30c222b..a284a19f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,6 +2,10 @@ set(FMT_GMOCK_DIR ../gmock) include_directories(.. ${FMT_GMOCK_DIR}) +if (BUILD_SHARED_LIBS) + set(FMT_IMPORT "-DFMT_SHARED") +endif () + # We compile Google Test ourselves instead of using pre-compiled libraries. # See the Google Test FAQ "Why is it not recommended to install a # pre-compiled copy of Google Test (for example, into /usr/local)?" @@ -45,6 +49,7 @@ endif () set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc) add_library(test-main STATIC ${TEST_MAIN_SRC}) +set_target_properties(test-main PROPERTIES COMPILE_FLAGS "${FMT_IMPORT}") target_link_libraries(test-main cppformat gmock) # Adds a test. @@ -54,6 +59,7 @@ function(add_fmt_test name) add_executable(${name} ${name}.cc ${add_fmt_test_UNPARSED_ARGUMENTS}) target_link_libraries(${name} test-main) if (NOT add_fmt_test_CUSTOM_LINK) + set_target_properties(${name} PROPERTIES COMPILE_FLAGS "${FMT_IMPORT}") target_link_libraries(${name} cppformat) endif () add_test(NAME ${name} COMMAND ${name})