Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
MartyRuntimeConfig.h
Go to the documentation of this file.
1#ifndef HYPERISO_MARTY_RUNTIME_CONFIG_H
2#define HYPERISO_MARTY_RUNTIME_CONFIG_H
3
4#include <algorithm>
5#include <filesystem>
6#include <optional>
7#include <sstream>
8#include <string>
9#include <vector>
10
11#include "Logger.h"
12#include "config.hpp"
13
31public:
32 struct InstallInfo {
33 std::filesystem::path requested_path;
34 std::filesystem::path prefix;
35 std::filesystem::path include_dir;
36 std::filesystem::path lib_dir;
37 std::filesystem::path marty_header;
38 std::filesystem::path marty_library;
39 std::filesystem::path marty_executable;
40 std::string source;
41 std::string error;
42 bool has_executable = false;
43 bool valid = false;
44 };
45
53 static InstallInfo set_external_install_path(const std::filesystem::path& path)
54 {
55 external_install_path() = path;
56 return inspect_install_path(path, "user-provided MARTY path");
57 }
58
63 {
64 external_install_path().reset();
65 }
66
71 {
72 if (external_install_path().has_value()) {
73 return inspect_install_path(*external_install_path(), "user-provided MARTY path");
74 }
75
76 return inspect_install_path(default_install_path(), default_source_label());
77 }
78
85 static InstallInfo require_available(const std::string& context)
86 {
87 auto info = resolve();
88 if (info.valid) {
89 LOG_DEBUG("MARTY runtime resolved for", context, ":", info.prefix.string());
90 return info;
91 }
92
94 "MartyConfigError",
95 "MARTY mode requested in", context,
96 "but no valid MARTY installation could be resolved.",
97 info.error,
98 "Call HyperisoMaster::pre_init_set_marty_path(<MARTY_INSTALL>) before init(),",
99 "or build/install the bundled MARTY with -DBUILD_WITH_MARTY=ON."
100 );
101 return info;
102 }
103
107 static std::string shell_quote(const std::filesystem::path& path)
108 {
109 std::string raw = path.string();
110 std::string quoted = "'";
111 for (char c : raw) {
112 if (c == '\'') {
113 quoted += "'\\''";
114 } else {
115 quoted += c;
116 }
117 }
118 quoted += "'";
119 return quoted;
120 }
121
122 static std::filesystem::path default_install_path()
123 {
124 return std::filesystem::path(project_tp_root.data()) / "MARTY" / "MARTY_INSTALL";
125 }
126
128 {
129 return external_install_path().has_value();
130 }
131
132private:
133 static std::optional<std::filesystem::path>& external_install_path()
134 {
135 static std::optional<std::filesystem::path> path;
136 return path;
137 }
138
139 static std::string default_source_label()
140 {
141#ifdef BUILD_WITH_MARTY
142 return "bundled MARTY install from BUILD_WITH_MARTY";
143#else
144 return "default bundled MARTY install path";
145#endif
146 }
147
148 static bool is_marty_library_name(const std::filesystem::path& path)
149 {
150 const auto filename = path.filename().string();
151 return filename == "libmarty.so"
152 || filename == "libmarty.dylib"
153 || filename == "libmarty.a";
154 }
155
156 static std::optional<std::filesystem::path> find_marty_library(const std::filesystem::path& lib_dir)
157 {
158 const std::vector<std::string> names = {
159 "libmarty.so",
160 "libmarty.dylib",
161 "libmarty.a"
162 };
163
164 for (const auto& name : names) {
165 std::filesystem::path candidate = lib_dir / name;
166 if (std::filesystem::exists(candidate)) {
167 return candidate;
168 }
169 }
170 return std::nullopt;
171 }
172
173 static std::filesystem::path normalize_prefix_candidate(const std::filesystem::path& requested)
174 {
175 if (requested.empty()) {
176 return requested;
177 }
178
179 std::filesystem::path p = std::filesystem::absolute(requested).lexically_normal();
180
181 if (std::filesystem::is_regular_file(p)) {
182 if (p.filename() == "marty.h") {
183 return p.parent_path().parent_path();
184 }
185 if (is_marty_library_name(p)) {
186 return p.parent_path().parent_path();
187 }
188 }
189
190 if (p.filename() == "include" && std::filesystem::exists(p / "marty.h")) {
191 return p.parent_path();
192 }
193
194 if (p.filename() == "lib" && find_marty_library(p).has_value()) {
195 return p.parent_path();
196 }
197
198 if (std::filesystem::exists(p / "include" / "marty.h")) {
199 return p;
200 }
201
202 if (std::filesystem::exists(p / "MARTY_INSTALL" / "include" / "marty.h")) {
203 return p / "MARTY_INSTALL";
204 }
205
206 if (std::filesystem::exists(p / "install" / "include" / "marty.h")) {
207 return p / "install";
208 }
209
210 return p;
211 }
212
213 static InstallInfo inspect_install_path(const std::filesystem::path& requested, std::string source)
214 {
215 InstallInfo info;
216 info.requested_path = requested;
217 info.source = std::move(source);
218 info.prefix = normalize_prefix_candidate(requested);
219 info.include_dir = info.prefix / "include";
220 info.lib_dir = info.prefix / "lib";
221 info.marty_header = info.include_dir / "marty.h";
222 info.marty_executable = info.prefix / "bin" / "marty";
223
224 std::vector<std::string> errors;
225
226 if (requested.empty()) {
227 errors.emplace_back("empty path");
228 }
229
230 if (!std::filesystem::exists(info.prefix)) {
231 errors.emplace_back("prefix does not exist: " + info.prefix.string());
232 }
233
234 if (!std::filesystem::exists(info.marty_header)) {
235 errors.emplace_back("missing header: " + info.marty_header.string());
236 }
237
238 auto lib = find_marty_library(info.lib_dir);
239 if (!lib.has_value()) {
240 errors.emplace_back("missing libmarty in: " + info.lib_dir.string());
241 } else {
242 info.marty_library = *lib;
243 }
244
245 info.has_executable = std::filesystem::exists(info.marty_executable)
246 && !std::filesystem::is_directory(info.marty_executable);
247
248 info.valid = errors.empty();
249 if (!info.valid) {
250 std::ostringstream oss;
251 oss << "Checked " << info.source << " at " << requested.string() << ". ";
252 for (size_t i = 0; i < errors.size(); ++i) {
253 if (i > 0) {
254 oss << " ";
255 }
256 oss << errors[i] << ".";
257 }
258 info.error = oss.str();
259 }
260
261 return info;
262 }
263};
264
265#endif // HYPERISO_MARTY_RUNTIME_CONFIG_H
#define LOG_ERROR(type,...)
Macro for logging error messages and terminating the application.
Definition Logger.h:41
#define LOG_DEBUG(...)
Macro for logging debug messages.
Definition Logger.h:45
Runtime resolver for the MARTY installation used by generated code.
static std::filesystem::path default_install_path()
static InstallInfo resolve()
Resolve the MARTY install that should be used now.
static bool was_external_path_provided()
static void clear_external_install_path()
Clear the user-provided path and return to the default fallback.
static std::string shell_quote(const std::filesystem::path &path)
Shell-quote a path for command strings passed to std::system().
static InstallInfo set_external_install_path(const std::filesystem::path &path)
Register a user-provided MARTY installation path.
static InstallInfo require_available(const std::string &context)
Validate and return the active MARTY installation.
std::filesystem::path marty_executable
std::filesystem::path requested_path
std::filesystem::path marty_library