Let us say:

API spec v1.20 could define:

typedef struct odp_foo_bar_t {
        /** This is foo*/
        uint8_t foo;
} odp_foo_bar_t;


API spec v1.30 could define:

typedef struct odp_foo_bar_t {
        /** @deprecated Foo is deprecated, use bar instead. */
        uint8_t foo;

        /** This is bar */
        uint8_t bar;
} odp_foo_bar_t;

Application (with out any changes) moves to v1.30, it still compiles and runs.

Application writer checks what is deprecated by searching for
'@deprecated' or looking at the release notes and changes his code for
v1.30.

On 2 May 2017 at 06:43, Savolainen, Petri (Nokia - FI/Espoo)
<petri.savolai...@nokia.com> wrote:
>
>
>> -----Original Message-----
>> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of maxim
>> Sent: Tuesday, May 02, 2017 1:06 PM
>> To: lng-odp@lists.linaro.org
>> Subject: Re: [lng-odp] [API-NEXT PATCH v2 0/4] Deprecated macros
>>
>> On ????., ??????. 12, 2017 at 10:33:24 -0500, Bill Fischofer wrote:
>> > On Wed, Apr 12, 2017 at 10:05 AM, Dmitry Eremin-Solenikov
>> > <dmitry.ereminsoleni...@linaro.org> wrote:
>> > > On 12.04.2017 17:24, Bill Fischofer wrote:
>> > >> On Wed, Apr 12, 2017 at 8:22 AM, Dmitry Eremin-Solenikov
>> > >> <dmitry.ereminsoleni...@linaro.org> wrote:
>> > >>> On 12.04.2017 15:21, Bill Fischofer wrote:
>> > >>>> On Wed, Apr 12, 2017 at 7:11 AM, Dmitry Eremin-Solenikov
>> > >>>> <dmitry.ereminsoleni...@linaro.org> wrote:
>> > >>>>> On 12.04.2017 14:50, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>> > >>>>>>
>> > >>>>>>
>> > >>>>>>> -----Original Message-----
>> > >>>>>>> From: Dmitry Eremin-Solenikov
>> [mailto:dmitry.ereminsoleni...@linaro.org]
>> > >>>>>>> Sent: Wednesday, April 12, 2017 2:32 PM
>> > >>>>>>> To: Petri Savolainen <petri.savolai...@linaro.org>; lng-
>> > >>>>>>> o...@lists.linaro.org
>> > >>>>>>> Subject: Re: [lng-odp] [API-NEXT PATCH v2 0/4] Deprecated macros
>> > >>>>>>>
>> > >>>>>>> On 30.03.2017 16:58, Petri Savolainen wrote:
>> > >>>>>>>> Replaced ODP_DEPRECATED macro (which was based on GCC
>> __attribute__)
>> > >>>>>>> with
>> > >>>>>>>> compiler independent mechanism to control if deprecated API
>> definitions
>> > >>>>>>> are
>> > >>>>>>>> visible to the application. ODP_DEPRECATED_API can be used both
>> in
>> > >>>>>>> application
>> > >>>>>>>> and implementation to check if deprecated APIs are enabled. By
>> default
>> > >>>>>>> those are
>> > >>>>>>>> disabled. Implementation may optimize the normal (new API) code
>> path.
>> > >>>>>>>>
>> > >>>>>>>> ODP_DEPRECATE() macro is used to rename definitions, so that
>> data
>> > >>>>>>> structure
>> > >>>>>>>> sizes are equal on both options. This enables implementation to
>> serve
>> > >>>>>>> both
>> > >>>>>>>> options with a single library (if it wishes to do so).
>> > >>>>>>>
>> > >>>>>>> My main question remains as it was before: is it possible for
>> the
>> > >>>>>>> distribution to supply (unoptimized) ODP binary and headers and
>> then for
>> > >>>>>>> the application to select if it builds with or without
>> deprecated API
>> > >>>>>>> using that binary/headers?
>> > >>>>>>
>> > >>>>>>
>> > >>>>>> Yes. This patch set keeps the same struct fields/etc for both
>> modes - only the names are scrambled (with __deprecated_ prefix) when
>> deprecated APIs are not supported (the default).
>> > >>>>>
>> > >>>>> If so. Consider I have built and installed ODP headers & binary
>> built
>> > >>>>> with --enable-deprecated-api.
>> > >>>>>
>> > >>>>> How do I build:
>> > >>>>>
>> > >>>>> - application that uses deprecated API?
>> > >>>>>   [I assume that the answer to this question is trivial: just
>> build as is].
>> > >>>>>
>> > >>>>> - application that wants to be sure that it does not use
>> deprecated API?
>> > >>>>
>> > >>>> As a practical matter, the support of deprecated APIs is similar to
>> > >>>> the current provision for debug builds (--enable-debug and
>> > >>>> --enable-debug-print in the current ./configure script). These
>> really
>> > >>>> are only of significance in the embedded space.
>> > >>>
>> > >>> Or for application developers.
>> > >>>
>> > >>>> In the cloud profile,
>> > >>>> applications use whatever ODP release(s) are installed on the
>> system
>> > >>>> and the normal library-matchings are used to ensure that
>> applications
>> > >>>> built for Release X are paired with library .so files compatible
>> with
>> > >>>> that release. In this case, there are no deprecated APIs since
>> > >>>> applications only move to newer ODP release levels when they are
>> > >>>> ready. A cloud host system may specify the minimum ODP release
>> level
>> > >>>> available on it, and that determines when laggards need to upgrade.
>> > >>>
>> > >>> Yep. That is the deployed ODP release. It is optimized for speed, it
>> is
>> > >>> optimized for that exact platform, etc. I'm more thinking about app
>> > >>> developers.
>> > >>>
>> > >>>>
>> > >>>> So ODP will never ship a distribution that was configured with
>> > >>>> --enable-deprecated-api. The only users of this feature will be
>> > >>>> embedded applications that are customizing ODP to their own needs.
>> > >>>
>> > >>> I'm thinking about SuSe, Canonical, RedHat or anybody else shipping
>> ODP
>> > >>> to enable application  development on that platform. They would
>> surely
>> > >>> want to enable deprecated API (because otherwise old applications
>> > >>> developed on that platform can stop building). But I'd expect that
>> it is
>> > >>> possible for the application developer to build an application
>> checking
>> > >>> that he does not use deprecated API anymore.
>> > >>
>> > >> This is really no different than supporting multiple levels of, say,
>> > >> the GCC compiler. Or any other package. At some point the old
>> releases
>> > >> are no longer supported, but for some time you can have multiple
>> > >> levels available at the same time and you just use the one that you
>> > >> need.
>> > >
>> > > We might want to consult maintainers. But from my previous experience,
>> > > supporting several 'levels' is a significant headache, that most of
>> > > maintainers would like to stand away from. Moreover, even if several
>> > > versions are provided by distro, app developers still would like to
>> have
>> > > 'migration' path. Consider the way deprecated API are implemented e.g.
>> > > in Gtk, Qt or other app frameworks.
>> >
>> > The migration path is very straightforward: Don't move until you're
>> > ready to move. When you are ready to move you change your application
>> > to use the new preferred APIs.
>> >
>> > Will some wait until they are forced to move because the older
>> > releases are no longer distributed? Sure. But that's just business as
>> > usual. The point is that distributions can choose to distribute
>> > whatever level(s) of ODP they wish. Our biggest problem is more likely
>> > to be not that they won't distribute older releases but the lag in
>> > getting them to distribute newer releases.
>> >
>> > It also points out that we really shouldn't be deprecating APIs in the
>> > first place. These should be very rare instances, not something so
>> > commonplace that we need a general framework to make it convenient to
>> > deprecate a bunch of stuff each release. An API is "forever" and we
>> > need to be mindful of that when we pour the concrete.
>> >
>> > As a practical matter, the main reason for deprecating an API is
>> > because it is superseded by a better way to do something. But keeping
>> > the older API around just means that applications don't get the
>> > advantage of using the newer way until such time as we get tired of
>> > carrying around the old baggage and the old forms get removed. So
>> > deprecation is more a documentation than a code issue, which is all
>> > that the original ODP_DEPRECATED() macros were intended to do.
>> >
>> > A likely more controversial issue is that we've stated that ODP makes
>> > no ABI compatibility claims from one release to the next. It's assumed
>> > that applications will recompile to move from ODP Release N to ODP
>> > Release N+1. In ODP, ABI compatibility is a statement of compatibility
>> > across different ODP implementations of a given API release, not
>> > across multiple API releases.
>> >
>>
>> I have some more thoughts on deprecating api / documentation.
>>
>> First lets clearly define what deprecation as:
>> Feature of making api functions of struct element for limited support
>> by ODP implementer in future.
>
>
> No. Deprecation is part of API specification. For example,
>
> API spec v1.20 could define:
>
> typedef struct odp_foo_bar_t {
>         /** This is foo*/
>         uint8_t foo;
> } odp_foo_bar_t;
>
>
> API spec v1.30 could define:
>
> typedef struct odp_foo_bar_t {
>         /** @deprecated Foo is deprecated, use bar instead. */
>         uint8_t ODP_DEPRECATE(foo);
>
>         /** This is bar */
>         uint8_t bar;
> } odp_foo_bar_t;
>
>
> By default, ODP_DEPRECATE() macro makes 'foo' unusable for the application. 
> Each implementation may choose to support only the default (foo unusable), or 
> also support all deprecated stuff (foo usable). API spec has only two modes: 
> with or without deprecated stuff. If you compile with deprecated, the above 
> example looks like this to the application:
>
> typedef struct odp_foo_bar_t {
>         /** @deprecated Foo is deprecated, use bar instead. */
>         uint8_t foo;
>
>         /** This is bar */
>         uint8_t bar;
> } odp_foo_bar_t;
>
>
> ... and without deprecation (the default) it looks like this
>
> typedef struct odp_foo_bar_t {
>         /** @deprecated Foo is deprecated, use bar instead. */
>         uint8_t ____dont_use_this_since_its_deprecated_foo;
>
>         /** This is bar */
>         uint8_t bar;
> } odp_foo_bar_t;
>
>
> Note: struct size does not change between the two modes.
>
>
>
>>
>> In that case:
>> - Upstream (Linaro/odp) has to provide common best practice way to do
>>   that.
>> - All api headers have to remain the same as main repo has, only some
>>   function can be marked as deprecated.
>> - Each ODP implementer can choose which functions he marks as deprecated
>>   and for how long. The same for data structures.
>
>
> Deprecated APIs are part of API spec. So, implementation cannot add or remove 
> the number of deprecated APIs. It can just choose to support all of those, or 
> none.
>
>
>>
>> What is delivery? How odp is shipped?
>> - library + headers (more common for enterprise software).
>> - git sources (more common for embedded).
>
> API spec is the primary deliverable of ODP project. Deprecation spec does not 
> include how SW is delivered, it just defines those things in API that are 
> invisible/visible to the application, when deprecation support is off/on. 
> It's a business choice for an implementation / class of implementations to 
> support deprecated APIs.
>
>
>>
>> In my understanding current approach with #idefs in api does not work
>> due to it's impossible to quickly compare headers with main line code
>> if everybody will start to mark unmark fields as deprecated
>> (implementers and main line at the same time.)
>
> The spec does not contain #ifdef. It marks deprecated stuff with 
> ODP_DEPRECATE(). An implementation must not add / remove those. The spec 
> files are the same for everybody.
>
>
>>
>> I see a way how we can get more clear definition here:
>> - ODP mainline provides documentation and ways how to mark deprecated
>>   function or types.
>
> This is the ODP_DEPRECATE() macro.
>
>
>> - ./configure has to have --enable-deprecated symbol
>
> It depends on implementation which build system is used, but obviously it 
> needs a way to enable deprecated APIs if it supports those.
>
>
>> - ./include/api headers have to be generated on ./configure stage
>>   regarding if deprecated symbols are supported or not. That include
>>   headers have to be shipped with library binary to package.
>
> This is no different from selecting if ABI compat is used. Both need to be 
> selected at build time (at latest). Obviously, for distros we always build 
> with ABI compat, we need to decide our position on deprecated APIs. Maybe 
> those are always off (as the default mode suggests).
>
>
>> - all deprecated api have to be in separate folder to be easy to remove
>>   something like ./include/api-deprecated/
>> - Doxygen note has to have all deprecated symbols documented.
>
>
> Separate folders are not needed. API spec files mark deprecated definitions 
> with both ODP_DEPRECATE() and @deprecated tag. Implementations re-use the 
> spec files as-is, or otherwise make sure that the same definitions are 
> visible/not-visible to the application through ODP API.
>
>
> -Petri
>
>>
>>
>> Now when we talk about real delivery we talk only about Long Term
>> Support releases. When we do this release we can discuss which api
>> people still want to support as deprecated. In that case we enable
>> this apis in the build. But apps developers will know that these apis
>> will no be valid on next release.
>>
>> In my understanding it has to solve patch original api headers with
>> deprecated macro and makes maintains more easy.
>>
>> Best regards,
>> Maxim.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>

Reply via email to