Thank you so much for kind explanation. This is really awesome especially for
newbies like me. This gives answers to me for all my own stupid questions like
why I need to investigate all the lib changes in order to determine bumping
current/revision/age numbers or not.

I'd definitely like to follow this rule to avoid any verion changes later, as
I expect the next release will be the last major update. For dependency parts,
I'll study and practice them for a while.

BTW, can I archive this like in f2fs-tools/VERSIONING?

Thanks,

On 08/28, Theodore Y. Ts'o wrote:
> On Tue, Aug 28, 2018 at 09:59:44AM -0700, Jaegeuk Kim wrote:
> > 
> > https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
> > 
> > I understood that, if there is no interface change but some implementation
> > changes, I need to bump revision. If new interface is added, for example, I
> > need to bump current while revision=0 and age++.
> 
> So part of the problem here is that libtool is doing something really
> strange because they are trying to use some abstract concept that is
> OS-independent.  I don't use libtool because I find it horribly
> complex and doesn't add enough value to be worth the complexity.
> 
> So I'll tell you how things work with respect to Linux's ELF version
> numbering system.  Translating this to libtool's wierd "current,
> revision, age" terminology is left as an exercise to the reader.  I've
> looked at the libtool documentation, and it confuses me horribly.
> Reading it, I suspect it's wrong, but I don't have the time to
> experiment to confirm that the documentation is wrong and how it
> diverges from the libtool implementation.
> 
> So let me explain things using the ELF shared library terminology,
> which is "major version, minor version, patchlevel".  This shows up in
> the library name:
>     
>       libudev.so.1.6.11
> 
> So in this example, the major version number is 1, the minor version
> is 6, and the patchlevel is 11.  The patchlevel is entirely optional,
> and many packages don't use it at all.  The minor number is also
> mostly useless on Linux, but it's still there for historical reasons.
> The patchlevel and minor version numbers were useful back for SunOS
> (and Linux a.out shared library), back when there weren't rpm and dpkg
> as package managers.
> 
> So many modern Linux shared libraries will only use the major and
> minor version numbers, e.g:
> 
>       libext2fs.so.2.4
> 
> The only thing you really need to worry about is the major version
> number, really.  The minor version is *supposed* to change when new
> interfaces has changed (but I and most other people don't do that any
> more).  But the big deal is that the major number *must* get bumped if
> an existing interface has *changed*.
> 
> So let's talk about the major version number, and then we'll talk
> about why the minor version number isn't really a big deal for Linux.
> 
> So if you change any of the library's function signatures --- and this
> includes changing a type from a 32-bit integer to a 64-bit integer,
> that's an ABI breakage, and so you must bump the major version number
> so that a program that was linked against libfoo.so.4 doesn't try to
> use libfoo.so.5.  That's really the key --- will a program linked
> against the previous version library break if it links against the
> newer version.  If it does, then you need to bump the version number.
> 
> So for structures, if you change any of the existing fields, or if the
> application program allocates the structure --- either by declaring it
> on the stack, or via malloc() --- and you expand the structure,
> obviously that will cause problem, and so that's an ABI break.
> 
> If however, you arrange to have structures allocated by the library,
> and struct members are always added at the end, then an older program
> won't have any problems.  You can guarantee this by simply only using
> a pointer to the struct in your public header files, and defining the
> struct in a private header file that is not available to userspace
> programs.
> 
> Similarly, adding new functions never breaks the ABI.  That's because
> older program won't try to use the newer interfaces.  So if I need to
> change an interface to a function, what I'll generally do is to define
> a new function, and then implement the older function in terms of the
> newer one.  For example:
> 
> extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
>                            unsigned int block_size, io_manager manager,
>                            ext2_filsys *ret_fs);
>                            
> extern errcode_t ext2fs_open2(const char *name, const char *io_options,
>                             int flags, int superblock,
>                             unsigned int block_size, io_manager manager,
>                             ext2_filsys *hret_fs);
> 
> As far as the minor version numbers are concerned, the dynamic linker
> doesn't use it.  In SunOS 4, if you have a DT_NEEDED for libfoo.so.4,
> and the dynamic linker finds in its search path:
> 
>     libfoo.so.4.8
>     libfoo.so.4.9
> 
> It will preferentially use libfoo.so.4.9.
> 
> That's not how it works in Linux, though.  In Linux there will be a
> symlink that points libfoo.so.4 to libfoo.so.4.9, and the linker just
> looks for libfoo.so.4.  One could imagine a package manager which
> adjusts the symlink to point at the library with the highest version,
> but given that libfoo.so.4.9 is supposed to contain a superset of
> libfoo.so.4.8, there's no point.  So we just in practice handle all of
> this in the package manager, or via an ELF symbol map.  Or, we just
> assume that since vast majority of software comes from the
> distribution, the distro package manager will just update libraries to
> the newer version as a matter of course, and nothing special needs to
> be done.
> 
> So in practice I don't bump the minor version number for e2fsprogs
> each time I add new interfaces, because in practice it really doesn't
> matter for Linux.  We have a much better system that gets used for
> Debian.
> 
> For example in Debian there is a file that contains when each symbol
> was first introduced into a library, by its package version number.
> See:
> 
> https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/debian/libext2fs2.symbols
> 
> This file contains a version number for each symbol in libext2fs2, and
> it tells us what version of libext2fs you need to guarantee that a
> particular symbol is present in the library.  Then when *other*
> packages are built that depend on libext2fs2, the minimum version of
> libext2fs can be calculated based on which symbols they use.
> 
> So for example the libf2fs-format4 package has a Debian dependency of:
> 
> Depends: libblkid1 (>= 2.17.2), libc6 (>= 2.14), libf2fs5, libuuid1 (>= 2.16)
> 
> The minimum version numbers needed for libblkid1 and libuuid1 are
> determined by figuring out all of the symbols used by the
> libf2fs-format4 package, and determining the minimum version number of
> libblkid1 that supports all of those blkid functions.
> 
> This gets done automatically, so I didn't have to figure this out.
> All I have in the debian/control file is:
> 
> Depends: ${misc:Depends}, ${shlibs:Depends}
> 
> Sorry this got so long, but hopefully you'll find this useful.  How
> you bend libtool to your will is something you'll have to figure out,
> because I don't use libtool in my packages.[1]
> 
> Cheers,
> 
>                                       - Ted
> 
> 
> [1] If you are interested in how I do things in e2fsprogs, take a look
> at the Makefile.elf-lib, Makefile.solaris-lib, Makefile.darwin-lib,
> etc. here:
> 
> https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/lib
> 
> This these Makefile fragments are then pulled into the generated
> makefile using autoconf's substitution rules, here:
> 
> https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/lib/ext2fs/Makefile.in
> 
> (Search for "@MAKEFILE_ELF@" in the above Makefile.in).
> 
> So when someone runs "configure --enable-elf-shlibs", they get the ELF
> shared libraries built.  On BSD and MacOS systems they just have to
> run "configure --enable-bsd-shlibs", and so on.
> 
> Personally, since most people don't bother to write truly portable
> programs, as their C code is full of Linux'isms, using libtool is just
> overkill, because they probably can't build on any other OS *anyway*
> so libtool's slow and complex abstraction layer is totally wasted.
> Might as well not use autoconf, automake, and libtool at all.
> 
> On the other hand, if you really *do* worry about portability on other
> OS's (e2fsprogs builds on MacOS, NetBSD, Hurd, Solaris, etc.) then
> using autoconf makes sense --- but I *still* don't think the
> complexity of libtool is worth it.

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to