[libcamera-devel] libcamera: Auto generate version information

Message ID 20190611201411.16369-1-kieran.bingham@ideasonboard.com
State Accepted
Headers show
Series
  • [libcamera-devel] libcamera: Auto generate version information
Related show

Commit Message

Kieran Bingham June 11, 2019, 8:14 p.m. UTC
Generate a version string, and provide a global singleton object which
allows applications to interogate the current libcamera version
information.

The version header is automatically updated by meson on each build.
The string roughly follows the semver [0] conventions of
major.minor.patch-label as a value.

[0] https://semver.org/

The utils/version-gen script will look for tags in the form vX.Y as
starting points for the version string. While the repository does not
have any matching tags, v0.0 will be assumed, resulting in versions with
both major and minor being set to '0', and the patch count resulting
from the number of patches in the history to that point.

Finally, a uniquely identifying shortened checksum is provided from git:

	v0.0.509.c544

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 Documentation/conf.py         |  6 ++++--
 include/libcamera/meson.build |  1 +
 include/libcamera/version.h   | 23 ++++++++++++++++++++
 meson.build                   |  9 +++++++-
 src/libcamera/meson.build     |  1 +
 src/libcamera/version.cpp     | 40 +++++++++++++++++++++++++++++++++++
 utils/version-gen             | 36 +++++++++++++++++++++++++++++++
 version.h.in                  |  3 +++
 8 files changed, 116 insertions(+), 3 deletions(-)
 create mode 100644 include/libcamera/version.h
 create mode 100644 src/libcamera/version.cpp
 create mode 100755 utils/version-gen
 create mode 100644 version.h.in

Comments

Laurent Pinchart June 11, 2019, 8:32 p.m. UTC | #1
Hi Kieran,

Thank you for the patch.

On Tue, Jun 11, 2019 at 09:14:11PM +0100, Kieran Bingham wrote:
> Generate a version string, and provide a global singleton object which
> allows applications to interogate the current libcamera version
> information.
> 
> The version header is automatically updated by meson on each build.
> The string roughly follows the semver [0] conventions of
> major.minor.patch-label as a value.
> 
> [0] https://semver.org/
> 
> The utils/version-gen script will look for tags in the form vX.Y as
> starting points for the version string. While the repository does not
> have any matching tags, v0.0 will be assumed, resulting in versions with
> both major and minor being set to '0', and the patch count resulting
> from the number of patches in the history to that point.
> 
> Finally, a uniquely identifying shortened checksum is provided from git:
> 
> 	v0.0.509.c544
> 
> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> ---
>  Documentation/conf.py         |  6 ++++--
>  include/libcamera/meson.build |  1 +
>  include/libcamera/version.h   | 23 ++++++++++++++++++++
>  meson.build                   |  9 +++++++-
>  src/libcamera/meson.build     |  1 +
>  src/libcamera/version.cpp     | 40 +++++++++++++++++++++++++++++++++++
>  utils/version-gen             | 36 +++++++++++++++++++++++++++++++
>  version.h.in                  |  3 +++
>  8 files changed, 116 insertions(+), 3 deletions(-)
>  create mode 100644 include/libcamera/version.h
>  create mode 100644 src/libcamera/version.cpp
>  create mode 100755 utils/version-gen
>  create mode 100644 version.h.in
> 
> diff --git a/Documentation/conf.py b/Documentation/conf.py
> index 970edf3d7298..e5980b98216d 100644
> --- a/Documentation/conf.py
> +++ b/Documentation/conf.py
> @@ -23,10 +23,12 @@ project = 'libcamera'
>  copyright = '2018-2019, The libcamera documentation authors'
>  author = u'Kieran Bingham, Jacopo Mondi, Laurent Pinchart, Niklas Söderlund'
>  
> +# Vesion information is provided by the build environment.

s/Vesion/Version/

> +#
>  # The short X.Y version
> -version = ''
> +# version = ''
>  # The full version, including alpha/beta/rc tags
> -release = '0.1'
> +# release = '0.1'

Should we just delete the version and release lines ?

>  # -- General configuration ---------------------------------------------------
> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
> index 1b86fdc7fca4..201832105457 100644
> --- a/include/libcamera/meson.build
> +++ b/include/libcamera/meson.build
> @@ -12,6 +12,7 @@ libcamera_api = files([
>      'signal.h',
>      'stream.h',
>      'timer.h',
> +    'version.h',
>  ])
>  
>  gen_header = join_paths(meson.current_source_dir(), 'gen-header.sh')
> diff --git a/include/libcamera/version.h b/include/libcamera/version.h
> new file mode 100644
> index 000000000000..ad21f148e748
> --- /dev/null
> +++ b/include/libcamera/version.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2019, Google Inc.
> + *
> + * version.h - Library version information
> + */
> +#ifndef __LIBCAMERA_VERSION_H__
> +#define __LIBCAMERA_VERSION_H__
> +
> +namespace libcamera {
> +
> +class LibcameraVersion
> +{
> +public:
> +	LibcameraVersion();
> +	std::string toString();
> +};
> +
> +extern LibcameraVersion version;
> +
> +} /* namespace libcamera */
> +
> +#endif /* __LIBCAMERA_VERSION_H__ */

This seems a bit overkill, can't we just install version.h ?

