View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0016013CMakeCMakepublic2016-03-11 05:442016-06-10 14:21
ReporterRuslan Baratov 
Assigned ToRoger Leigh 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product VersionCMake 3.5 
Target VersionCMake 3.5.1Fixed in VersionCMake 3.5.1 
Summary0016013: FindBoost: iostreams depends on regex [3.5 regression]
DescriptionLooks like the fact that boost.iostreams depends on boost.regex hardcoded in new version of FindBoost module. So such code no longer works:
 
    find_package(Boost REQUIRED COMPONENTS iostreams)

and produce an error:

   Could not find the following static Boost libraries:
       boost_regex

if I have only boost.iostreams installed (without boost.regex).

Example works fine (build/run) without boost.regex with CMake 3.4.3
TagsNo tags attached.
Attached Files

 Relationships
related to 0016020closedRoger Leigh FindBoost "Automatically add missing component dependencies" fails with header-only libraries 

  Notes
(0040660)
Ruslan Baratov (reporter)
2016-03-11 05:51

I don't know where the information about dependency comes from. Here is `otool -L` result on `libboost_iostreams-mt.dylib` installed by brew on OSX:

    /usr/local/opt/boost/lib/libboost_iostreams-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
    /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
(0040662)
Brad King (manager)
2016-03-11 08:23

For reference, the dependency table was added here:

 FindBoost: Embed component dependency table
 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5183c6e5 [^]
(0040665)
Roger Leigh (developer)
2016-03-12 15:02

Dear Ruslan,

The information comes from the headers, and is supplementary to the dependencies in the shared lib itself. It's akin to the autolink behaviour you get with MSVC--in fact, it's derived directly from the autolink header usage for each header in each component. See Utilities/Scripts/BoostScanDeps.cmake for the script which scans the headers to generate the dependency information. You can run this against your Boost headers to see what it generates. The instructions for doing this are in FindBoost.cmake.

If you look at boost/iostreams/filter/{grep|regex}.hpp, you will see that the regex headers are included here (and by extension, a dependency upon libboost_regex). This is the reason why it's included. But on systems the unused libraries will be culled by the linker.

When developing the feature, this behaviour was discussed. The current approach is conservative: when you use Boost::Iostreams, the dependencies include all dependencies of all the boost/iostreams headers, which will guarantee a successful link under all circumstances with shared or static libs for a typical boost build. But if you don't use (in this case) boost/iostreams/filter, you are getting a dependency you don't need. But it might *potentially* be needed; at the granularity of a single component, we have no means to determine that when FindBoost is run.

If we went the other way, and restricted ourselves only to dependencies under our component, we would avoid this, but require the user to manually specify all indirect dependencies (which are Boost-version-specific and are the main reason for adding the support in the first place). It would also remove *essential* dependencies such as boost_filesystem on boost_system. Having these dependencies work consistently was the primary driver for this support--it obviates the need for every use of FindBoost to hard-code the indirect dependencies, which are often done incorrectly given the variation between boost releases.

I'd certainly be happy to consider any change which would improve things, but I think it's also fair to say that it's behaving as designed. The issue here is the granularity of the cmake find_package components. If you say you want iostreams, we have no way to determine which specific bits of iostreams you will be using at the header level. And we have no way at present of classifying dependencies as essential or optional--maybe something to consider? We currently scan all headers in each component and then follow all their inter- and intra-component includes to find the libraries. That's a simple but consistent rule, but if there are headers which are rarely used and for which an explicit dependency would make sense, we could potentially hard-code such behaviour in the scanner. But it's a non-trivial task--you'd have to assess this for every header with an intra-component include and do it for all boost versions. Which is why we opted for the simple and conservative approach. But if you have any ideas for improving the behaviour, please do suggest them!

Kind regards,
Roger
(0040666)
Roger Leigh (developer)
2016-03-12 15:08

I should also mention that building without regex isn't the only case where this can break. It can also break e.g. on Windows when you build with a custom zlib or bzip2. The autolink information is static and doesn't know what name to link against so is fragile, and our generated dependencies are likewise as fragile. But it's the best we can do, both in FindBoost and as an end user--the compile-time options are not something we can easily cope with.

