MinitScript  0.9.31 PRE-BETA
Generator.cpp
Go to the documentation of this file.
2 
3 #include <array>
4 #include <string>
5 #include <utility>
6 #include <vector>
7 
13 
15 
20 
21 using std::array;
22 using std::pair;
23 using std::string;
24 using std::vector;
25 
26 void Generator::generateMain(
27  const string& scriptURI,
28  const string& className,
29  const string& mainURI,
30  bool useLibrary,
31  bool nativeOnly
32 ) {
33  string library;
34  if (useLibrary == true) {
35  library =
36  string() +
37  "auto library = make_unique<NativeLibrary>(context.get());" + "\n" +
38  "\t" + "script->setLibrary(library.get());";
39  }
40  //
41  try {
42  Console::printLine("Generating main C++ file: " + mainURI);
43 
44  auto mainSource = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/transpilation", "script-main.cpp");
45  mainSource = StringTools::replace(mainSource, "{$script}", scriptURI);
46  mainSource = StringTools::replace(mainSource, "{$script-class}", className);
47  mainSource = StringTools::replace(mainSource, "{$library}", library);
48  mainSource = StringTools::replace(mainSource, "{$native-only}", nativeOnly == true?"true":"false");
49  FileSystem::setContentFromString(FileSystem::getPathName(mainURI), FileSystem::getFileName(mainURI), mainSource);
50  } catch (Exception& exception) {
51  Console::printLine("An error occurred: " + string(exception.what()));
52  }
53 }
54 
55 void Generator::generateLibrary(
56  const vector<pair<string, string>>& scriptClassPairs,
57  const string& libraryURI,
58  bool nativeOnly
59 ) {
60  string libraryCode;
61  libraryCode+= string() + "auto scriptURI = pathName + \"/\" + fileName;" + "\n";
62  string libraryIncludes;
63  for (const auto& scriptClassPair: scriptClassPairs) {
64  const auto& scriptURI = scriptClassPair.first;
65  const auto& className = scriptClassPair.second;
66  libraryIncludes+= string() + "#include \"" + className + ".h\"" + "\n";
67  libraryCode+= string() + "\t" + "if (scriptURI == \"" + scriptURI + "\") {" + "\n";
68  libraryCode+= string() + "\t\t" + "script = make_unique<" + className + ">();" + "\n";
69  libraryCode+= string() + "\t" + "} else" + "\n";
70  }
71 
72  //
73  try {
74  Console::printLine("Generating library C++ file");
75  auto mainSource = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/transpilation", "NativeLibrary.cpp");
76  mainSource = StringTools::replace(mainSource, "{$library-includes}", libraryIncludes);
77  mainSource = StringTools::replace(mainSource, "{$library-code}", libraryCode);
78  mainSource = StringTools::replace(mainSource, "{$native-only}", nativeOnly == true?"true":"false");
79  FileSystem::setContentFromString(FileSystem::getPathName(libraryURI), FileSystem::getFileName(libraryURI), mainSource);
80  } catch (Exception& exception) {
81  Console::printLine("An error occurred: " + string(exception.what()));
82  }
83 }
84 
85 void Generator::generateMakefile(const string& srcPath, const string& makefileURI, bool library, const string& basePath, const vector<string>& excludePaths) {
86  //
87  try {
88  Console::printLine("Scanning source files");
89  vector<string> sourceFiles;
90  vector<string> mainSourceFiles;
91  scanPath((basePath.empty() == true?"":basePath + "/") + srcPath, sourceFiles, mainSourceFiles);
92 
93  // cut off base path
94  if (basePath.empty() == false) {
95  for (auto& sourceFile: sourceFiles) sourceFile = StringTools::substring(sourceFile, basePath.size() + 1);
96  for (auto& mainSourceFile: mainSourceFiles) mainSourceFile = StringTools::substring(mainSourceFile, basePath.size() + 1);
97  }
98 
99  // exclude paths
100  if (excludePaths.empty() == false) {
101  array<vector<string>*, 2> sourceFileSets = { &sourceFiles, &mainSourceFiles };
102  for (auto i = 0; i < sourceFileSets.size(); i++) {
103  for (auto j = 0; j < sourceFileSets[i]->size(); j++) {
104  for (const auto& excludePath: excludePaths) {
105  if (StringTools::startsWith((*sourceFileSets[i])[j], srcPath + "/" + excludePath + "/") == true) {
106  sourceFileSets[i]->erase(sourceFileSets[i]->begin() + j);
107  j--;
108  break;
109  }
110  }
111  }
112  }
113  }
114 
115  //
116  string sourceFilesVariable = "\\\n";
117  for (const auto& file: sourceFiles) sourceFilesVariable+= "\t" + file + " \\\n";
118  sourceFilesVariable+= "\n";
119 
120  //
121  string mainSourceFilesVariable = "\\\n";
122  for (const auto& file: mainSourceFiles) mainSourceFilesVariable+= "\t" + file + " \\\n";
123  mainSourceFilesVariable+= "\n";
124 
125  //
126  Console::printLine("Generating Makefile");
127 
128  //
129  auto makefileSource = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/makefiles", library == true?"Library-Makefile":"Makefile");
130  makefileSource = StringTools::replace(makefileSource, "{$MINITSCRIPT_DATA}", MINITSCRIPT_DATA);
131  makefileSource = StringTools::replace(makefileSource, "{$source-path}", srcPath);
132  makefileSource = StringTools::replace(makefileSource, "{$source-files}", sourceFilesVariable);
133  if (library == false) makefileSource = StringTools::replace(makefileSource, "{$main-source-files}", mainSourceFilesVariable);
134  FileSystem::setContentFromString(FileSystem::getPathName(makefileURI), FileSystem::getFileName(makefileURI), makefileSource);
135  } catch (Exception& exception) {
136  Console::printLine("An error occurred: " + string(exception.what()));
137  }
138 }
139 
140 void Generator::generateNMakefile(const string& srcPath, const string& makefileURI, bool library, const string& basePath, const vector<string>& excludePaths) {
141  //
142  try {
143  Console::printLine("Scanning source files");
144  vector<string> sourceFiles;
145  vector<string> mainSourceFiles;
146  scanPath((basePath.empty() == true?"":basePath + "/") + srcPath, sourceFiles, mainSourceFiles);
147 
148  // cut off base path
149  if (basePath.empty() == false) {
150  for (auto& sourceFile: sourceFiles) sourceFile = StringTools::substring(sourceFile, basePath.size() + 1);
151  for (auto& mainSourceFile: mainSourceFiles) mainSourceFile = StringTools::substring(mainSourceFile, basePath.size() + 1);
152  }
153 
154  // exclude paths
155  if (excludePaths.empty() == false) {
156  array<vector<string>*, 2> sourceFileSets = { &sourceFiles, &mainSourceFiles };
157  for (auto i = 0; i < sourceFileSets.size(); i++) {
158  for (auto j = 0; j < sourceFileSets[i]->size(); j++) {
159  for (const auto& excludePath: excludePaths) {
160  if (StringTools::startsWith((*sourceFileSets[i])[j], srcPath + "/" + excludePath + "/") == true) {
161  sourceFileSets[i]->erase(sourceFileSets[i]->begin() + j);
162  j--;
163  break;
164  }
165  }
166  }
167  }
168  }
169 
170  //
171  string sourceFilesVariable = "\\\n";
172  for (const auto& file: sourceFiles) sourceFilesVariable+= "\t" + file + " \\\n";
173  sourceFilesVariable+= "\n";
174 
175  //
176  string makefileSource;
177 
178  //
179  if (library == true) {
180  Console::printLine("Generating Makefile");
181  //
182  makefileSource = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/makefiles", "Library-Makefile.nmake");
183  auto makefileMainSourceTemplate = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/makefiles", "Makefile.nmake.main");
184  makefileSource = StringTools::replace(makefileSource, "{$MINITSCRIPT_DATA}", MINITSCRIPT_DATA);
185  makefileSource = StringTools::replace(makefileSource, "{$source-files}", sourceFilesVariable);
186  makefileSource+= "\n";
187  } else {
188  //
189  string mainTargets;
190  for (const auto& file: mainSourceFiles) {
191  if (mainTargets.empty() == false) mainTargets+= " ";
192  mainTargets+= StringTools::substring(file, file.rfind('/') + 1, file.find("-main.cpp"));
193  }
194  //
195  Console::printLine("Generating Makefile");
196  //
197  makefileSource = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/makefiles", "Makefile.nmake");
198  auto makefileMainSourceTemplate = FileSystem::getContentAsString(MINITSCRIPT_DATA + "/resources/minitscript/templates/makefiles", "Makefile.nmake.main");
199  makefileSource = StringTools::replace(makefileSource, "{$MINITSCRIPT_DATA}", MINITSCRIPT_DATA);
200  makefileSource = StringTools::replace(makefileSource, "{$source-files}", sourceFilesVariable);
201  makefileSource = StringTools::replace(makefileSource, "{$main-targets}", mainTargets);
202  makefileSource+= "\n";
203 
204  //
205  for (const auto& file: mainSourceFiles) {
206  auto makefileMainSource = makefileMainSourceTemplate;
207  auto mainTarget = StringTools::substring(file, file.rfind('/') + 1, file.find("-main.cpp"));
208  auto mainTargetSource = file;
209  auto mainTargetExecutable = mainTarget + ".exe";
210  makefileMainSource = StringTools::replace(makefileMainSource, "{$main-target}", mainTarget);
211  makefileMainSource = StringTools::replace(makefileMainSource, "{$main-target-source}", mainTargetSource);
212  makefileMainSource = StringTools::replace(makefileMainSource, "{$main-target-executable}", mainTargetExecutable);
213  makefileSource+= makefileMainSource + "\n";
214  }
215  }
216  //
217  FileSystem::setContentFromString(FileSystem::getPathName(makefileURI), FileSystem::getFileName(makefileURI), makefileSource);
218  } catch (Exception& exception) {
219  Console::printLine("An error occurred: " + string(exception.what()));
220  }
221 }
222 
223 void Generator::scanPath(const string& path, vector<string>& sourceFiles, vector<string>& mainSourceFiles) {
224  class SourceFilesFilter : public virtual FileSystem::FileNameFilter {
225  public:
226  virtual ~SourceFilesFilter() {}
227 
228  bool accept(const string& pathName, const string& fileName) override {
229  if (fileName == ".") return false;
230  if (fileName == "..") return false;
231  if (FileSystem::isPath(pathName + "/" + fileName) == true) return true;
232  // skip on CPP files that gets #include ed
233  if (StringTools::endsWith(StringTools::toLowerCase(fileName), ".incl.cpp") == true) return false;
234  if (StringTools::endsWith(StringTools::toLowerCase(fileName), ".include.cpp") == true) return false;
235  // CPP hit, yes
236  if (StringTools::endsWith(StringTools::toLowerCase(fileName), ".cpp") == true) return true;
237  return false;
238  }
239  };
240  //
241  SourceFilesFilter sourceFilesFilter;
242  vector<string> files;
243  //
244  FileSystem::list(path, files, &sourceFilesFilter);
245  //
246  for (const auto& fileName: files) {
247  if (StringTools::endsWith(fileName, "-main.cpp") == true) {
248  mainSourceFiles.push_back(path + "/" + fileName);
249  } else
250  if (StringTools::endsWith(fileName, ".cpp") == true) {
251  sourceFiles.push_back(path + "/" + fileName);
252  } else {
253  scanPath(path + "/" + fileName, sourceFiles, mainSourceFiles);
254  }
255  }
256 }
MinitScript generator.
Definition: Generator.h:18
#define MINITSCRIPT_DATA
Definition: minitscript.h:22
std::exception Exception
Exception base class.
Definition: Exception.h:18