main.cpp
1 /*
2  name: tools/libmaker/main.cpp
3 
4  This file is part of ARCS - Augmented Reality Component System
5  (version 2-current), written by Jean-Yves Didier
6  for IBISC Laboratory (http://www.ibisc.univ-evry.fr)
7 
8  Copyright (C) 2013 Université d'Evry-Val d'Essonne
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 
23 
24  Please send bugreports with examples or suggestions to
25  jean-yves.didier__at__ibisc.univ-evry.fr
26 */
27 
28 
29 #include "arcslibmakerparser.h"
30 #include <QCoreApplication>
31 #include <QFileInfo>
32 #include <QDir>
33 #include <iostream>
34 #include <fstream>
35 
75 bool useWrapper = false;
76 
77 QString header_preamble = "#include<arcs/arcslibtoolkit.h>\n#include<QMetaType>\n";
78 QString header_line = "#include<@>\n" ;
79 
80 QString type_struct_line = "Q_DECLARE_METATYPE(@)\n";
81 
82 QString register_preamble =
83 "extern \"C\" DLL_EXPORT void arcsLibraryRegister(ARCSComponentMap* cmap," \
84 " ARCSFamilyMap* fmap, ARCSTypeMap* tmap)\n{\n";
85 QString unregister_preamble =
86 "extern \"C\" DLL_EXPORT void arcsLibraryUnregister(ARCSComponentMap* cmap," \
87 "ARCSFamilyMap* fmap, ARCSTypeMap* tmap)\n{\n";
88 
89 QString register_component_line = "\tcmap->insert(\"@\",new ARCSNativeComponentTemplate<@>());\n";
90 QString register_family_line = "\tfmap->insert(\"@\",new @());\n"; //ARCSFamilyFactoryTemplate<@>());\n";
91 QString register_variant_line ="\tqRegisterMetaType<@>(\"@\");\n" ;
92 QString register_type_line = "\tatf = new @();\n" \
93  "\ttmap->insert(atf->getTypeName(), atf);\n";
94 
95 QString register_type_linebis = "\ttmap->insert(\"@\", new ARCSTypeFactoryTemplate_@());\n" \
96 "\tqRegisterMetaType<@>(\"@\");\n";
97 //
98 
99 QString unregister_component_line = "\tdelete cmap->take(\"@\");\n";
100 QString unregister_family_line = "\tdelete fmap->take(\"@\");\n";
101 QString unregister_type_line = "\tdelete tmap->take(\"@\");\n" \
102 "\tQMetaType::unregisterType(\"@\");\n";
103 //
104 
105 QString qmake_append =
106 "\n\nALXFILE = @\nOTHER_FILES += @\narcslibrary.output = alm_${QMAKE_FILE_BASE}.cpp\n" \
107 "arcslibrary.input = ALXFILE\narcslibrary.commands = arcslibmaker ${QMAKE_FILE_NAME}\n" \
108 "arcslibrary.variable_out = SOURCES\n" \
109 "QMAKE_EXTRA_COMPILERS += arcslibrary\n";
110 
111 QString qmake_preamble =
112  "win32-msvc* {\n TEMPLATE = vclib\n } else {\nTEMPLATE = lib\n}\n" \
113  "INCLUDEPATH += $$(ARCSDIR)/include\n" \
114  "LIBS += -L$$(ARCSDIR)/lib -larcs\n"\
115  "CONFIG += dll\n"\
116  "QT = core\n\n" ;
117 
118 QString qmake_header = "HEADERS += @\n";
119 
120 QString qmake_source = "SOURCES += @\n";
121 
122 
123 //#include<QApplication>
124 
154 QString replace(QString src, QString insert)
155 {
156  QString res = src;
157  return src.replace("@", insert).replace("*(", "Star("); //.replace("::","DotDot");
158 }
159 
160 
161 
162 
163 QString cppFileBase(char* fn)
164 {
165  QFileInfo fi(fn);
166 
167  return fi.canonicalPath() +QDir::separator() + "alm_" + fi.baseName() + ".cpp";
168 }
169 
170 
171 void writeHeaders(std::ofstream & file, QStringList hl)
172 {
173  //file << qPrintable(header_preamble);
174 
175  for( int i=0; i < hl.count() ; i++)
176  file << qPrintable(replace(header_line, hl[i]));
177  file << std::endl;
178 }
179 
180 
181 void writeTypeList(std::ofstream &file, QStringList tl)
182 {
183  for (int i=0; i < tl.count() ; i++)
184  file << qPrintable(replace(type_struct_line,tl[i]));
185  file << std::endl;
186 }
187 
188 
189 
190 void writeRegisterWrapper(std::ofstream &file, QStringList cl, QStringList fl, QList<ARCSTypeWrapper> tl)
191 {
192  int i;
193  file << "extern \"C\" DLL_EXPORT void arcsLibraryRegister(ARCSComponentMap* " ;
194  if (cl.count())
195  file << "cmap";
196  file << ", ARCSFamilyMap* ";
197  if (fl.count())
198  file << "fmap";
199  file << ", ARCSTypeMap* ";
200  if (tl.count())
201  file << "tmap";
202  file << ")\n{\n";
203 
204 
205  //qPrintable(register_preamble) ;
206 
207  for (i=0; i < cl.count() ; i++)
208  file << qPrintable(replace(register_component_line,cl[i])) ;
209  file << std::endl;
210 
211 
212  for (i=0; i < fl.count() ; i++)
213  file << qPrintable(replace(register_family_line,fl[i]));
214  file << std::endl;
215 
216  for (i=0; i < tl.count() ; i++)
217  {
218  ARCSTypeWrapper atw = tl[i];
219  if (atw.getWrapper().isEmpty())
220  file << qPrintable(replace(register_type_linebis,atw.getName()));
221  else
222  {
223  if (!useWrapper)
224  file << "\tARCSTypeFactory* atf;" ;
225  useWrapper = true;
226  file << qPrintable(replace(register_type_line, atw.getWrapper()))
227  << qPrintable(replace(register_variant_line, atw.getName()));
228  }
229  }
230 
231  file << "}" << std::endl << std::endl;
232 }
233 
234 
235 void writeUnRegisterWrapper(std::ofstream &file,QStringList cl, QStringList fl, QList<ARCSTypeWrapper> tl)
236 {
237  int i;
238  file << "extern \"C\" DLL_EXPORT void arcsLibraryUnregister(ARCSComponentMap* " ;
239  if (cl.count())
240  file << "cmap";
241  file << ", ARCSFamilyMap* ";
242  if (fl.count())
243  file << "fmap";
244  file << ", ARCSTypeMap* ";
245  if (tl.count())
246  file << "tmap";
247  file << ")\n{\n";
248 
249 // file << qPrintable(unregister_preamble) ;
250 
251 
252  for (i=0; i < cl.count() ; i++)
253  file << qPrintable(replace(unregister_component_line,cl[i])) ;
254  file << std::endl;
255 
256 
257  for (i=0; i < fl.count() ; i++)
258  file << qPrintable(replace(unregister_family_line,fl[i]));
259  file << std::endl;
260 
261  for (i=0; i < tl.count() ; i++)
262  {
263  ARCSTypeWrapper atw= tl[i];
264  //if (atw.getWrapper().isEmpty())
265  //{
266  file << qPrintable(replace(unregister_type_line,atw.getName()));
267  }
268 
269  file << "}" << std::endl << std::endl;
270 }
271 
272 
273 void appendProjectFile(std::ofstream & of)
274 {
275  QStringList alxFilter;
276  alxFilter << "*.alx";
277 
278  QDir dir = QDir::current() ; // le rep courant
279  dir.refresh();
280  QStringList alxFiles = dir.entryList(alxFilter, QDir::Files | QDir::Readable | QDir::Writable );
281 
282  if (alxFiles.count() <= 0 )
283  return ;
284 
285  of << qPrintable(replace(qmake_append, alxFiles[0])) << std::endl;
286 
287 }
288 
289 
290 
291 void projectMode()
292 {
293  int i;
294  QStringList proFilter;
295  proFilter << "*.pro";
296 
297  QDir dir = QDir::current() ; // le rep courant
298  QStringList proFiles = dir.entryList(proFilter, QDir::Files | QDir::Readable | QDir::Writable );
299 
300  std::ofstream of;
301 
302  if (proFiles.count() > 0)
303  {
304  of.open(qPrintable(proFiles[0]),std::ios_base::app);
305  if (!of.is_open())
306  return ;
307  }
308  else
309  {
310  // 1 : récupérer le nom de projet
311  QString proName = QDir::current().dirName() + ".pro" ;
312  of.open(qPrintable(proName));
313  if (!of.is_open())
314  return ;
315 
316  // 2 : créer le fichier
317  QString path = QDir(QCoreApplication::applicationDirPath() + QDir::separator() + "..").canonicalPath() ;
318  of << qPrintable(replace(qmake_preamble, path));
319 
320 
321  // 3 : ajouter les infos sur les .h et les .cpp
322  QStringList headerFilter;
323  headerFilter << "*.h";
324  QStringList headerFiles = dir.entryList(headerFilter, QDir::Files);
325  for (i = 0; i < headerFiles.count() ; i++)
326  of << qPrintable(replace(qmake_header, headerFiles[i]));
327 
328  QStringList sourceFilter;
329  sourceFilter << "*.cpp" << "*.c";
330  QStringList sourceFiles = dir.entryList(sourceFilter, QDir::Files);
331  for (i = 0; i < sourceFiles.count() ; i++)
332  of << qPrintable(replace(qmake_source, sourceFiles[i]));
333 
334  }
335 
336  // tester ici si un fichier alx existe, sinon le créer avec un squelette.
337  QStringList alxFilter(QString("*.alx"));
338  QStringList alxFiles = dir.entryList(alxFilter, QDir::Files | QDir::Readable | QDir::Writable );
339  if( alxFiles.count() <= 0)
340  {
341  QString alxTarget = "lib"+QDir::current().dirName() + ".alx" ;
342  if (QFile::copy(":/alx_skeleton.xml",alxTarget))
343  QFile::setPermissions(alxTarget,QFile::permissions(alxTarget) | QFile::WriteOwner | QFile::WriteUser);
344  }
345 
346 
347  appendProjectFile(of);
348  of.close();
349 }
350 
351 
352 void usage(char* prg)
353 {
354  std::cout << prg << " [--help] [file]" << std::endl;
355 
356  std::cout << prg << " has two modes, one for generating ARCS library wrappers,"
357  << std::endl << " the second for adding ARCS options to Qt project files."
358  << std::endl << std::endl
359  << "The first mode needs an xml file describing the library contents."
360  << std::endl;
361 }
362 
363 int main(int argc, char* argv[])
364 {
365  QCoreApplication app(argc, argv);
366 
367  if (argc > 1)
368  {
369  if (QString(argv[1]) == "--help")
370  {
371  usage(argv[0]);
372  return 0;
373  }
374  else
375  {
376  ARCSLibMakerParser almp ;
377  almp.setFileName(argv[1]);
378  if (almp.parseFile())
379  {
380  //std::cout << qPrintable(cppFileBase(argv[1])) << std::endl;
381  std::ofstream of( qPrintable(cppFileBase(argv[1])) );
382  if (! of.is_open())
383  return 2;
384  of << qPrintable( header_preamble ) ;
385  //writeTypeList(of, almp.getTypes());
386  writeHeaders(of, almp.getHeaders());
387  //writeTypeList(of, almp.getTypes());
388  writeRegisterWrapper(of, almp.getComponents(), almp.getFamilies(), almp.getTypes());
389  writeUnRegisterWrapper(of, almp.getComponents(), almp.getFamilies(), almp.getTypes());
390  of.close();
391  }
392  else
393  return 1;
394  }
395  }
396  else
397  {
398  projectMode();
399  }
400 
401  return 0;
402 }