Build dynamic library by default
Using a statically linked dune-common together with the Python bindings leads to hard-to-diagnose crashes and other bugs (specifically, a double 'free' in the destructor of DebugStream). This patch therefore enables shared libraries by default, and adds an explanation of why this is necessary.
Merge request reports
Activity
The same for
dune-uggrid
: staging/dune-uggrid!242mentioned in merge request staging/dune-uggrid!242
This implementation always builds dynamic libraries. Static libraries also have its use cases. IMO we have to instead design default CMake presets for the python bindings rather hard coding this into de build system.
I think this should be in 2.10.
- We have a modular design, this means that either every module also has to set this, or the user may end up with mixed libraries. This can be even more confusing: each kind has its own set of challenges. If we want to have a consistent behavior across modules, this is too late for the release.
- This sounds like trying to masquerade bugs that we could not solve (or we were not aware of). Shared libraries might solve the immediate bug in dune-common, but why to ship something where we have even less experience with?
Edited by Santiago Ospina De Los RíosIn the cmake docu they write that there are two types of presets, the one the could be checked-in to the repository, the other one a private preset. Maybe we can ship a preset for the python bindings.
I agree, that changing the default library type to "shared" in just one module looks surprising to me and it is not very well tested so short before a release. We could instead add a proper error/warning message in case python bindings are enabled and static libraries are beeing used.
An error/warning would be much better IMO than the status quo. Note though that an error will mean that a default Dune build will always fail: Python bindings are on by default (rightfully so, IMO), but so are static-only libraries.
Implementing an error messages exceeds my CMake guru level, unfortunately.
I will be more than happy to replace this by something better after 2.10. However, right now I recommend this new "easy" Python interface to people, and it crashes without helpful error message as soon as they do something nontrivial with
UGGrid
. Yes, maybe it says "for Python you need to enable shared libraries when building", but honest, who reads that?And I don't see the downside to my proposal. What's so bad about mixing shared libraries with static ones?
A downside of dynamic libraries, also pointed out by @andreas.dedner, is that we need to make sure all the paths to the dynamically loaded libraries and dependencies are correctly set in the packages/executables, even when copied around. This is not trivial. Actually, CMake should help with that and we can probably investigate this again, but it would take some time and the outcome is open. It probably works nicely in a local setup, if you just run
dunecontrol
, but in combination with installation and packaging we need to be more careful.
9 9 message(FATAL_ERROR "CMake 3.29.1 is not compatible with Dune. Use a different CMake version.") 10 10 endif() 11 11 12 # Build shared libraries by default. 13 # 14 # Rationale: When using Dune via its C++ interface you can use static 10 10 endif() 11 11 12 # Build shared libraries by default. 13 # 14 # Rationale: When using Dune via its C++ interface you can use static 15 # or dynamic libraries as you like. However, for the Python bindings 16 # you have to use dynamic libraries. That is because dune-common 17 # contains a few global variables, for example 'DebugStream'. 18 # The just-in-time compiler that builds the Dune Python bindings 19 # produces a collection of dynamic libraries. If dune-common is built 20 # as a static library, then a copy of this static library is included 21 # in each of the JIT-compiled dynamic libraries. 22 # As a consequence, the global variables of dune-common exist not once, 23 # but once in every JIT-compiled dynamic library, which leads to 24 # hard-to-diagnose crashes and wrong results. 25 set(BUILD_SHARED_LIBS 1) Using a regular variable will not allow users to change this. Suggestion:
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
later on in the CMakeLists file, one could also check for properly set
BUILD_SHARED_LIBS
flag in case python bindings are enabled: Maybe something likeif(DUNE_ENABLE_PYTHONBINDINGS) if (NOT BUILD_SHARED_LIBS) message(FATAL_ERROR "The option BUILD_SHARED_LIBS is required for the Python bindings to work correctly. Set this option on the command line or the Dune .opts file.") endif() add_subdirectory(python) endif()
Edited by Simon Praetoriuschanged this line in version 2 of the diff
In fact this MR makes the tests on github fail already. Switching to shared libs might be a problem for the packaging, e.g., https://github.com/dune-project/dune-testpypi/actions/runs/10680388545/job/29601736577
At the moment package building does not work with shared libraries. The issue is that they are build in an isolated environment and then need to be copied into the venv. Shared libraries are not easy to move - at least we didn't get it to work. Samuel and myself did some work on this end of 2020/2021 (see log messages) playing around with setting rpaths etc. but couldn't get it to work. So decided to turn off shared libs for the packaging. So if we enable shared by default this has to be turned off during build from package index, i.e.,
if(not SKBUILD)
We could check while loading any python module from
dune-ug
iflibduneug
was shared. If not a meaningful error message could be printed. That does not change anything for current setup as long as I don't usedune.grid.uggrid
in my code. If I do then an error message is probably useful. Just not sure how to check thatlibduneug
is available asso
file...So,
BUILD_SHARED_LIBS
seems to work in our system tests. I will run the testing-scenarios again to see the effect of the latest changes. If this does not work (if fails), we cannot (yet) activateBUILD_SHARED_LIBS
by default. Adding a warning (or even an error) if shared libraries are not activated (which is not the current default) seems to be a strange behavior as well. We claim that it is not working without that flag but the flag is not set by default but the python bindings are enabled by default (leading to a CMake warning by default) - this is surprising.Not sure whether we find an acceptable solution for 2.10 so quickly. Maybe we can backport a solution once we have decided on a behavior.
Edited by Simon PraetoriusNot sure whether we find an acceptable solution for 2.10 so quickly.
I think is fine to change to shared libraries (although I would prefer the warning TBH). But making this change on the same day of the release is not acceptable. We simply cannot foresee all the possible consequences of this change in few hours.
- Resolved by Santiago Ospina De Los Ríos
Independent of whether this will be the default or not, we should investigate why the CI for the core modules fails when
dune-common
has dynamic libraries. As far as I can see, this is not even related to the python bindings.
added 91 commits
-
76172bd3...b4c8be7f - 90 commits from branch
master
- e13bc94a - Build dynamic library by default
-
76172bd3...b4c8be7f - 90 commits from branch
mentioned in issue infrastructure/dune-nightly-test#2