diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp
index 24fe709108fe..3dfe84fcf95e 100644
--- a/src/libcamera/ipa_manager.cpp
+++ b/src/libcamera/ipa_manager.cpp
@@ -102,6 +102,15 @@ IPAManager::IPAManager()
 	if (ret > 0)
 		ipaCount += ret;
 
+	/*
+	 * Utilise the Elf runpath to supply the IPA build directory, allowing
+	 * us to load IPA's before they are installed for testing and
+	 * development.
+	 */
+	const char *runpath = utils::get_runpath();
+	if (runpath)
+		ipaCount += addPath(runpath, true);
+
 	const char *modulePaths = utils::secure_getenv("LIBCAMERA_IPA_MODULE_PATH");
 	if (!modulePaths) {
 		if (!ipaCount)
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 68d89559b290..87c5bbbb17a4 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -107,6 +107,7 @@ libcamera = shared_library('camera',
                            install : true,
                            link_with : libcamera_link_with,
                            include_directories : includes,
+                           build_rpath : ipa_build_path,
                            dependencies : libcamera_deps)
 
 libcamera_dep = declare_dependency(sources : [libcamera_api, libcamera_ipa_api, libcamera_h],
diff --git a/src/meson.build b/src/meson.build
index 5adcd61fd913..42e1eb984ccd 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -2,6 +2,13 @@ if get_option('android')
     subdir('android')
 endif
 
+# Provide libcamera with a reference to the current build for IPA
+# loading. This allows IPAs to be successfully loaded when tests and
+# applications are run from the build tree, but is stripped during the
+# install phase, ensuring we maintain reproducible builds.
+
+ipa_build_path = join_paths(meson.current_build_dir(), 'ipa')
+
 subdir('libcamera')
 subdir('ipa')
 subdir('cam')
