Ceph compilation on inclusion of /usr/include/c++/v1/deque

Willem Jan Withagen wjw at digiware.nl
Sat Feb 20 20:00:21 UTC 2016


On 20-2-2016 16:50, Dimitry Andric wrote:
> On 20 Feb 2016, at 16:09, Willem Jan Withagen <wjw at digiware.nl> wrote:
>>
>> I'm trying to build a port of Ceph for FreeBSD, which is sort of trying
>> to shoot at a tank with a watergun.... :)
> 
> This is very nice, it would be good to have Ceph on FreeBSD.  Note that
> if you have problems with porting, usually the freebsd-ports mailing
> list is a better audience.
> 
> 
>> I you want to reproduce it is rather labourious, but not all that complex:
>> git clone https://github.com/wjwithagen/ceph.git
>> cd ceph
>> git checkout wip-wjw-freebsd-tests
>> ./do_freebsd.sh
>>
>> And wait for the error to appear.
> ...
>> /usr/include/c++/v1/deque:912:49: error: invalid application of 'sizeof'
>> to an incomplete type 'value_type' (aka 'RGWPeriod')
>>    static const difference_type __block_size = sizeof(value_type) < 256
>> ? 4096 / sizeof(value_type) : 16;
>>                                                ^~~~~~~~~~~~~~~~~~
>> /usr/include/c++/v1/deque:1159:15: note: in instantiation of template
>> class 'std::__1::__deque_base<RGWPeriod,
>>      std::__1::allocator<RGWPeriod> >' requested here
>>    : private __deque_base<_Tp, _Allocator>
>>              ^
>> rgw/rgw_period_history.h:26:27: note: in instantiation of template class
>> 'std::__1::deque<RGWPeriod, std::__1::allocator<RGWPeriod>
>>> ' requested here
>>    std::deque<RGWPeriod> periods;
>>                          ^
>> rgw/rgw_period_history.h:16:7: note: forward declaration of 'RGWPeriod'
>> class RGWPeriod;
>>      ^
> 
> Without having to build anything, I see the problem already. :) The
> error message is unfortunately rather confusing, but the gist of it is
> that the implementation of std::deque<> requires a complete type.
> 
> Which means that you cannot do this:
> 
>     #include <deque>
>     class foo;
>     std::deque<foo> bar;
> 
> Compiling this example with clang and libc++ will result in (not all
> errors shown, no need to):
> 
>     In file included from deque-test.cpp:1:
>     /usr/include/c++/v1/deque:912:49: error: invalid application of 'sizeof' to an incomplete type 'value_type' (aka 'foo')
>         static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
>                                                     ^~~~~~~~~~~~~~~~~~
>     /usr/include/c++/v1/deque:1159:15: note: in instantiation of template class 'std::__1::__deque_base<foo, std::__1::allocator<foo> >' requested here
>         : private __deque_base<_Tp, _Allocator>
>                   ^
>     deque-test.cpp:3:17: note: in instantiation of template class 'std::__1::deque<foo, std::__1::allocator<foo> >' requested here
>     std::deque<foo> bar;
>                     ^
>     deque-test.cpp:2:7: note: forward declaration of 'foo'
>     class foo;
>           ^
> 
> Similarly, compiling the example with g++ and libstdc++ (6.0.0 from
> ports) results in:
> 
>     In file included from /usr/local/lib/gcc6/include/c++/deque:64:0,
>                      from deque-test.cpp:1:
>     /usr/local/lib/gcc6/include/c++/bits/stl_deque.h: In instantiation of 'void std::_Deque_base<_Tp, _Alloc>::_M_initialize_map(std::size_t) [with _Tp = foo; _Alloc = std::allocator<foo>; std::size_t = unsigned int]':
>     /usr/local/lib/gcc6/include/c++/bits/stl_deque.h:490:26:   required from 'std::_Deque_base<_Tp, _Alloc>::_Deque_base() [with _Tp = foo; _Alloc = std::allocator<foo>]'
>     /usr/local/lib/gcc6/include/c++/bits/stl_deque.h:884:23:   required from 'std::deque<_Tp, _Alloc>::deque() [with _Tp = foo; _Alloc = std::allocator<foo>]'
>     deque-test.cpp:3:17:   required from here
>     /usr/local/lib/gcc6/include/c++/bits/stl_deque.h:682:74: error: invalid application of 'sizeof' to incomplete type 'foo'
>            const size_t __num_nodes = (__num_elements/ __deque_buf_size(sizeof(_Tp))
>                                                                               ^
>     /usr/local/lib/gcc6/include/c++/bits/stl_deque.h:713:31: error: invalid application of 'sizeof' to incomplete type 'foo'
>           % __deque_buf_size(sizeof(_Tp)));
>                                    ^
> 
> Looking at rgw_period_history.h, it is indeed using an incomplete type:
> 
>     #include <deque>
>     #include <mutex>
>     #include <system_error>
>     #include <boost/intrusive/avl_set.hpp>
>     #include "include/assert.h"
>     #include "include/types.h"
> 
>     namespace bi = boost::intrusive;
> 
>     class RGWPeriod;
> 
>     /**
>      * RGWPeriodHistory tracks the relative history of all inserted periods,
>      * coordinates the pulling of missing intermediate periods, and provides a
>      * Cursor object for traversing through the connected history.
>      */
>     class RGWPeriodHistory final {
>       /// an ordered history of consecutive periods
>       struct History : public bi::avl_set_base_hook<> {
>         std::deque<RGWPeriod> periods;
> 
> E.g at this point, all the compiler has is a forward declaration of
> RGWPeriod.  If this even compiles on Linux, I am unsure how it manages
> to do so. :-)  Maybe the Linux build pulls in some other header first,
> getting the full definition of RGWPeriod somehow?
> 
> In any case, the easiest fix is probably to switch around the inclusions
> of the headers in rgw_period_history.cc, e.g. changing:
> 
>     #include "rgw_period_history.h"
>     #include "rgw_rados.h"
> 
> to:
> 
>     #include "rgw_rados.h"
>     #include "rgw_period_history.h"
> 
> Since rgw_rados.h contains the full definition of RGWPeriod, the forward
> declaration on line 16 of rgw_period_history.h can then be deleted.
> 
> Alternatively, include rgw_rados.h directly in rgw_period_history.h,
> which is what I would do.  I am unsure how Ceph upstream thinks about
> that, though.  Maybe you can check with them?

Hi Dimitry,

Thanx for all the advise.
It is going to take some time to absorbe all. :)

I've got a FreeBSD pull running, and on and off I'm commented by other
committers as to how or why... You've given enough text to actually put
in the commit message. And we'll find out how they feel about it.

As to running this by the ports list, I have not really seen any this
type of problem passing by there. Next to that I expected it more to be
GCC <> Clang because every commit is run through Jenkins compilation and
testing, and it would be noticed there.

Thanx for the help,
--WjW



More information about the freebsd-toolchain mailing list