Release Versioning is the process of assigning version numbers to software releases. Versioning helps manage the project in four ways. First, it allows us to refer to a particular state of the source code using friendly names, like Crypto++ 5.6.2 rather than a check-in number like R541. Second, it helps convey significance to a unique state of the software in time. Third, it helps locate a previous software state in source control, if needed. Fourth, it helps convey information about ABI and API compatibility.
This pages discusses how the project names a version of Crypto++, what to expect when a version number changes, and how to locate a particular state of the source code in Subversion or Git. The page also provides a brief history of releases. A related topic is Release Testing, and what it takes to release a version of Crypto++.
There is no definitive guide on versioning requirements, but it is important to follow best practices when a change occurs. The version number assigned to a release often conveys information on both ABI and API compatibility. Best practices often attempt to capture client compatibility requirements, especially in the context of shared objects and dynamic linking.
Header files with definitions and inlined functions makes consistent versioning a challenge because the library attempts to respect requirements on a number of different platforms. Each platform, like Debian and Apple, has its own expectation of what changes when a number is incremented or bumped. Some distributions, like Debian, will also monitor source control for a tagged release event and then automatically kick-off an update. Since its an automatic process, care must be taken to avoid problems for down stream.
Currently there is no process to evaluate the effects of changing source code on the ABI or API. The project does not use an ABI tracker in order to automate binary compatibility analysis. The project would like to add it in the future.
Crypto++ historically utilizes a scheme consisting of a prefix and monotonically increasing version information for naming releases. The prefix is CRYPTOPP, and the version information consists of Major, Minor, and an optional Compatibility (or Patch Level). Each part of the name is separated with an underscore or _. Sometimes the third number is omitted in casual conversation when its 0 or discussing a "family" or "line", so be aware potential ambiguities that could arise.
The library does not use the 4th tuple, sometimes called Revision Level, and it does not use letters like a or b. In addition, the library does not use an odd/even scheme. Finally, the library does not name release candidates.
Example of Crypto++ releases and release candidates are shown in the table below. The first column is the version, the second column is the tag name, the third column is the filesystem date. The filesystem date is the time on the server, and not the release date reported by subversion.
The fourth column is the symbolic define from config.h. The symbolic define is CRYPTOPP_VERSION. The fifth column is the filename made available for download. The sixth and seventh columns provide revision and check-in numbers, if available.
|Crypto++ 4 and earlier were in CVS. There is no historical source control record, other than filesystem names and dates.|
The major version is incremented or bumped when a breaking change occurs. This change may break API and ABI compatibility, and sometimes requires clients to recompile to fix compile errors because of changes in the library. For example, if a base interface changes, then it will likely require client code to change to adhere to the new specification.
A number of changes can occur at this time, and they include:
- symbols added or removed
- static variables added or removed
- function signatures added or removed
- class members added or removed
- object binary layout changes
- object vtables changes
The minor version is incremented when new functionality is added to the library. This change attempts to retain API compatibility, but may break ABI compatibility in a minor manner. This change should not not break clients using public interfaces.
Broadly speaking, this change means the library is being advanced without breaking changes. For example, HMQV and FHMQV were added at 5.7, but clients that linked against 5.6.2 or 5.6.3 could use it without requiring a recompile. In this case, new classes were added; and no existing classes we modified.
An example of a minor break to the ABI is adding symbols to an existing class (as opposed to adding a new class). When symbols are added to the existing class, symbols within the scope of the class change and the vtable may change. RDRAND and RDSEED cause a minor ABI break in the CPU class because it added two symbols (g_hasRDRAND and g_hasRDSEED) and two functions (HasRDRAND() and HasRDSEED()).
The compatibility version is bumped when a bug fix or maintenance release occurs. This change attempts to retain both ABI and API compatibility. This change should not break clients, and sometimes includes new functionality.
Broadly speaking, this change means the library is fixing undesired or errant behavior. For example, many of the changes between 5.6.2 and 5.6.3 were remediations to findings from tools like Undefined Behavior sanitizer, Address sanitizer and Valgrind.
After releasing the library the project's version should be bumped. For example, if Crypto++ 5.6.4 was released, then the compatibility number should be changed from 4 to 5 in in 5.6.5. And if Crypto++ 5.7.0 was released, then the version should be changed to 5.7.1.
This change helps with user questions that start with "I'm using Crypto++ 5.6.3 and I'm having problems with ...". When the project encounters the question, its unclear if its the 5.6.3 release ZIP, or Master without the next version bump. The change also helps determine the actual compatibility level during development. That is, if Master advertises version information X.Y.Z, then it better be compatible with X.Y.
Its also OK to release under a more appropriate version number. For example, the following is perfectly valid: release 5.6.3, bump to 5.6.4 during development, and then release 5.7.0. In this case version information is monotonically increasing, and there is no confusion or disambiguation needed.
The locations of version numbers are:
- config.h and CRYPTOPP_VERSION
- config.compat and CRYPTOPP_VERSION
- cryptlib.h and Doxygen comment
- cryptopp.rc and VERSION_INFO block
- Doxyfile and PROJECT_NUMBER
- CMakeList.txt and cryptopp_VERSION_*
Also see the discussion Post-release version number increment on the user mailing list.
Distributions must often maintain a list of files to include in a DEB, RPM or other package. The following will list files added and removed between tagged releases:
$ git clone https://github.com/weidai11/cryptopp.git cryptopp $ cd cryptopp $ git diff-tree -r --summary CRYPTOPP_5_6_2 CRYPTOPP_5_6_3 | grep -v "change" create mode 100644 Filelist.txt create mode 100755 GNUmakefile-cross create mode 100644 Install.txt create mode 100644 TestVectors/hkdf.txt create mode 100644 config.recommend create mode 100755 cryptest.sh create mode 100644 hkdf.h create mode 100755 make-rdrand.cmd create mode 100644 mersenne.h create mode 100755 rdrand-masm.cmd create mode 100755 rdrand-nasm.sh create mode 100644 rdrand.S create mode 100644 rdrand.asm create mode 100644 rdrand.cpp create mode 100644 rdrand.h create mode 100644 trap.h create mode 100644 vs2010.zip
Thanks to CJM on the Unix & Linux Stack Exchnage for the suggestion.