[CXX-880] MongoDB C++11 driver fails to build on FreeBSD Created: 30/Mar/16  Updated: 08/Jan/24  Resolved: 19/May/16

Status: Closed
Project: C++ Driver
Component/s: Portability
Affects Version/s: 3.0.0
Fix Version/s: 3.0.2

Type: Bug Priority: Blocker - P1
Reporter: Jimmy [X] Assignee: Mira Carey
Resolution: Done Votes: 1
Labels: neweng
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

The driver fails to build on FreeBSD with the following errors:

[  4%] Building CXX object src/bsoncxx/CMakeFiles/bsoncxx.dir/types/value.cpp.o
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/types/value.cpp:48:
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/enums/type.hpp:20:1: error: static_assert failed "Copy may throw"
BSONCXX_ENUM(utf8, 0x02)
^~~~~~~~~~~~~~~~~~~~~~~~
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/types/value.cpp:36:9: note: expanded from macro 'BSONCXX_ENUM'
        static_assert(std::is_nothrow_copy_constructible<b_##name>::value, "Copy may throw");  \
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/types/value.cpp:48:
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/enums/type.hpp:31:1: error: static_assert failed "Copy may throw"
BSONCXX_ENUM(code, 0x0D)
^~~~~~~~~~~~~~~~~~~~~~~~
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/types/value.cpp:36:9: note: expanded from macro 'BSONCXX_ENUM'
        static_assert(std::is_nothrow_copy_constructible<b_##name>::value, "Copy may throw");  \
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/types/value.cpp:48:
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/enums/type.hpp:32:1: error: static_assert failed "Copy may throw"
BSONCXX_ENUM(symbol, 0x0E)
^~~~~~~~~~~~~~~~~~~~~~~~~~
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/types/value.cpp:36:9: note: expanded from macro 'BSONCXX_ENUM'
        static_assert(std::is_nothrow_copy_constructible<b_##name>::value, "Copy may throw");  \
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 errors generated.
*** [src/bsoncxx/CMakeFiles/bsoncxx.dir/types/value.cpp.o] Error code 1

Interesting that BSON types b_symbol, b_code and b_utf8 fail nothrow requirement of the constructor. The fix I applied in this case is to rewrite "bsoncxx/types/value.cpp:32"

#if !defined(BSONCXX_POLY_USE_BOOST)

as

#if defined(BSONCXX_POLY_USE_BOOST)

Another error relates to failure of the Clang to select and appropriate overloaded function when using chrono::count(), here's an error example for modify_collection.cpp (it fails also on collection.cpp, basically anywhere append() is called with chrono::count()):

[ 20%] Building CXX object src/mongocxx/CMakeFiles/mongocxx.dir/options/modify_collection.cpp.o
In file included from /home/karrotkake/mongo-cxx-driver/src/mongocxx/options/modify_collection.cpp:17:
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/builder/stream/document.hpp:18:
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/builder/stream/key_context.hpp:19:
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/builder/stream/value_context.hpp:70:16: error: call to member
      function 'append' is ambiguous
        _core->append(std::forward<T>(t));
        ~~~~~~~^~~~~~
/home/karrotkake/mongo-cxx-driver/src/mongocxx/options/modify_collection.cpp:38:55: note: in instantiation of
      function template specialization
      'bsoncxx::v_noabi::builder::stream::value_context<bsoncxx::v_noabi::builder::stream::key_context<bsoncxx::v_noabi::builder::stream::closed_context>
      >::operator<<<long long>' requested here
                              << "expireAfterSeconds" << seconds.count() << finalize);

The problem comes from the fact that libc++ <chrono> defines seconds, milliseconds etc. as:

typedef duration<long long,        milli> milliseconds;
typedef duration<long long              > seconds;

But append() accepts int32_t, int64_t etc., and int64_t is defined in system <stdint.h> header as

typedef long int64_t

So compiler fails during overload resolutio to select correct version of append(), because chrono::count() returns long long which, supposedly, can match into both append(int32_t) and append(int64_t).

Also here's the include hierarchy of Clang's (libc++) <cstdint> header:

. /usr/include/c++/v1/cstdint
.. /usr/include/c++/v1/__config
... /usr/include/sys/endian.h
.... /usr/include/sys/cdefs.h
.... /usr/include/sys/_types.h
..... /usr/include/machine/_types.h
...... /usr/include/x86/_types.h



 Comments   
Comment by Mira Carey [ 19/May/16 ]

I've resolved this ticket as fixed (we observed the same behavior on clang 3.5.1 and the committed fix allowed that build to move forward).

If there's something more that's also broken that you run into after that, feel free to reopen or file a separate ticket if it seems distinct.

-Jason

Comment by Githook User [ 19/May/16 ]

Author:

{u'username': u'hanumantmk', u'name': u'Jason Carey', u'email': u'jcarey@argv.me'}

Message: CXX-880 Don't mask lifecycle methods in b_ types

Some b_ types had overly binding universal forwarding ctors. We need to sfinae those out if the
passed arg is of the type, so that we don't mask lifecycle methods.

closes #487
Branch: master
https://github.com/mongodb/mongo-cxx-driver/commit/d20926ba607e110b7fd699e1cfe0e3ddcfa0bf01

Comment by Mira Carey [ 19/May/16 ]

https://github.com/mongodb/mongo-cxx-driver/pull/487

Comment by Jimmy [X] [ 31/Mar/16 ]

Here's the results:
cmake .. -DCMAKE_BUILD_TYPE=Release -DBSONCXX_POLY_USE_STD_EXPERIMENTAL=ON -DCMAKE_CXX_STANDARD=14

 
[  1%] Building CXX object src/bsoncxx/CMakeFiles/bsoncxx.dir/array/element.cpp.o
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/array/element.cpp:15:
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/array/element.hpp:20:
In file included from /home/karrotkake/mongo-cxx-driver/src/bsoncxx/document/element.hpp:20:
/home/karrotkake/mongo-cxx-driver/src/bsoncxx/stdx/string_view.hpp:49:10: fatal error: 
      'experimental/string_view' file not found
#include <experimental/string_view>

cmake .. -DCMAKE_BUILD_TYPE=Release -DBSONCXX_POLY_USE_MNMLSTC=ON
Fails with the static_assert decribed in the OP

cmake .. -DCMAKE_BUILD_TYPE=Release -DBSONCXX_POLY_USE_BOOST=ON
This fails on CMake stage

Detected version of Boost is too old.  Requested version was 1.56 (or
  newer).

Unfortunately, I can't upgrade Boost right now to a more recent version.

So the only way to get past the static_assert failure is to make sure BSONCXX_ENUM gets defined as:

#define BSONCXX_ENUM(name, val)                                                                \
    value::value(b_##name value) noexcept : _type(static_cast<bsoncxx::type>(val)),            \
                                            _b_##name(std::move(value)) {                      \
        static_assert(std::is_nothrow_destructible<b_##name>::value, "Destruction may throw"); \
    }

Which means changing #if !defined(BSONCXX_POLY_USE_BOOST) to #if defined(BSONCXX_POLY_USE_BOOST)

Comment by Andrew Morrow (Inactive) [ 30/Mar/16 ]

Apologies, those should read like

-DBSONCXX_POLY_USE_BOOST=ON
-DBSONCXX_POLY_USE_STD_EXPERIMENTAL=ON

Comment by Jimmy [X] [ 30/Mar/16 ]

I'm not specifying any concrete polyfill, so it uses which ever it decides (in this case it's #if !defined(BSONCXX_POLY_USE_BOOST)). Passing those defines directly to CMake doesn't work

cmake -DCMAKE_BUILD_TYPE=Release -DBSONCXX_POLY_USE_STD_EXPERIMENTAL ..
Parse error in command line argument: -DBSONCXX_POLY_USE_STD_EXPERIMENTAL
Should be: VAR:type=value
CMake Error: No cmake script provided.
CMake Error: Problem processing arguments. Aborting.

Comment by Andrew Morrow (Inactive) [ 30/Mar/16 ]

Are you trying to build the driver with the boost polyfills, as opposed to the MNMLSTC polyfills? That could be part of the difference. You should be able to make that choice at CMake time by passing -DBSONCXX_POLY_USE_MNMLSTC, -DBSONCXX_POLY_USE_STD_EXPERIMENTAL, or -DBSONCXX_POLY_USE_BOOST to CMake. I'd be interested to know which of those choices results in the static assertion firing.

Comment by Jimmy [X] [ 30/Mar/16 ]

Thanks for the quick response. Yeah the noexcept static_assert failure is pretty strange. Could it be connected to some problems with Boost? As for the chrono, it is indeed the same issue as in CXX-878. I'll keep static_cast<int64_t> for now, until you release an updated version.

Comment by Andrew Morrow (Inactive) [ 30/Mar/16 ]

Thanks for the bug report. I believe the issue with std::chrono conversions was already reported in CXX-878.

However, the failure to detect the b_ types as noexcept is puzzling and somewhat worrying. They are definitely intended to be and the design of the value class depends on it, which is why we have the static_asserts.

I'm planning to issue 3.0.1 today or tomorrow, which rolls up several other important build fixes, and I don't want to delay it further, but I will make this and the chrono issue as reported here and in CXX-878 a priority for 3.0.2.

Comment by Jimmy [X] [ 30/Mar/16 ]

Couldn't find and edit button, so here's some edits:

The fixes I applied where Clang fails to select correct append() because chrono::count() returns long long was to manually static_cast to int64_t all calls to count():

void modify_collection::index(bsoncxx::document::view_or_value index_spec,
                              std::chrono::seconds seconds) {
    _index.emplace(document{} << "keyPattern" << bsoncxx::types::b_document{std::move(index_spec)}
                              << "expireAfterSeconds" << static_cast<int64_t>(seconds.count()) << finalize);
}

With these fixes driver succesfully builds.

Generated at Wed Feb 07 22:00:39 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.