Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions source/citnames/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ target_sources(citnames_a
source/semantic/ToolIntelFortran.cc
source/semantic/ToolWrapper.cc
source/semantic/ToolExtendingWrapper.cc
source/semantic/ToolLinker.cc
source/semantic/ToolAr.cc
INTERFACE
$<TARGET_OBJECTS:citnames_a>
)
Expand Down
101 changes: 95 additions & 6 deletions source/citnames/source/Citnames.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,44 @@ namespace {
}
return output.size();
}

size_t transform_links(cs::semantic::Build &build, const db::EventsDatabaseReader::Ptr& events, std::list<cs::LinkEntry> &output) {
for (const auto &event : *events) {
const auto entries = build.recognize(event)
.map<std::list<cs::LinkEntry>>([](const auto &semantic) -> std::list<cs::LinkEntry> {
const auto candidate = dynamic_cast<const cs::semantic::Link *>(semantic.get());
return (candidate != nullptr) ? candidate->into_link_entries() : std::list<cs::LinkEntry>();
})
.unwrap_or({});
std::copy(entries.begin(), entries.end(), std::back_inserter(output));
}
return output.size();
}

size_t transform_ar(cs::semantic::Build &build, const db::EventsDatabaseReader::Ptr& events, std::list<cs::ArEntry> &output) {
for (const auto &event : *events) {
const auto entries = build.recognize(event)
.map<std::list<cs::ArEntry>>([](const auto &semantic) -> std::list<cs::ArEntry> {
const auto candidate = dynamic_cast<const cs::semantic::Ar *>(semantic.get());
return (candidate != nullptr) ? candidate->into_ar_entries() : std::list<cs::ArEntry>();
})
.unwrap_or({});
std::copy(entries.begin(), entries.end(), std::back_inserter(output));
}
return output.size();
}
}

