build: use Semantic Versioning

See https://semver.org for details, but it basically formalizes our
decision to not break API nor ABI in minor releases.

Closes #953
parent 2d3ed2a6
...@@ -8,4 +8,4 @@ for file in $(git diff-index --cached --name-only HEAD | grep -E '\.(cpp|cc|hpp| ...@@ -8,4 +8,4 @@ for file in $(git diff-index --cached --name-only HEAD | grep -E '\.(cpp|cc|hpp|
clang-format --dry-run --Werror "$file" >/dev/null 2>&1 || (echo 'Run ninja clang-format before committing' 1>&2 && false) clang-format --dry-run --Werror "$file" >/dev/null 2>&1 || (echo 'Run ninja clang-format before committing' 1>&2 && false)
done done
grep "VERSION_GIT_DATE $(date +%Y%m%d)" version.txt || (echo 'Update VERSION_GIT_DATE in version.txt before committing' 1>&2 && false) grep "$(date +%Y%m%d)" version.txt || (echo 'Update the commit date in version.txt before committing' 1>&2 && false)
...@@ -12,8 +12,12 @@ set(CMAKE_CXX_STANDARD 17) ...@@ -12,8 +12,12 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
file(READ "version.txt" VERSION_FILE_RAW)
string(STRIP "${VERSION_FILE_RAW}" VERSION_FILE)
project (pistache project (pistache
LANGUAGES C CXX) LANGUAGES C CXX
VERSION ${VERSION_FILE})
include(GNUInstallDirs) include(GNUInstallDirs)
...@@ -42,50 +46,17 @@ if (PISTACHE_USE_SSL) ...@@ -42,50 +46,17 @@ if (PISTACHE_USE_SSL)
find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto) find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto)
endif () endif ()
# Set release version... # Set version numbers in a header file
# Retrieve from external file...
file(READ "version.txt" VERSION_FILE)
# Extract version...
# Major...
string(REGEX MATCH "VERSION_MAJOR *([0-9]*)" _ ${VERSION_FILE})
set(VERSION_MAJOR ${CMAKE_MATCH_1})
# Minor...
string(REGEX MATCH "VERSION_MINOR *([0-9]+)" _ ${VERSION_FILE})
set(VERSION_MINOR ${CMAKE_MATCH_1})
# Patch...
string(REGEX MATCH "VERSION_PATCH *([0-9]+)" _ ${VERSION_FILE})
set(VERSION_PATCH ${CMAKE_MATCH_1})
# Git date... set(VERSION_MAJOR ${pistache_VERSION_MAJOR})
string(REGEX MATCH "VERSION_GIT_DATE *([0-9]+)" _ ${VERSION_FILE}) set(VERSION_MINOR ${pistache_VERSION_MINOR})
set(VERSION_GIT_DATE ${CMAKE_MATCH_1}) set(VERSION_PATCH ${pistache_VERSION_PATCH})
set(VERSION_GIT_DATE ${pistache_VERSION_TWEAK})
# Full version configure_file (
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-git${VERSION_GIT_DATE}) "include/pistache/version.h.in"
"include/pistache/version.h"
# Make available in a header file... @ONLY
configure_file ( )
"include/pistache/version.h.in"
"include/pistache/version.h"
@ONLY
)
# Set public interface version...
# Major should be incremented every time a non-backward compatible change
# occurs in the ABI...
string(REGEX MATCH "SONAME_VERSION_MAJOR *([0-9]*)" _ ${VERSION_FILE})
set(SONAME_VERSION_MAJOR ${CMAKE_MATCH_1})
# Minor should be incremented every time a backward compatible change occurs
# in the ABI...
string(REGEX MATCH "SONAME_VERSION_MINOR *([0-9]+)" _ ${VERSION_FILE})
set(SONAME_VERSION_MINOR ${CMAKE_MATCH_1})
add_subdirectory (src) add_subdirectory (src)
......
...@@ -38,29 +38,25 @@ Pistache was originally created by Mathieu Stefani (`@octal`). He continues to c ...@@ -38,29 +38,25 @@ Pistache was originally created by Mathieu Stefani (`@octal`). He continues to c
The [Launchpad Team](https://launchpad.net/~pistache+team) administers the daily and stable Ubuntu pre-compiled packages. The [Launchpad Team](https://launchpad.net/~pistache+team) administers the daily and stable Ubuntu pre-compiled packages.
### Release Versioning ### Versioning
Please update `version.txt` accordingly with each unstable or stable release. The version of the library's public interface (ABI) is not the same as the release version, but we choose to always guarantee that the major release version and the soname version will match. The interface version is primarily associated with the _external_ interface of the library. Different platforms handle this differently, such as AIX, GNU/Linux, and Solaris.
### Interface Versioning GNU Libtool abstracts each platform's idiosyncrasies away because it is more portable than using `ar(1)` or `ranlib(1)` directly. However, it is [not supported in Meson](https://mesonbuild.com/FAQ.html#how-do-i-do-the-equivalent-of-libtools-exportsymbol-and-exportregex) so we made do without it by setting the SONAME directly.
The version of the library's public interface (ABI) is not the same as the release version. The interface version is primarily associated with the _external_ interface of the library. Different platforms handle this differently, such as AIX, GNU/Linux, and Solaris.
GNU Libtool abstracts each platform's idiosyncrasies away because it is more portable than using `ar(1)` or `ranlib(1)` directly. However, it is a pain to integrate with CMake so we made do without it by setting the SONAME directly.
When Pistache is installed it will normally ship: When Pistache is installed it will normally ship:
- `libpistache-<release>.so.X.Y`: This is the actual shared-library binary file. The _X_ and _Y_ values are the major and minor interface versions respectively. - `libpistache.so.X.Y.Z`: This is the actual shared-library binary file. The _X_, _Y_ and _Z_ values are the major, minor and patch interface versions respectively.
- `libpistache-<release>.so.X`: This is the _soname_ soft link that points to the binary file. It is what other programs and other libraries reference internally. You should never need to directly reference this file in your build environment. - `libpistache.so.X`: This is the _soname_ soft link that points to the binary file. It is what other programs and other libraries reference internally. You should never need to directly reference this file in your build environment.
- `libpistache-<release>.so`: This is the _linker name_ entry. This is also a soft link that refers to the soname with the highest major interface version. This linker name is what is referred to on the linker command line. This file is created by the installation process. - `libpistache.so`: This is the _linker name_ entry. This is also a soft link that refers to the soname with the highest major interface version. This linker name is what is referred to on the linker command line.
- `libpistache-<release>.a`: This is the _static archive_ form of the library. Since when using a static library all of its symbols are normally resolved before runtime, an interface version in the filename is unnecessary. - `libpistache.a`: This is the _static archive_ form of the library. Since when using a static library all of its symbols are normally resolved before runtime, an interface version in the filename is unnecessary.
If your contribution has modified the interface, you may need to update the major or minor interface versions. Otherwise user applications and build environments will eventually break. This is because they will attempt to link against an incorrect version of the library -- or worse, link correctly but with undefined runtime behaviour. If your contribution has modified the interface, you may need to update the major or minor interface versions. Otherwise user applications and build environments will eventually break. This is because they will attempt to link against an incorrect version of the library -- or worse, link correctly but with undefined runtime behaviour.
The major version should be incremented every time a non-backward compatible change occured in the ABI. The minor version should be incremented every time a backward compatible change occurs. This can be done by modifying `version.txt` accordingly. The major version should be incremented when you make incompatible API or ABI changes. The minor version should be incremented when you add functionality in a backwards compatible manner. The patch version should be incremented when you make backwards compatible bug fixes. This can be done by modifying `version.txt` accordingly. Also remember to always update the commit date in the aformentioned file.
## Precompiled Packages ## Precompiled Packages
...@@ -87,7 +83,7 @@ Currently Pistache is built and tested on a number of [architectures](https://wi ...@@ -87,7 +83,7 @@ Currently Pistache is built and tested on a number of [architectures](https://wi
The project builds [daily unstable snapshots](https://launchpad.net/~pistache+team/+archive/ubuntu/unstable) in a separate unstable PPA. To use it, run the following: The project builds [daily unstable snapshots](https://launchpad.net/~pistache+team/+archive/ubuntu/unstable) in a separate unstable PPA. To use it, run the following:
```console ```sh
$ sudo add-apt-repository ppa:pistache+team/unstable $ sudo add-apt-repository ppa:pistache+team/unstable
$ sudo apt update $ sudo apt update
$ sudo apt install libpistache-dev $ sudo apt install libpistache-dev
...@@ -97,7 +93,7 @@ $ sudo apt install libpistache-dev ...@@ -97,7 +93,7 @@ $ sudo apt install libpistache-dev
Currently there are no stable release of Pistache published into the [stable](https://launchpad.net/~pistache+team/+archive/ubuntu/stable) PPA. However, when that time comes, run the following to install a stable package: Currently there are no stable release of Pistache published into the [stable](https://launchpad.net/~pistache+team/+archive/ubuntu/stable) PPA. However, when that time comes, run the following to install a stable package:
```console ```sh
$ sudo add-apt-repository ppa:pistache+team/stable $ sudo add-apt-repository ppa:pistache+team/stable
$ sudo apt update $ sudo apt update
$ sudo apt install libpistache-dev $ sudo apt install libpistache-dev
...@@ -145,19 +141,19 @@ executable( ...@@ -145,19 +141,19 @@ executable(
If you want to build the library from source in case the dependency is not found on the system, you can add this repository as a submodule in the `subprojects` directory of your project, and edit the `dependency()` call as follows: If you want to build the library from source in case the dependency is not found on the system, you can add this repository as a submodule in the `subprojects` directory of your project, and edit the `dependency()` call as follows:
```meson ```meson
dependencies: dependency('libpistache', fallback: 'pistache') dependency('libpistache', fallback: 'pistache')
``` ```
If you're using a Meson version older than 0.55.0 you'll have to use the "older" syntax for `dependency()`: If you're using a Meson version older than 0.55.0 you'll have to use the "older" syntax for `dependency()`:
```meson ```meson
dependencies: dependency('libpistache', fallback: ['pistache', 'pistache_dep']) dependency('libpistache', fallback: ['pistache', 'pistache_dep'])
``` ```
Lastly, if you'd like to build the fallback as a static library you can specify it with the `default_options` keyword: Lastly, if you'd like to build the fallback as a static library you can specify it with the `default_options` keyword:
```meson ```meson
dependencies: dependency('libpistache', fallback: 'pistache', default_options: 'default_library=static') dependency('libpistache', fallback: 'pistache', default_options: 'default_library=static')
``` ```
### CMake ### CMake
...@@ -205,7 +201,7 @@ $ meson setup build \ ...@@ -205,7 +201,7 @@ $ meson setup build \
-DPISTACHE_BUILD_EXAMPLES=true \ -DPISTACHE_BUILD_EXAMPLES=true \
-DPISTACHE_BUILD_TESTS=true \ -DPISTACHE_BUILD_TESTS=true \
-DPISTACHE_BUILD_DOCS=false \ -DPISTACHE_BUILD_DOCS=false \
--prefix=$PWD/prefix --prefix="$PWD/prefix"
$ meson compile -C build $ meson compile -C build
$ meson install -C build $ meson install -C build
``` ```
...@@ -239,7 +235,7 @@ using namespace Pistache; ...@@ -239,7 +235,7 @@ using namespace Pistache;
struct HelloHandler : public Http::Handler { struct HelloHandler : public Http::Handler {
HTTP_PROTOTYPE(HelloHandler) HTTP_PROTOTYPE(HelloHandler)
void onRequest(const Http::Request&, Http::ResponseWriter writer) override{ void onRequest(const Http::Request&, Http::ResponseWriter writer) override {
writer.send(Http::Code::Ok, "Hello, World!"); writer.send(Http::Code::Ok, "Hello, World!");
} }
}; };
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
# #
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
configure_file(input: 'version.h.in', output: 'version.h', configuration: version_data_conf, install: get_option('PISTACHE_INSTALL'), install_dir: get_option('includedir')/'pistache') configure_file(input: 'version.h.in', output: 'version.h', configuration: version_conf, install: get_option('PISTACHE_INSTALL'), install_dir: get_option('includedir')/'pistache')
install_headers([ install_headers(
'async.h', 'async.h',
'base64.h', 'base64.h',
'client.h', 'client.h',
...@@ -41,7 +41,7 @@ install_headers([ ...@@ -41,7 +41,7 @@ install_headers([
'type_checkers.h', 'type_checkers.h',
'typeid.h', 'typeid.h',
'utils.h', 'utils.h',
'view.h' 'view.h',
], subdir: 'pistache') subdir: 'pistache')
install_subdir('serializer', install_dir: get_option('includedir')/'pistache') install_subdir('serializer', install_dir: get_option('includedir')/'pistache')
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
project( project(
'pistache', 'pistache',
'cpp', 'cpp',
version: '0.0.003', # TODO: This should be assigned dynamically from version.txt version: '0.0.3', # In Meson 0.57 this can be replaced with files('version.txt')
license: 'Apache-2.0', license: 'Apache-2.0',
default_options: [ default_options: [
'cpp_std=c++17', 'cpp_std=c++17',
...@@ -86,26 +86,27 @@ if get_option('PISTACHE_USE_SSL') ...@@ -86,26 +86,27 @@ if get_option('PISTACHE_USE_SSL')
deps_libpistache += dependency('openssl') deps_libpistache += dependency('openssl')
endif endif
version_data_raw = '' version_array = []
if meson.version().version_compare('>=0.57.0') if meson.version().version_compare('>=0.57.0')
fs = import('fs') version_array = import('fs').read('version.txt').strip().split('.')
version_data_raw = fs.read('version.txt').split('\n')
else else
# Ugly workaround for reading a file # Ugly workaround for reading a file
version_data_raw = run_command( version_array = run_command(
import('python').find_installation(), '-c', 'print(open("version.txt").read())' import('python').find_installation(), '-c', 'print(open("version.txt").read())'
).stdout().strip().split('\n') ).stdout().strip().split('.')
endif endif
version_data_conf = configuration_data()
foreach _ : version_data_raw
if _ != ''
__ = _.split(' ')
version_data_conf.set(__[0], __[-1])
endif
endforeach
pistache_version_str = '.'.join([version_data_conf.get_unquoted('VERSION_MAJOR'), version_data_conf.get_unquoted('VERSION_MINOR'), version_data_conf.get_unquoted('VERSION_PATCH')]) version_major = version_array[0]
pistache_soversion_str = '.'.join([version_data_conf.get_unquoted('SONAME_VERSION_MAJOR'), version_data_conf.get_unquoted('SONAME_VERSION_MINOR')]) version_minor = version_array[1]
version_patch = version_array[2]
version_git_date = version_array[3]
version_str = '@0@.@1@.@2@'.format(version_major, version_minor, version_patch)
version_conf = configuration_data()
version_conf.set('VERSION_MAJOR', version_major)
version_conf.set('VERSION_MINOR', version_minor)
version_conf.set('VERSION_PATCH', version_patch)
version_conf.set('VERSION_GIT_DATE', version_git_date)
incl_pistache = include_directories('include') incl_pistache = include_directories('include')
......
...@@ -71,14 +71,14 @@ if (PISTACHE_USE_SSL) ...@@ -71,14 +71,14 @@ if (PISTACHE_USE_SSL)
endif () endif ()
endif () endif ()
set(Pistache_OUTPUT_NAME "pistache")
if (BUILD_SHARED_LIBS) if (BUILD_SHARED_LIBS)
set_target_properties(pistache_shared PROPERTIES set_target_properties(pistache_shared PROPERTIES
OUTPUT_NAME ${Pistache_OUTPUT_NAME}-${VERSION} OUTPUT_NAME ${PROJECT_NAME}
SOVERSION ${SONAME_VERSION_MAJOR}.${SONAME_VERSION_MINOR} VERSION ${pistache_VERSION}
SOVERSION ${pistache_VERSION_MAJOR}
) )
endif () endif ()
set_target_properties(pistache_static PROPERTIES set_target_properties(pistache_static PROPERTIES
OUTPUT_NAME ${Pistache_OUTPUT_NAME} OUTPUT_NAME ${PROJECT_NAME}
) )
...@@ -41,8 +41,7 @@ libpistache = library( ...@@ -41,8 +41,7 @@ libpistache = library(
include_directories: incl_pistache, include_directories: incl_pistache,
dependencies: deps_libpistache, dependencies: deps_libpistache,
install: get_option('PISTACHE_INSTALL'), install: get_option('PISTACHE_INSTALL'),
version: pistache_version_str, version: version_str,
soversion: pistache_soversion_str,
pic: get_option('b_staticpic') pic: get_option('b_staticpic')
) )
...@@ -52,12 +51,11 @@ if meson.version().version_compare('>=0.54.0') ...@@ -52,12 +51,11 @@ if meson.version().version_compare('>=0.54.0')
meson.override_dependency('libpistache', pistache_dep) meson.override_dependency('libpistache', pistache_dep)
endif endif
pkg = import('pkgconfig') import('pkgconfig').generate(
pkg.generate(
libpistache, libpistache,
name: 'Pistache', name: 'Pistache',
description: 'An elegant C++ REST framework.', description: 'An elegant C++ REST framework',
url: 'http://pistache.io', url: 'http://pistache.io',
version: pistache_version_str+'-git'+version_data_conf.get_unquoted('VERSION_GIT_DATE'), version: '@0@-git@1@'.format(version_str, version_git_date),
filebase: 'libpistache' filebase: 'libpistache'
) )
VERSION_MAJOR 0 0.0.3.20211030
VERSION_MINOR 0
VERSION_PATCH 003
VERSION_GIT_DATE 20211020
SONAME_VERSION_MAJOR 1
SONAME_VERSION_MINOR 0
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment