On Thu, Apr 23, 2015 at 8:19 AM, Robert Ramey
I've been enabling limited gcc visibility so that it works similarly to msvc *_DECL attributes and will export from the DLL/DSO only those symbols which need to be exported.
I've had a lot of difficulty with this.
I followed the instructions
http://www.boost.org/doc/libs/1_58_0/libs/config/doc/html/boost_config/boost...
which more or less boil down to using BOOST_SYMBOL_EXPORT when functions are exported, BOOST_SYMBOL_IMPORT when functions are imported, and BOOST_SYMBOL_VISIBLE on class declarations.
I set my Jamfile.v2 in the library build to enable gcc visibility=hidden and let her rip.
After the more or less normal back and forth it seemed that the library built and work on all platforms/compilers. .... EXCEPT Mingw. Hmmmm - this shouldn't be too tough, just look at how the other libraries did it. Turns out that it seems that no boost libraries actually enable gcc visibility in their builds - at least as far as I can tell. (I didn't dig into the depths of jam tools files).
I'm restricting visibility in Boost.Log. For now it's only in develop, I'm planning to merge it to master for the next release. I didn't test it personally with MinGW but the test matrix doesn't show failures.
After a fair amount of research I concluded that for windows platforms - regardless of whether they are built with minnow (gcc) or mdvc, one needs to define BOOST_SYMBOL_VISIBLE as BOOST_SYMBOL_IMPORT or BOOST_SYMBOL_IMPORT which of course makes things more complicated.
No, I don't think this is right. BOOST_SYMBOL_VISIBLE has no effect with MSVC, and probably even Windows in general, because AFAIK the runtime linker there has no support for symbol relocation similar to Linux. But the macro should still be used to mark types for portability. BOOST_SYMBOL_VISIBLE should be used on types which can be used as exceptions or in dynamic_casts across dynamic library boundaries. The net effect of such markup is to make the type info visible to the linker so that it is able to relocate references to the type info from different modules to a single instance. On Windows this is not needed (and not performed) because the language runtime there works with type info by value and not by address. This is true for both MSVC and GCC. BOOST_SYMBOL_EXPORT/IMPORT are similar to BOOST_SYMBOL_VISIBLE on UNIX-like systems in the sense that exporting a symbol (a function or data) on those systems is just a matter of making it visible to the runtime linker. So when you build your library and use BOOST_SYMBOL_EXPORT, it expands to something similar to BOOST_SYMBOL_VISIBLE. BOOST_SYMBOL_IMPORT can be empty because there is nothing to do to "import" a symbol, but the macro is still needed for compatibility with Windows. On Windows though exported symbols are not simply made visible but their name is mangled differently. This requires to mark the symbols both when exported and imported (and for some reason the markup is different, hence the two macros for that). So the general advice is to have your own macro (say, MY_LIB_API), which is defined to BOOST_SYMBOL_EXPORT when your library is built and BOOST_SYMBOL_IMPORT otherwise. Now, which symbols need to be marked. Basically, every symbol that can be used across the library boundary needs to be marked with MY_LIB_API. Primarily this means functions. You can also mark the whole class with MY_LIB_API, and this would result in automatically exporting all its functions, including the implicitly defined ones, like constructors, destructor and assignment, as well as static data members. See [1] for more details. Personally, I try to avoid that because it makes the library interface less explicit and usually it results in exporting more things than I want to. I usually export class members individually. If the class also needs to be an exception or participate in dynamic_casts you can mark it with MY_LIB_API (and not mark any members). Although it's probably still better to mark the class with BOOST_SYMBOL_VISIBLE (in addition to marking the exported members with MY_LIB_API). There are quirks with regard to where to use MY_LIB_API - in symbol declaration, definition or both. At least some MSVC versions may silently ignore the export attribute if it's not used where needed. This may be a bug or there may be an explanation somewhere, I don't know. From my practice you should mark both declaration and definition of functions to work around that. When exporting a function template specialization, you have to mark the declaration and explicit instantiation of the template (but not the template definition). You can find a few examples in Boost.Log [2][3]. Getting back to BOOST_SYMBOL_VISIBLE and MinGW, I'm not sure what effect it has there, but I think it should be close to none. In any case, it should not export anything because it is not needed in the contexts where the macro should be used, and where exporting is needed MY_LIB_API should be used instead. Then again, there are multiple flavors of MinGW out there, including the legacy MinGW32 where some GCC versions were broken wrt exceptions and dynamic_casts (which used type info addresses, like on Linux). If you're having problems with such broken MinGW then you have my condolences; I don't think you can work around it without crippling the user's code (basically, you'll have to reimplement part of the compiler runtime). I would recommend using a more recent GCC and MinGW64 instead. I hope it helps. [1] https://msdn.microsoft.com/en-us/library/81h27t8c.aspx [2] https://github.com/boostorg/log/blob/develop/include/boost/log/core/core.hpp https://github.com/boostorg/log/blob/develop/src/core.cpp [3] https://github.com/boostorg/log/blob/develop/include/boost/log/utility/setup... https://github.com/boostorg/log/blob/develop/src/filter_parser.cpp