// -*- c++ -*- // Distributed under the BSD 2-Clause License. // See accompanying file LICENSE for details. #include "deps.h" #include "util.h" #include namespace { /* Format example: build/src/libctor_a-libctor_cc.o: src/libctor.cc \ src/getoptpp/getoptpp.hpp src/ctor.h src/configure.h src/rebuild.h \ src/A\ B\ C.h src/task.h src/build.h src/unittest.h */ std::vector readDepsMake(const std::string& dep_file) { auto str = readFile(dep_file); std::vector output; std::string tmp; enum class State { pre_colon, post_colon, in_escape, } state{State::pre_colon}; auto old_state{state}; for(const auto& c : str) { if(c == '\r') { // just always ignore windows extra newline char continue; } switch(state) { case State::pre_colon: if(c == ':') // ignore everything until the colon { state = State::post_colon; continue; } continue; case State::post_colon: if(c == '\n') { // done if(!tmp.empty()) { output.emplace_back(tmp); } return output; } if(c == '\\') { old_state = state; state = State::in_escape; continue; } if(c == '\t' || c == ' ') // new token { if(!tmp.empty()) { output.emplace_back(tmp); } tmp.clear(); continue; } break; case State::in_escape: if(c == '\n') { // linewrap state = old_state; continue; } state = old_state; break; } tmp += c; } if(!tmp.empty()) { output.emplace_back(tmp); } return output; } } std::vector readDeps(const std::string& dep_file, ctor::toolchain toolchain) { if(!std::filesystem::exists(dep_file)) { return {}; } switch(toolchain) { case ctor::toolchain::any: case ctor::toolchain::none: return {}; // makefile .d file based: case ctor::toolchain::gcc: case ctor::toolchain::clang: return readDepsMake(dep_file); } return {}; }