#include "SourceFile.h" #include #include #include #include #include "toolchain.h" static bool startsWith(BBBParser &parser, const char *str) { for (size_t i = 0; str[i] != '\0'; ++i) { if (parser.peek() != str[i]) return false; parser.skip(); } return true; } SourceFile::FileType SourceFile::fileTypeFrom(const std::string &name) { size_t idx = name.find_last_of('.'); if (idx >= std::string::npos) { return FileType::UNKNOWN; } char ext[16] = { 0 }; strncpy(ext, name.c_str() + idx, sizeof(ext) - 1); if (strcmp(ext, ".c") == 0) { return FileType::C; } else if ( (strcmp(ext, ".C") == 0) || (strcmp(ext, ".cc") == 0) || (strcmp(ext, ".cpp") == 0) || (strcmp(ext, ".cxx") == 0)) { return FileType::CXX; } return FileType::UNKNOWN; } SourceFile::SourceFile( std::string dir, std::string name, FileType type, BBBParser::Variables vars): dir_(std::move(dir)), name_(std::move(name)), type_(type), vars_(std::move(vars)) { std::ifstream file(dir_ + "/" + name_); BBBParser parser(file, BBBParser::FLAG_ONE_LINE); while (file.good()) { if (startsWith(parser, "//#bb")) { parser.parse(vars_); } else { while (file.good() && parser.get() != '\n'); } } } const std::vector *SourceFile::variable(const std::string &name) const { auto it = vars_.find(name); if (it == vars_.end()) { return nullptr; } return &it->second; } const std::vector &SourceFile::compileFlags() const { if (hasCompileFlags_) { return compileFlags_; } const std::vector *pkgs = variable("pkgs"); if (pkgs != nullptr) { toolchain::pkgFlags(*pkgs, compileFlags_); } const std::vector *cflags; switch (type_) { case SourceFile::FileType::C: cflags = variable("cflags"); break; case SourceFile::FileType::CXX: cflags = variable("cxxflags"); break; case SourceFile::FileType::UNKNOWN: break; } if (cflags != nullptr) { for (const std::string &flag: *cflags) { compileFlags_.push_back(flag); } } return compileFlags_; } const std::vector &SourceFile::ldLibs() const { const std::vector *pkgs = variable("pkgs"); if (pkgs != nullptr) { toolchain::pkgLDLibs(*pkgs, ldLibs_); } const std::vector *libs = variable("ldlibs"); if (libs != nullptr) { for (const std::string &flag: *libs) { ldLibs_.push_back(flag); } } hasLDLibs_ = true; return ldLibs_; } std::vector SourceFile::dependencies() const { std::vector deps; toolchain::getDependencies(compileFlags(), type_, dir_, name_, deps); return deps; } bool SourceFile::needsRecompile(const std::string &outDir) const { std::string outPath = outDir + "/" + name_ + ".o"; if (!sys::fileExists(outPath)) { return true; } sys::FileInfo outInfo = sys::fileInfo(outPath); std::vector deps = dependencies(); for (std::string &dep: deps) { sys::FileInfo depInfo = sys::fileInfo(dep); if (depInfo.mTimeSec > outInfo.mTimeSec || ( depInfo.mTimeSec == outInfo.mTimeSec && depInfo.mTimeNsec > outInfo.mTimeNsec)) { return true; } } return false; } void SourceFile::compile(const std::string &outDir) const { std::cerr << "Compile " << dir_ << '/' << name_ << '\n'; toolchain::compile(compileFlags(), type_, dir_, name_, outDir); }