lsst.cpputils gee37125a88+b319181507
Loading...
Searching...
No Matches
packaging.cc
Go to the documentation of this file.
1/*
2 * LSST Data Management System
3 * Copyright 2008, 2009, 2010 LSST Corporation.
4 *
5 * This product includes software developed by the
6 * LSST Project (http://www.lsst.org/).
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the LSST License Statement and
19 * the GNU General Public License along with this program. If not,
20 * see <http://www.lsstcorp.org/LegalNotices/>.
21 */
22
24
25#include <dlfcn.h>
26
27#include <filesystem>
28#include <iostream>
29#include <sstream>
30#include <string>
31#include "lsst/pex/exceptions.h"
32
33namespace lsst {
34namespace cpputils {
35
37 std::string envVar = packageName; // package's environment variable
38
39 transform(envVar.begin(), envVar.end(), envVar.begin(), (int (*)(int)) toupper);
40 envVar += "_DIR";
41
42 char const *dir = getenv(envVar.c_str());
43 if (!dir) {
44 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Package " + packageName + " not found");
45 }
46
47 return dir;
48}
49
50std::string getPackageDirFromAddress(void const* addressInLibrary) {
51 // A null pointer is a caller precondition violation, not a lookup failure;
52 // reject it explicitly rather than relying on dladdr's unspecified behavior.
53 if (addressInLibrary == nullptr) {
55 "Null address passed to getPackageDirFromAddress");
56 }
57
58 // dladdr resolves an address to the shared object whose memory map contains
59 // it, regardless of which library's code is calling dladdr. Passing an
60 // address from the target package's own library therefore yields that
61 // library's path (works identically for .so on Linux and .dylib on macOS).
62 Dl_info info{};
63 if (dladdr(addressInLibrary, &info) == 0 || info.dli_fname == nullptr) {
65 "Could not locate the shared library for the given address");
66 }
67
69 std::filesystem::path libraryPath = std::filesystem::canonical(info.dli_fname, ec);
70 if (ec) {
72 "Could not resolve shared library path '" +
73 std::string(info.dli_fname) + "': " + ec.message());
74 }
75
76 // .../<packageRoot>/lib/lib<name>.{so,dylib} -> <packageRoot>
77 return libraryPath.parent_path().parent_path().string();
78}
79
80}} // namespace lsst::cpputils
#define LSST_EXCEPT(type,...)
T begin(T... args)
T c_str(T... args)
T end(T... args)
T message(T... args)
std::string getPackageDirFromAddress(void const *addressInLibrary)
return the root directory of the package whose shared library contains the given address
Definition packaging.cc:50
std::string getPackageDir(std::string const &packageName)
return the root directory of a setup package
Definition packaging.cc:36