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. >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>