One other thought. Maybe we should make component dependencies optional, so if they aren't present we don't raise an error. That would be a simple solution to the problem. It would cater for different compile options, and would still fail if a directly-requested dependency is missing, but would handle system-specific linker variations gracefully. The only downside is not handling broken installations with missing parts, but it might be an acceptable compromise.
(0040667)
Ruslan Baratov (reporter)
2016-03-12 22:49

tl;dr It's a bug, I don't need regex when I do link iostreams. It broke correct/existing/working code.

> If you look at boost/iostreams/filter/{grep|regex}.hpp, you will see that the regex headers are included here

If library use some header-only stuff (like inline members) there is no need to do link.

> When developing the feature, this behaviour was discussed

Yep, and I've mentioned that such approach is broken by design. See ZLIB/BZip2 optional dependencies note:
* http://www.mail-archive.com/cmake-developers%40cmake.org/msg14835.html [^]

> If you say you want iostreams, we have no way to determine which specific bits of iostreams you will be using at the header level

But user know. Also it's not boost specific feature. Same way you can create CMake package that has optional dependencies and the fact that optional dependency used is known only by user.

> I'd certainly be happy to consider any change which would improve things

Only required dependency should be listed, optional dependencies should be removed.
(0040671)
Roger Leigh (developer)
2016-03-14 10:03

Please could you try the patch here:

  https://github.com/Kitware/CMake/compare/master...rleigh-dundee:boost-fix?expand=1 [^]

and let me know if it fixes the problem for you.

This is what I proposed above as a potential solution, but you didn't provide any comment upon that.

Note that the determination of whether a dependency is "required" or "optional" is not at all clear-cut. While we might say that regex is optional in this context, since it depends upon the headers included, we can't generalise this for all cases. We could need to be able to determine that boost_system is a requirement of boost_filesystem, and this means that we need to have some heuristic for which headers in each component are "used as standard" and which are less commonly used. This *isn't* akin to cmake packages with optional dependencies since it's based upon *how* a package is used--we can't encode this at the level of the package, it's finer-grained than that. There's no way to manage that level of complexity across all the Boost versions. While you say that "the user knows", that's not really true except in the most trivial case--these dependencies vary between boost versions, and the user's choice may well break with different boost versions; making this work robustly across all versions for all components is the entire purpose of this change, so that the end-user doesn't have to hardcode things and potentially make incorrect assumptions.

That said, I hope that the patch as proposed is a good enough compromise to satisfy both points of view.
(0040682)
Ruslan Baratov (reporter)
2016-03-14 14:18

> Please could you try the patch here

Works fine for me, thanks.

By the way is there a way to disable imported libraries creation? Like to turn on some option before `find_package`?
(0040683)
Roger Leigh (developer)
2016-03-14 14:50

OK, I'll push it into next soon.

Regarding import libraries, no user-settable variable exists to disable them. Do you have need of such a feature? If so, what's the rationale for that?
(0040685)
Ruslan Baratov (reporter)
2016-03-14 23:23

> Do you have need of such a feature?

It would be nice.

> If so, what's the rationale for that?

I have my own BoostConfig.cmake module which do call standard FindBoost.cmake. I think it will conflict with new Boost::* targets. Just want to avoid maintaining cmake-find code from FindBoost.cmake myself.
(0040686)
Ruslan Baratov (reporter)
2016-03-14 23:26

Note to admins:

Sometimes I've wrote a message, push "Add Note" and got error:

"Invalid form security token. This could be caused by a session timeout, or accidentally submitting the form twice."

When I push back button in my browser my comment is lost and I have to write it again from scratch.
(0040687)
Roger Leigh (developer)
2016-03-15 05:28

Merged to next for testing.

Regarding your BoostConfig.cmake, what's the reason it can't use the FindBoost imported targets? The expectation would be that users would use the FindBoost ones by default over needing addititional custom macros. How do your macros differ? Why would the custom macro need to dictate the behaviour of the upstream FindBoost?

I would expect that given the ability to export library configurations with use of the imported targets, and their other advantages, that we would always provide them by default.
(0040688)
Ruslan Baratov (reporter)
2016-03-15 05:52

