boostorg / boost_install

8 stars 30 forks source link

CMake package of libraries with dependencies to external libraries #18

Open sdebionne opened 4 years ago

sdebionne commented 4 years ago

Some Boost libraries have dependencies to third party libraries: Boost.Iostreams (zlib, bzip2), Boost.Local (ICU), Boost.MPI (some MPI lib) come to mind.

In the current configuration package generated by the boost-install rule, the dependency to the third party library is not set explicitly. If we look at the Iostreams test:

add_executable(test_gzip test_gzip.cpp)
target_link_libraries(test_gzip Boost::iostreams)
target_link_libraries(test_gzip ZLIB::ZLIB) # should not be necessary

This introduce subtle issues with the linking order since the dependency graph is

test_gzip  <-- Boost::iostreams
           <-- ZLIB::ZLIB

instead of

test_gzip  <-- Boost::iostreams <-- ZLIB::ZLIB

A possible solution would be to add something like find_dependency(ZLIB) and target_link_libraries(Boost::iostreams ZLIB::ZLIB) in the CMake config file.

pdimov commented 4 years ago

The problem with Iostreams is that ZLIB is an optional dependency. find_dependency by itself is probably not appropriate.

pdimov commented 4 years ago

Actually it's even worse than that, Iostreams may build its own zlib from source and install it. :-/

sdebionne commented 4 years ago

Well Iostreams was just an example, my real issue is with MPI :-) and that is most probably fixed with 63c74f6, thanks.

When the install-boost rule runs, do we have access to the configuration? I guess this information is available somewhere in the build system... If so, could we conditionally generate the dependency bloc?

pdimov commented 4 years ago

That's not easy at all. The architecture of b2 is such that it works in two passes, roughly equivalent to cmake .. and cmake --build .. The CMake configs are created during the first pass, whereas the information whether Iostreams links with zlib is only available during the second pass. For example, if you do b2 address-model=32,64 and you have a 32 bit zlib but not a 64 bit one, the 32 bit Iostreams will link to zlib, and the 64 bit one will not. (Assuming that NO_ZLIB and ZLIB_SOURCE aren't set.)

It's probably possible to hack something that will mostly work, I suppose.

There might be a way to do it properly, but my b2 knowledge isn't at that level yet.

sdebionne commented 4 years ago

OK I understand better the complexity. I have only basic user knowledge about Boost.Build so won't be able to help you much. I guess the idea would be to generate the CMake config at build time (as opposed to config time). Maybe we could take some inspiration from the install rule that apparently knows about the dependencies since it has an option <install-dependencies>on to install them with the main target.

mathstuf commented 4 years ago

boostorg/uuid#68 might mean that even header-only bits need a target per library.

mathstuf commented 4 years ago

Another solution might be to add BOOST_BOOST_NO_AUTO_LINK to only skip autolinking statements for Boost → Boost dependencies.

Lastique commented 4 years ago

There are more mundane cases where an external dependency is needed but not exposed in the config files. For example, in Boost.Filesystem (https://github.com/boostorg/filesystem/issues/156), Boost.Log and Boost.Atomic we need to link the Boost libraries against some Windows SDK (synchronization, bcrypt, advapi32, etc.) or system (rt, socket, nsl, ipv6) libraries. It is important to expose those dependencies because when linking against static Boost libraries the user must still specify the private dependencies in the linker command line.

pdimov commented 3 years ago

I've added code to develop that translates linking to lib foo ; on the b2 side to the equivalent of target_link_libraries(boost_xxx foo) on the CMake side. The logic is not particularly smart, as it links to foo even for lib foo : <name>bar ; but it seems to work for the current uses in Boost.