blob: 1968958571e006051f38194a0c318e092cdb3ce4 [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2021, Google Inc.
*
* source_paths.cpp - Identify libcamera source and build paths
*/
#include "libcamera/internal/source_paths.h"
#include <dlfcn.h>
#include <elf.h>
#include <link.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libcamera/base/utils.h>
/**
* \file source_paths.h
* \brief Identify the build and source path of a not-yet-installed library
*/
/* musl doesn't declare _DYNAMIC in link.h, declare it manually. */
extern ElfW(Dyn) _DYNAMIC[];
namespace libcamera {
namespace {
/**
* \brief Check if libcamera is installed or not
*
* Utilise the build_rpath dynamic tag which is stripped out by meson at
* install time to determine at runtime if the library currently executing
* has been installed or not.
*
* \return True if libcamera is installed, false otherwise
*/
bool isLibcameraInstalled()
{
/*
* DT_RUNPATH (DT_RPATH when the linker uses old dtags) is removed on
* install.
*/
for (const ElfW(Dyn) *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) {
if (dyn->d_tag == DT_RUNPATH || dyn->d_tag == DT_RPATH)
return false;
}
return true;
}
} /* namespace */
namespace utils {
/**
* \brief Retrieve the path to the build directory
*
* During development, it is useful to run libcamera binaries directly from the
* build directory without installing them. This function helps components that
* need to locate resources in the build tree, such as IPA modules or IPA proxy
* workers, by providing them with the path to the root of the build directory.
* Callers can then use it to complement or override searches in system-wide
* directories.
*
* If libcamera has been installed, the build directory path is not available
* and this function returns an empty string.
*
* \return The path to the build directory if running from a build, or an empty
* string otherwise
*/
std::string libcameraBuildPath()
{
if (isLibcameraInstalled())
return std::string();
Dl_info info;
/* Look up our own symbol. */
int ret = dladdr(reinterpret_cast<void *>(libcameraBuildPath), &info);
if (ret == 0)
return std::string();
std::string path = dirname(info.dli_fname) + "/../../";
char *real = realpath(path.c_str(), nullptr);
if (!real)
return std::string();
path = real;
free(real);
return path + "/";
}
/**
* \brief Retrieve the path to the source directory
*
* During development, it is useful to run libcamera binaries directly from the
* build directory without installing them. This function helps components that
* need to locate resources in the source tree, such as IPA configuration
* files, by providing them with the path to the root of the source directory.
* Callers can then use it to complement or override searches in system-wide
* directories.
*
* If libcamera has been installed, the source directory path is not available
* and this function returns an empty string.
*
* \return The path to the source directory if running from a build directory,
* or an empty string otherwise
*/
std::string libcameraSourcePath()
{
std::string path = libcameraBuildPath();
if (path.empty())
return std::string();
path += "source";
char *real = realpath(path.c_str(), nullptr);
if (!real)
return std::string();
path = real;
free(real);
struct stat statbuf;
int ret = stat(path.c_str(), &statbuf);
if (ret < 0 || (statbuf.st_mode & S_IFMT) != S_IFDIR)
return std::string();
return path + "/";
}
} /* namespace utils */
} /* namespace libcamera */