diff --git a/include/fmt/core.h b/include/fmt/core.h index 286d6a7f..99c78ed0 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -253,9 +253,10 @@ # endif #else # define FMT_CLASS_API -# if defined(__GNUC__) || defined(__clang__) -# define FMT_API __attribute__((visibility("default"))) -# define FMT_EXTERN_TEMPLATE_API FMT_API +# if defined(FMT_EXPORT) || defined(FMT_SHARED) +# if defined(__GNUC__) || defined(__clang__) +# define FMT_API __attribute__((visibility("default"))) +# endif # endif #endif #ifndef FMT_API diff --git a/include/fmt/format.h b/include/fmt/format.h index 3f6ab357..65d2c251 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -902,7 +902,7 @@ template struct basic_data { FMT_API static constexpr const char right_padding_shifts[] = {0, 31, 0, 1, 0}; }; -#ifndef FMT_HEADER_ONLY +#ifdef FMT_SHARED // Required for -flto, -fivisibility=hidden and -shared to work extern template struct basic_data; #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index abaef78a..1de7469d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -213,6 +213,21 @@ if (FMT_PEDANTIC AND NOT WIN32) "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") endif () +# This test are disabled on Windows because it is only *NIX issue. +if (FMT_PEDANTIC AND NOT WIN32) + add_test(static-export-test ${CMAKE_CTEST_COMMAND} + -C ${CMAKE_BUILD_TYPE} + --build-and-test + "${CMAKE_CURRENT_SOURCE_DIR}/static-export-test" + "${CMAKE_CURRENT_BINARY_DIR}/static-export-test" + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options + "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}" + "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") +endif () + # Activate optional CUDA tests if CUDA is found. For version selection see # https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#cpp14-language-features if (FMT_CUDA_TEST) diff --git a/test/static-export-test/CMakeLists.txt b/test/static-export-test/CMakeLists.txt new file mode 100644 index 00000000..7690d7b5 --- /dev/null +++ b/test/static-export-test/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.1...3.18) + +project(fmt-link CXX) + +set(BUILD_SHARED_LIBS OFF) +set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE) +set(CMAKE_CXX_VISIBILITY_PRESET "hidden") + +# Broken LTO on GCC 4 +if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5) + set(BROKEN_LTO ON) +endif () + +if (NOT BROKEN_LTO AND CMAKE_VERSION VERSION_GREATER "3.8") + # CMake 3.9+ + include(CheckIPOSupported) + check_ipo_supported(RESULT HAVE_IPO) + if (HAVE_IPO) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) + endif () +endif () + +add_subdirectory(../.. fmt) +set_property(TARGET fmt PROPERTY POSITION_INDEPENDENT_CODE ON) + +add_library(library-test SHARED library.cc) +target_link_libraries(library-test PRIVATE fmt::fmt) + +add_executable(exe-test main.cc) +target_link_libraries(exe-test PRIVATE library-test) diff --git a/test/static-export-test/library.cc b/test/static-export-test/library.cc new file mode 100644 index 00000000..fe4801ba --- /dev/null +++ b/test/static-export-test/library.cc @@ -0,0 +1,5 @@ +#include + +__attribute__((visibility("default"))) std::string foo() { + return fmt::format(FMT_COMPILE("foo bar {}"), 4242); +} diff --git a/test/static-export-test/main.cc b/test/static-export-test/main.cc new file mode 100644 index 00000000..38f7999e --- /dev/null +++ b/test/static-export-test/main.cc @@ -0,0 +1,6 @@ +#include +#include + +extern std::string foo(); + +int main() { std::cout << foo() << std::endl; }