[config] gcc,msvc,mingw visibility
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). 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. So here is what I came up with. My questions are: a) did I do this right? b) is there a simpler way c) if the answer to the above is no - can the documentation be updated? Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/config-gcc-msvc-mingw-visibility-tp467471... Sent from the Boost - Dev mailing list archive at Nabble.com.
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
... snip ... OK, I pretty much understood this you described. Though You've certainly explained it better than I have. I've always had this working under msvc but have problems in extending it gcc. It wasn't a huge deal and everything went more or less smoothly.
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.
That is not my experience 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 don't think that's it. The versions in the test matrix seem recent to me. BUT when I cam up against MinGW I have serious problems. It seems that MinGW uses the windows attributes in it's gcc compiler - all versions tested by boost. So the test matrix showed everything fine except for MinGW. So I haven't been able to reconcile all the macros in this gcc/win32 combination. I looked at all the other libraries. They support MSVC export/inport - but don't enable gcc visibility=hidden so it seems that this is the first time the problem has come up. I took another stab at it but this broke my windows links on the test matrix. I'm still on it. -- View this message in context: http://boost.2283326.n4.nabble.com/config-gcc-msvc-mingw-visibility-tp467471... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 04/24/2015 01:35 AM, Robert Ramey wrote:
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 don't think that's it. The versions in the test matrix seem recent to me.
BUT when I cam up against MinGW I have serious problems. It seems that MinGW uses the windows attributes in it's gcc compiler - all versions tested by boost. So the test matrix showed everything fine except for MinGW. So I haven't been able to reconcile all the macros in this gcc/win32 combination. I looked at all the other libraries. They support MSVC export/inport - but don't enable gcc visibility=hidden so it seems that this is the first time the problem has come up.
From what I understand, this is by design. Instead of thinking about symbol import/export as "how the compiler I'm using behaves," it's more of a target platform issue. When you're compiling a shared library for Linux, the resulting ELF file exports all symbols by default. Windows DLLs, however, are the opposite: they only export symbols that are explicitly marked (e.g. "dllexport" on MSVC). There are gcc flavors that target each platform, so gcc on Linux doesn't need any symbol annotation, while mingw requires that the symbols you want to export be marked as such. I'm not a Windows development expert at all, but I *think* that if you treat mingw like you treat MSVC with regard to symbol export/import, then it should work. Jason
participants (3)
-
Andrey Semashev
-
Jason Roehm
-
Robert Ramey