2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ */
34 #include "boost/filesystem.hpp"
35 #include "bbtkBBPInterpreter.h"
37 namespace bf = boost::filesystem;
39 typedef std::vector<std::vector<int> > Graph;
41 typedef std::set<std::string> Dependencies;
42 typedef std::vector<Dependencies> DependenciesVector;
43 typedef std::vector<std::string> BoxesVector;
45 std::vector<bf::path> getFileList(const std::string& path);
47 bool isCycle(const Graph& g);
48 bool checkCycle(const Graph& g, const int& i, std::vector<bool>& v);
50 void setPriorities(const Graph& g, std::vector<int>& p);
51 void setPriority(const Graph& g, const int i, std::vector<int>& p);
53 int main(int argc, char **argv)
58 std::cout << "bbpConfigurator usage: bbConfigurator <path_to_bbs> <package_name> <output_path>" << std::endl;
62 std::string path_bbs(argv[1]);
63 std::string package_name(argv[2]);
64 std::string path_out(argv[3]);
66 std::cout << "bbpConfigurator launched with bbs path: '" << path_bbs <<
67 "', package: '" << package_name <<
68 "', output path: '" << path_out << "'." << std::endl;
70 // Get bbs files in path_bbs
71 std::vector<bf::path> files = getFileList(path_bbs);
74 std::cout << "bbpConfigurator: No files to check in bbs path. "
75 "An empty bbp will be created for the package '" << package_name << "'." << std::endl;
77 // Write results to bbp file
79 std::string fname = path_out + "\\" + package_name + ".bbp";
81 std::string fname = path_out + "/" + package_name + ".bbp";
84 std::ofstream out(fname.c_str());
85 out << "#-----------------------------------------" << std::endl;
86 out << "# Include script for bbtk package '" << package_name << "'" << std::endl;
87 out << "# Automatically generated by bbpConfigurator" << std::endl;
88 out << "#-----------------------------------------" << std::endl;
89 out << "load "<< package_name << std::endl;
90 out << "#-----------------------------------------" << std::endl;
91 out << "package "<< package_name << std::endl;
92 out << "#-----------------------------------------" << std::endl;
93 out << "endpackage" << std::endl;
94 out << "#-- EOF ----------------------------------" << std::endl;
103 // Order files by dependencies
104 // Get DependenciesVector and Box Names
105 DependenciesVector deps;
109 for (int i = 0; i < (int)files.size(); ++i)
111 bbtk::BBPInterpreter::Pointer I = bbtk::BBPInterpreter::New();
112 I->InterpretFile(files[i].string());
115 boxs.push_back( ((bbtk::BBPInterpreter*)(I.get()))->boxName );
118 // deps.push_back( ((bbtk::BBPInterpreter*)(I.get()))->dependencies );
119 //--> Cleanning string package:boxname -> boxname
120 std::set<std::string> tmpDependencies1= ((bbtk::BBPInterpreter*)(I.get()))->dependencies ;
121 std::set<std::string> tmpDependencies2;
122 std::set<std::string>::const_iterator sit(tmpDependencies1.begin()), send(tmpDependencies1.end());
125 // std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": ";
126 for(;sit!=send;++sit)
128 pos=(*sit).find(":");
129 if (pos== std::string::npos )
131 tmpDependencies2.insert( *sit );
132 // std::cout << *sit << ' ';
134 tmpStr=(*sit).substr(pos+1);
135 tmpDependencies2.insert( tmpStr );
136 // std::cout << tmpStr << ' ';
140 // std::cout << std::endl;
141 deps.push_back( tmpDependencies2 );
146 // //print box name and dependencies OLD VERSION
147 // std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": ";
149 // Dependencies::iterator it = ((bbtk::BBPInterpreter*)(I.get()))->dependencies.begin();
150 // it != ((bbtk::BBPInterpreter*)(I.get()))->dependencies.end();
152 // std::cout << *it << ", ";
154 // std::cout << std::endl;
158 // Only keep dependencies from package
159 Dependencies boxNamesSet(boxs.begin(), boxs.end());
161 //std::cout << "after: " << std::endl;
162 for (DependenciesVector::iterator it = deps.begin(); it != deps.end(); it++)
165 std::set_intersection(it->begin(), it->end(), boxNamesSet.begin(), boxNamesSet.end(),std::back_inserter(tmp));
166 Dependencies tmp1(tmp.begin(),tmp.end());
168 // //print clean dependencies
169 // for( Dependencies::iterator it1 = it->begin(); it1 != it->end(); it1++)
171 // std::cout << *it1 << ", ";
173 // std::cout << std::endl;
177 // Create dependencies graph
178 std::vector<std::vector<int> > g(boxs.size(), std::vector<int>());
179 std::map<std::string, int> idxs;
182 for (int i = 0; i < (int)boxs.size(); ++i)
188 for (DependenciesVector::iterator dit = deps.begin(); dit != deps.end(); dit++, boxit++)
190 for (Dependencies::iterator ddit = dit->begin(); ddit != dit->end(); ddit++)
192 g[boxit].push_back(idxs[*ddit]);
196 // Check there are no cycles in graph
199 std::cout << "bbpConfigurator: There are dependency cycles, please check your scripts in '" <<
200 path_bbs << "'. No bbp file created." << std::endl;
205 std::cout << "bbpConfigurator: No cycles detected in dependency graph." << std::endl;
206 std::vector<int> priorities(boxs.size(), -1);
207 setPriorities(g, priorities);
208 // for (int i = 0; i < (int)priorities.size(); i++)
210 // std::cout << priorities[i] << " ";
212 // std::cout << std::endl;
214 // Write results to bbp file
216 std::string fname = path_out + "\\" + package_name + ".bbp";
218 std::string fname = path_out + "/" + package_name + ".bbp";
221 std::ofstream out(fname.c_str());
222 out << "#-----------------------------------------" << std::endl;
223 out << "# Include script for bbtk package '" << package_name << "'" << std::endl;
224 out << "# Automatically generated by bbpConfigurator" << std::endl;
225 out << "#-----------------------------------------" << std::endl;
226 out << "load "<< package_name << std::endl;
227 out << "#-----------------------------------------" << std::endl;
228 out << "package "<< package_name << std::endl;
229 out << "#-----------------------------------------" << std::endl;
231 //each bbs file ordered.
232 //include [package_name]/boxes/[file_bbs]
233 //#-----------------------------------------
235 // for (int i = 0; i < (int)files.size(); ++i) {
236 // out << "include " << package_name << "/boxes/" << files[i].filename().string() << std::endl;
237 // out << "#-----------------------------------------" << std::endl;
240 // find max priority level
242 for (int i = 0; i < (int)priorities.size(); i++)
244 mx_priority = std::max(mx_priority, priorities[i]);
247 // for each priority level print scripts in that level.
248 for (int i = 0; i <= mx_priority; i++)
250 for (int j = 0; j < (int)priorities.size(); j++)
252 if(priorities[j] == i)
255 #if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41
256 out << "include " << package_name << "/boxes/" << files[j].filename() << std::endl;
258 out << "include " << package_name << "/boxes/" << files[j].filename().string() << std::endl;
261 out << "#-----------------------------------------" << std::endl;
265 out << "endpackage" << std::endl;
266 out << "#-- EOF ----------------------------------" << std::endl;
270 std::cout << "bbpConfigurator: bbp file created at '" << fname << "'." << std::endl;
274 //==========================================================================
276 // extract of the tarjan's algorithm for strongly connected components
277 bool isCycle(const Graph& g)
279 for (int it = 0; it < (int)g.size(); ++it) {
280 std::vector<bool> visited (g.size(), false);
281 if (checkCycle(g, it, visited))
283 //std::cout << "At " << it << std::endl;
290 //==========================================================================
292 // dfs search to check cycles.
293 bool checkCycle(const Graph& g, const int& i, std::vector<bool>& v)
297 for(int dit = 0; dit < (int)g[i].size(); dit++)
300 if(d < 0 || d >= (int)g.size() || v[d])
302 //std::cout << "Checking " << i << " dependency " << dit << "=" << d << std::endl;
305 if(checkCycle(g,d,v))
312 //==========================================================================
314 // find precedence in graph. 0 are the boxes that have no deps, 1 boxes that have deps from 0 or less, 2 boxes that have deps from 1 or less, etc.
315 void setPriorities(const Graph& g, std::vector<int>& p)
317 for(int i = 0; i < (int)g.size(); i++)
320 setPriority(g, i, p);
324 //==========================================================================
326 // dfs search to find dependencies
327 void setPriority(const Graph& g, const int i, std::vector<int>& p)
330 for(int j = 0; j < (int)g[i].size(); j++)
332 setPriority(g, g[i][j], p);
333 pi = std::max(pi, p[g[i][j]]);
338 //==========================================================================
340 std::vector<bf::path> getFileList(const std::string& path)
342 std::vector<bf::path> files;
344 bf::path pth(path.c_str());
345 if(bf::exists(pth) && bf::is_directory(pth))
347 bf::directory_iterator end_itr;
348 bf::directory_iterator itr(pth);
349 for(itr; itr != end_itr; ++itr)
351 if(!is_directory(itr->status()))
354 #if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41
355 std::string nm(itr->path().filename());
357 std::string nm(itr->path().filename().string());
359 if(nm.substr(nm.size()-4) == ".bbs")
361 //std::cout << itr->path().filename().string() << std::endl;
362 files.push_back(itr->path());
369 std::cout<< "bbpConfigurator: The path to the bbs's doesn't exist or is not a folder. ('" << path << "')" << std::endl;
373 // Order files by name
374 for (int i = 0; i < (int)files.size()-1; ++i) {
375 for (int j = i+1; j < (int)files.size(); ++j) {
378 #if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41
379 if(files[j].filename() < files[i].filename())
381 if(files[j].filename().string() < files[i].filename().string())
385 bf::path tmp = files[i];