diff --git a/meson.build b/meson.build
index a49c484fe64e..f27bfd479a5c 100644
--- a/meson.build
+++ b/meson.build
@@ -10,20 +10,30 @@ project('libcamera', 'c', 'cpp',
     ],
     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.build_root()).stdout().strip()
-if libcamera_git_version == ''
-    libcamera_git_version = meson.project_version()
+fs_mod = import('fs')
+if not fs_mod.is_file('version.gen')
+    # Generate version information. The libcamera_git_version variable contains the
+    # 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.build_root()).stdout().strip()
+    if libcamera_git_version == ''
+        libcamera_git_version = meson.project_version()
+    endif
+else
+    # Read the version information from the file generated by the utils/run-dist.sh
+    # script on a 'meson dist' command.
+    libcamera_git_version = run_command(['cat', 'version.gen']).stdout().strip()
 endif
 
 libcamera_version = libcamera_git_version.split('+')[0]
 
+# This script gererates the version.gen file on a 'meson dist' command.
+meson.add_dist_script('utils/run-dist.sh')
+
 # Configure the build environment.
 cc = meson.get_compiler('c')
 cxx = meson.get_compiler('cpp')
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 243dd3c180eb..360eaf80ecf1 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -93,12 +93,11 @@ endforeach
 
 libcamera_sources += control_sources
 
-gen_version = meson.source_root() / 'utils' / 'gen-version.sh'
-
-version_cpp = vcs_tag(command : [gen_version, meson.build_root()],
-                      input : 'version.cpp.in',
-                      output : 'version.cpp',
-                      fallback : meson.project_version())
+version_data = configuration_data()
+version_data.set('VCS_TAG', libcamera_git_version)
+version_cpp = configure_file(input : 'version.cpp.in',
+                             output : 'version.cpp',
+                             configuration : version_data)
 
 libcamera_sources += version_cpp
 
diff --git a/utils/run-dist.sh b/utils/run-dist.sh
new file mode 100644
index 000000000000..1b2a6348c6bc
--- /dev/null
+++ b/utils/run-dist.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# On a meson dist run, generate the version string and store it in a file.
+# This will late be picked up by the build system and used in place of running
+# the utils/gen-version.sh script again since we may not be running in the
+# upstream git source tree, and so version information would be lost.
+"$MESON_DIST_ROOT"/utils/gen-version.sh > "$MESON_DIST_ROOT"/version.gen