> diff --git a/meson.build b/meson.build
> index 4d3e99d3e58f..5182546382c5 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -1,6 +1,8 @@
>  project('libcamera', 'c', 'cpp',
>      meson_version : '>= 0.40',
> -    version : '0.1',
> +    version : run_command('utils/version-gen',
> +                          '@0@'.format(meson.source_root()),
> +                          check : true).stdout().strip(),
>      default_options : [
>          'werror=true',
>          'warning_level=2',
> @@ -13,6 +15,11 @@ project('libcamera', 'c', 'cpp',
>  #       generated from this too.
>  api_version = '0.1'
>  
> +vcs_tag(command: ['utils/version-gen', '.'],
> +        input: 'version.h.in',
> +	output: 'version.h',
> +	fallback: '')

Mixing tabs and spaces.

Don't you need to add the customtarget object returned by vcs_tag to
dependencies or sources for something ? Otherwise meson won't know what
depends on version.h.

> +
>  cc = meson.get_compiler('c')
>  config_h = configuration_data()
>  
> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> index 1ca1083cf5c7..b9a4153839c9 100644
> --- a/src/libcamera/meson.build
> +++ b/src/libcamera/meson.build
> @@ -25,6 +25,7 @@ libcamera_sources = files([
>      'utils.cpp',
>      'v4l2_device.cpp',
>      'v4l2_subdevice.cpp',
> +    'version.cpp',
>  ])
>  
>  libcamera_headers = files([
> diff --git a/src/libcamera/version.cpp b/src/libcamera/version.cpp
> new file mode 100644
> index 000000000000..81f692f7cae7
> --- /dev/null
> +++ b/src/libcamera/version.cpp
> @@ -0,0 +1,40 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2019, Google Inc.
> + *
> + * version.cpp - Version information
> + */
> +
> +#include <libcamera/version.h>
> +
> +#include "log.h"
> +
> +/* The version header is automatically generated at the base of the project. */
> +#include "../../version.h"
> +
> +namespace libcamera {
> +
> +LOG_DEFINE_CATEGORY(Version)
> +
> +/**
> + * \class LibcameraVersion
> + *
> + * Reports library version information
> + */
> +
> +LibcameraVersion::LibcameraVersion()
> +{
> +	LOG(Version, Info) << "Libcamera Version " << toString();
> +}
> +
> +/**
> + * \brief Return the library version as a string
> + */
> +std::string LibcameraVersion::toString()
> +{
> +	return LIBCAMERA_VERSION;
> +}
> +
> +static LibcameraVersion version;
> +
> +} /* namespace libcamera */
> diff --git a/utils/version-gen b/utils/version-gen
> new file mode 100755
> index 000000000000..b8e53d77b63e
> --- /dev/null
> +++ b/utils/version-gen
> @@ -0,0 +1,36 @@
> +#!/bin/sh

Missing SPDX header.

> +
> +if test -n "$1"

Please use

if [[ ]] ; then

Our scripts rely on bash, so I think I would specify that explicitly
instead of /bin/sh.

> +then
> +	cd "$1"
> +fi
> +
> +# No fall back is provided for tarball releases or such, as we do not yet provide releases.

Line break at 80 columns ?

Tarball releases should just ship version.h.

> +
> +# Get a short description from the tree.
> +version=$(git describe --abbrev=4 --match "v[0-9]*" 2>/dev/null)
> +
> +if test -z "$version"
> +then

if [[ -z "$version" ]] ; then

> +	# Handle an un-tagged repository
> +	sha=$(git describe --abbrev=4 --always 2>/dev/null)
> +	commits=$(git log --oneline | wc -l 2>/dev/null)
> +	version=v0.0.$commits.$sha
> +fi
> +
> +
> +git update-index --refresh > /dev/null 2>&1

What does this do ?

> +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=

$(...) instead of `...`

> +
> +# Strip the 'g'

Anything wrong with the 'g' ? :-)

> +version=$(echo "$version" | sed -e 's/-g/-/g')
> +
> +# Fix the '-' (the patch count) to a '.' as a version increment.
> +version=$(echo "$version" | sed -e 's/-/./g')
> +
> +if test -n "$dirty"
> +then

if [[ -n "$dirty" ]] ; then

> +	version=$version-dirty
> +fi
> +
> +echo $version
> diff --git a/version.h.in b/version.h.in
> new file mode 100644
> index 000000000000..142819645b64
> --- /dev/null
> +++ b/version.h.in
> @@ -0,0 +1,3 @@

Should this have a comment stating that the file is auto-generated ?

> +#pragma once

We usually use #ifdef #define #endif, is there a specific reason to use
a #pragma instead ?

> +
> +#define LIBCAMERA_VERSION "@VCS_TAG@"
Kieran Bingham June 11, 2019, 10:25 p.m. UTC | #2
Hi Laurent,

On 11/06/2019 21:32, Laurent Pinchart wrote:
> Hi Kieran,
> 
> Thank you for the patch.
> 
> On Tue, Jun 11, 2019 at 09:14:11PM +0100, Kieran Bingham wrote:
>> Generate a version string, and provide a global singleton object which
>> allows applications to interogate the current libcamera version
>> information.
>>
>> The version header is automatically updated by meson on each build.
>> The string roughly follows the semver [0] conventions of
>> major.minor.patch-label as a value.
>>
>> [0] https://semver.org/
>>
>> The utils/version-gen script will look for tags in the form vX.Y as
>> starting points for the version string. While the repository does not
>> have any matching tags, v0.0 will be assumed, resulting in versions with
>> both major and minor being set to '0', and the patch count resulting
>> from the number of patches in the history to that point.
>>
>> Finally, a uniquely identifying shortened checksum is provided from git:
>>
>> 	v0.0.509.c544
>>
>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>> ---
>>  Documentation/conf.py         |  6 ++++--
>>  include/libcamera/meson.build |  1 +
>>  include/libcamera/version.h   | 23 ++++++++++++++++++++
>>  meson.build                   |  9 +++++++-
>>  src/libcamera/meson.build     |  1 +
>>  src/libcamera/version.cpp     | 40 +++++++++++++++++++++++++++++++++++
>>  utils/version-gen             | 36 +++++++++++++++++++++++++++++++
>>  version.h.in                  |  3 +++
>>  8 files changed, 116 insertions(+), 3 deletions(-)
>>  create mode 100644 include/libcamera/version.h
>>  create mode 100644 src/libcamera/version.cpp
>>  create mode 100755 utils/version-gen
>>  create mode 100644 version.h.in
>>
>> diff --git a/Documentation/conf.py b/Documentation/conf.py
>> index 970edf3d7298..e5980b98216d 100644
>> --- a/Documentation/conf.py
>> +++ b/Documentation/conf.py
>> @@ -23,10 +23,12 @@ project = 'libcamera'
>>  copyright = '2018-2019, The libcamera documentation authors'
>>  author = u'Kieran Bingham, Jacopo Mondi, Laurent Pinchart, Niklas Söderlund'
>>  
>> +# Vesion information is provided by the build environment.
> 
> s/Vesion/Version/

Eeep. Fixed.

> 
>> +#
>>  # The short X.Y version
>> -version = ''
>> +# version = ''
>>  # The full version, including alpha/beta/rc tags
>> -release = '0.1'
>> +# release = '0.1'
> 
> Should we just delete the version and release lines ?

I chose to keep these intentionally. The rest of the conf.py contains
'template' lines.

I can remove if you prefer, but the whole conf.py could probably be
stripped right down too.

> 
>>  # -- General configuration ---------------------------------------------------
>> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
>> index 1b86fdc7fca4..201832105457 100644
>> --- a/include/libcamera/meson.build
>> +++ b/include/libcamera/meson.build
>> @@ -12,6 +12,7 @@ libcamera_api = files([
>>      'signal.h',
>>      'stream.h',
>>      'timer.h',
>> +    'version.h',
>>  ])
>>  
>>  gen_header = join_paths(meson.current_source_dir(), 'gen-header.sh')
>> diff --git a/include/libcamera/version.h b/include/libcamera/version.h
>> new file mode 100644
>> index 000000000000..ad21f148e748
>> --- /dev/null
>> +++ b/include/libcamera/version.h
>> @@ -0,0 +1,23 @@
>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
>> +/*
>> + * Copyright (C) 2019, Google Inc.
>> + *
>> + * version.h - Library version information
>> + */
>> +#ifndef __LIBCAMERA_VERSION_H__
>> +#define __LIBCAMERA_VERSION_H__
>> +
>> +namespace libcamera {
>> +
>> +class LibcameraVersion
>> +{
>> +public:
>> +	LibcameraVersion();
>> +	std::string toString();
>> +};
>> +
>> +extern LibcameraVersion version;
>> +
>> +} /* namespace libcamera */
>> +
>> +#endif /* __LIBCAMERA_VERSION_H__ */
> 
> This seems a bit overkill, can't we just install version.h ?

I wanted to provide a way for an application or otherwise to obtain the
information at runtime.

The static global instance 'version' prints a debug line through our LOG
interface at library start up, and I wanted to be able to expose that
string if needed.

Hrm... seems I messed up the patch anyway, I can't extern a static :-) -
Making it just 'global' to fix.


>> diff --git a/meson.build b/meson.build
>> index 4d3e99d3e58f..5182546382c5 100644
>> --- a/meson.build
>> +++ b/meson.build
>> @@ -1,6 +1,8 @@
>>  project('libcamera', 'c', 'cpp',
>>      meson_version : '>= 0.40',
>> -    version : '0.1',
>> +    version : run_command('utils/version-gen',
>> +                          '@0@'.format(meson.source_root()),
>> +                          check : true).stdout().strip(),
>>      default_options : [
>>          'werror=true',
>>          'warning_level=2',
>> @@ -13,6 +15,11 @@ project('libcamera', 'c', 'cpp',
>>  #       generated from this too.
>>  api_version = '0.1'
>>  
>> +vcs_tag(command: ['utils/version-gen', '.'],
>> +        input: 'version.h.in',
>> +	output: 'version.h',
>> +	fallback: '')
> 
> Mixing tabs and spaces.

Oops! I thought I fixed that.


> Don't you need to add the customtarget object returned by vcs_tag to
> dependencies or sources for something ? Otherwise meson won't know what
> depends on version.h.

I think you're right, but I can't see how to express a dependency on
only a single object file.

I'll have to ask that one in #mesonbuild.

I don't know what magic is happening, but it does seem to be doing the
right thing anyway.

I've tested this with a few iterations of changing files that should not
directly recreate the version.o or libcamera.so - but does affect the
version-gen output, such as changing between a clean tree, and a -dirty
label - and the library does seem to be correctly updated.

I'll call this one 'resolved by magic' for now.

>> +
>>  cc = meson.get_compiler('c')
>>  config_h = configuration_data()
>>  
>> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
>> index 1ca1083cf5c7..b9a4153839c9 100644
>> --- a/src/libcamera/meson.build
>> +++ b/src/libcamera/meson.build
>> @@ -25,6 +25,7 @@ libcamera_sources = files([
>>      'utils.cpp',
>>      'v4l2_device.cpp',
>>      'v4l2_subdevice.cpp',
>> +    'version.cpp',
>>  ])
>>  
>>  libcamera_headers = files([
>> diff --git a/src/libcamera/version.cpp b/src/libcamera/version.cpp
>> new file mode 100644
>> index 000000000000..81f692f7cae7
>> --- /dev/null
>> +++ b/src/libcamera/version.cpp
>> @@ -0,0 +1,40 @@
>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
>> +/*
>> + * Copyright (C) 2019, Google Inc.
>> + *
>> + * version.cpp - Version information
>> + */
>> +
>> +#include <libcamera/version.h>
>> +
>> +#include "log.h"
>> +
>> +/* The version header is automatically generated at the base of the project. */
>> +#include "../../version.h"
>> +
>> +namespace libcamera {
>> +
>> +LOG_DEFINE_CATEGORY(Version)
>> +
>> +/**
>> + * \class LibcameraVersion
>> + *
>> + * Reports library version information
>> + */
>> +
>> +LibcameraVersion::LibcameraVersion()
>> +{
>> +	LOG(Version, Info) << "Libcamera Version " << toString();
>> +}
>> +
>> +/**
>> + * \brief Return the library version as a string
>> + */
>> +std::string LibcameraVersion::toString()
>> +{
>> +	return LIBCAMERA_VERSION;
>> +}
>> +
>> +static LibcameraVersion version;
>> +
>> +} /* namespace libcamera */
>> diff --git a/utils/version-gen b/utils/version-gen
>> new file mode 100755
>> index 000000000000..b8e53d77b63e
>> --- /dev/null
>> +++ b/utils/version-gen
>> @@ -0,0 +1,36 @@
>> +#!/bin/sh
> 
> Missing SPDX header.

As a component of the build system, is this GPL? or LGPL?


>> +
>> +if test -n "$1"
> 
> Please use
> 
> if [[ ]] ; then
> 
> Our scripts rely on bash, so I think I would specify that explicitly
> instead of /bin/sh.

I am intentionally trying to stay posix shell compliant.

libcamera$ git grep bash
utils/ipu3/ipu3-capture.sh:#!/bin/bash
utils/ipu3/ipu3-process.sh:#!/bin/bash

There's a big difference between non-essential helper scripts for a user
to run - and a script which is executed by the build system...

Thus I'm not sure being reliant on bash is the right thing ...

I should run shellcheck too :)
	(Fixed those warnings too)

> 
>> +then
>> +	cd "$1"
>> +fi
>> +
>> +# No fall back is provided for tarball releases or such, as we do not yet provide releases.
> 
> Line break at 80 columns ?
> 

Fixed.

> Tarball releases should just ship version.h.

Sure, but the build system will have to know not to regenerate it.

We'll sort that later.

>> +
>> +# Get a short description from the tree.
>> +version=$(git describe --abbrev=4 --match "v[0-9]*" 2>/dev/null)
>> +
>> +if test -z "$version"
>> +then
> 
> if [[ -z "$version" ]] ; then
> 
>> +	# Handle an un-tagged repository
>> +	sha=$(git describe --abbrev=4 --always 2>/dev/null)
>> +	commits=$(git log --oneline | wc -l 2>/dev/null)
>> +	version=v0.0.$commits.$sha
>> +fi
>> +
>> +
>> +git update-index --refresh > /dev/null 2>&1
> 
> What does this do ?

Prevents changed timestamps causing a -dirty label. I've added a comment.

> 
>> +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
> 
> $(...) instead of `...`
> 
>> +
>> +# Strip the 'g'
> 
> Anything wrong with the 'g' ? :-)

Would you like to keep it?

>> +version=$(echo "$version" | sed -e 's/-g/-/g')
>> +
>> +# Fix the '-' (the patch count) to a '.' as a version increment.
>> +version=$(echo "$version" | sed -e 's/-/./g')
>> +
>> +if test -n "$dirty"
>> +then
> 
> if [[ -n "$dirty" ]] ; then
> 
>> +	version=$version-dirty
>> +fi
>> +
>> +echo $version
>> diff --git a/version.h.in b/version.h.in
>> new file mode 100644
>> index 000000000000..142819645b64
>> --- /dev/null
>> +++ b/version.h.in
>> @@ -0,0 +1,3 @@
> 
> Should this have a comment stating that the file is auto-generated ?

Added.

> 
>> +#pragma once
> 
> We usually use #ifdef #define #endif, is there a specific reason to use
> a #pragma instead ?
> 

Probably just because of the sample vcs_tag generator file I looked
at... It was in January so I don't recall anything specific.
 (I'm trying to clear my backlog of misc patches)

I'll change to #ifdefs

>> +
>> +#define LIBCAMERA_VERSION "@VCS_TAG@"
>
Laurent Pinchart June 12, 2019, 8:39 a.m. UTC | #3
Hi Kieran,

On Tue, Jun 11, 2019 at 11:25:43PM +0100, Kieran Bingham wrote:
> On 11/06/2019 21:32, Laurent Pinchart wrote:
> > On Tue, Jun 11, 2019 at 09:14:11PM +0100, Kieran Bingham wrote:
> >> Generate a version string, and provide a global singleton object which
> >> allows applications to interogate the current libcamera version
> >> information.
> >>
> >> The version header is automatically updated by meson on each build.
> >> The string roughly follows the semver [0] conventions of
> >> major.minor.patch-label as a value.
> >>
> >> [0] https://semver.org/
> >>
> >> The utils/version-gen script will look for tags in the form vX.Y as
> >> starting points for the version string. While the repository does not
> >> have any matching tags, v0.0 will be assumed, resulting in versions with
> >> both major and minor being set to '0', and the patch count resulting
> >> from the number of patches in the history to that point.
> >>
> >> Finally, a uniquely identifying shortened checksum is provided from git:
> >>
> >> 	v0.0.509.c544
> >>
> >> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> >> ---
> >>  Documentation/conf.py         |  6 ++++--
> >>  include/libcamera/meson.build |  1 +
> >>  include/libcamera/version.h   | 23 ++++++++++++++++++++
> >>  meson.build                   |  9 +++++++-
> >>  src/libcamera/meson.build     |  1 +
> >>  src/libcamera/version.cpp     | 40 +++++++++++++++++++++++++++++++++++
> >>  utils/version-gen             | 36 +++++++++++++++++++++++++++++++
> >>  version.h.in                  |  3 +++
> >>  8 files changed, 116 insertions(+), 3 deletions(-)
> >>  create mode 100644 include/libcamera/version.h
> >>  create mode 100644 src/libcamera/version.cpp
> >>  create mode 100755 utils/version-gen
> >>  create mode 100644 version.h.in
> >>
> >> diff --git a/Documentation/conf.py b/Documentation/conf.py
> >> index 970edf3d7298..e5980b98216d 100644
> >> --- a/Documentation/conf.py
> >> +++ b/Documentation/conf.py
> >> @@ -23,10 +23,12 @@ project = 'libcamera'
> >>  copyright = '2018-2019, The libcamera documentation authors'
> >>  author = u'Kieran Bingham, Jacopo Mondi, Laurent Pinchart, Niklas Söderlund'
> >>  
> >> +# Vesion information is provided by the build environment.
> > 
> > s/Vesion/Version/
> 
> Eeep. Fixed.
> 
> >> +#
> >>  # The short X.Y version
> >> -version = ''
> >> +# version = ''
> >>  # The full version, including alpha/beta/rc tags
> >> -release = '0.1'
> >> +# release = '0.1'
> > 
> > Should we just delete the version and release lines ?
> 
> I chose to keep these intentionally. The rest of the conf.py contains
> 'template' lines.
> 
> I can remove if you prefer, but the whole conf.py could probably be
> stripped right down too.

If you want to keep them please make sure they match the stock template
file.

By the way, where does the build environment provide version information
to sphinx ?

> >>  # -- General configuration ---------------------------------------------------
> >> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
> >> index 1b86fdc7fca4..201832105457 100644
> >> --- a/include/libcamera/meson.build
> >> +++ b/include/libcamera/meson.build
> >> @@ -12,6 +12,7 @@ libcamera_api = files([
> >>      'signal.h',
> >>      'stream.h',
> >>      'timer.h',
> >> +    'version.h',
> >>  ])
> >>  
> >>  gen_header = join_paths(meson.current_source_dir(), 'gen-header.sh')
> >> diff --git a/include/libcamera/version.h b/include/libcamera/version.h
> >> new file mode 100644
> >> index 000000000000..ad21f148e748
> >> --- /dev/null
> >> +++ b/include/libcamera/version.h
> >> @@ -0,0 +1,23 @@
> >> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> >> +/*
> >> + * Copyright (C) 2019, Google Inc.
> >> + *
> >> + * version.h - Library version information
> >> + */
> >> +#ifndef __LIBCAMERA_VERSION_H__
> >> +#define __LIBCAMERA_VERSION_H__
> >> +
> >> +namespace libcamera {
> >> +
> >> +class LibcameraVersion
> >> +{
> >> +public:
> >> +	LibcameraVersion();
> >> +	std::string toString();
> >> +};
> >> +
> >> +extern LibcameraVersion version;
> >> +
> >> +} /* namespace libcamera */
> >> +
> >> +#endif /* __LIBCAMERA_VERSION_H__ */
> > 
> > This seems a bit overkill, can't we just install version.h ?
> 
> I wanted to provide a way for an application or otherwise to obtain the
> information at runtime.

Sure, I think that's useful, but I think just moving version.h to
include/libcamera/ and installing it would be better. Applications would
have access to the raw data, and can do whatever they want with it. I'd
go one step further, and provide numerical version information too, but
that can be for later.

> The static global instance 'version' prints a debug line through our LOG
> interface at library start up, and I wanted to be able to expose that
> string if needed.

If you want to log the version I would do so in CameraManager. That's
better than in a global constructor that would likely be called before
the logging infrastructure is initialised.

> Hrm... seems I messed up the patch anyway, I can't extern a static :-) -
> Making it just 'global' to fix.
> 
> >> diff --git a/meson.build b/meson.build
> >> index 4d3e99d3e58f..5182546382c5 100644
> >> --- a/meson.build
> >> +++ b/meson.build
> >> @@ -1,6 +1,8 @@
> >>  project('libcamera', 'c', 'cpp',
> >>      meson_version : '>= 0.40',
> >> -    version : '0.1',
> >> +    version : run_command('utils/version-gen',
> >> +                          '@0@'.format(meson.source_root()),
> >> +                          check : true).stdout().strip(),
> >>      default_options : [
> >>          'werror=true',
> >>          'warning_level=2',
> >> @@ -13,6 +15,11 @@ project('libcamera', 'c', 'cpp',
> >>  #       generated from this too.
> >>  api_version = '0.1'
> >>  
> >> +vcs_tag(command: ['utils/version-gen', '.'],
> >> +        input: 'version.h.in',
> >> +	output: 'version.h',
> >> +	fallback: '')
> > 
> > Mixing tabs and spaces.
> 
> Oops! I thought I fixed that.
> 
> > Don't you need to add the customtarget object returned by vcs_tag to
> > dependencies or sources for something ? Otherwise meson won't know what
> > depends on version.h.
> 
> I think you're right, but I can't see how to express a dependency on
> only a single object file.
> 
> I'll have to ask that one in #mesonbuild.
> 
> I don't know what magic is happening, but it does seem to be doing the
> right thing anyway.

Until we hit the right race :-)

> I've tested this with a few iterations of changing files that should not
> directly recreate the version.o or libcamera.so - but does affect the
> version-gen output, such as changing between a clean tree, and a -dirty
> label - and the library does seem to be correctly updated.

Note that once you have compiled the project, ninja will have generated
dependency information, and will rebuild the .h and .cpp files
correctly. To test for races you need to wipe the build directory. You
can then use 'ninja target' with the target being set to a file that
includes version.h, and watch it fail when building that target only.

> I'll call this one 'resolved by magic' for now.
> 
> >> +
> >>  cc = meson.get_compiler('c')
> >>  config_h = configuration_data()
> >>  
> >> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> >> index 1ca1083cf5c7..b9a4153839c9 100644
> >> --- a/src/libcamera/meson.build
> >> +++ b/src/libcamera/meson.build
> >> @@ -25,6 +25,7 @@ libcamera_sources = files([
> >>      'utils.cpp',
> >>      'v4l2_device.cpp',
> >>      'v4l2_subdevice.cpp',
> >> +    'version.cpp',
> >>  ])
> >>  
> >>  libcamera_headers = files([
> >> diff --git a/src/libcamera/version.cpp b/src/libcamera/version.cpp
> >> new file mode 100644
> >> index 000000000000..81f692f7cae7
> >> --- /dev/null
> >> +++ b/src/libcamera/version.cpp
> >> @@ -0,0 +1,40 @@
> >> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> >> +/*
> >> + * Copyright (C) 2019, Google Inc.
> >> + *
> >> + * version.cpp - Version information
> >> + */
> >> +
> >> +#include <libcamera/version.h>
> >> +
> >> +#include "log.h"
> >> +
> >> +/* The version header is automatically generated at the base of the project. */
> >> +#include "../../version.h"
> >> +
> >> +namespace libcamera {
> >> +
> >> +LOG_DEFINE_CATEGORY(Version)
> >> +
> >> +/**
> >> + * \class LibcameraVersion
> >> + *
> >> + * Reports library version information
> >> + */
> >> +
> >> +LibcameraVersion::LibcameraVersion()
> >> +{
> >> +	LOG(Version, Info) << "Libcamera Version " << toString();
> >> +}
> >> +
> >> +/**
> >> + * \brief Return the library version as a string
> >> + */
> >> +std::string LibcameraVersion::toString()
> >> +{
> >> +	return LIBCAMERA_VERSION;
> >> +}
> >> +
> >> +static LibcameraVersion version;
> >> +
> >> +} /* namespace libcamera */
> >> diff --git a/utils/version-gen b/utils/version-gen
> >> new file mode 100755
> >> index 000000000000..b8e53d77b63e
> >> --- /dev/null
> >> +++ b/utils/version-gen
> >> @@ -0,0 +1,36 @@
> >> +#!/bin/sh
> > 
> > Missing SPDX header.
> 
> As a component of the build system, is this GPL? or LGPL?

I'd say GPL-2+. I just realised that gen-headers doesn't have an SPDX
header either. Feel free to fix both, or I can send a patch.

> >> +
> >> +if test -n "$1"
> > 
> > Please use
> > 
> > if [[ ]] ; then
> > 
> > Our scripts rely on bash, so I think I would specify that explicitly
> > instead of /bin/sh.
> 
> I am intentionally trying to stay posix shell compliant.
> 
> libcamera$ git grep bash
> utils/ipu3/ipu3-capture.sh:#!/bin/bash
> utils/ipu3/ipu3-process.sh:#!/bin/bash
> 
> There's a big difference between non-essential helper scripts for a user
> to run - and a script which is executed by the build system...
> 
> Thus I'm not sure being reliant on bash is the right thing ...

I believe we'll introduce bash-isms even if we try not to, and they will
result in failures later. If we mandate usage of bash it should be less
of an issue. If you're confident about being able to write 100%
posix-compliant shell script, I would use [ instead of [[.

> I should run shellcheck too :)
> 	(Fixed those warnings too)
> 
> >> +then
> >> +	cd "$1"
> >> +fi
> >> +
> >> +# No fall back is provided for tarball releases or such, as we do not yet provide releases.
> > 
> > Line break at 80 columns ?
> 
> Fixed.
> 
> > Tarball releases should just ship version.h.
> 
> Sure, but the build system will have to know not to regenerate it.
> 
> We'll sort that later.
> 
> >> +
> >> +# Get a short description from the tree.
> >> +version=$(git describe --abbrev=4 --match "v[0-9]*" 2>/dev/null)
> >> +
> >> +if test -z "$version"
> >> +then
> > 
> > if [[ -z "$version" ]] ; then
> > 
> >> +	# Handle an un-tagged repository
> >> +	sha=$(git describe --abbrev=4 --always 2>/dev/null)
> >> +	commits=$(git log --oneline | wc -l 2>/dev/null)
> >> +	version=v0.0.$commits.$sha
> >> +fi
> >> +
> >> +
> >> +git update-index --refresh > /dev/null 2>&1
> > 
> > What does this do ?
> 
> Prevents changed timestamps causing a -dirty label. I've added a comment.
> 
> >> +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
> > 
> > $(...) instead of `...`
> > 
> >> +
> >> +# Strip the 'g'
> > 
> > Anything wrong with the 'g' ? :-)
> 
> Would you like to keep it?

I don't mind either way, it's included in the Linux kernel version so I
got used to it, I think it would confuse me a bit not to have it.

> >> +version=$(echo "$version" | sed -e 's/-g/-/g')
> >> +
> >> +# Fix the '-' (the patch count) to a '.' as a version increment.
> >> +version=$(echo "$version" | sed -e 's/-/./g')
> >> +
> >> +if test -n "$dirty"
> >> +then
> > 
> > if [[ -n "$dirty" ]] ; then
> > 
> >> +	version=$version-dirty
> >> +fi
> >> +
> >> +echo $version
> >> diff --git a/version.h.in b/version.h.in
> >> new file mode 100644
> >> index 000000000000..142819645b64
> >> --- /dev/null
> >> +++ b/version.h.in
> >> @@ -0,0 +1,3 @@
> > 
> > Should this have a comment stating that the file is auto-generated ?
> 
> Added.
> 
> >> +#pragma once
> > 
> > We usually use #ifdef #define #endif, is there a specific reason to use
> > a #pragma instead ?
> 
> Probably just because of the sample vcs_tag generator file I looked
> at... It was in January so I don't recall anything specific.
>  (I'm trying to clear my backlog of misc patches)
> 
> I'll change to #ifdefs
> 
> >> +
> >> +#define LIBCAMERA_VERSION "@VCS_TAG@"
Kieran Bingham June 12, 2019, 9:30 a.m. UTC | #4
Hi Laurent,

On 12/06/2019 09:39, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Tue, Jun 11, 2019 at 11:25:43PM +0100, Kieran Bingham wrote:
>> On 11/06/2019 21:32, Laurent Pinchart wrote:
>>> On Tue, Jun 11, 2019 at 09:14:11PM +0100, Kieran Bingham wrote:
>>>> Generate a version string, and provide a global singleton object which
>>>> allows applications to interogate the current libcamera version
>>>> information.
>>>>
>>>> The version header is automatically updated by meson on each build.
>>>> The string roughly follows the semver [0] conventions of
>>>> major.minor.patch-label as a value.
>>>>
>>>> [0] https://semver.org/
>>>>
>>>> The utils/version-gen script will look for tags in the form vX.Y as
>>>> starting points for the version string. While the repository does not
>>>> have any matching tags, v0.0 will be assumed, resulting in versions with
>>>> both major and minor being set to '0', and the patch count resulting
>>>> from the number of patches in the history to that point.
>>>>
>>>> Finally, a uniquely identifying shortened checksum is provided from git:
>>>>
>>>> 	v0.0.509.c544
>>>>
>>>> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
>>>> ---
>>>>  Documentation/conf.py         |  6 ++++--
>>>>  include/libcamera/meson.build |  1 +
>>>>  include/libcamera/version.h   | 23 ++++++++++++++++++++
>>>>  meson.build                   |  9 +++++++-
>>>>  src/libcamera/meson.build     |  1 +
>>>>  src/libcamera/version.cpp     | 40 +++++++++++++++++++++++++++++++++++
>>>>  utils/version-gen             | 36 +++++++++++++++++++++++++++++++
>>>>  version.h.in                  |  3 +++
>>>>  8 files changed, 116 insertions(+), 3 deletions(-)
>>>>  create mode 100644 include/libcamera/version.h
>>>>  create mode 100644 src/libcamera/version.cpp
>>>>  create mode 100755 utils/version-gen
>>>>  create mode 100644 version.h.in
>>>>
>>>> diff --git a/Documentation/conf.py b/Documentation/conf.py
>>>> index 970edf3d7298..e5980b98216d 100644
>>>> --- a/Documentation/conf.py
>>>> +++ b/Documentation/conf.py
>>>> @@ -23,10 +23,12 @@ project = 'libcamera'
>>>>  copyright = '2018-2019, The libcamera documentation authors'
>>>>  author = u'Kieran Bingham, Jacopo Mondi, Laurent Pinchart, Niklas Söderlund'
>>>>  
>>>> +# Vesion information is provided by the build environment.
>>>
>>> s/Vesion/Version/
>>
>> Eeep. Fixed.
>>
>>>> +#
>>>>  # The short X.Y version
>>>> -version = ''
>>>> +# version = ''
>>>>  # The full version, including alpha/beta/rc tags
>>>> -release = '0.1'
>>>> +# release = '0.1'
>>>
>>> Should we just delete the version and release lines ?
>>
>> I chose to keep these intentionally. The rest of the conf.py contains
>> 'template' lines.
>>
>> I can remove if you prefer, but the whole conf.py could probably be
>> stripped right down too.
> 
> If you want to keep them please make sure they match the stock template
> file.
> 
> By the way, where does the build environment provide version information
> to sphinx ?

I have no idea. It 'just works' with this update, when you rebuild the
documentation - the generated string is present in the output documentation.

I did nothing specific to make this happen. It just happens when you
don't override the version and release tags in this file.


>>>>  # -- General configuration ---------------------------------------------------
>>>> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
>>>> index 1b86fdc7fca4..201832105457 100644
>>>> --- a/include/libcamera/meson.build
>>>> +++ b/include/libcamera/meson.build
>>>> @@ -12,6 +12,7 @@ libcamera_api = files([
>>>>      'signal.h',
>>>>      'stream.h',
>>>>      'timer.h',
>>>> +    'version.h',
>>>>  ])
>>>>  
>>>>  gen_header = join_paths(meson.current_source_dir(), 'gen-header.sh')
>>>> diff --git a/include/libcamera/version.h b/include/libcamera/version.h
>>>> new file mode 100644
>>>> index 000000000000..ad21f148e748
>>>> --- /dev/null
>>>> +++ b/include/libcamera/version.h
>>>> @@ -0,0 +1,23 @@
>>>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
>>>> +/*
>>>> + * Copyright (C) 2019, Google Inc.
>>>> + *
>>>> + * version.h - Library version information
>>>> + */
>>>> +#ifndef __LIBCAMERA_VERSION_H__
>>>> +#define __LIBCAMERA_VERSION_H__
>>>> +
>>>> +namespace libcamera {
>>>> +
>>>> +class LibcameraVersion
>>>> +{
>>>> +public:
>>>> +	LibcameraVersion();
>>>> +	std::string toString();
>>>> +};
>>>> +
>>>> +extern LibcameraVersion version;
>>>> +
>>>> +} /* namespace libcamera */
>>>> +
>>>> +#endif /* __LIBCAMERA_VERSION_H__ */
>>>
>>> This seems a bit overkill, can't we just install version.h ?
>>
>> I wanted to provide a way for an application or otherwise to obtain the
>> information at runtime.
> 
> Sure, I think that's useful, but I think just moving version.h to
> include/libcamera/ and installing it would be better. Applications would
> have access to the raw data, and can do whatever they want with it. I'd
> go one step further, and provide numerical version information too, but
> that can be for later.

No - then they have access to the information they *compile against*
which (although it should be the same) might not be the same as the
version that they *run* against.

I agree, it might be worth providing this at compile time too though.

>> The static global instance 'version' prints a debug line through our LOG
>> interface at library start up, and I wanted to be able to expose that
>> string if needed.
> 
> If you want to log the version I would do so in CameraManager. That's
> better than in a global constructor that would likely be called before
> the logging infrastructure is initialised.

OK - that sounds reasonable too.


>> Hrm... seems I messed up the patch anyway, I can't extern a static :-) -
>> Making it just 'global' to fix.
>>
>>>> diff --git a/meson.build b/meson.build
>>>> index 4d3e99d3e58f..5182546382c5 100644
>>>> --- a/meson.build
>>>> +++ b/meson.build
>>>> @@ -1,6 +1,8 @@
>>>>  project('libcamera', 'c', 'cpp',
>>>>      meson_version : '>= 0.40',
>>>> -    version : '0.1',
>>>> +    version : run_command('utils/version-gen',
>>>> +                          '@0@'.format(meson.source_root()),
>>>> +                          check : true).stdout().strip(),
>>>>      default_options : [
>>>>          'werror=true',
>>>>          'warning_level=2',
>>>> @@ -13,6 +15,11 @@ project('libcamera', 'c', 'cpp',
>>>>  #       generated from this too.
>>>>  api_version = '0.1'
>>>>  
>>>> +vcs_tag(command: ['utils/version-gen', '.'],
>>>> +        input: 'version.h.in',
>>>> +	output: 'version.h',
>>>> +	fallback: '')
>>>
>>> Mixing tabs and spaces.
>>
>> Oops! I thought I fixed that.
>>
>>> Don't you need to add the customtarget object returned by vcs_tag to
>>> dependencies or sources for something ? Otherwise meson won't know what
>>> depends on version.h.
>>
>> I think you're right, but I can't see how to express a dependency on
>> only a single object file.
>>
>> I'll have to ask that one in #mesonbuild.
>>
>> I don't know what magic is happening, but it does seem to be doing the
>> right thing anyway.
> 
> Until we hit the right race :-)

Sure I love a day at the races ! :)

>> I've tested this with a few iterations of changing files that should not
>> directly recreate the version.o or libcamera.so - but does affect the
>> version-gen output, such as changing between a clean tree, and a -dirty
>> label - and the library does seem to be correctly updated.
> 
> Note that once you have compiled the project, ninja will have generated
> dependency information, and will rebuild the .h and .cpp files
> correctly. To test for races you need to wipe the build directory. You
> can then use 'ninja target' with the target being set to a file that
> includes version.h, and watch it fail when building that target only.

OK - I haven't yet understood where that happens. My head is still stuck
in the dark ages with autoconf, and I know how make used to create .d
files - but ninja is still magic to me.


>> I'll call this one 'resolved by magic' for now.
>>

"Abracadabra, a dove" ...
<pulls white rabbit out of hat instead and looks perplexed>

>>>> +
>>>>  cc = meson.get_compiler('c')
>>>>  config_h = configuration_data()
>>>>  
>>>> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
>>>> index 1ca1083cf5c7..b9a4153839c9 100644
>>>> --- a/src/libcamera/meson.build
>>>> +++ b/src/libcamera/meson.build
>>>> @@ -25,6 +25,7 @@ libcamera_sources = files([
>>>>      'utils.cpp',
>>>>      'v4l2_device.cpp',
>>>>      'v4l2_subdevice.cpp',
>>>> +    'version.cpp',
>>>>  ])
>>>>  
>>>>  libcamera_headers = files([
>>>> diff --git a/src/libcamera/version.cpp b/src/libcamera/version.cpp
>>>> new file mode 100644
>>>> index 000000000000..81f692f7cae7
>>>> --- /dev/null
>>>> +++ b/src/libcamera/version.cpp
>>>> @@ -0,0 +1,40 @@
>>>> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
>>>> +/*
>>>> + * Copyright (C) 2019, Google Inc.
>>>> + *
>>>> + * version.cpp - Version information
>>>> + */
>>>> +
>>>> +#include <libcamera/version.h>
>>>> +
>>>> +#include "log.h"
>>>> +
>>>> +/* The version header is automatically generated at the base of the project. */
>>>> +#include "../../version.h"
>>>> +
>>>> +namespace libcamera {
>>>> +
>>>> +LOG_DEFINE_CATEGORY(Version)
>>>> +
>>>> +/**
>>>> + * \class LibcameraVersion
>>>> + *
>>>> + * Reports library version information
>>>> + */
>>>> +
>>>> +LibcameraVersion::LibcameraVersion()
>>>> +{
>>>> +	LOG(Version, Info) << "Libcamera Version " << toString();
>>>> +}
>>>> +
>>>> +/**
>>>> + * \brief Return the library version as a string
>>>> + */
>>>> +std::string LibcameraVersion::toString()
>>>> +{
>>>> +	return LIBCAMERA_VERSION;
>>>> +}
>>>> +
>>>> +static LibcameraVersion version;
>>>> +
>>>> +} /* namespace libcamera */
>>>> diff --git a/utils/version-gen b/utils/version-gen
>>>> new file mode 100755
>>>> index 000000000000..b8e53d77b63e
>>>> --- /dev/null
>>>> +++ b/utils/version-gen
>>>> @@ -0,0 +1,36 @@
>>>> +#!/bin/sh
>>>
>>> Missing SPDX header.
>>
>> As a component of the build system, is this GPL? or LGPL?
> 
> I'd say GPL-2+. I just realised that gen-headers doesn't have an SPDX
> header either. Feel free to fix both, or I can send a patch.

Lets fix gen-headers separately.

>>>> +
>>>> +if test -n "$1"
>>>
>>> Please use
>>>
>>> if [[ ]] ; then
>>>
>>> Our scripts rely on bash, so I think I would specify that explicitly
>>> instead of /bin/sh.
>>
>> I am intentionally trying to stay posix shell compliant.
>>
>> libcamera$ git grep bash
>> utils/ipu3/ipu3-capture.sh:#!/bin/bash
>> utils/ipu3/ipu3-process.sh:#!/bin/bash
>>
>> There's a big difference between non-essential helper scripts for a user
>> to run - and a script which is executed by the build system...
>>
>> Thus I'm not sure being reliant on bash is the right thing ...
> 
> I believe we'll introduce bash-isms even if we try not to, and they will
> result in failures later. If we mandate usage of bash it should be less
> of an issue. If you're confident about being able to write 100%
> posix-compliant shell script, I would use [ instead of [[.

Shellcheck will check for posix compliance when scripts begin with
#!/bin/sh.

This might be another reason to just go back to importing the autoconf's
implementation:

http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=blob;f=build-aux/git-version-gen

>> I should run shellcheck too :)
>> 	(Fixed those warnings too)
>>
>>>> +then
>>>> +	cd "$1"
>>>> +fi
>>>> +
>>>> +# No fall back is provided for tarball releases or such, as we do not yet provide releases.
>>>
>>> Line break at 80 columns ?
>>
>> Fixed.
>>
>>> Tarball releases should just ship version.h.
>>
>> Sure, but the build system will have to know not to regenerate it.
>>
>> We'll sort that later.
>>
>>>> +
>>>> +# Get a short description from the tree.
>>>> +version=$(git describe --abbrev=4 --match "v[0-9]*" 2>/dev/null)
>>>> +
>>>> +if test -z "$version"
>>>> +then
>>>
>>> if [[ -z "$version" ]] ; then
>>>
>>>> +	# Handle an un-tagged repository
>>>> +	sha=$(git describe --abbrev=4 --always 2>/dev/null)
>>>> +	commits=$(git log --oneline | wc -l 2>/dev/null)
>>>> +	version=v0.0.$commits.$sha
>>>> +fi
>>>> +
>>>> +
>>>> +git update-index --refresh > /dev/null 2>&1
>>>
>>> What does this do ?
>>
>> Prevents changed timestamps causing a -dirty label. I've added a comment.
>>
>>>> +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
>>>
>>> $(...) instead of `...`
>>>
>>>> +
>>>> +# Strip the 'g'
>>>
>>> Anything wrong with the 'g' ? :-)
>>
>> Would you like to keep it?
> 
> I don't mind either way, it's included in the Linux kernel version so I
> got used to it, I think it would confuse me a bit not to have it.

The 'methodology' I was following here was from the gnu git-version-gen
which removes the 'g', as does the original "GIT-VERSION-GEN" from git
itself.

I had wanted to simplify things, hence splitting out our needs - but now
I'm thinking it's better just to use the external script.

I'll look again and decide before reposting, but I'll re-back-burner
this task for this week. It's consumed too many cycles already.

>>>> +version=$(echo "$version" | sed -e 's/-g/-/g')
>>>> +
>>>> +# Fix the '-' (the patch count) to a '.' as a version increment.
>>>> +version=$(echo "$version" | sed -e 's/-/./g')
>>>> +
>>>> +if test -n "$dirty"
>>>> +then
>>>
>>> if [[ -n "$dirty" ]] ; then
>>>
>>>> +	version=$version-dirty
>>>> +fi
>>>> +
>>>> +echo $version
>>>> diff --git a/version.h.in b/version.h.in
>>>> new file mode 100644
>>>> index 000000000000..142819645b64
>>>> --- /dev/null
>>>> +++ b/version.h.in
>>>> @@ -0,0 +1,3 @@
>>>
>>> Should this have a comment stating that the file is auto-generated ?
>>
>> Added.
>>
>>>> +#pragma once
>>>
>>> We usually use #ifdef #define #endif, is there a specific reason to use
>>> a #pragma instead ?
>>
>> Probably just because of the sample vcs_tag generator file I looked
>> at... It was in January so I don't recall anything specific.
>>  (I'm trying to clear my backlog of misc patches)
>>
>> I'll change to #ifdefs
>>
>>>> +
>>>> +#define LIBCAMERA_VERSION "@VCS_TAG@"
>

Patch

diff --git a/Documentation/conf.py b/Documentation/conf.py
index 970edf3d7298..e5980b98216d 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -23,10 +23,12 @@  project = 'libcamera'
 copyright = '2018-2019, The libcamera documentation authors'
 author = u'Kieran Bingham, Jacopo Mondi, Laurent Pinchart, Niklas Söderlund'
 
+# Vesion information is provided by the build environment.
+#
 # The short X.Y version
-version = ''
+# version = ''
 # The full version, including alpha/beta/rc tags
-release = '0.1'
+# release = '0.1'
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index 1b86fdc7fca4..201832105457 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -12,6 +12,7 @@  libcamera_api = files([
     'signal.h',
     'stream.h',
     'timer.h',
+    'version.h',
 ])
 
 gen_header = join_paths(meson.current_source_dir(), 'gen-header.sh')
diff --git a/include/libcamera/version.h b/include/libcamera/version.h
new file mode 100644
index 000000000000..ad21f148e748
--- /dev/null
+++ b/include/libcamera/version.h
@@ -0,0 +1,23 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * version.h - Library version information
+ */
+#ifndef __LIBCAMERA_VERSION_H__
+#define __LIBCAMERA_VERSION_H__
+
+namespace libcamera {
+
+class LibcameraVersion
+{
+public:
+	LibcameraVersion();
+	std::string toString();
+};
+
+extern LibcameraVersion version;
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_VERSION_H__ */
diff --git a/meson.build b/meson.build
index 4d3e99d3e58f..5182546382c5 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,8 @@ 
 project('libcamera', 'c', 'cpp',
     meson_version : '>= 0.40',
-    version : '0.1',
+    version : run_command('utils/version-gen',
+                          '@0@'.format(meson.source_root()),
+                          check : true).stdout().strip(),
     default_options : [
         'werror=true',
         'warning_level=2',
@@ -13,6 +15,11 @@  project('libcamera', 'c', 'cpp',
 #       generated from this too.
 api_version = '0.1'
 
+vcs_tag(command: ['utils/version-gen', '.'],
+        input: 'version.h.in',
+	output: 'version.h',
+	fallback: '')
+
 cc = meson.get_compiler('c')
 config_h = configuration_data()
 
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 1ca1083cf5c7..b9a4153839c9 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -25,6 +25,7 @@  libcamera_sources = files([
     'utils.cpp',
     'v4l2_device.cpp',
     'v4l2_subdevice.cpp',
+    'version.cpp',
 ])
 
 libcamera_headers = files([
diff --git a/src/libcamera/version.cpp b/src/libcamera/version.cpp
new file mode 100644
index 000000000000..81f692f7cae7
--- /dev/null
+++ b/src/libcamera/version.cpp
@@ -0,0 +1,40 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * version.cpp - Version information
+ */
+
+#include <libcamera/version.h>
+
+#include "log.h"
+
+/* The version header is automatically generated at the base of the project. */
+#include "../../version.h"
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(Version)
+
+/**
+ * \class LibcameraVersion
+ *
+ * Reports library version information
+ */
+
+LibcameraVersion::LibcameraVersion()
+{
+	LOG(Version, Info) << "Libcamera Version " << toString();
+}
+
+/**
+ * \brief Return the library version as a string
+ */
+std::string LibcameraVersion::toString()
+{
+	return LIBCAMERA_VERSION;
+}
+
+static LibcameraVersion version;
+
+} /* namespace libcamera */
diff --git a/utils/version-gen b/utils/version-gen
new file mode 100755
index 000000000000..b8e53d77b63e
--- /dev/null
+++ b/utils/version-gen
@@ -0,0 +1,36 @@ 
+#!/bin/sh
+
+if test -n "$1"
+then
+	cd "$1"
+fi
+
+# No fall back is provided for tarball releases or such, as we do not yet provide releases.
+
+# Get a short description from the tree.
+version=$(git describe --abbrev=4 --match "v[0-9]*" 2>/dev/null)
+
+if test -z "$version"
+then
+	# Handle an un-tagged repository
+	sha=$(git describe --abbrev=4 --always 2>/dev/null)
+	commits=$(git log --oneline | wc -l 2>/dev/null)
+	version=v0.0.$commits.$sha
+fi
+
+
+git update-index --refresh > /dev/null 2>&1
+dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
+
+# Strip the 'g'
+version=$(echo "$version" | sed -e 's/-g/-/g')
+
+# Fix the '-' (the patch count) to a '.' as a version increment.
+version=$(echo "$version" | sed -e 's/-/./g')
+
+if test -n "$dirty"
+then
+	version=$version-dirty
+fi
+
+echo $version
diff --git a/version.h.in b/version.h.in
new file mode 100644
index 000000000000..142819645b64
--- /dev/null
+++ b/version.h.in
@@ -0,0 +1,3 @@ 
+#pragma once
+
+#define LIBCAMERA_VERSION "@VCS_TAG@"