Build tool
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SourceFile.cc 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "SourceFile.h"
  2. #include <iostream>
  3. #include <fstream>
  4. #include <sstream>
  5. #include <string.h>
  6. #include "toolchain.h"
  7. static bool startsWith(BBBParser &parser, const char *str) {
  8. for (size_t i = 0; str[i] != '\0'; ++i) {
  9. if (parser.peek() != str[i])
  10. return false;
  11. parser.skip();
  12. }
  13. return true;
  14. }
  15. SourceFile::FileType SourceFile::fileTypeFrom(const std::string &name) {
  16. size_t idx = name.find_last_of('.');
  17. if (idx >= std::string::npos) {
  18. return FileType::UNKNOWN;
  19. }
  20. char ext[16] = { 0 };
  21. strncpy(ext, name.c_str() + idx, sizeof(ext) - 1);
  22. if (strcmp(ext, ".c") == 0) {
  23. return FileType::C;
  24. } else if (
  25. (strcmp(ext, ".C") == 0) ||
  26. (strcmp(ext, ".cc") == 0) ||
  27. (strcmp(ext, ".cpp") == 0) ||
  28. (strcmp(ext, ".cxx") == 0)) {
  29. return FileType::CXX;
  30. }
  31. return FileType::UNKNOWN;
  32. }
  33. SourceFile::SourceFile(
  34. std::string dir, std::string name,
  35. FileType type, BBBParser::Variables vars):
  36. dir_(std::move(dir)), name_(std::move(name)),
  37. type_(type), vars_(std::move(vars)) {
  38. std::ifstream file(dir_ + "/" + name_);
  39. BBBParser parser(file, BBBParser::FLAG_ONE_LINE);
  40. while (file.good()) {
  41. if (startsWith(parser, "//#bb")) {
  42. parser.parse(vars_);
  43. } else {
  44. while (file.good() && parser.get() != '\n');
  45. }
  46. }
  47. }
  48. const std::vector<std::string> *SourceFile::variable(const std::string &name) const {
  49. auto it = vars_.find(name);
  50. if (it == vars_.end()) {
  51. return nullptr;
  52. }
  53. return &it->second;
  54. }
  55. const std::vector<std::string> &SourceFile::compileFlags() const {
  56. if (hasCompileFlags_) {
  57. return compileFlags_;
  58. }
  59. const std::vector<std::string> *pkgs = variable("pkgs");
  60. if (pkgs != nullptr) {
  61. toolchain::pkgFlags(*pkgs, compileFlags_);
  62. }
  63. const std::vector<std::string> *cflags;
  64. switch (type_) {
  65. case SourceFile::FileType::C:
  66. cflags = variable("cflags");
  67. break;
  68. case SourceFile::FileType::CXX:
  69. cflags = variable("cxxflags");
  70. break;
  71. case SourceFile::FileType::UNKNOWN:
  72. break;
  73. }
  74. if (cflags != nullptr) {
  75. for (const std::string &flag: *cflags) {
  76. compileFlags_.push_back(flag);
  77. }
  78. }
  79. return compileFlags_;
  80. }
  81. const std::vector<std::string> &SourceFile::ldLibs() const {
  82. const std::vector<std::string> *pkgs = variable("pkgs");
  83. if (pkgs != nullptr) {
  84. toolchain::pkgLDLibs(*pkgs, ldLibs_);
  85. }
  86. const std::vector<std::string> *libs = variable("ldlibs");
  87. if (libs != nullptr) {
  88. for (const std::string &flag: *libs) {
  89. ldLibs_.push_back(flag);
  90. }
  91. }
  92. hasLDLibs_ = true;
  93. return ldLibs_;
  94. }
  95. std::vector<std::string> SourceFile::dependencies() const {
  96. std::vector<std::string> deps;
  97. toolchain::getDependencies(compileFlags(), type_, dir_, name_, deps);
  98. return deps;
  99. }
  100. bool SourceFile::needsRecompile(const std::string &outDir) const {
  101. std::string outPath = outDir + "/" + name_ + ".o";
  102. if (!sys::fileExists(outPath)) {
  103. return true;
  104. }
  105. sys::FileInfo outInfo = sys::fileInfo(outPath);
  106. std::vector<std::string> deps = dependencies();
  107. for (std::string &dep: deps) {
  108. sys::FileInfo depInfo = sys::fileInfo(dep);
  109. if (depInfo.mTimeSec > outInfo.mTimeSec || (
  110. depInfo.mTimeSec == outInfo.mTimeSec &&
  111. depInfo.mTimeNsec > outInfo.mTimeNsec)) {
  112. return true;
  113. }
  114. }
  115. return false;
  116. }
  117. void SourceFile::compile(const std::string &outDir) const {
  118. std::cerr << "Compile " << dir_ << '/' << name_ << '\n';
  119. toolchain::compile(compileFlags(), type_, dir_, name_, outDir);
  120. }