-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Building with -fvisibility=hidden fails on linking #665
Comments
Hi @sopvop, thanks so much for the feedback. Building with hidden visibility is definitely something we'd like to do. Please give us a little time to review this proposal and get back to you. (For example, one thing that jumps out at me right away is that, while we try really hard not to, we sometimes use FOO_API to export whole classes on Windows (e.g., in the Houdini plugin code) -- so I'd be concerned about having to explain when to use FOO_CLASS_API and when to use FOO_API when exporting whole types). |
Filed as internal issue #USD-4842. |
Hi again @sopvop, Thanks so much for your patience with this, we had a chance to vet your proposal and overall we like it a lot. We have a few suggestions to run by you as well. Here's our current proposal (just small tweaks over your proposal, with a naming suggestion as well):
For 1, this is exactly your proposal and we're additionally suggesting the use of the term VAGUE since we'd like for this macro to represent only exporting vague objects. Unfortunately, we've verified that on gcc (at least on our version of it, 4.8.x) adding default visibility to the class exports everything, not just the vague objects. Despite that, we still think it's a good idea to call it One of the things we're concerned about is that we don't know how much of the code needs to be tagged with The fact that gcc doesn't limit the symbols in this case is what leads us to 3. In order to make sure that we export as few symbols as possible, we're asking that any class tagged with For 4, it's currently against our coding practices to tag Finally, for 5, we'd actually love to have hidden visibility turned on by default everywhere -- once this work is done and we merge the PR, we'll apply it to our internal build system as well (which is a bit different) to make sure that we keep hidden visibility working by default. Thank you so much again for the great suggestion, I think this will be a great addition. |
This is true for gcc 6 as well, so I assume that's just how gcc works.
If we do the minimal changes required to build USD, then only classes exported to python via boost which have base classes also exported to boost need to be marked, since that feature uses dynamic_cast. If usage of USD required usage of dynamic_cast, or exceptions, then those classes would also have to be marked. Though schema classes have their own type of RTTI and dynamic_cast only used in hydra renderer (I haven't researched why though), the usage of boost python would still require classes to be tagged. But otherwise I believe changes will be minimal. The easiest first change, and the one which won't break any client code, is compiling python modules with "hidden" default visibility. In some cases it reduces size of the binary by more than half. Building other libraries with I'll try to make PR this week. |
After a lot of research on how to do this right, and without too much meaningless work, I came to the conclusion that adding export declarations to class methods is not the best way. Best way would be to only add FOO_API to a class only, and let all members be exported. This is how big c++ projects do it (like Qt), if they ever bother with visibility at all. I see no reason to not export class method, if you export class. The benefits are tiny, and this selective export only works on windows, anyway. My proposal for this is just add FOO_API to all exported classes, and remove it from all methods. |
Hi @sopvop , ex-Pixar intern here. For what it's worth, I came across this thread while trying to evaluate whether I should also in my own projects export whole classes or do the same as what USD was doing (only export public methods). I stumbled upon the following issue: pybind/pybind11#2132 I'm really very far from being an expert in this stuff, but I just wanted to note that Qt extensively uses the pimpl idiom, and does not use STL classes (e.g., std::string, std::vector, etc.), and therefore exporting whole classes is perhaps less of a concern in their cases (it's not going to bloat their dynamic tables with thousands of template classes). Exporting STL classes, especially in Windows DLLs, seems a little frowned upon according to my research. That being said, maybe your conclusion is still the most sensible one, and exporting whole classes makes sense for USD too (and most libraries), not just Qt. Especially when writing Python bindings is important. I'm still a bit unclear about all this and just sharing my thoughts, in case it's useful. Sorry for the noise. |
Exporting STL classes fails in subtle ways in Microsoft's libraries whenever there is shared state across classes. Things will often appear to work correctly, but subtle bugs occur when two different DLLs access the same supposedly shared state, but actually each DLL has its own copy, initialized independently. A second problem with exporting whole classes, is that when templates are involved, as @dalboris notes, symbol tables can become so large that linking fails. We started the OpenEXR project with whole class exports. OpenEXR has a much simpler class structure than USD, and over time, subtle Windows specific issues piled up, including severe problems such as stack corruptions, until we finally bit the bullet and explicitly exported the API, as USD does. OpenEXR's cross platform behavior is now correct, and the Windows specific bugs resulting from class exports have all been resolved. |
Thanks @meshula for the added details and historical notes, very instructive and appreciated. |
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
…build, and altering a few default settings: commit 74ee7e4733e4edfa05331541bf3504705c6d139f Author: Mark Tucker <[email protected]> Date: Wed Sep 29 23:15:43 2021 -0400 Attempt to link pxOsd against osdCPU only, not osdGPU. This might help eliminate indirect dependencies on OpenGL. commit 51a35a4875df8f877332fab27b272baa5ca4043f Author: Mark Tucker <[email protected]> Date: Tue Jun 15 16:02:57 2021 -0400 Switch the default value for USD_ABC_XFORM_PRIM_COLLAPSE from true to false, since this seems to be what most Houdini users expect. commit 0b909bf6fa83e254e1abc145b0414677836adac9 Author: Robert Vinluan <[email protected]> Date: Thu Nov 26 15:34:48 2020 -0500 Ensure default (public) symbol visibility on macOS Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols. commit 6b09d26522d74811f759485b39990330fe3366f9 Author: Mark Tucker <[email protected]> Date: Sat Feb 6 12:39:51 2021 -0500 Provide a define that will allow render delegate developers to disable python support while building their render delegates against Houdini's USD library (which is always built with python support enabled). commit 2c77e917a41aa7ae06bac64165c1c214de0f2268 Author: Mark Tucker <[email protected]> Date: Wed Jul 22 03:32:45 2020 -0400 Houdini-specific patches unique to the SideFX build process, but also potentially useful for anyone wanting to build USD for use within Houdini.
commit 3607f3e816dfebdfbc5229346ee639181d37e50a Author: Mark Tucker <[email protected]> Date: Thu Apr 14 23:36:15 2022 -0400 Squashed commit of MaterialX-related changes for Houdini's USD library: commit 257c6fec870d85b68854b62a351716dc40e7ce06 Author: Mark Tucker <[email protected]> Date: Sun Jul 18 12:54:20 2021 -0400 A few small additions new to 21.08 for changes to Mtlx build and changes to sdrOsl plugin code. commit addbe745150062fe67267333251ad5f717a326fd Author: Mark Tucker <[email protected]> Date: Thu Apr 14 23:28:00 2022 -0400 Eliminate any specification of the MaterialX "libraries" path at compile time. This assumes a particular installation location, or that a specific project-relative path will always be valid, and there's no reason to think this. commit a8232398dbffc0affc53b33a04400e97602facc7 Author: Mark Tucker <[email protected]> Date: Sun Jul 18 00:26:08 2021 -0400 Provide a flag to turn on the MATERIALX_BUILD_SHARED_LIBS define in libraries that build against MaterialX. This is required to enable defines within MaterialX code that allow importing symbols from shared libraries on Windows. # Conflicts: # cmake/modules/FindMaterialX.cmake # pxr/imaging/hdSt/CMakeLists.txt commit 99dd54bee1d5f0a09039e0079205e6722f9934b8 Author: Mark Tucker <[email protected]> Date: Thu Apr 14 23:14:17 2022 -0400 Squashed commit of the following Houdini-specific changes to the USD build, and altering a few default settings: commit 74ee7e4733e4edfa05331541bf3504705c6d139f Author: Mark Tucker <[email protected]> Date: Wed Sep 29 23:15:43 2021 -0400 Attempt to link pxOsd against osdCPU only, not osdGPU. This might help eliminate indirect dependencies on OpenGL. commit 51a35a4875df8f877332fab27b272baa5ca4043f Author: Mark Tucker <[email protected]> Date: Tue Jun 15 16:02:57 2021 -0400 Switch the default value for USD_ABC_XFORM_PRIM_COLLAPSE from true to false, since this seems to be what most Houdini users expect. commit 0b909bf6fa83e254e1abc145b0414677836adac9 Author: Robert Vinluan <[email protected]> Date: Thu Nov 26 15:34:48 2020 -0500 Ensure default (public) symbol visibility on macOS Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols. commit 6b09d26522d74811f759485b39990330fe3366f9 Author: Mark Tucker <[email protected]> Date: Sat Feb 6 12:39:51 2021 -0500 Provide a define that will allow render delegate developers to disable python support while building their render delegates against Houdini's USD library (which is always built with python support enabled). commit 2c77e917a41aa7ae06bac64165c1c214de0f2268 Author: Mark Tucker <[email protected]> Date: Wed Jul 22 03:32:45 2020 -0400 Houdini-specific patches unique to the SideFX build process, but also potentially useful for anyone wanting to build USD for use within Houdini. # Conflicts: # cmake/defaults/ProjectDefaults.cmake # cmake/macros/Private.cmake # cmake/macros/Public.cmake # cmake/modules/FindPySide.cmake # pxr/usdImaging/usdImagingGL/plugInfo.json
commit 3607f3e816dfebdfbc5229346ee639181d37e50a Author: Mark Tucker <[email protected]> Date: Thu Apr 14 23:36:15 2022 -0400 Squashed commit of MaterialX-related changes for Houdini's USD library: commit 257c6fec870d85b68854b62a351716dc40e7ce06 Author: Mark Tucker <[email protected]> Date: Sun Jul 18 12:54:20 2021 -0400 A few small additions new to 21.08 for changes to Mtlx build and changes to sdrOsl plugin code. commit addbe745150062fe67267333251ad5f717a326fd Author: Mark Tucker <[email protected]> Date: Thu Apr 14 23:28:00 2022 -0400 Eliminate any specification of the MaterialX "libraries" path at compile time. This assumes a particular installation location, or that a specific project-relative path will always be valid, and there's no reason to think this. commit a8232398dbffc0affc53b33a04400e97602facc7 Author: Mark Tucker <[email protected]> Date: Sun Jul 18 00:26:08 2021 -0400 Provide a flag to turn on the MATERIALX_BUILD_SHARED_LIBS define in libraries that build against MaterialX. This is required to enable defines within MaterialX code that allow importing symbols from shared libraries on Windows. # Conflicts: # cmake/modules/FindMaterialX.cmake # pxr/imaging/hdSt/CMakeLists.txt commit 99dd54bee1d5f0a09039e0079205e6722f9934b8 Author: Mark Tucker <[email protected]> Date: Thu Apr 14 23:14:17 2022 -0400 Squashed commit of the following Houdini-specific changes to the USD build, and altering a few default settings: commit 74ee7e4733e4edfa05331541bf3504705c6d139f Author: Mark Tucker <[email protected]> Date: Wed Sep 29 23:15:43 2021 -0400 Attempt to link pxOsd against osdCPU only, not osdGPU. This might help eliminate indirect dependencies on OpenGL. commit 51a35a4875df8f877332fab27b272baa5ca4043f Author: Mark Tucker <[email protected]> Date: Tue Jun 15 16:02:57 2021 -0400 Switch the default value for USD_ABC_XFORM_PRIM_COLLAPSE from true to false, since this seems to be what most Houdini users expect. commit 0b909bf6fa83e254e1abc145b0414677836adac9 Author: Robert Vinluan <[email protected]> Date: Thu Nov 26 15:34:48 2020 -0500 Ensure default (public) symbol visibility on macOS Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols. commit 6b09d26522d74811f759485b39990330fe3366f9 Author: Mark Tucker <[email protected]> Date: Sat Feb 6 12:39:51 2021 -0500 Provide a define that will allow render delegate developers to disable python support while building their render delegates against Houdini's USD library (which is always built with python support enabled). commit 2c77e917a41aa7ae06bac64165c1c214de0f2268 Author: Mark Tucker <[email protected]> Date: Wed Jul 22 03:32:45 2020 -0400 Houdini-specific patches unique to the SideFX build process, but also potentially useful for anyone wanting to build USD for use within Houdini. # Conflicts: # cmake/defaults/ProjectDefaults.cmake # cmake/macros/Private.cmake # cmake/macros/Public.cmake # cmake/modules/FindPySide.cmake # pxr/usdImaging/usdImagingGL/plugInfo.json
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
…s#665) ### Description of Change(s) Remove the redudant StartEndIndex ### Fixes Issue(s) - <!-- Please follow the Contributing and Building guidelines to run tests against your change. Place an X in the box if tests are run and are all tests passing. --> - [ ] I have verified that all unit tests pass with the proposed changes <!-- Place an X in the box if you have submitted a signed Contributor License Agreement. A signed CLA must be received before pull requests can be merged. For instructions, see: http://openusd.org/release/contributing_to_usd.html --> - [ ] I have submitted a signed Contributor License Agreement (cherry picked from commit f7c5c8641af209c597493892ae5256e625224237)
Houdini recently moved to hidden visibility on Mac, however, USD currently cannot build with hidden visibility. See PixarAnimationStudios#665. Loading USD libraries and Houdini USD plugin libraries into the same process produces two sets of the same USD symbols: one set of external USD symbols from the USD libraries; and the other set of non-external USD symbols from the Houdini plugin libraries. The macOS loader cannot coalesce the two sets causing duplicate symbols in the process. The duplicate symbols cause various issues including dynamic_cast to fail in cases where it is expected to succeed. This change ensures that default visibility is set for code dealing with USD, whether it is code compiled into the USD libraries or Houdini's plugin libraries. This guarantees one set of external USD symbols loaded into the process. Note that there are no issues with mixing Houdini plugin libraries (hidden visibility) and USD libraries (default visibility) on Linux. The Linux loader can coalesce the two sets of USD symbols.
Description of Issue
If you try to build USD with gcc or clang with
-fvisility=hidden
it will fail when linking.Steps to Reproduce
Why is this important.
Importance of builiding with hidden visibility is well described in GCC Wiki here.
tldr: It allows compiler and linker to do more optimizations, makes startup faster and binaries smaller.
Unlike MSVC, gcc does not export typeinfo and vtable of class by default. MSVC exports it if any member has attribute
__declspec(dllexport)
but gcc (and clang IIRC) require class to be declared with visibility attribute:In USD sources FOO_API macro expand to
__attribute__ ((visibility ("default")))
on gcc or__declspec(dllexport)
on windows, and those have different semantics when applied to types.GCC will only export necessary rtti machinery (vtable, typeinfo and the like), but msvc will export all members as if all of them have
__declspec(dllexport)
attribute.Fix
I propose to add
FOO_CLASS_API
or similarly named macro toapi.h
headers which will expand to__attribute__ ((visibility ("default")))
on gcc/clang and to nothing on windows. And add it to codegen templates and all public classes.The text was updated successfully, but these errors were encountered: