Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Feb 2016 11:42:22 +0100
From:      Willem Jan Withagen <wjw@digiware.nl>
To:        Dimitry Andric <dim@FreeBSD.org>
Cc:        FreeBSD Toolchain <freebsd-toolchain@freebsd.org>
Subject:   Re: Ceph compilation on inclusion of /usr/include/c++/v1/deque
Message-ID:  <56C9948E.60509@digiware.nl>
In-Reply-To: <56C8C2D1.9070603@digiware.nl>
References:  <56C88191.7030801@digiware.nl> <FF4EAE21-82C5-4105-8AED-993C6F3B2F7B@FreeBSD.org> <56C8C2D1.9070603@digiware.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
On 20-2-2016 20:47, Willem Jan Withagen wrote:
> On 20-2-2016 16:50, Dimitry Andric wrote:
>> On 20 Feb 2016, at 16:09, Willem Jan Withagen <wjw@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.

There were some more loop dependancies which required forward
declaration and alter inclusion of include files.
But in the end I got it to compile again.

So thanx for the help.
--WjW





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?56C9948E.60509>