namespace cs {

rust::Result<int> Command::execute() const {
cs::CompilationDatabase output(configuration_.output.format, configuration_.output.content);
std::list<cs::Entry> entries;
std::list<cs::LinkEntry> link_entries;
std::list<cs::ArEntry> ar_entries;

// get current compilations from the input.
return db::EventsDatabaseReader::from(arguments_.input)
auto compile_result = db::EventsDatabaseReader::from(arguments_.input)
.map<size_t>([this, &entries](const auto &commands) {
cs::semantic::Build build(configuration_.compilation);
return transform(build, commands, entries);
Expand All @@ -212,7 +240,7 @@ namespace cs {
})
: rust::Result<size_t>(rust::Ok(new_entries_count));
})
.and_then<size_t>([this, &output, &entries](const size_t & size) {
.and_then<size_t>([this, &output, &entries](auto size) {
// write the entries into the output file.
spdlog::debug("compilation entries to output. [size: {}]", size);

Expand All @@ -221,12 +249,73 @@ namespace cs {
return rename_file(temporary_file, arguments_.output)
? result
: rust::Err(std::runtime_error(fmt::format("Failed to rename file: {}", arguments_.output)));
});

auto link_result = rust::Result<size_t>(rust::Ok<size_t>(0));
if (!configuration_.output.link_commands_output.empty()) {
link_result = db::EventsDatabaseReader::from(arguments_.input)
.map<size_t>([this, &link_entries](const auto &commands) {
cs::semantic::Build build(configuration_.compilation);
return transform_links(build, commands, link_entries);
})
.map<int>([](auto size) {
// just map to success exit code if it was successful.
spdlog::debug("compilation entries written. [size: {}]", size);
return EXIT_SUCCESS;
.and_then<size_t>([this, &output, &link_entries](auto new_entries_count) {
spdlog::debug("link entries created. [size: {}]", new_entries_count);
return (arguments_.append)
? output.from_link_json(arguments_.output, link_entries)
.template map<size_t>([&new_entries_count](auto old_entries_count) {
spdlog::debug("link entries have read. [size: {}]", old_entries_count);
return new_entries_count + old_entries_count;
})
: rust::Result<size_t>(rust::Ok(new_entries_count));
})
.and_then<size_t>([this, &output, &link_entries](auto size) {
// write the link entries into a separate output file if configured
spdlog::debug("link entries to output. [size: {}]", size);

const fs::path link_temp_file(configuration_.output.link_commands_output.string() + ".tmp");
auto link_write_result = output.to_link_json(link_temp_file, link_entries);
return rename_file(link_temp_file, configuration_.output.link_commands_output)
? link_write_result
: rust::Err(std::runtime_error(fmt::format("Failed to rename file: {}", configuration_.output.link_commands_output)));
});
}

auto ar_result = rust::Result<size_t>(rust::Ok<size_t>(0));
if (!configuration_.output.ar_commands_output.empty()) {
ar_result = db::EventsDatabaseReader::from(arguments_.input)
.map<size_t>([this, &ar_entries](const auto &commands) {
cs::semantic::Build build(configuration_.compilation);
return transform_ar(build, commands, ar_entries);
})
.and_then<size_t>([this, &output, &ar_entries](auto new_entries_count) {
spdlog::debug("ar entries created. [size: {}]", new_entries_count);
return (arguments_.append)
? output.from_ar_json(arguments_.output, ar_entries)
.template map<size_t>([&new_entries_count](auto old_entries_count) {
spdlog::debug("ar entries have read. [size: {}]", old_entries_count);
return new_entries_count + old_entries_count;
})
: rust::Result<size_t>(rust::Ok(new_entries_count));
})
.and_then<size_t>([this, &output, &ar_entries](auto size) {
// write the ar entries into a separate output file if configured
spdlog::debug("ar entries to output. [size: {}]", size);

const fs::path ar_temp_file(configuration_.output.ar_commands_output.string() + ".tmp");
auto ar_write_result = output.to_ar_json(ar_temp_file, ar_entries);
return rename_file(ar_temp_file, configuration_.output.ar_commands_output)
? ar_write_result
: rust::Err(std::runtime_error(fmt::format("Failed to rename file: {}", configuration_.output.ar_commands_output)));
});
}

return rust::merge(compile_result, rust::merge(link_result, ar_result))
.map<int>([](const auto &sizes) -> int {
const auto&[compile_size, link_and_ar_sizes] = sizes;
const auto&[link_size, ar_size] = link_and_ar_sizes;
spdlog::debug("compilation entries written. [size: {}]", compile_size);
return compile_size + link_size + ar_size;
});
}

Command::Command(Arguments arguments, cs::Configuration configuration) noexcept
Expand Down
20 changes: 18 additions & 2 deletions source/citnames/source/Configuration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,31 @@ namespace cs {
}

void from_json(const nlohmann::json &j, Output &rhs) {
j.at("format").get_to(rhs.format);
j.at("content").get_to(rhs.content);
if (j.contains("format")) {
j.at("format").get_to(rhs.format);
}
if (j.contains("content")) {
j.at("content").get_to(rhs.content);
}
if (j.contains("link_commands_output")) {
j.at("link_commands_output").get_to(rhs.link_commands_output);
}
if (j.contains("ar_commands_output")) {
j.at("ar_commands_output").get_to(rhs.ar_commands_output);
}
}

void to_json(nlohmann::json &j, const Output &rhs) {
j = nlohmann::json{
{"format", rhs.format},
{"content", rhs.content},
};
if (!rhs.link_commands_output.empty()) {
j["link_commands_output"] = rhs.link_commands_output;
}
if (!rhs.ar_commands_output.empty()) {
j["ar_commands_output"] = rhs.ar_commands_output;
}
}

void from_json(const nlohmann::json &j, CompilerWrapper &rhs) {
Expand Down
2 changes: 2 additions & 0 deletions source/citnames/source/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ namespace cs {
struct Output {
Format format;
Content content;
fs::path link_commands_output; // Path to the link commands output file
fs::path ar_commands_output; // Path to the ar commands output file
};

// Represents a compiler wrapper that the tool will recognize.
Expand Down
Loading