X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=kernel%2Fappli%2FbbpConfigurator%2FbbpConfigurator.cpp;h=a4fa7ac72ba0b355723e2bb8eba208078f6bb07b;hb=333b90638d58e788efffee2c61da9e152016e292;hp=7a1df7986685f31b7eda805fc65b339c3c56b1f5;hpb=cd39bfaca5c64598de7046df6989f244fc6e32cd;p=bbtk.git diff --git a/kernel/appli/bbpConfigurator/bbpConfigurator.cpp b/kernel/appli/bbpConfigurator/bbpConfigurator.cpp index 7a1df79..a4fa7ac 100644 --- a/kernel/appli/bbpConfigurator/bbpConfigurator.cpp +++ b/kernel/appli/bbpConfigurator/bbpConfigurator.cpp @@ -28,19 +28,34 @@ #include #include #include +#include +#include +#include #include "boost/filesystem.hpp" -//#include "boost/filesystem/operations.hpp" -//#include "boost/filesystem/path.hpp" +#include "bbtkBBPInterpreter.h" namespace bf = boost::filesystem; -//using namespace bbtk; +typedef std::vector > Graph; + +typedef std::set Dependencies; +typedef std::vector DependenciesVector; +typedef std::vector BoxesVector; + +std::vector getFileList(const std::string& path); + +bool isCycle(const Graph& g); +bool checkCycle(const Graph& g, const int& i, std::vector& v); + +void setPriorities(const Graph& g, std::vector& p); +void setPriority(const Graph& g, const int i, std::vector& p); int main(int argc, char **argv) { + // Check arguments if (argc != 4) { - std::cout << "usage : bbConfigurator " << std::endl; + std::cout << "bbpConfigurator usage: bbConfigurator " << std::endl; return 1; } @@ -48,20 +63,302 @@ int main(int argc, char **argv) std::string package_name(argv[2]); std::string path_out(argv[3]); + std::cout << "bbpConfigurator launched with bbs path: '" << path_bbs << + "', package: '" << package_name << + "', output path: '" << path_out << "'." << std::endl; + + // Get bbs files in path_bbs + std::vector files = getFileList(path_bbs); + if(files.size() == 0) + { + std::cout << "bbpConfigurator: No files to check in bbs path. " + "An empty bbp will be created for the package '" << package_name << "'." << std::endl; + + // Write results to bbp file + #ifdef WIN32 + std::string fname = path_out + "\\" + package_name + ".bbp"; + #else + std::string fname = path_out + "/" + package_name + ".bbp"; + #endif + + std::ofstream out(fname.c_str()); + out << "#-----------------------------------------" << std::endl; + out << "# Include script for bbtk package '" << package_name << "'" << std::endl; + out << "# Automatically generated by bbpConfigurator" << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "load "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "package "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "endpackage" << std::endl; + out << "#-- EOF ----------------------------------" << std::endl; + + out.close(); + + + return 0; + } + + + // Order files by dependencies + // Get DependenciesVector and Box Names + DependenciesVector deps; + BoxesVector boxs; + + + for (int i = 0; i < (int)files.size(); ++i) + { + bbtk::BBPInterpreter::Pointer I = bbtk::BBPInterpreter::New(); + I->InterpretFile(files[i].string()); + + + boxs.push_back( ((bbtk::BBPInterpreter*)(I.get()))->boxName ); + +// EED 2016/02/19 +// deps.push_back( ((bbtk::BBPInterpreter*)(I.get()))->dependencies ); + //--> Cleanning string package:boxname -> boxname + std::set tmpDependencies1= ((bbtk::BBPInterpreter*)(I.get()))->dependencies ; + std::set tmpDependencies2; + std::set::const_iterator sit(tmpDependencies1.begin()), send(tmpDependencies1.end()); + int pos; + std::string tmpStr; +// std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": "; + for(;sit!=send;++sit) + { + pos=(*sit).find(":"); + if (pos== std::string::npos ) + { + tmpDependencies2.insert( *sit ); +// std::cout << *sit << ' '; + } else { + tmpStr=(*sit).substr(pos+1); + tmpDependencies2.insert( tmpStr ); +// std::cout << tmpStr << ' '; + } // if + + } // for +// std::cout << std::endl; + deps.push_back( tmpDependencies2 ); + //<-- + + + +// //print box name and dependencies OLD VERSION +// std::cout << ((bbtk::BBPInterpreter*)(I.get()))->boxName << ": "; +// for( +// Dependencies::iterator it = ((bbtk::BBPInterpreter*)(I.get()))->dependencies.begin(); +// it != ((bbtk::BBPInterpreter*)(I.get()))->dependencies.end(); +// it++) { +// std::cout << *it << ", "; +// } +// std::cout << std::endl; + + } // for i + + // Only keep dependencies from package + Dependencies boxNamesSet(boxs.begin(), boxs.end()); + +//std::cout << "after: " << std::endl; + for (DependenciesVector::iterator it = deps.begin(); it != deps.end(); it++) + { + BoxesVector tmp; + std::set_intersection(it->begin(), it->end(), boxNamesSet.begin(), boxNamesSet.end(),std::back_inserter(tmp)); + Dependencies tmp1(tmp.begin(),tmp.end()); + it->swap( tmp1 ); +// //print clean dependencies +// for( Dependencies::iterator it1 = it->begin(); it1 != it->end(); it1++) +// { +// std::cout << *it1 << ", "; +// } +// std::cout << std::endl; + + } + + // Create dependencies graph + std::vector > g(boxs.size(), std::vector()); + std::map idxs; + + + for (int i = 0; i < (int)boxs.size(); ++i) + { + idxs[boxs[i]] = i; + } + + int boxit = 0; + for (DependenciesVector::iterator dit = deps.begin(); dit != deps.end(); dit++, boxit++) + { + for (Dependencies::iterator ddit = dit->begin(); ddit != dit->end(); ddit++) + { + g[boxit].push_back(idxs[*ddit]); + } + } + + // Check there are no cycles in graph + if(isCycle(g)) + { + std::cout << "bbpConfigurator: There are dependency cycles, please check your scripts in '" << + path_bbs << "'. No bbp file created." << std::endl; + return 2; + } + else + { + std::cout << "bbpConfigurator: No cycles detected in dependency graph." << std::endl; + std::vector priorities(boxs.size(), -1); + setPriorities(g, priorities); +// for (int i = 0; i < (int)priorities.size(); i++) +// { +// std::cout << priorities[i] << " "; +// } +// std::cout << std::endl; + + // Write results to bbp file + #ifdef WIN32 + std::string fname = path_out + "\\" + package_name + ".bbp"; + #else + std::string fname = path_out + "/" + package_name + ".bbp"; + #endif + + std::ofstream out(fname.c_str()); + out << "#-----------------------------------------" << std::endl; + out << "# Include script for bbtk package '" << package_name << "'" << std::endl; + out << "# Automatically generated by bbpConfigurator" << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "load "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + out << "package "<< package_name << std::endl; + out << "#-----------------------------------------" << std::endl; + + //each bbs file ordered. + //include [package_name]/boxes/[file_bbs] + //#----------------------------------------- + + // for (int i = 0; i < (int)files.size(); ++i) { + // out << "include " << package_name << "/boxes/" << files[i].filename().string() << std::endl; + // out << "#-----------------------------------------" << std::endl; + // } + + // find max priority level + int mx_priority = 0; + for (int i = 0; i < (int)priorities.size(); i++) + { + mx_priority = std::max(mx_priority, priorities[i]); + } + + // for each priority level print scripts in that level. + for (int i = 0; i <= mx_priority; i++) + { + for (int j = 0; j < (int)priorities.size(); j++) + { + if(priorities[j] == i) + { +//EED 2017-03-28 +#if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41 + out << "include " << package_name << "/boxes/" << files[j].filename() << std::endl; +#else + out << "include " << package_name << "/boxes/" << files[j].filename().string() << std::endl; +#endif + + out << "#-----------------------------------------" << std::endl; + } + } + } + out << "endpackage" << std::endl; + out << "#-- EOF ----------------------------------" << std::endl; + + out.close(); + + std::cout << "bbpConfigurator: bbp file created at '" << fname << "'." << std::endl; + } + return 0; +} +//========================================================================== + +// extract of the tarjan's algorithm for strongly connected components +bool isCycle(const Graph& g) +{ + for (int it = 0; it < (int)g.size(); ++it) { + std::vector visited (g.size(), false); + if (checkCycle(g, it, visited)) + { + //std::cout << "At " << it << std::endl; + return true; + } + } + return false; +} + +//========================================================================== + +// dfs search to check cycles. +bool checkCycle(const Graph& g, const int& i, std::vector& v) +{ + + v[i] = true; + for(int dit = 0; dit < (int)g[i].size(); dit++) + { + int d = g[i][dit]; + if(d < 0 || d >= (int)g.size() || v[d]) + { + //std::cout << "Checking " << i << " dependency " << dit << "=" << d << std::endl; + return true; + } + if(checkCycle(g,d,v)) + return true; + } + v[i] = false; + return false; +} + +//========================================================================== + +// 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. +void setPriorities(const Graph& g, std::vector& p) +{ + for(int i = 0; i < (int)g.size(); i++) + { + if(p[i] == -1) + setPriority(g, i, p); + } +} + +//========================================================================== + +// dfs search to find dependencies +void setPriority(const Graph& g, const int i, std::vector& p) +{ + int pi = -1; + for(int j = 0; j < (int)g[i].size(); j++) + { + setPriority(g, g[i][j], p); + pi = std::max(pi, p[g[i][j]]); + } + p[i]=pi+1; +} + +//========================================================================== + +std::vector getFileList(const std::string& path) +{ std::vector files; - bf::path pth(path_bbs.c_str()); + bf::path pth(path.c_str()); if(bf::exists(pth) && bf::is_directory(pth)) { bf::directory_iterator end_itr; - for(bf::directory_iterator itr(pth); itr != end_itr; ++itr) + bf::directory_iterator itr(pth); + for(itr; itr != end_itr; ++itr) { if(!is_directory(itr->status())) { +//EED 2017-03-28 +#if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41 + std::string nm(itr->path().filename()); +#else std::string nm(itr->path().filename().string()); +#endif if(nm.substr(nm.size()-4) == ".bbs") { - std::cout << itr->path().filename().string() << std::endl; + //std::cout << itr->path().filename().string() << std::endl; files.push_back(itr->path()); } } @@ -69,13 +366,21 @@ int main(int argc, char **argv) } else { - std::cout<< "the path to the bbs's should be a folder and not a file."; - return 1; + std::cout<< "bbpConfigurator: The path to the bbs's doesn't exist or is not a folder. ('" << path << "')" << std::endl; + return files; } + // Order files by name for (int i = 0; i < (int)files.size()-1; ++i) { for (int j = i+1; j < (int)files.size(); ++j) { + +//EED 2017-03-28 +#if BOOST_MAJOR_VERSION <= 1 && BOOST_MINOR_VERSION <=41 + if(files[j].filename() < files[i].filename()) +#else if(files[j].filename().string() < files[i].filename().string()) +#endif + { bf::path tmp = files[i]; files[i] = files[j]; @@ -84,37 +389,5 @@ int main(int argc, char **argv) } } -#ifdef WIN32 - std::string fname = path_out + "\\" + package_name + ".bbp"; -#else - std::string fname = path_out + "/" + package_name + ".bbp"; -#endif - - std::ofstream out(fname.c_str()); - out << "#-----------------------------------------" << std::endl; - out << "# Include script for bbtk package '" << package_name << "'" << std::endl; - out << "# Automatically generated by bbpConfigurator" << std::endl; - out << "#-----------------------------------------" << std::endl; - out << "load "<< package_name << std::endl; - out << "#-----------------------------------------" << std::endl; - out << "package "<< package_name << std::endl; - out << "#-----------------------------------------" << std::endl; - - //each bbs file ordered. - //include [package_name]/boxes/[file_bbs] - //#----------------------------------------- - for (int i = 0; i < (int)files.size(); ++i) { - out << "include " << package_name << "/boxes/" << files[i].filename().string() << std::endl; - out << "#-----------------------------------------" << std::endl; - } - - out << "endpackage" << std::endl; - out << "#-- EOF ----------------------------------" << std::endl; - - out.close(); - - return 0; + return files; } -//========================================================================== - -