[CMake] Can/should we specify optional dependencies
I have a regex bug report relating to linking to ICU when using CMake: https://github.com/boostorg/regex/issues/143 Is there a correct way to specify in the CMake file that if you use header X, then you should also link to library Y, but otherwise not? Thanks, John. -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
The most correct solution would be providing a separate regex-icu package altogether, that depends on both regex and ICU, but I don't think Boost rolls that way. Optional dependencies are really nasty. I guess what one could do is have a package component and request ICU support explicitly: # The user requests regex with ICU, so it's safe to # find_dependency(ICU i18n) in the package config for ICU # internationalization and link it with the # regex/headers target find_package(Boost REQUIRED regexWithICU)
On 10/8/21 5:07 PM, John Maddock via Boost wrote:
I have a regex bug report relating to linking to ICU when using CMake: https://github.com/boostorg/regex/issues/143
Is there a correct way to specify in the CMake file that if you use header X, then you should also link to library Y, but otherwise not?
I don't think so, unless you create a new library (target, in CMake terms) that will depend on ICU, and that users will have to "link" with. Or you could conditionally enable ICU support based on CMake config option. We do something like this in Boost.Filesystem: https://github.com/boostorg/filesystem/blob/ec93082b6b54cd734b236638e7c4ba76... Either way, the user will have to do something explicitly - either add linking with the new target or specify the option in the CMake command line. Simply including a C++ header won't work as that is beyond CMake scope.
Andrey Semashev wrote:
Or you could conditionally enable ICU support based on CMake config option. We do something like this in Boost.Filesystem:
https://github.com/boostorg/filesystem/blob/ec93082b6b54cd734b236638e7c4ba76...
The closest example is https://github.com/boostorg/locale/blob/33d06c0c4be7f9bcfb05e200c72f752e9777...
On 08/10/2021 16:10, Peter Dimov via Boost wrote:
Andrey Semashev wrote:
Or you could conditionally enable ICU support based on CMake config option. We do something like this in Boost.Filesystem:
https://github.com/boostorg/filesystem/blob/ec93082b6b54cd734b236638e7c4ba76... The closest example is
https://github.com/boostorg/locale/blob/33d06c0c4be7f9bcfb05e200c72f752e9777...
Thanks for the examples everyone, much appreciated. I confess I'm having a hard time seeing how a configuration option is better than the user simply adding the dependency to their executable CMake file? Thanks, John. -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
On 10/9/21 6:59 PM, John Maddock via Boost wrote:
On 08/10/2021 16:10, Peter Dimov via Boost wrote:
Andrey Semashev wrote:
Or you could conditionally enable ICU support based on CMake config option. We do something like this in Boost.Filesystem:
https://github.com/boostorg/filesystem/blob/ec93082b6b54cd734b236638e7c4ba76...
The closest example is
https://github.com/boostorg/locale/blob/33d06c0c4be7f9bcfb05e200c72f752e9777...
Thanks for the examples everyone, much appreciated.
I confess I'm having a hard time seeing how a configuration option is better than the user simply adding the dependency to their executable CMake file?
If you mean ICU dependency then that's exposing Boost.Regex implementation details (which is what an internal dependency is) to users. At least, make it a Boost.Regex target for users to depend on. However, a config option has a configurability advantage. For example, a user who consumes a product that uses Boost.Regex may choose whether the whole product will depend on ICU or not. Personally, I would prefer this kind of flexibility.
On 09/10/2021 18:11, Andrey Semashev via Boost wrote:
On 10/9/21 6:59 PM, John Maddock via Boost wrote:
On 08/10/2021 16:10, Peter Dimov via Boost wrote:
Andrey Semashev wrote:
Or you could conditionally enable ICU support based on CMake config option. We do something like this in Boost.Filesystem:
https://github.com/boostorg/filesystem/blob/ec93082b6b54cd734b236638e7c4ba76...
The closest example is
https://github.com/boostorg/locale/blob/33d06c0c4be7f9bcfb05e200c72f752e9777...
Thanks for the examples everyone, much appreciated.
I confess I'm having a hard time seeing how a configuration option is better than the user simply adding the dependency to their executable CMake file? If you mean ICU dependency then that's exposing Boost.Regex implementation details (which is what an internal dependency is) to users. At least, make it a Boost.Regex target for users to depend on. Making it a separate target does make sense to me.
However, a config option has a configurability advantage. For example, a user who consumes a product that uses Boost.Regex may choose whether the whole product will depend on ICU or not. Personally, I would prefer this kind of flexibility.
I don't see how this can work - either the code includes boost/regex/icu.hpp in which there is a dependency, or it doesn't and there is no dependency. In other words it's a software design issue whether the dependency exists or not, there's nothing an end user can configure. Thanks, John. -- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
On 10/9/21 9:54 PM, John Maddock via Boost wrote:
On 09/10/2021 18:11, Andrey Semashev via Boost wrote:
On 10/9/21 6:59 PM, John Maddock via Boost wrote:
On 08/10/2021 16:10, Peter Dimov via Boost wrote:
Andrey Semashev wrote:
Or you could conditionally enable ICU support based on CMake config option. We do something like this in Boost.Filesystem:
https://github.com/boostorg/filesystem/blob/ec93082b6b54cd734b236638e7c4ba76...
The closest example is
https://github.com/boostorg/locale/blob/33d06c0c4be7f9bcfb05e200c72f752e9777...
Thanks for the examples everyone, much appreciated.
I confess I'm having a hard time seeing how a configuration option is better than the user simply adding the dependency to their executable CMake file? If you mean ICU dependency then that's exposing Boost.Regex implementation details (which is what an internal dependency is) to users. At least, make it a Boost.Regex target for users to depend on. Making it a separate target does make sense to me.
However, a config option has a configurability advantage. For example, a user who consumes a product that uses Boost.Regex may choose whether the whole product will depend on ICU or not. Personally, I would prefer this kind of flexibility.
I don't see how this can work - either the code includes boost/regex/icu.hpp in which there is a dependency, or it doesn't and there is no dependency.
In other words it's a software design issue whether the dependency exists or not, there's nothing an end user can configure.
Is there no other backend an application could use instead of ICU?
John Maddock wrote:
I have a regex bug report relating to linking to ICU when using CMake: https://github.com/boostorg/regex/issues/143
Is there a correct way to specify in the CMake file that if you use header X, then you should also link to library Y, but otherwise not?
I don't see how. CMake doesn't know whether someone will include header X or not. With compiled libraries, we use CMake options to control whether the library is built with support for ICU or not, but here we don't build anything. I suppose you could still add a build option that won't do anything except `target_link_libraries(boost_regex INTERFACE ICU::in)`, as suggested in the issue (although for consistency the option should be named BOOST_REGEX_ENABLE_ICU because that's the convention the other libraries use.)
On 9/10/2021 03:40, Peter Dimov wrote:
John Maddock wrote:
I have a regex bug report relating to linking to ICU when using CMake: https://github.com/boostorg/regex/issues/143
Is there a correct way to specify in the CMake file that if you use header X, then you should also link to library Y, but otherwise not?
I don't see how. CMake doesn't know whether someone will include header X or not.
Provided that you can assume that the config (in the form of a #define) is visible to every compilation unit (or at least those that consume the library in some fashion), then you could make the header file itself define and do nothing (or perhaps raise a #error) if not enabled in the configuration. This way, attempts to use the header will fail unless enabled in the config, which would allow you to add dependencies as required. I'm not sure how straightforward it is to do this in CMake, although I thought "building everything with the same settings" is explicitly one of its goals.
participants (5)
-
Andrey Semashev
-
Gavin Lambert
-
Horváth V.
-
John Maddock
-
Peter Dimov