On Tue, May 2, 2017 at 9:20 AM, Maxim Uvarov <[email protected]> wrote:
> On 05/02/17 14:43, Savolainen, Petri (Nokia - FI/Espoo) wrote: > > > > > >> -----Original Message----- > >> From: lng-odp [mailto:[email protected]] On Behalf Of > maxim > >> Sent: Tuesday, May 02, 2017 1:06 PM > >> To: [email protected] > >> 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 > >>> <[email protected]> wrote: > >>>> On 12.04.2017 17:24, Bill Fischofer wrote: > >>>>> On Wed, Apr 12, 2017 at 8:22 AM, Dmitry Eremin-Solenikov > >>>>> <[email protected]> wrote: > >>>>>> On 12.04.2017 15:21, Bill Fischofer wrote: > >>>>>>> On Wed, Apr 12, 2017 at 7:11 AM, Dmitry Eremin-Solenikov > >>>>>>> <[email protected]> wrote: > >>>>>>>> On 12.04.2017 14:50, Savolainen, Petri (Nokia - FI/Espoo) wrote: > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>> -----Original Message----- > >>>>>>>>>> From: Dmitry Eremin-Solenikov > >> [mailto:[email protected]] > >>>>>>>>>> Sent: Wednesday, April 12, 2017 2:32 PM > >>>>>>>>>> To: Petri Savolainen <[email protected]>; lng- > >>>>>>>>>> [email protected] > >>>>>>>>>> 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 > > > > So use case is only one - if you have source code for application based > on api X and you want to jump to api level X+Y and if old api is > supported as deprecated then app should compile and run without > modifications. Right? > > In that case ABI compatibility more like will be broken but old API has > to be supported. > Inter-release ABI compatibility is something ODP has explicitly said is not a design goal. If we want to change that we need to discuss that as a separate topic. The goal of ABI compatibility in ODP is for binary application portability across different ODP implementations of the same API level. > > Maxim. > > > >> > >> > >> 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. > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >
