-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Enable building Catch2 as a dynamic library #2398
Conversation
Signed-off-by: Alecto Irene Perez <[email protected]>
Codecov Report
@@ Coverage Diff @@
## devel #2398 +/- ##
==========================================
- Coverage 91.36% 91.08% -0.28%
==========================================
Files 157 153 -4
Lines 7430 7288 -142
==========================================
- Hits 6788 6638 -150
- Misses 642 650 +8 |
I thought about this a bit, and I am willing to merge it if you add a CMake warning when compiling dynamic libs under Windows platform (or default visibility set to hidden, as everyone should be doing anyway 😃 ). |
This commit makes the default visibility hidden, and annotates the necessary types and classes to be public
src/catch2/interfaces/catch_interfaces_enum_values_registry.hpp src/catch2/interfaces/catch_interfaces_generatortracker.hpp src/catch2/interfaces/catch_interfaces_registry_hub.hpp src/catch2/interfaces/catch_interfaces_reporter_factory.hpp src/catch2/interfaces/catch_interfaces_reporter_registry.hpp src/catch2/interfaces/catch_interfaces_tag_alias_registry.hpp src/catch2/internal/catch_case_insensitive_comparisons.hpp src/catch2/internal/catch_fatal_condition_handler.cpp src/catch2/internal/catch_fatal_condition_handler.hpp src/catch2/internal/catch_istream.cpp src/catch2/internal/catch_preprocessor_remove_parens.hpp src/catch2/internal/catch_reusable_string_stream.hpp src/catch2/internal/catch_test_case_registry_impl.cpp src/catch2/internal/catch_test_case_registry_impl.hpp src/catch2/matchers/catch_matchers_floating_point.hpp src/catch2/matchers/internal/catch_matchers_combined_tu.cpp src/catch2/reporters/catch_reporter_cumulative_base.cpp src/catch2/reporters/catch_reporter_cumulative_base.hpp src/catch2/reporters/catch_reporter_streaming_base.hpp tests/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp tests/ExtraTests/X22-BenchmarksInCumulativeReporter.cpp tests/ExtraTests/X26-ReporterPreferencesForPassingAssertionsIsRespected.cpp tests/ExtraTests/X27-CapturedStdoutInTestCaseEvents.cpp tests/ExtraTests/X28-ListenersGetEventsBeforeReporters.cpp tests/SelfTest/Baselines/automake.sw.multi.approved.txt tests/SelfTest/Baselines/compact.sw.multi.approved.txt tests/SelfTest/Baselines/console.sw.multi.approved.txt tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt tests/SelfTest/IntrospectiveTests/CmdLineHelpers.tests.cpp tests/SelfTest/IntrospectiveTests/ColourImpl.tests.cpp tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp tests/SelfTest/IntrospectiveTests/TestCaseInfoHasher.tests.cpp
775e79c
to
87cbc79
Compare
I set the default visibility to hidden. I had to add so many instances of |
The reason it shows so many changes is because I had to merge in devel since my branch was no longer current. If you look at the change on the commandline vs the current devel branch you'll see it's not so bad. It's just hundreds and hundreds of insertions of CATCH_DLL_PUBLIC. But I did what you wanted. |
If you want I can update the CI matrix to have both building with and without shared libraries |
huh, why? I only said I wanted to add a dev warning if people built the dynamic library with hidden visibility default. ... Oh, I see how my last post could've been misinterpreted. RIP 😆 |
Okay so... I'm sorry for the misunderstanding. I thought you wanted the default visibility to be hidden, and I figured it had been something you were putting off because of all the annotations it required, so I thought I'd take care of it. If the default visibility is set to hidden for all targets, and Catch2 is built as a shared library, it'll fail to compile straight-up due to the linker errors, and I think a warning won't be enough. What if we make the visibility set_target_properties(Catch2 PROPERTIES CXX_VISIBILITY_PRESET default)
set_target_properties(Catch2WithMain PROPERTIES CXX_VISIBILITY_PRESET default) |
Not like it was my time that was spent doing this 🙃
This wouldn't be wrong some time ago, but I've spent the last ~year getting builds of a multilibrary, old, commercial, linux-only project to work on new platforms and be done in a sane manner, and I don't think that a reasonable annotation set for Catch2 is possible. The issue boils down to the fact that Catch2's API surface is massive (I would say that more than half of its symbols are exported naturally, most of the rest are exported transitively), so almost everything would have to be annotated. Annotated exports are good if your users can use only a small subset of the symbols in the binary (e.g. we export <100 C symbols for a C++ library with 50k+ symbols compiled in, which in turn more than halves the binary size). This applies even if the visibility for tests is handled differently -- trying to link tests against dyn libraries is a common way to have massively larger export set than actually needed by the users.
As you say, if the visibility is hidden, the linking will fail. The reason to still have a warning is twofold:
There is an argument to make it a hard error, but then we would also need to provide a way to override this for users who "know better" for some reason (e.g. they have explicit export files).
I am not sure what would happen on Linux if the user also added |
@codeinred Are you planning to finish the PR? |
I am, yes!! I'm so sorry it's taken so long. I've been dealing with finals for school |
The thing about symbol visibility is that Windows does the right thing. On Windows, you have no options but to have everything hidden, unless annotated otherwise. Unfortunately for UNIX-like systems, legacy dictates different defaults and they can only recommend doing the right thing. For C++ targets, you need to set two properties to effectively pass the
There are some issues indeed, since this is a workaround for a UNIX-ism. For the record, CMake parses the PE/COFF object files and dumps the COFF (or bigobj) symbol table from an OBJ file using filters that assume MSVC ABI (and its name mangling). |
@horenmar The I have come to the conclusion that for us the only sane way to build Catch2 as a DLL is to annotate the source code. Would you consider accepting a PR that does this, if it is clean and done right? If not, we'll have to maintain a custom patch on our side, which is also an option. (It will probably break every time we upgrade to a newer version of Catch, but it shouldn't be hard to fix.) |
The feature is implemented entirely in this file: https://github.com/Kitware/CMake/blob/master/Source/bindexplib.cxx |
Yes, I know, thanks @friendlyanon. I did try to use |
@stefanhaller Do you have a strong reason not to use Catch2 as a static library? Anyway, I would be willing to accept a patch that annotates the sources if it comes with good CI design. The current test projects are not suitable to testing proper annotations, because |
Yes, we have an architecture where Catch2 is used both from the executable and from one or more DLLs that the executable depends on. If we build as a static library, each of these get their own copy of Catch2's singletons (mostly
This seems to make the approach infeasible (like you said earlier 😄), so for now I'm going with maintaining my own local patch. Thanks. |
Description
This PR enables users to opt in to building Catch2 as a shared library by passing
-DBUILD_SHARED_LIBS=ON
when building Catch2.Having Catch2 available as a shared library reduces build times and enables faster compilation and faster iteration of test code.
Catch2 will still be built as a static library by default.
GitHub Issues
This PR request resolves Issue #2397, Enable Users to Opt-In to Building Catch2 as a Shared Library