libcamera: Rework automatic version generation to avoid rebuilds
Commit b817bcec6b
("libcamera: Auto generate version information")
generates version information in order to automatically include it
various locations (Sphinx and Doxygen documentation, libcamera::version
variable available at runtime, and version.h available at compile time).
Unfortunately this causes lots of unnecessary rebuilds when modifying
the git tree state, which hinders development.
The problem is caused by the generated version.h being listed as a
dependency for the whole libcamera. This is required as meson (to the
best of my knowledge) doesn't provide a way to explicitly specify the
dependency of a single object file (camera_manager.o in this case, as
camera_manager.cpp is the only consumer of the generated version string)
on the custom target used to generate version.h. The dependency can't be
automatically detected at build time, like dependencies on normal
headers that are generated by parsing the source, because the version.h
header may not exist yet. The build could then fail in a racy way.
This change attempts at solving the issue by generating a version.cpp
instead of a version.h to set the git-based version. This minimises the
number of files that need to be rebuild when then git tree state
changes, while retaining the main purpose of the original automatic
version generation, the ability to access the git-based version string
at runtime. We however lose the ability to access git-based version
information at build time in an application building against libcamera,
but there is no expected use case for this.
The version string is moved from the libcamera namespace to the
CameraManager class in order to avoid including version.h inside
libcamera (in version.cpp and in camera_manager.cpp), which would create
dependencies causing more rebuild steps, as described above.
On the other hand, major, minor and patch level version numbers are
useful at build time. This commit changes the generation of version.h in
order to add three macros named LIBCAMERA_VERSION_MAJOR,
LIBCAMERA_VERSION_MINOR and LIBCAMERA_VERSION_PATCH for this purpose.
version.h is not included by any other libcamera header or source file,
and thus doesn't force a rebuild of the library.
The Sphinx and Doxygen documentation keep their git-based version
information, which is set during the configuration of the build and then
doesn't track git commits. We may want to investigate how to improve
this, but given that git-based version for the documentation has very
few use cases outside of tagging nightly builds, this isn't considered
an issue at the moment.
The documentation install directory now uses the base version string, in
order to avoid increasing the number of documentation directories
needlessly. This shouldn't cause any issue as the API should not change
without a change to the version number.
The version number generation and handling code now also standardises
the version variables to not start with a 'v' prefix in meson, in order
to simplify their handling. The prefix is added when generating the
relevant files.
Note that we go back to specifying the fallback version in the main
meson.build, in the call to the project() function. For the time being I
believe this should be a good compromise to avoid unnecessary
recompilation, and moving the fallback version to a different file for
tarball releases can be built on top of this.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
0de1a9f318
commit
c4281ba3bb
11 changed files with 84 additions and 45 deletions
|
@ -1,5 +1,5 @@
|
||||||
doc_install_dir = join_paths(get_option('datadir'), 'doc',
|
doc_install_dir = join_paths(get_option('datadir'), 'doc',
|
||||||
'libcamera-@0@'.format(meson.project_version()))
|
'libcamera-@0@'.format(libcamera_version))
|
||||||
|
|
||||||
#
|
#
|
||||||
# Doxygen
|
# Doxygen
|
||||||
|
@ -9,7 +9,7 @@ doxygen = find_program('doxygen', required : false)
|
||||||
|
|
||||||
if doxygen.found()
|
if doxygen.found()
|
||||||
cdata = configuration_data()
|
cdata = configuration_data()
|
||||||
cdata.set('VERSION', meson.project_version())
|
cdata.set('VERSION', 'v@0@'.format(libcamera_git_version))
|
||||||
cdata.set('TOP_SRCDIR', meson.source_root())
|
cdata.set('TOP_SRCDIR', meson.source_root())
|
||||||
cdata.set('TOP_BUILDDIR', meson.build_root())
|
cdata.set('TOP_BUILDDIR', meson.build_root())
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ if sphinx.found()
|
||||||
'index.rst',
|
'index.rst',
|
||||||
]
|
]
|
||||||
|
|
||||||
release = 'release=' + meson.project_version()
|
release = 'release=v' + libcamera_git_version
|
||||||
|
|
||||||
custom_target('documentation',
|
custom_target('documentation',
|
||||||
command : [sphinx, '-D', release, '-q', '-W', '-b', 'html',
|
command : [sphinx, '-D', release, '-q', '-W', '-b', 'html',
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
void removeCamera(Camera *camera);
|
void removeCamera(Camera *camera);
|
||||||
|
|
||||||
static CameraManager *instance();
|
static CameraManager *instance();
|
||||||
|
static const std::string &version() { return version_; }
|
||||||
|
|
||||||
void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
|
void setEventDispatcher(std::unique_ptr<EventDispatcher> dispatcher);
|
||||||
EventDispatcher *eventDispatcher();
|
EventDispatcher *eventDispatcher();
|
||||||
|
@ -46,6 +47,8 @@ private:
|
||||||
std::vector<std::shared_ptr<Camera>> cameras_;
|
std::vector<std::shared_ptr<Camera>> cameras_;
|
||||||
|
|
||||||
std::unique_ptr<EventDispatcher> dispatcher_;
|
std::unique_ptr<EventDispatcher> dispatcher_;
|
||||||
|
|
||||||
|
static const std::string version_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
|
@ -16,8 +16,12 @@ cat <<EOF > "$dst_file"
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
for header in "$src_dir"/*.h ; do
|
headers=$(for header in "$src_dir"/*.h ; do
|
||||||
header=$(basename "$header")
|
header=$(basename "$header")
|
||||||
|
echo "$header"
|
||||||
|
done ; echo "version.h" | sort)
|
||||||
|
|
||||||
|
for header in $headers ; do
|
||||||
echo "#include <libcamera/$header>" >> "$dst_file"
|
echo "#include <libcamera/$header>" >> "$dst_file"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,6 @@ libcamera_api = files([
|
||||||
'timer.h',
|
'timer.h',
|
||||||
])
|
])
|
||||||
|
|
||||||
gen_version = join_paths(meson.source_root(), 'utils', 'gen-version.sh')
|
|
||||||
|
|
||||||
version_h = vcs_tag(command : [gen_version, meson.current_source_dir()],
|
|
||||||
input : 'version.h.in',
|
|
||||||
output : 'version.h',
|
|
||||||
fallback : 'v0.0')
|
|
||||||
|
|
||||||
gen_header = files('gen-header.sh')
|
gen_header = files('gen-header.sh')
|
||||||
|
|
||||||
libcamera_h = custom_target('gen-header',
|
libcamera_h = custom_target('gen-header',
|
||||||
|
@ -32,5 +25,16 @@ libcamera_h = custom_target('gen-header',
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : 'include/libcamera')
|
install_dir : 'include/libcamera')
|
||||||
|
|
||||||
|
version = libcamera_version.split('.')
|
||||||
|
libcamera_version_config = configuration_data()
|
||||||
|
libcamera_version_config.set('LIBCAMERA_VERSION_MAJOR', version[0])
|
||||||
|
libcamera_version_config.set('LIBCAMERA_VERSION_MINOR', version[1])
|
||||||
|
libcamera_version_config.set('LIBCAMERA_VERSION_PATCH', version[2])
|
||||||
|
|
||||||
|
configure_file(input : 'version.h.in',
|
||||||
|
output : 'version.h',
|
||||||
|
configuration : libcamera_version_config,
|
||||||
|
install_dir : 'include/libcamera')
|
||||||
|
|
||||||
install_headers(libcamera_api,
|
install_headers(libcamera_api,
|
||||||
subdir : 'libcamera')
|
subdir : 'libcamera')
|
||||||
|
|
|
@ -9,14 +9,8 @@
|
||||||
#ifndef __LIBCAMERA_VERSION_H__
|
#ifndef __LIBCAMERA_VERSION_H__
|
||||||
#define __LIBCAMERA_VERSION_H__
|
#define __LIBCAMERA_VERSION_H__
|
||||||
|
|
||||||
#include <string>
|
#define LIBCAMERA_VERSION_MAJOR @LIBCAMERA_VERSION_MAJOR@
|
||||||
|
#define LIBCAMERA_VERSION_MINOR @LIBCAMERA_VERSION_MINOR@
|
||||||
#define LIBCAMERA_VERSION "@VCS_TAG@"
|
#define LIBCAMERA_VERSION_PATCH @LIBCAMERA_VERSION_PATCH@
|
||||||
|
|
||||||
namespace libcamera {
|
|
||||||
|
|
||||||
extern const std::string version;
|
|
||||||
|
|
||||||
} /* namespace libcamera */
|
|
||||||
|
|
||||||
#endif /* __LIBCAMERA_VERSION_H__ */
|
#endif /* __LIBCAMERA_VERSION_H__ */
|
||||||
|
|
19
meson.build
19
meson.build
|
@ -1,8 +1,6 @@
|
||||||
project('libcamera', 'c', 'cpp',
|
project('libcamera', 'c', 'cpp',
|
||||||
meson_version : '>= 0.40',
|
meson_version : '>= 0.40',
|
||||||
version : run_command('utils/gen-version.sh',
|
version : '0.0.0',
|
||||||
'@0@'.format(meson.source_root()),
|
|
||||||
check : true).stdout().strip(),
|
|
||||||
default_options : [
|
default_options : [
|
||||||
'werror=true',
|
'werror=true',
|
||||||
'warning_level=2',
|
'warning_level=2',
|
||||||
|
@ -10,6 +8,21 @@ project('libcamera', 'c', 'cpp',
|
||||||
],
|
],
|
||||||
license : 'LGPL 2.1+')
|
license : 'LGPL 2.1+')
|
||||||
|
|
||||||
|
# Generate version information. The libcamera_git_version variable contains the
|
||||||
|
# full version with git patch count and SHA1 (e.g. 1.2.3+211-c94a24f4), while
|
||||||
|
# the libcamera_version variable contains the major.minor.patch (e.g. 1.2.3)
|
||||||
|
# only. If the source tree isn't under git control, or if it matches the last
|
||||||
|
# git version tag, the build metadata (e.g. +211-c94a24f4) is omitted from
|
||||||
|
# libcamera_git_version.
|
||||||
|
libcamera_git_version = run_command('utils/gen-version.sh',
|
||||||
|
meson.source_root()).stdout().strip()
|
||||||
|
if libcamera_git_version == ''
|
||||||
|
libcamera_git_version = meson.project_version()
|
||||||
|
endif
|
||||||
|
|
||||||
|
libcamera_version = libcamera_git_version.split('+')[0]
|
||||||
|
|
||||||
|
# Configure the build environment.
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
config_h = configuration_data()
|
config_h = configuration_data()
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include <libcamera/camera.h>
|
#include <libcamera/camera.h>
|
||||||
#include <libcamera/event_dispatcher.h>
|
#include <libcamera/event_dispatcher.h>
|
||||||
#include <libcamera/version.h>
|
|
||||||
|
|
||||||
#include "device_enumerator.h"
|
#include "device_enumerator.h"
|
||||||
#include "event_dispatcher_poll.h"
|
#include "event_dispatcher_poll.h"
|
||||||
|
@ -26,11 +25,6 @@ namespace libcamera {
|
||||||
|
|
||||||
LOG_DEFINE_CATEGORY(Camera)
|
LOG_DEFINE_CATEGORY(Camera)
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief The library global version string
|
|
||||||
*/
|
|
||||||
const std::string version(LIBCAMERA_VERSION);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class CameraManager
|
* \class CameraManager
|
||||||
* \brief Provide access and manage all cameras in the system
|
* \brief Provide access and manage all cameras in the system
|
||||||
|
@ -85,7 +79,7 @@ int CameraManager::start()
|
||||||
if (enumerator_)
|
if (enumerator_)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
LOG(Camera, Info) << "libcamera " << version;
|
LOG(Camera, Info) << "libcamera " << version_;
|
||||||
|
|
||||||
enumerator_ = DeviceEnumerator::create();
|
enumerator_ = DeviceEnumerator::create();
|
||||||
if (!enumerator_ || enumerator_->enumerate())
|
if (!enumerator_ || enumerator_->enumerate())
|
||||||
|
@ -232,6 +226,12 @@ CameraManager *CameraManager::instance()
|
||||||
return &manager;
|
return &manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn const std::string &CameraManager::version()
|
||||||
|
* \brief Retrieve the libcamera version string
|
||||||
|
* \return The libcamera version string
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the event dispatcher
|
* \brief Set the event dispatcher
|
||||||
* \param[in] dispatcher Pointer to the event dispatcher
|
* \param[in] dispatcher Pointer to the event dispatcher
|
||||||
|
|
|
@ -79,8 +79,16 @@ control_types_cpp = custom_target('control_types_cpp',
|
||||||
|
|
||||||
libcamera_sources += control_types_cpp
|
libcamera_sources += control_types_cpp
|
||||||
|
|
||||||
|
gen_version = join_paths(meson.source_root(), 'utils', 'gen-version.sh')
|
||||||
|
|
||||||
|
version_cpp = vcs_tag(command : [gen_version, meson.source_root()],
|
||||||
|
input : 'version.cpp.in',
|
||||||
|
output : 'version.cpp',
|
||||||
|
fallback : meson.project_version())
|
||||||
|
|
||||||
|
libcamera_sources += version_cpp
|
||||||
|
|
||||||
libcamera_deps = [
|
libcamera_deps = [
|
||||||
declare_dependency(sources : version_h),
|
|
||||||
cc.find_library('dl'),
|
cc.find_library('dl'),
|
||||||
libudev,
|
libudev,
|
||||||
]
|
]
|
||||||
|
|
16
src/libcamera/version.cpp.in
Normal file
16
src/libcamera/version.cpp.in
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019, Google Inc.
|
||||||
|
*
|
||||||
|
* version.cpp - libcamera version
|
||||||
|
*
|
||||||
|
* This file is auto-generated. Do not edit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libcamera/camera_manager.h>
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
const std::string CameraManager::version_("v@VCS_TAG@");
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
|
@ -26,7 +26,7 @@ MainWindow::MainWindow(const OptionsParser::Options &options)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
title_ = "QCam " + QString::fromStdString(libcamera::version);
|
title_ = "QCam " + QString::fromStdString(CameraManager::version());
|
||||||
setWindowTitle(title_);
|
setWindowTitle(title_);
|
||||||
connect(&titleTimer_, SIGNAL(timeout()), this, SLOT(updateTitle()));
|
connect(&titleTimer_, SIGNAL(timeout()), this, SLOT(updateTitle()));
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@ then
|
||||||
cd "$1" 2>/dev/null || exit 1
|
cd "$1" 2>/dev/null || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Bail out if the directory isn't under git control
|
||||||
|
git rev-parse --git-dir >/dev/null 2>&1 || exit 1
|
||||||
|
|
||||||
# Get a short description from the tree.
|
# Get a short description from the tree.
|
||||||
version=$(git describe --abbrev=8 --match "v[0-9]*" 2>/dev/null)
|
version=$(git describe --abbrev=8 --match "v[0-9]*" 2>/dev/null)
|
||||||
|
|
||||||
|
@ -16,22 +19,16 @@ then
|
||||||
# Handle an un-tagged repository
|
# Handle an un-tagged repository
|
||||||
sha=$(git describe --abbrev=8 --always 2>/dev/null)
|
sha=$(git describe --abbrev=8 --always 2>/dev/null)
|
||||||
commits=$(git log --oneline | wc -l 2>/dev/null)
|
commits=$(git log --oneline | wc -l 2>/dev/null)
|
||||||
version=v0.0.$commits.$sha
|
version="v0.0.0-$commits-g$sha"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Prevent changed timestamps causing -dirty labels
|
# Append a '-dirty' suffix if the working tree is dirty. Prevent false
|
||||||
|
# positives due to changed timestamps by running git update-index.
|
||||||
git update-index --refresh > /dev/null 2>&1
|
git update-index --refresh > /dev/null 2>&1
|
||||||
dirty=$(git diff-index --name-only HEAD 2>/dev/null) || dirty=
|
git diff-index --quiet HEAD || version="$version-dirty"
|
||||||
|
|
||||||
# Strip the 'g', and replace the preceeding '-' with a '+' to denote a label
|
# Replace first '-' with a '+' to denote build metadata, strip the 'g' in from
|
||||||
version=$(echo "$version" | sed -e 's/-g/+/g')
|
# of the git SHA1 and remove the initial 'v'.
|
||||||
|
version=$(echo "$version" | sed -e 's/-/+/' | sed -e 's/-g/-/' | cut -c 2-)
|
||||||
# Fix the '-' (the patch count) to a '.' as a version increment.
|
|
||||||
version=$(echo "$version" | sed -e 's/-/./g')
|
|
||||||
|
|
||||||
if [ -n "$dirty" ]
|
|
||||||
then
|
|
||||||
version=$version-dirty
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$version"
|
echo "$version"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue