Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
GppCompilerStrategy.cpp
Go to the documentation of this file.
3
4#include <algorithm>
5#include <array>
6#include <cstdio>
7#include <cctype>
8#include <filesystem>
9#include <sstream>
10#include <stdexcept>
11
12namespace {
13
14std::string trim(std::string value) {
15 const auto not_space = [](unsigned char c) { return !std::isspace(c); };
16 value.erase(value.begin(), std::find_if(value.begin(), value.end(), not_space));
17 value.erase(std::find_if(value.rbegin(), value.rend(), not_space).base(), value.end());
18 return value;
19}
20
21std::string command_output(const std::string& command) {
22 std::array<char, 256> buffer{};
23 std::string result;
24
25 FILE* pipe = popen((command + " 2>/dev/null").c_str(), "r");
26 if (!pipe) {
27 return {};
28 }
29
30 while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
31 result += buffer.data();
32 }
33
34 const int status = pclose(pipe);
35 if (status != 0) {
36 return {};
37 }
38
39 return trim(result);
40}
41
42std::filesystem::path find_libgfortran() {
43 const std::string from_gpp = command_output("g++ -print-file-name=libgfortran.so");
44 if (!from_gpp.empty() && from_gpp != "libgfortran.so" && std::filesystem::exists(from_gpp)) {
45 return from_gpp;
46 }
47
48 const std::string from_gfortran = command_output("gfortran -print-file-name=libgfortran.so");
49 if (!from_gfortran.empty() && from_gfortran != "libgfortran.so" && std::filesystem::exists(from_gfortran)) {
50 return from_gfortran;
51 }
52
53 return {};
54}
55
56std::filesystem::path require_libgfortran() {
57 const auto lib = find_libgfortran();
58 if (!lib.empty()) {
59 return lib;
60 }
61
62 throw std::runtime_error(
63 "MARTY generated-code compilation requires libgfortran, but the linker "
64 "cannot find libgfortran.so.\n"
65 "Install the Fortran development package, for example on Ubuntu/Debian:\n"
66 " sudo apt update && sudo apt install gfortran\n"
67 "Then verify with:\n"
68 " g++ -print-file-name=libgfortran.so\n"
69 "The command must print an absolute path, not just 'libgfortran.so'."
70 );
71}
72
73} // namespace
74
75void GppCompilerStrategy::compile_run(const std::string& sourceFile, const std::string& outputBinary) {
76 if (!this->check_if_compile(outputBinary)) {
77 this->compile(sourceFile, outputBinary);
78 }
79
80 std::string command_run = "cd " + FileNameManager::getInstance(wilson, model)->getOutputDir() + " && " + outputBinary;
81 executeCommand(command_run);
82}
83
84void GppCompilerStrategy::compile(const std::string& sourceFile, const std::string& outputBinary) {
85 const auto marty = MartyRuntimeConfig::require_available("GppCompilerStrategy::compile");
86 if (!marty.valid) {
87 return;
88 }
89
90 const auto libgfortran = require_libgfortran();
91
92 const std::string include_dir = MartyRuntimeConfig::shell_quote(marty.include_dir);
93 const std::string lib_dir = MartyRuntimeConfig::shell_quote(marty.lib_dir);
94 const std::string libgfortran_path = MartyRuntimeConfig::shell_quote(libgfortran);
95
96 std::string command_compile = "g++ -o " + outputBinary + " " + sourceFile
97 + " -I" + include_dir
98 + " -L" + lib_dir
99 + " -Wl,-rpath," + lib_dir
100 + " -lmarty " + libgfortran_path;
101
102 executeCommand(command_compile);
103}
bool executeCommand(const std::string &command)
Executes a shell command and captures its output.
Declares a compilation strategy using g++ directly.
virtual bool check_if_compile(const std::string &outputBinary)
Checks whether a compiled binary already exists and is non-empty.
std::string model
Model name.
std::string wilson
Wilson basis / label name.
static std::shared_ptr< FileNameManager > getInstance(const std::string &wilson="", const std::string &model="")
Retrieves a FileNameManager for a given (wilson, model) pair.
void compile(const std::string &sourceFile, const std::string &outputBinary) override
Compiles the given source file using g++ and links against MARTY.
void compile_run(const std::string &sourceFile, const std::string &outputBinary) override
Compiles if necessary and then runs the resulting binary.
static std::string shell_quote(const std::filesystem::path &path)
Shell-quote a path for command strings passed to std::system().
static InstallInfo require_available(const std::string &context)
Validate and return the active MARTY installation.