AutoBinder.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (c) 2008-2022 the Urho3D project
  2. // License: MIT
  3. #include <clang/ASTMatchers/ASTMatchFinder.h>
  4. #include <clang/Driver/Options.h>
  5. #include <clang/Tooling/CommonOptionsParser.h>
  6. #include <clang/Tooling/Tooling.h>
  7. #include <Mustache/mustache.hpp>
  8. #include <unordered_set>
  9. using namespace clang;
  10. using namespace clang::ast_matchers;
  11. using namespace clang::driver;
  12. using namespace clang::tooling;
  13. using namespace llvm;
  14. static cl::extrahelp commonHelp(CommonOptionsParser::HelpMessage);
  15. static cl::extrahelp moreHelp(
  16. "\tFor example, to run AutoBinder on all files in a subtree of the\n"
  17. "\tsource tree, use:\n"
  18. "\n"
  19. "\t find path/in/substree -name '*.cpp'|xargs AutoBinder -p build/path \\\n"
  20. "\t -t template/path -o output/path -s script0 -s script1\n"
  21. "\n"
  22. "\tNote, that path/in/subtree and current directory should follow the\n"
  23. "\trules described above.\n"
  24. "\n"
  25. "Most probably you want to invoke 'autobinder' built-in target instead of invoking this tool\n"
  26. "directly. The 'autobinder' target invokes this tool in a right context prepared by build system.\n"
  27. "\n"
  28. );
  29. static cl::OptionCategory autobinderCategory("AutoBinder options");
  30. static std::unique_ptr<opt::OptTable> options(createDriverOptTable());
  31. static cl::opt<std::string> templatePath("t", cl::desc("Template path"), cl::cat(autobinderCategory));
  32. static cl::opt<std::string> outputPath("o", cl::desc("Output path"), cl::cat(autobinderCategory));
  33. static cl::list<std::string> scripts("s", cl::desc("Script subsystems"), cl::cat(autobinderCategory));
  34. struct Data
  35. {
  36. std::unordered_set<std::string> symbols_;
  37. };
  38. static const std::string categories_[] = {"class", "enum"};
  39. static std::unordered_map<std::string, Data> categoryData_;
  40. class ExtractCallback : public MatchFinder::MatchCallback
  41. {
  42. public :
  43. virtual void run(const MatchFinder::MatchResult& result)
  44. {
  45. for (auto& i: categories_)
  46. {
  47. auto symbol = result.Nodes.getNodeAs<StringLiteral>(i);
  48. if (symbol)
  49. categoryData_[i].symbols_.insert(symbol->getString());
  50. }
  51. }
  52. virtual void onStartOfTranslationUnit()
  53. {
  54. static unsigned count = sizeof("Extracting") / sizeof(char) - 1;
  55. outs() << '.' << (++count % 100 ? "" : "\n"); // Sending a heart beat
  56. }
  57. };
  58. static int BindingGenerator()
  59. {
  60. // TODO: WIP
  61. return EXIT_SUCCESS;
  62. }
  63. int main(int argc, const char** argv)
  64. {
  65. // Parse the arguments and pass them to the the internal sub-tools
  66. CommonOptionsParser optionsParser(argc, argv, autobinderCategory);
  67. ClangTool bindingExtractor(optionsParser.getCompilations(), optionsParser.getSourcePathList());
  68. // Setup finder to match against AST nodes from Urho3D library source files
  69. ExtractCallback extractCallback;
  70. MatchFinder bindingFinder;
  71. // Find exported class declarations with Urho3D namespace
  72. bindingFinder.addMatcher(
  73. recordDecl(
  74. unless(hasAttr(attr::Annotate)),
  75. #ifndef _MSC_VER
  76. hasAttr(attr::Visibility),
  77. #else
  78. hasAttr(attr::DLLExport),
  79. #endif
  80. matchesName("^::Urho3D::")).bind("class"), &extractCallback);
  81. // Find enum declarations with Urho3D namespace
  82. bindingFinder.addMatcher(
  83. enumDecl(
  84. unless(hasAttr(attr::Annotate)),
  85. matchesName("^::Urho3D::")).bind("enum"), &extractCallback);
  86. // Unbuffered stdout stream to keep the Travis-CI's log flowing and thus prevent it from killing a potentially long running job
  87. outs().SetUnbuffered();
  88. // Success when both sub-tools are run successfully
  89. return (outs() << "Extracting", true) &&
  90. bindingExtractor.run(newFrontendActionFactory(&bindingFinder).get()) == EXIT_SUCCESS &&
  91. (outs() << "\nBinding", true) &&
  92. BindingGenerator() == EXIT_SUCCESS &&
  93. (outs() << "\n", true) ?
  94. EXIT_SUCCESS : EXIT_FAILURE;
  95. }