return ret; | return ret; | ||||
} | } | ||||
msvc_deps_info dds::parse_msvc_output_for_deps(std::string_view output, std::string_view leader) { | |||||
auto lines = split_view(output, "\n"); | |||||
std::string cleaned_output; | |||||
deps_info deps; | |||||
for (auto line : lines) { | |||||
line = trim_view(line); | |||||
if (!starts_with(line, leader)) { | |||||
cleaned_output += std::string(line); | |||||
cleaned_output.push_back('\n'); | |||||
continue; | |||||
} | |||||
auto remaining = trim_view(line.substr(leader.size())); | |||||
deps.inputs.emplace_back(fs::weakly_canonical(remaining)); | |||||
} | |||||
if (!cleaned_output.empty()) { | |||||
// Remove the extra newline at the back | |||||
cleaned_output.pop_back(); | |||||
} | |||||
return {deps, cleaned_output}; | |||||
} | |||||
void dds::update_deps_info(database& db, const deps_info& deps) { | void dds::update_deps_info(database& db, const deps_info& deps) { | ||||
db.store_mtime(deps.output, fs::last_write_time(deps.output)); | db.store_mtime(deps.output, fs::last_write_time(deps.output)); | ||||
db.store_file_command(deps.output, {deps.command, deps.command_output}); | db.store_file_command(deps.output, {deps.command, deps.command_output}); |
deps_info parse_mkfile_deps_file(path_ref where); | deps_info parse_mkfile_deps_file(path_ref where); | ||||
deps_info parse_mkfile_deps_str(std::string_view str); | deps_info parse_mkfile_deps_str(std::string_view str); | ||||
struct msvc_deps_info { | |||||
struct deps_info deps_info; | |||||
std::string cleaned_output; | |||||
}; | |||||
msvc_deps_info parse_msvc_output_for_deps(std::string_view output, std::string_view leader); | |||||
void update_deps_info(database& db, const deps_info&); | void update_deps_info(database& db, const deps_info&); | ||||
struct deps_rebuild_info { | struct deps_rebuild_info { | ||||
std::string previous_command_output; | std::string previous_command_output; | ||||
}; | }; | ||||
deps_rebuild_info | |||||
get_rebuild_info(database& db, path_ref output_path); | |||||
deps_rebuild_info get_rebuild_info(database& db, path_ref output_path); | |||||
} // namespace dds | } // namespace dds |
deps = dds::parse_mkfile_deps_str("foo.c"); | deps = dds::parse_mkfile_deps_str("foo.c"); | ||||
CHECK(deps.output.empty()); | CHECK(deps.output.empty()); | ||||
CHECK(deps.inputs.empty()); | CHECK(deps.inputs.empty()); | ||||
} | |||||
TEST_CASE("Parse MSVC deps") { | |||||
auto mscv_output = R"( | |||||
Note: including file: C:\foo\bar\filepath/thing.hpp | |||||
Note: including file: C:\foo\bar\filepath/baz.h | |||||
Note: including file: C:\foo\bar\filepath/quux.h | |||||
Note: including file: C:\foo\bar\filepath/cats/quux.h | |||||
Other line | |||||
Something else | |||||
)"; | |||||
auto res = dds::parse_msvc_output_for_deps(mscv_output, "Note: including file:"); | |||||
auto& deps = res.deps_info; | |||||
auto new_output = res.cleaned_output; | |||||
CHECK(new_output == "\nOther line\nSomething else\n"); | |||||
CHECK(deps.inputs | |||||
== std::vector<dds::fs::path>({ | |||||
"C:\\foo\\bar\\filepath/thing.hpp", | |||||
"C:\\foo\\bar\\filepath/baz.h", | |||||
"C:\\foo\\bar\\filepath/quux.h", | |||||
"C:\\foo\\bar\\filepath/cats/quux.h", | |||||
})); | |||||
} | } |