Heavy ion Analysis Libriares
Loading...
Searching...
No Matches
hal_cmake.cpp
1/*
2 * hal_cmake.cpp
3 *
4 * Created on: 13 wrz 2022
5 * Author: Daniel Wielanek
6 * E-mail: daniel.wielanek@gmail.com
7 * Warsaw University of Technology, Faculty of Physics
8 */
9
10#include "Std.h"
11#include "StdString.h"
12#include <TRegexp.h>
13#include <TSystem.h>
14#include <fstream>
15#include <iostream>
16
35void PrepareLib(TString name);
36
37void SetNames(TString& plusPath,
38 TString& pattern,
39 TString& toCopy,
40 TString& headerGuard,
41 TString& newGuard,
42 TString& name,
43 TString inputName);
44
45void PrepareMonitor(TString name, TString type1, TString type2);
46
47void UpdateLib();
48
49void MakeLinkDef(TString name, std::vector<TString> sources);
50
51std::vector<TString> ParseHeader(TString sourceName);
52
53void PrepareCutClass(TString type, TString name);
54
55int main(int argc, char* argv[]) {
56 if (argc < 2) {
57 std::cout << "not enough params, type --help" << std::endl;
58 return 0;
59 }
60 auto args = Hal::Std::ConvertMainArgs(argc, argv);
61 if (args[0].first == "help") { // print help
62 std::cout << "options" << std::endl;
63 std::cout << "--dir=[LIBRARYNAME] prepare cmake template for this directory" << std::endl;
64 std::cout << "--updatedir update cmake SRC list and linkdef" << std::endl;
65 std::cout << "--template=[TYPE] --name=[NAME] prepares template for class" << std::endl;
66 std::cout << "\t TYPE = event-cut, track-cut, twotrack-cut for cuts" << std::endl;
67 std::cout << "\t TYPE = event-monx, event-mony, event-monz, for x, xy, xyz, property monitors for events" << std::endl;
68 std::cout << "\t TYPE = track-monx, track-mony, track-monz, for x, xy, xyz, property monitors for tracks" << std::endl;
69 std::cout << "\t TYPE = twotrack-monx, twotrack-mony, twotrack-monz, for x, xy, xyz, property monitors for pairs"
70 << std::endl;
71 std::cout << "\tName = name of class e.g. hal_cmake --type=event-cut --name=Multiplicity " << std::endl;
72 }
73 if (args[0].first == "dir") {
74 PrepareLib(args[0].second);
75 return 1;
76 }
77 if (args[0].first == "updatedir") {
78 UpdateLib();
79 return 1;
80 }
81 if (args[0].first == "template") {
82 auto vec = Hal::Std::ExplodeString(args[0].second, '-');
83 if (vec.size() <= 1) return 0;
84 if (vec[1].EqualTo("cut")) { PrepareCutClass(args[0].second, args[1].second); }
85 if (vec[1].EqualTo("monx")) { PrepareMonitor(args[1].second, vec[0], "x"); }
86 if (vec[1].EqualTo("mony")) { PrepareMonitor(args[1].second, vec[0], "y"); }
87 if (vec[1].EqualTo("monz")) { PrepareMonitor(args[1].second, vec[0], "z"); }
88 }
89
90
91 return 1;
92}
93
94void PrepareLib(TString name) {
95 TString plusPath = Hal::Std::GetHalrootPlus();
96 TString toCopy = plusPath + "templates/CMakeLists.txt";
97 TString tempFile[2] = {"temp.txt", "temp2.txt"};
98 gSystem->CopyFile(toCopy, tempFile[0], kTRUE);
99
100 Hal::Std::ReplaceInFile(tempFile[0], tempFile[1], "__HAL_NAME_OF_LINKDEF__", Form("%sLinkDef.h", name.Data()));
101 Hal::Std::ReplaceInFile(tempFile[1], tempFile[0], "__HAL_NAME_OF_LIBRARY__", name);
102 auto list = Hal::Std::GetListOfFiles("", "cxx", kFALSE, 3);
103 auto list2 = Hal::Std::GetListOfFiles("", "cpp", kFALSE, 3);
104
105 for (auto i : list2)
106 list.push_back(i);
107
108 TString sources = "";
109 for (auto i : list) {
110 sources = sources + " " + i + "\n";
111 }
112
113 Hal::Std::ReplaceInFile(tempFile[0], tempFile[1], "__HAL_NAME_OF_CXX_FILES__", sources);
114 gSystem->CopyFile(tempFile[1], "CMakeLists.txt", kTRUE);
115 gSystem->Exec("rm temp.txt temp2.txt");
116 MakeLinkDef(Form("%sLinkDef.h", name.Data()), list);
117}
118
119void UpdateLib() {
120 std::ifstream cmake;
121 cmake.open("CMakeLists.txt");
122 if (!cmake.good()) { // file cannot be parsed
123 cmake.close();
124 std::cout << "Cannto find CMakeLists.txt here" << std::endl;
125 return;
126 }
127 TString temp;
128 std::ofstream other;
129 other.open("CMakeLists.temp");
130 Bool_t listOpen = kFALSE;
131 auto cppFiles = Hal::Std::GetListOfFiles("", "cxx", kFALSE, 3);
132 auto list2 = Hal::Std::GetListOfFiles("", "cpp", kFALSE, 3);
133
134 for (auto i : list2)
135 cppFiles.push_back(i);
136 while (!temp.ReadLine(cmake, kFALSE).eof()) {
137 if (temp.Contains("SRCS")) {
138 other << temp << std::endl;
139 listOpen = kTRUE;
140 for (auto file : cppFiles) {
141 other << file << std::endl;
142 }
143 }
144 if (listOpen && temp.Contains(")")) listOpen = kFALSE;
145 if (!listOpen) other << temp << std::endl;
146 }
147 gSystem->Exec("mv CMakeLists.temp CMakeLists.txt");
148 auto headers = Hal::Std::GetListOfFiles("", "h", kFALSE, 1);
149 TString linkdef;
150 for (auto header : headers) {
151 if (header.EndsWith("LinkDef.h")) {
152 linkdef = header;
153 break;
154 }
155 }
156 if (linkdef.Length() == 0) {
157 std::cout << "Cannot find linkdef !" << std::endl;
158 return;
159 }
160 MakeLinkDef(linkdef, cppFiles);
161}
162
163void SetNames(TString& plusPath,
164 TString& pattern,
165 TString& toCopy,
166 TString& headerGuard,
167 TString& newGuard,
168 TString& name,
169 TString inputName) {
170 pattern = inputName;
171 toCopy = plusPath + "templates/" + inputName;
172 headerGuard = "TEMPLATES_" + inputName;
173 headerGuard.ToUpper();
174 newGuard = name;
175 newGuard.ToUpper();
176}
177
178void PrepareCutClass(TString type, TString name) {
179 TString plusPath = Hal::Std::GetHalrootPlus();
180 TString toCopy;
181 TString pattern;
182 TString headerGuard;
183 TString newGuard;
184
185
186 if (type.EqualTo("event-cut", TString::ECaseCompare::kIgnoreCase)) {
187 SetNames(plusPath, pattern, toCopy, headerGuard, newGuard, name, "EventCutTemplate");
188 }
189 if (type.EqualTo("track-cut", TString::ECaseCompare::kIgnoreCase)) {
190 SetNames(plusPath, pattern, toCopy, headerGuard, newGuard, name, "TrackCutTemplate");
191 }
192 if (type.EqualTo("twotrack-cut", TString::ECaseCompare::kIgnoreCase)) {
193 SetNames(plusPath, pattern, toCopy, headerGuard, newGuard, name, "TwoTrackCutTemplate");
194 }
195 if (toCopy.Length() == 0) {
196 std::cout << "Wrong flag in template type" << std::endl;
197 return;
198 }
199 TString tempFile[2] = {"temp.txt", "temp2.txt"};
200 gSystem->CopyFile(Form("%s.cxx", toCopy.Data()), tempFile[0]);
201 Hal::Std::ReplaceInFile(tempFile[0], Form("%s.cxx", name.Data()), pattern, name);
202 gSystem->CopyFile(Form("%s.h", toCopy.Data()), tempFile[0], kTRUE);
203 Hal::Std::ReplaceInFile(tempFile[0], tempFile[1], pattern, name); // replace classname
204 Hal::Std::ReplaceInFile(tempFile[1], Form("%s.h", name.Data()), headerGuard, newGuard);
205 gSystem->Exec("rm temp.txt temp2.txt");
206}
207
208std::vector<TString> ParseHeader(TString sourceName) {
209 TString header = sourceName.ReplaceAll(".cpp", ".h");
210 header = sourceName.ReplaceAll(".cxx", ".h");
211 std::ifstream file;
212 file.open(header);
213 std::vector<TString> res;
214 if (!file.good()) { // file cannot be parsed
215 file.close();
216 return res;
217 }
218 TString temp;
219 auto replaceEverything = [](TString& str, std::initializer_list<TString> list) {
220 for (auto i : list) {
221 str = str.ReplaceAll(i, "");
222 }
223 };
224
225 std::vector<std::pair<TString, int>> namespaceArray;
226 Int_t bracket = 0;
227 while (!temp.ReadLine(file).eof()) {
228 TString line = temp;
229 Int_t bra = line.CountChar('{');
230 Int_t ket = line.CountChar('}');
231 Int_t dBracket = bra - ket;
232 TString curNamespace;
233 if (line.Contains("namespace") && !line.Contains("using")) {
237 Int_t npos = line.First('n');
238 Int_t nLast = -1;
239 if (line.Contains("/*") || line.Contains("*/") || line.Contains("//")) { nLast = line.First('/'); }
240 if (nLast != -1) {
241 if (npos > nLast) {
242 bracket += dBracket;
243 continue; // namespace after comment
244 }
245 }
246 curNamespace = line;
247 replaceEverything(curNamespace, {"namespace", "}", " ", "\t", "{"});
248 if (curNamespace.Length()) {
249 std::pair<TString, int> name(curNamespace, bracket + dBracket);
250 Bool_t replaced = kFALSE;
251 for (auto& i : namespaceArray) {
252 if (i.second == name.second) {
253 i = name; // replace existing namespace
254 replaced = kTRUE;
255 break;
256 }
257 }
258 if (!replaced) { namespaceArray.push_back(name); }
259 }
260 }
261 bracket += dBracket;
262
263 if (line.Contains("ClassDef")) { // we have a classdef
264 replaceEverything(line, {"ClassDef(", ")", ";", " "});
265 line = line(0, line.Last(','));
266 TString myNamespace = "";
267 Int_t realBracket = bracket - 1; // usually we are at class brackets
268 for (auto i : namespaceArray) {
269 if (realBracket >= i.second) { myNamespace = myNamespace + "::" + i.first; }
270 }
271 if (myNamespace.BeginsWith("::")) { myNamespace = Hal::Std::RemoveNChars(myNamespace, 2, 'b'); }
272 if (myNamespace.Length() > 0 && !myNamespace.EndsWith("::")) { myNamespace = myNamespace + "::"; }
273 res.push_back(myNamespace + line);
274 };
275 }
276 return res;
277}
278
279void MakeLinkDef(TString name, std::vector<TString> sources) {
280 std::ofstream linkdef;
281 linkdef.open(name);
282 linkdef << "#ifdef __CINT__" << std::endl;
283 linkdef << "" << std::endl;
284 linkdef << "#pragma link off all globals;" << std::endl;
285 linkdef << "#pragma link off all classes;" << std::endl;
286 linkdef << "#pragma link off all functions;" << std::endl;
287 linkdef << "" << std::endl;
288 for (auto cppFIle : sources) {
289 auto cppClasses = ParseHeader(cppFIle);
290 for (auto singleClass : cppClasses) {
291 linkdef << "#pragma link C++ class ";
292 linkdef << singleClass << "+;" << std::endl; // remove 4 last characters
293 }
294 }
295 linkdef << "" << std::endl;
296 linkdef << "#endif" << std::endl;
297 linkdef.close();
298}
299
300void PrepareMonitor(TString name, TString type1, TString type2) {
301 TString baseClassName;
302 if (type2 == "x") {
303 baseClassName = "PropertyMonitorTemplateX";
304 } else if (type2 == "y") {
305 baseClassName = "PropertyMonitorTemplateXY";
306 } else if (type2 == "z") {
307 baseClassName = "PropertyMonitorTemplateXYZ";
308 } else {
309 return;
310 }
311 TString cutUpdate;
312 TString updateMethod;
313 if (type1 == "event") {
314 cutUpdate = "Hal::ECutUpdate::kEvent";
315 updateMethod = " Hal::Event *event = (Hal::Event*)obj;";
316 } else if (type1 == "track") {
317 cutUpdate = "Hal::ECutUpdate::kTrack";
318 updateMethod = " Hal::Track *track = (Hal::Track*)obj; ";
319 } else if (type1 == "twotrack") {
320 cutUpdate = "Hal::ECutUpdate::kTwoTrack";
321 updateMethod = " Hal::TwoTrack *pair = (Hal::TwoTrack*)obj; ";
322 } else {
323 return;
324 }
325 TString plusPath = Hal::Std::GetHalrootPlus();
326 TString toCopy;
327 TString pattern;
328 TString headerGuard;
329 TString newGuard;
330 SetNames(plusPath, pattern, toCopy, headerGuard, newGuard, name, baseClassName);
331 gSystem->CopyFile(Form("%s.cxx", toCopy.Data()), Form("%s.cxx", name.Data()));
332 gSystem->CopyFile(Form("%s.h", toCopy.Data()), Form("%s.h", name.Data()));
333 Hal::Std::ReplaceInFile(Form("%s.h", name.Data()), Form("%s.h", name.Data()), {headerGuard, baseClassName}, {newGuard, name});
334 // header
335 Hal::Std::ReplaceInFile(Form("%s.cxx", name.Data()),
336 Form("%s.cxx", name.Data()),
337 {TString("__UPDATE_METHOD__"), TString("__UPDATE__"), baseClassName},
338 {updateMethod, cutUpdate, name});
339 // header
340}