command_builder.h 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #pragma once
  2. #include <iostream>
  3. #include <sstream>
  4. #include <string>
  5. #include "types.h"
  6. namespace build {
  7. class command_builder {
  8. private:
  9. indent_t indent_;
  10. std::stringstream buffer_;
  11. public:
  12. command_builder(std::string const & cmd, int indent = 0);
  13. template <typename T> command_builder && operator<<(T const & value) &&;
  14. // TODO(samjaffe): Use the type system for things here...
  15. command_builder & operator<<(version const & vers) &;
  16. command_builder & operator<<(source_file const & file) &;
  17. command_builder & operator<<(output_file const & file) &;
  18. template <typename T> command_builder & operator<<(T const & value) &;
  19. template <typename T>
  20. command_builder & operator<<(std::vector<T> const & value) &;
  21. int execute() const;
  22. };
  23. command_builder::command_builder(std::string const & cmd, int indent)
  24. : indent_{indent}, buffer_() {
  25. buffer_ << cmd;
  26. }
  27. template <typename T>
  28. command_builder && command_builder::operator<<(T const & value) && {
  29. return std::move((*this) << value);
  30. }
  31. template <typename T>
  32. command_builder & command_builder::operator<<(T const & value) & {
  33. buffer_ << ' ' << value;
  34. return *this;
  35. }
  36. command_builder & command_builder::operator<<(version const & vers) & {
  37. switch (vers) {
  38. case version::cxx11:
  39. buffer_ << ' ' << "-std=c++11";
  40. break;
  41. case version::cxx14:
  42. buffer_ << ' ' << "-std=c++14";
  43. break;
  44. case version::cxx17:
  45. buffer_ << ' ' << "-std=c++17";
  46. break;
  47. case none:
  48. break;
  49. }
  50. return *this;
  51. }
  52. command_builder & command_builder::operator<<(source_file const & file) & {
  53. buffer_ << " -c " << file.get();
  54. return *this;
  55. }
  56. command_builder & command_builder::operator<<(output_file const & file) & {
  57. buffer_ << " -o " << file.get();
  58. return *this;
  59. }
  60. template <typename T>
  61. command_builder &
  62. command_builder::operator<<(std::vector<T> const & value) & {
  63. for (T const & v : value) {
  64. (*this) << v;
  65. }
  66. return *this;
  67. }
  68. std::ostream & operator<<(std::ostream & os, indent_t const & value) {
  69. for (int i = 0; i < value.value; ++i) {
  70. os << " ";
  71. }
  72. return os;
  73. }
  74. int command_builder::execute() const {
  75. std::string cmdstr = buffer_.str();
  76. std::cout << indent_ << cmdstr << std::endl;
  77. return std::system(cmdstr.c_str());
  78. }
  79. }