> Regarding your BoostConfig.cmake, what's the reason it can't use the FindBoost imported targets?

I got errors with another example, something about Boost::regex. Not sure what is the cause so I just suggest easy-simple solution.

> How do your macros differ?

It works with CMake 3.0. I don't want to up the requirement just because of FindBoost.cmake.

Implementation diff is that it is configured/installed on Boost build stage so it has information about how Boost is configured. E.g. user can run Boost.iostreams build with option NO_BZIP2=1 and NO_ZLIB=0 and additional ZLIB dependency will be added, BZIP2 dependency will not be added to BoostConfig.cmake. This information simply lost (uneasy to recover) when Boost already installed.
(0040690)
Brad King (manager)
2016-03-15 09:46

Re 0016013:0040687: Thanks. I rebased the fix on the 'release' branch:

 FindBoost: Tolerate missing indirect dependencies
 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=17a1faa7 [^]
(0040691)
Brad King (manager)
2016-03-15 10:02

A problem with the call to list(REMOVE_ITEM) was exposed by nightly testing. Please try this revised version to make sure it still solves the problem:

 FindBoost: Tolerate missing indirect dependencies
 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e2f387fa [^]
(0040697)
Ruslan Baratov (reporter)
2016-03-15 13:38

> Please try this revised version to make sure it still solves the problem

Works for me
(0040701)
Brad King (manager)
2016-03-16 13:16

Thanks for testing. The change linked in 0016013:0040691 has been merged to the 'release' branch for inclusion in CMake 3.5.1.
(0040704)
Dan Kegel (reporter)
2016-03-16 14:25

The patch seems to work here, too. Thanks.

For completeness, here's how I layered the patch on top of the cmake that brew installed:

wget 'https://cmake.org/gitweb?p=cmake.git;a=patch;h=e2f387fa' [^]
mv gitweb* /tmp/findboost.patch
cd /usr/local/Cellar/cmake/3.5.0/share/cmake
sudo patch -p1 < /tmp/findboost.patch
(0041223)
Kitware Robot (administrator)
2016-06-10 14:21

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.

 Issue History
Date Modified Username Field Change
2016-03-11 05:44 Ruslan Baratov New Issue
2016-03-11 05:51 Ruslan Baratov Note Added: 0040660
2016-03-11 08:22 Brad King Assigned To => Roger Leigh
2016-03-11 08:22 Brad King Status new => assigned
2016-03-11 08:23 Brad King Note Added: 0040662
2016-03-12 15:02 Roger Leigh Note Added: 0040665
2016-03-12 15:08 Roger Leigh Note Added: 0040666
2016-03-12 22:49 Ruslan Baratov Note Added: 0040667
2016-03-14 10:03 Roger Leigh Note Added: 0040671
2016-03-14 10:11 Roger Leigh Status assigned => feedback
2016-03-14 14:18 Ruslan Baratov Note Added: 0040682
2016-03-14 14:18 Ruslan Baratov Status feedback => assigned
2016-03-14 14:50 Roger Leigh Note Added: 0040683
2016-03-14 23:23 Ruslan Baratov Note Added: 0040685
2016-03-14 23:26 Ruslan Baratov Note Added: 0040686
2016-03-15 05:28 Roger Leigh Note Added: 0040687
2016-03-15 05:52 Ruslan Baratov Note Added: 0040688
2016-03-15 08:56 Brad King Relationship added related to 0016020
2016-03-15 09:46 Brad King Note Added: 0040690
2016-03-15 10:02 Brad King Note Added: 0040691
2016-03-15 10:05 Brad King Target Version => CMake 3.5.1
2016-03-15 13:38 Ruslan Baratov Note Added: 0040697
2016-03-16 13:16 Brad King Note Added: 0040701
2016-03-16 13:16 Brad King Status assigned => resolved
2016-03-16 13:16 Brad King Resolution open => fixed
2016-03-16 13:16 Brad King Fixed in Version => CMake 3.5.1
2016-03-16 14:25 Dan Kegel Note Added: 0040704
2016-06-10 14:21 Kitware Robot Note Added: 0041223
2016-06-10 14:21 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team