33 #include <boost/algorithm/string.hpp> 34 #include <boost/filesystem.hpp> 35 #include <boost/functional/hash.hpp> 45 #define snprintf _snprintf 46 #define pclose _pclose 48 #define PATH_MAX MAX_PATH 49 #if defined(__MINGW32__) 56 #include <sys/types.h> 74 #if PY_VERSION_HEX < 0x03000000 75 #undef PyBytes_AsString 76 #undef PyUnicode_AsUTF8 77 #undef PyUnicode_FromString 78 #define PyBytes_AsString PyString_AsString 79 #define PyUnicode_AsUTF8 PyString_AsString 80 #define PyUnicode_FromString PyString_FromString 88 namespace fs = boost::filesystem;
121 static const std::string
g_ros_os =
"osx";
124 static const std::string g_ros_os =
"win32";
126 static const std::string g_ros_os =
"linux";
134 : std::runtime_error(what)
161 const std::string& path,
162 const std::string& manifest_path,
163 const std::string& manifest_name) :
166 manifest_path_(manifest_path),
167 manifest_name_(manifest_name),
168 manifest_loaded_(false),
169 manifest_(true, tinyxml2::COLLAPSE_WHITESPACE),
170 deps_computed_(false),
171 is_metapackage_(false)
178 assert(is_wet_package_);
179 assert(manifest_loaded_);
182 for(tinyxml2::XMLElement* el = root->FirstChildElement(
"name"); el; el = el->NextSiblingElement(
"name"))
184 name_ = el->GetText();
188 std::string tagname_license =
"license";
189 for(tinyxml2::XMLElement* el = root->FirstChildElement(tagname_license.c_str()); el; el = el->NextSiblingElement(tagname_license.c_str()))
191 licenses_.push_back(el->GetText());
194 for(tinyxml2::XMLElement* el = root->FirstChildElement(
"export"); el; el = el->NextSiblingElement(
"export"))
196 if(el->FirstChildElement(
"metapackage"))
198 is_metapackage_ =
true;
206 return manifest_name_ == MANIFEST_TAG_STACK || (is_wet_package_ && is_metapackage_);
211 return manifest_name_ == MANIFEST_TAG_PACKAGE || (is_wet_package_ && !is_metapackage_);
226 size_t start_num_pkgs) :
229 start_time_(start_time),
231 start_num_pkgs_(start_num_pkgs) {}
243 const std::string& cache_prefix,
244 const std::string& name,
245 const std::string& tag) :
246 manifest_name_(manifest_name),
247 cache_prefix_(cache_prefix),
261 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
275 log(
"Warning", msg, append_errno);
281 log(
"Error", msg, append_errno);
287 char* rpp = getenv(
"ROS_PACKAGE_PATH");
293 const char *path_delim =
";";
295 const char *path_delim = ":"; 298 std::vector<std::string> rpp_strings;
299 boost::split(rpp_strings, rpp,
300 boost::is_any_of(path_delim),
301 boost::token_compress_on);
302 for(std::vector<std::string>::const_iterator it = rpp_strings.begin();
303 it != rpp_strings.end();
323 if(!fs::is_directory(path))
326 catch(fs::filesystem_error& e)
328 logWarn(std::string(
"error while looking at ") + path +
": " + e.what());
334 for(fs::directory_iterator dit = fs::directory_iterator(path);
335 dit != fs::directory_iterator();
338 if(!fs::is_regular_file(dit->path()))
349 catch(fs::filesystem_error& e)
353 if(e.code().value() != EACCES)
355 logWarn(std::string(
"error while crawling ") + path +
": " + e.what() +
"; " + e.code().message());
388 std::vector<DirectoryCrawlRecord*> dummy;
389 boost::unordered_set<std::string> dummy2;
390 for(std::vector<std::string>::const_iterator p =
search_paths_.begin();
409 for(fs::path path = fs::current_path();
411 path = path.parent_path())
415 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 416 name = fs::path(path).filename();
419 name = fs::path(path).filename().string();
427 catch(fs::filesystem_error& e)
451 std::set<std::string>& packages)
454 boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
457 std::vector<std::string> search_paths;
458 search_paths.push_back(it->second->path_);
459 rp2.
crawl(search_paths,
true);
460 std::set<std::pair<std::string, std::string> > names_paths;
461 rp2.
list(names_paths);
462 for(std::set<std::pair<std::string, std::string> >::const_iterator iit = names_paths.begin();
463 iit != names_paths.end();
465 packages.insert(iit->first);
470 logError(std::string(
"stack ") + name +
" not found");
481 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
485 std::vector<std::string> search_paths;
486 search_paths.push_back(it->second->path_);
487 rp2.
crawl(search_paths,
true);
488 std::set<std::pair<std::string, std::string> > names_paths;
489 rp2.
list(names_paths);
490 for(std::set<std::pair<std::string, std::string> >::const_iterator iit = names_paths.begin();
491 iit != names_paths.end();
494 if(iit->first == name)
497 path = it->second->path_;
503 logError(std::string(
"stack containing package ") + name +
" not found");
510 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
514 std::pair<std::string, std::string> item;
515 item.first = it->first;
516 item.second = it->second->path_;
524 dups.resize(
dups_.size());
526 for(boost::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
539 for(boost::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
543 dups[it->first].resize(it->second.size());
545 for(std::vector<std::string>::const_iterator jt = it->second.begin();
546 jt != it->second.end();
549 dups[it->first][j] = *jt;
557 std::vector<std::string>&
deps)
559 std::vector<Stackage*> stackages;
573 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
574 it != stackages.end();
576 deps.push_back((*it)->name_);
582 std::vector<std::string>&
deps)
584 std::vector<Stackage*> stackages;
587 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
588 it != stackages.end();
590 deps.push_back((*it)->name_);
596 std::vector<std::string>&
deps)
604 std::vector<Stackage*> deps_vec;
605 boost::unordered_set<Stackage*> deps_hash;
606 std::vector<std::string> indented_deps;
608 for(std::vector<std::string>::const_iterator it = indented_deps.begin();
609 it != indented_deps.end();
623 const std::string& to,
633 std::list<std::list<Stackage*> > acc_list;
643 output.append(std::string(
"Dependency chains from ") +
644 from +
" to " + to +
":\n");
645 for(std::list<std::list<Stackage*> >::const_iterator it = acc_list.begin();
646 it != acc_list.end();
650 for(std::list<Stackage*>::const_iterator iit = it->begin();
654 if(iit != it->begin())
655 output.append(
"-> ");
656 output.append((*iit)->name_ +
" ");
665 std::vector<std::string>& manifests)
673 std::vector<Stackage*> deps_vec;
675 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
676 it != deps_vec.end();
678 manifests.push_back((*it)->manifest_path_);
690 std::set<std::string>&
rosdeps)
698 std::vector<Stackage*> deps_vec;
700 deps_vec.push_back(stackage);
703 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
704 it != deps_vec.end();
709 _rosdeps(*it, rosdeps, MANIFEST_TAG_ROSDEP);
714 _rosdeps(*it, rosdeps,
"build_depend");
715 _rosdeps(*it, rosdeps,
"buildtool_depend");
716 _rosdeps(*it, rosdeps,
"run_depend");
718 _rosdeps(*it, rosdeps,
"build_export_depend");
719 _rosdeps(*it, rosdeps,
"buildtool_export_depend");
720 _rosdeps(*it, rosdeps,
"exec_depend");
722 _rosdeps(*it, rosdeps,
"doc_depend");
723 _rosdeps(*it, rosdeps,
"test_depend");
739 for(tinyxml2::XMLElement* ele = root->FirstChildElement(tag_name);
741 ele = ele->NextSiblingElement(tag_name))
746 if((att_str = ele->Attribute(MANIFEST_ATTR_NAME)))
748 rosdeps.insert(std::string(
"name: ") + att_str);
753 const char* dep_pkgname = ele->GetText();
756 rosdeps.insert(std::string(
"name: ") + dep_pkgname);
764 std::vector<std::string>&
vcs)
772 std::vector<Stackage*> deps_vec;
774 deps_vec.push_back(stackage);
777 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
778 it != deps_vec.end();
782 for(tinyxml2::XMLElement* ele = root->FirstChildElement(MANIFEST_TAG_VERSIONCONTROL);
784 ele = ele->NextSiblingElement(MANIFEST_TAG_VERSIONCONTROL))
788 if((att_str = ele->Attribute(MANIFEST_ATTR_TYPE)))
790 result.append(
"type: ");
791 result.append(att_str);
793 if((att_str = ele->Attribute(MANIFEST_ATTR_URL)))
795 result.append(
"\turl: ");
796 result.append(att_str);
798 vcs.push_back(result);
812 const std::string& attrib,
bool deps_only,
813 std::vector<std::pair<std::string, bool> >& flags)
819 static bool init_py =
false;
820 static PyObject* pName;
821 static PyObject* pModule;
822 static PyObject* pDict;
823 static PyObject* pFunc;
828 std::vector<Stackage*> deps_vec;
830 deps_vec.push_back(stackage);
832 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
833 it != deps_vec.end();
836 if(!(*it)->is_wet_package_)
838 std::vector<std::string> dry_flags;
843 for(std::vector<std::string>::const_iterator it = dry_flags.begin(); it != dry_flags.end(); ++it)
845 flags.push_back(std::pair<std::string, bool>(*it,
false));
851 PyGILState_STATE gstate = PyGILState_Ensure();
857 pModule = PyImport_Import(pName);
861 PyGILState_Release(gstate);
862 std::string errmsg =
"could not find python module 'rosdep2.rospack'. is rosdep up-to-date (at least 0.10.4)?";
865 pDict = PyModule_GetDict(pModule);
866 pFunc = PyDict_GetItemString(pDict,
"call_pkg_config");
869 if(!PyCallable_Check(pFunc))
872 PyGILState_Release(gstate);
873 std::string errmsg =
"could not find python function 'rosdep2.rospack.call_pkg_config'. is rosdep up-to-date (at least 0.10.7)?";
877 PyObject* pArgs = PyTuple_New(2);
879 PyTuple_SetItem(pArgs, 0, pOpt);
881 PyTuple_SetItem(pArgs, 1, pPkg);
882 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
888 PyGILState_Release(gstate);
889 std::string errmsg =
"could not call python function 'rosdep2.rospack.call_pkg_config'";
892 if(pValue == Py_None)
895 std::string errmsg =
"python function 'rosdep2.rospack.call_pkg_config' could not call 'pkg-config " + type +
" " + (*it)->name_ +
"' without errors";
899 flags.push_back(std::pair<std::string, bool>(
PyBytes_AsString(pValue),
true));
909 PyGILState_Release(gstate);
924 static bool init_py =
false;
925 static PyObject* pName;
926 static PyObject* pModule;
927 static PyObject* pFunc;
930 PyGILState_STATE gstate = PyGILState_Ensure();
936 pModule = PyImport_Import(pName);
940 PyGILState_Release(gstate);
941 std::string errmsg =
"could not find python module 'catkin_pkg.rospack'. is catkin_pkg up-to-date (at least 0.1.8)?";
944 PyObject* pDict = PyModule_GetDict(pModule);
945 pFunc = PyDict_GetItemString(pDict,
"reorder_paths");
948 if(!PyCallable_Check(pFunc))
951 PyGILState_Release(gstate);
952 std::string errmsg =
"could not find python function 'catkin_pkg.rospack.reorder_paths'. is catkin_pkg up-to-date (at least 0.1.8)?";
957 PyObject* pArgs = PyTuple_New(1);
959 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
965 PyGILState_Release(gstate);
966 std::string errmsg =
"could not call python function 'catkin_pkg.rospack.reorder_paths'";
980 PyGILState_Release(gstate);
987 const std::string& attrib,
bool deps_only,
988 std::vector<std::string>& flags)
996 std::vector<Stackage*> deps_vec;
998 deps_vec.push_back(stackage);
1000 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1001 it != deps_vec.end();
1020 const std::string& attrib,
1021 std::vector<std::string>& flags)
1024 for(tinyxml2::XMLElement* ele = root->FirstChildElement(MANIFEST_TAG_EXPORT);
1026 ele = ele->NextSiblingElement(MANIFEST_TAG_EXPORT))
1028 bool os_match =
false;
1029 const char *best_match = NULL;
1030 for(tinyxml2::XMLElement* ele2 = ele->FirstChildElement(lang.c_str());
1032 ele2 = ele2->NextSiblingElement(lang.c_str()))
1035 if ((os_str = ele2->Attribute(
"os")))
1037 if(g_ros_os == std::string(os_str))
1040 logWarn(std::string(
"ignoring duplicate ") + lang +
" tag with os=" + os_str +
" in export block");
1043 best_match = ele2->Attribute(attrib.c_str());
1051 best_match = ele2->Attribute(attrib.c_str());
1053 logWarn(std::string(
"ignoring duplicate ") + lang +
" tag in export block");
1059 std::string expanded_str;
1062 flags.push_back(expanded_str);
1068 if((lang ==
"cpp") && (attrib ==
"cflags"))
1072 if(fs::is_regular_file(msg_gen / MSG_GEN_GENERATED_FILE))
1074 msg_gen /= fs::path(
"cpp") /
"include";
1075 flags.push_back(std::string(
"-I" + msg_gen.string()));
1077 if(fs::is_regular_file(srv_gen / SRV_GEN_GENERATED_FILE))
1079 srv_gen /= fs::path(
"cpp") /
"include";
1080 flags.push_back(std::string(
"-I" + srv_gen.string()));
1088 const std::string& top,
1089 std::vector<std::string>& flags)
1092 std::vector<Stackage*> stackages;
1096 boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
1100 stackages.push_back(it->second);
1106 std::vector<Stackage*> top_deps;
1109 boost::unordered_set<Stackage*> top_deps_set;
1110 for(std::vector<Stackage*>::iterator it = top_deps.begin();
1111 it != top_deps.end();
1113 top_deps_set.insert(*it);
1114 std::vector<Stackage*>::iterator it = stackages.begin();
1115 while(it != stackages.end())
1117 if((*it)->name_ != top &&
1118 (top_deps_set.find(*it) == top_deps_set.end()))
1119 it = stackages.erase(it);
1125 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
1126 it != stackages.end();
1130 for(tinyxml2::XMLElement* ele = root->FirstChildElement(MANIFEST_TAG_EXPORT);
1132 ele = ele->NextSiblingElement(MANIFEST_TAG_EXPORT))
1134 for(tinyxml2::XMLElement* ele2 = ele->FirstChildElement(name.c_str());
1136 ele2 = ele2->NextSiblingElement(name.c_str()))
1138 const char *att_str;
1139 if((att_str = ele2->Attribute(attrib.c_str())))
1141 std::string expanded_str;
1144 flags.push_back((*it)->name_ +
" " + expanded_str);
1154 std::vector<std::string>& gens)
1162 std::vector<Stackage*> deps_vec;
1164 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1165 it != deps_vec.end();
1168 fs::path msg_gen = fs::path((*it)->path_) /
1169 MSG_GEN_GENERATED_DIR /
1171 fs::path srv_gen = fs::path((*it)->path_) /
1172 SRV_GEN_GENERATED_DIR /
1174 if(fs::is_regular_file(msg_gen))
1175 gens.push_back(msg_gen.string());
1176 if(fs::is_regular_file(srv_gen))
1177 gens.push_back(srv_gen.string());
1194 const std::string& msg,
1199 fprintf(stderr,
"[%s] %s: %s",
1200 name_.c_str(), level.c_str(), msg.c_str());
1202 fprintf(stderr,
": %s", strerror(errno));
1203 fprintf(stderr,
"\n");
1226 std::vector<Stackage*>&
deps)
1232 logError(std::string(
"no such package ") + name);
1239 std::vector<Stackage*> deps_vec;
1241 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1242 it != deps_vec.end();
1244 deps.push_back(*it);
1257 std::list<std::list<Stackage*> >& acc_list)
1260 for(std::vector<Stackage*>::const_iterator it = from->
deps_.begin();
1261 it != from->
deps_.end();
1264 if((*it)->name_ == to->
name_)
1266 std::list<Stackage*> acc;
1267 acc.push_back(from);
1269 acc_list.push_back(acc);
1273 std::list<std::list<Stackage*> > l;
1275 for(std::list<std::list<Stackage*> >::iterator iit = l.begin();
1279 iit->push_front(from);
1280 acc_list.push_back(*iit);
1288 std::vector<Stackage*>&
deps,
bool ignore_missing)
1294 logError(std::string(
"no such package ") + name);
1299 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
1304 std::vector<Stackage*> deps_vec;
1306 for(std::vector<Stackage*>::const_iterator iit = deps_vec.begin();
1307 iit != deps_vec.end();
1310 if((*iit)->name_ == name)
1312 deps.push_back(it->second);
1330 std::vector<std::string>& dirs)
1333 std::vector<DirectoryCrawlRecord*> dcrs;
1334 boost::unordered_set<std::string> dcrs_hash;
1335 for(std::vector<std::string>::const_iterator p = search_path.begin();
1336 p != search_path.end();
1345 snprintf(buf,
sizeof(buf),
"%.6f", total);
1346 dirs.push_back(std::string(
"Full tree crawl took ") + buf +
" seconds.");
1347 dirs.push_back(
"Directories marked with (*) contain no manifest. You may");
1348 dirs.push_back(
"want to delete these directories.");
1349 dirs.push_back(
"To get just of list of directories without manifests,");
1350 dirs.push_back(
"re-run the profile with --zombie-only");
1351 dirs.push_back(
"-------------------------------------------------------------");
1354 std::reverse(dcrs.begin(), dcrs.end());
1356 for(std::vector<DirectoryCrawlRecord*>::const_iterator it = dcrs.begin();
1364 if(length < 0 || i < length)
1365 dirs.push_back((*it)->path_);
1372 snprintf(buf,
sizeof(buf),
"%.6f", (*it)->crawl_time_);
1373 if(length < 0 || i < length)
1374 dirs.push_back(std::string(buf) +
" " +
1375 ((*it)->zombie_ ?
"* " :
" ") +
1389 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 1390 std::string name = fs::path(path).filename();
1393 std::string name = fs::path(path).filename().string();
1399 if(fs::is_regular_file(dry_manifest_path))
1403 else if(fs::is_regular_file(wet_manifest_path))
1429 std::vector<std::string> dups;
1445 bool collect_profile_data,
1446 std::vector<DirectoryCrawlRecord*>& profile_data,
1447 boost::unordered_set<std::string>& profile_hash)
1449 if(depth > MAX_CRAWL_DEPTH)
1450 throw Exception(
"maximum depth exceeded during crawl");
1454 if(!fs::is_directory(path))
1457 catch(fs::filesystem_error& e)
1459 logWarn(std::string(
"error while looking at ") + path +
": " + e.what());
1466 if(fs::is_regular_file(catkin_ignore))
1469 catch(fs::filesystem_error& e)
1471 logWarn(std::string(
"error while looking for ") + catkin_ignore.string() +
": " + e.what());
1483 if(fs::is_regular_file(nosubdirs))
1486 catch(fs::filesystem_error& e)
1488 logWarn(std::string(
"error while looking for ") + nosubdirs.string() +
": " + e.what());
1497 if(fs::is_regular_file(rospack_manifest))
1500 catch(fs::filesystem_error& e)
1502 logWarn(std::string(
"error while looking for ") + rospack_manifest.string() +
": " + e.what());
1506 if(collect_profile_data)
1508 if(profile_hash.find(path) == profile_hash.end())
1513 profile_data.push_back(dcr);
1514 profile_hash.insert(path);
1520 for(fs::directory_iterator dit = fs::directory_iterator(path);
1521 dit != fs::directory_iterator();
1524 if(fs::is_directory(dit->path()))
1526 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 1527 std::string name = dit->path().filename();
1530 std::string name = dit->path().filename().string();
1533 if(name.size() == 0 || name[0] ==
'.')
1537 collect_profile_data, profile_data, profile_hash);
1541 catch(fs::filesystem_error& e)
1545 if(e.code().value() != EACCES)
1547 logWarn(std::string(
"error while crawling ") + path +
": " + e.what());
1551 if(collect_profile_data && dcr != NULL)
1557 if(
stackages_.size() == dcr->start_num_pkgs_)
1558 dcr->zombie_ =
true;
1570 std::string errmsg = std::string(
"error parsing manifest of package ") +
1614 tinyxml2::XMLElement* root;
1617 const char* dep_pkgname;
1618 for(tinyxml2::XMLElement *dep_ele = root->FirstChildElement(depend_tag.c_str());
1620 dep_ele = dep_ele->NextSiblingElement(depend_tag.c_str()))
1624 dep_pkgname = dep_ele->Attribute(
tag_.c_str());
1628 dep_pkgname = dep_ele->GetText();
1634 std::string errmsg = std::string(
"bad depend syntax (no 'package/stack' attribute) in manifest ") + stackage->
name_ +
" at " + stackage->
manifest_path_;
1638 else if(dep_pkgname == stackage->
name_)
1655 stackage->
deps_.push_back(dep);
1659 std::string errmsg =
get_manifest_type() +
" '" + stackage->
name_ +
"' depends on non-existent package '" + dep_pkgname +
"' and rosdep claims that it is not a system dependency. Check the ROS_PACKAGE_PATH or try calling 'rosdep update'";
1666 if (std::find(stackage->
deps_.begin(), stackage->
deps_.end(), dep) == stackage->
deps_.end())
1668 stackage->
deps_.push_back(dep);
1678 static bool initialized =
false;
1689 static std::map<std::string, bool> cache;
1690 if(cache.find(pkgname) != cache.end())
1692 return cache.find(pkgname)->second;
1696 PyGILState_STATE gstate = PyGILState_Ensure();
1698 static PyObject* pModule = 0;
1699 static PyObject* pDict = 0;
1703 pModule = PyImport_Import(pName);
1708 PyGILState_Release(gstate);
1709 std::string errmsg =
"could not find python module 'rosdep2.rospack'. is rosdep up-to-date (at least 0.10.4)?";
1712 pDict = PyModule_GetDict(pModule);
1715 static PyObject* pView = 0;
1718 PyObject* pFunc = PyDict_GetItemString(pDict,
"init_rospack_interface");
1719 if(!PyCallable_Check(pFunc))
1722 PyGILState_Release(gstate);
1723 std::string errmsg =
"could not find python function 'rosdep2.rospack.init_rospack_interface'. is rosdep up-to-date (at least 0.10.4)?";
1726 pView = PyObject_CallObject(pFunc, NULL);
1730 PyGILState_Release(gstate);
1731 std::string errmsg =
"could not call python function 'rosdep2.rospack.init_rospack_interface'";
1735 static bool rospack_view_not_empty =
false;
1736 if(!rospack_view_not_empty)
1738 PyObject* pFunc = PyDict_GetItemString(pDict,
"is_view_empty");
1739 if(!PyCallable_Check(pFunc))
1742 PyGILState_Release(gstate);
1743 std::string errmsg =
"could not find python function 'rosdep2.rospack.is_view_empty'. is rosdep up-to-date (at least 0.10.8)?";
1746 PyObject* pArgs = PyTuple_New(1);
1747 PyTuple_SetItem(pArgs, 0, pView);
1748 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
1751 if(PyObject_IsTrue(pValue))
1754 PyGILState_Release(gstate);
1755 std::string errmsg =
"the rosdep view is empty: call 'sudo rosdep init' and 'rosdep update'";
1758 rospack_view_not_empty =
true;
1761 PyObject* pFunc = PyDict_GetItemString(pDict,
"is_system_dependency");
1762 if(!PyCallable_Check(pFunc))
1765 PyGILState_Release(gstate);
1766 std::string errmsg =
"could not call python function 'rosdep2.rospack.is_system_dependency'. is rosdep up-to-date (at least 0.10.4)?";
1770 PyObject* pArgs = PyTuple_New(2);
1771 PyTuple_SetItem(pArgs, 0, pView);
1773 PyTuple_SetItem(pArgs, 1, pDep);
1774 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
1778 bool value = PyObject_IsTrue(pValue);
1788 PyGILState_Release(gstate);
1790 cache[pkgname] = value;
1798 std::vector<Stackage*>&
deps,
1799 bool no_recursion_on_wet)
1801 boost::unordered_set<Stackage*> deps_hash;
1802 std::vector<std::string> indented_deps;
1804 deps_hash, deps,
false, indented_deps, no_recursion_on_wet);
1810 boost::unordered_set<Stackage*>& deps_hash,
1811 std::vector<Stackage*>&
deps,
1812 bool get_indented_deps,
1813 std::vector<std::string>& indented_deps,
1814 bool no_recursion_on_wet,
1815 std::vector<std::string>& dep_chain)
1824 for(std::vector<Stackage*>::const_iterator it = stackage->
deps_.begin();
1825 it != stackage->
deps_.end();
1827 deps.push_back(*it);
1831 if(depth > MAX_DEPENDENCY_DEPTH) {
1833 for(std::vector<std::string>::const_iterator it = dep_chain.begin();
1834 it != dep_chain.end();
1837 std::vector<std::string>::const_iterator begin = dep_chain.begin();
1838 std::vector<std::string>::const_iterator cycle_begin = std::find(begin, it, *it);
1839 if(cycle_begin != it) {
1841 for(std::vector<std::string>::const_iterator jt = cycle_begin; jt != it; ++jt) {
1842 if(jt != cycle_begin) cycle +=
", ";
1848 throw Exception(std::string(
"maximum dependency depth exceeded (likely circular dependency") + cycle +
")");
1851 for(std::vector<Stackage*>::const_iterator it = stackage->
deps_.begin();
1852 it != stackage->
deps_.end();
1855 if(get_indented_deps)
1857 std::string indented_dep;
1858 for(
int i=0; i<depth; i++)
1859 indented_dep.append(
" ");
1860 indented_dep.append((*it)->name_);
1861 indented_deps.push_back(indented_dep);
1864 bool first = (deps_hash.find(*it) == deps_hash.end());
1867 deps_hash.insert(*it);
1871 deps.push_back(*it);
1873 if(!(*it)->is_wet_package_ || !no_recursion_on_wet)
1878 dep_chain.push_back((*it)->name_);
1880 get_indented_deps, indented_deps,
1881 no_recursion_on_wet, dep_chain);
1882 dep_chain.pop_back();
1887 deps.push_back(*it);
1896 boost::unordered_set<Stackage*>& deps_hash,
1897 std::vector<Stackage*>&
deps,
1898 bool get_indented_deps,
1899 std::vector<std::string>& indented_deps,
1900 bool no_recursion_on_wet)
1902 std::vector<std::string> dep_chain;
1903 dep_chain.push_back(stackage->
name_);
1910 no_recursion_on_wet,
1917 fs::path cache_path;
1919 char* ros_home = getenv(
"ROS_HOME");
1921 cache_path = ros_home;
1928 char* home_drive = getenv(
"HOMEDRIVE");
1929 char* home_path = getenv(
"HOMEPATH");
1930 if(home_drive && home_path)
1931 cache_path = fs::path(home_drive) / fs::path(home_path) / fs::path(DOTROS_NAME);
1934 struct passwd* passwd_ent;
1936 if((passwd_ent = getpwuid(geteuid())))
1937 home_path = passwd_ent->pw_dir;
1939 home_path = getenv(
"HOME");
1941 cache_path = fs::path(home_path) / fs::path(DOTROS_NAME);
1948 if(!fs::is_directory(cache_path))
1950 fs::create_directory(cache_path);
1953 catch(fs::filesystem_error& e)
1955 logWarn(std::string(
"cannot create rospack cache directory ") +
1956 cache_path.string() +
": " + e.what());
1959 return cache_path.string();
1966 char* rpp = getenv(
"ROS_PACKAGE_PATH");
1968 boost::hash<std::string> hash_func;
1969 value = hash_func(rpp);
1972 snprintf(buffer, 21,
"%020lu", value);
1985 char linebuf[30000];
1988 if (!fgets(linebuf,
sizeof(linebuf), cache))
1990 if (linebuf[0] ==
'#')
1992 char* newline_pos = strchr(linebuf,
'\n');
2012 if(!cache_path.size())
2014 logWarn(
"no location available to write cache file. Try setting ROS_HOME or HOME.");
2018 size_t len = cache_path.size() + 1;
2019 char *tmp_cache_dir =
new char[len];
2020 strncpy(tmp_cache_dir, cache_path.c_str(), len);
2021 #if defined(_MSC_VER) 2023 char tmp_cache_path[PATH_MAX];
2024 char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
2025 _splitpath_s(tmp_cache_dir, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME,
2027 char full_dir[_MAX_DRIVE + _MAX_DIR];
2028 _makepath_s(full_dir, _MAX_DRIVE + _MAX_DIR, drive, dir, NULL, NULL);
2029 snprintf(tmp_cache_path,
sizeof(tmp_cache_path),
"%s\\.rospack_cache.XXXXXX", full_dir);
2030 #elif defined(__MINGW32__) 2031 char tmp_cache_path[PATH_MAX];
2032 char* temp_name = tempnam(dirname(tmp_cache_dir),
".rospack_cache.");
2033 snprintf(tmp_cache_path,
sizeof(tmp_cache_path), temp_name);
2036 char *temp_dirname = dirname(tmp_cache_dir);
2037 len = strlen(temp_dirname) + 22 + 1;
2038 char *tmp_cache_path =
new char[len];
2039 snprintf(tmp_cache_path, len,
"%s/.rospack_cache.XXXXXX", temp_dirname);
2041 #if defined(__MINGW32__) 2044 int fd = open(tmp_cache_path, O_RDWR | O_EXCL | _O_CREAT, 0644);
2047 logWarn(std::string(
"unable to create temporary cache file ") +
2048 tmp_cache_path,
true);
2052 FILE *cache = fdopen(fd,
"w");
2053 #elif defined(WIN32) 2054 if (_mktemp_s(tmp_cache_path, PATH_MAX) != 0)
2057 "[rospack] Unable to generate temporary cache file name: %u",
2062 FILE *cache = fopen(tmp_cache_path,
"w");
2064 int fd = mkstemp(tmp_cache_path);
2067 fprintf(stderr,
"[rospack] Unable to create temporary cache file %s: %s\n",
2068 tmp_cache_path, strerror(errno));
2072 FILE *cache = fdopen(fd,
"w");
2076 fprintf(stderr,
"[rospack] Unable open cache file %s: %s\n",
2077 tmp_cache_path, strerror(errno));
2081 char *rpp = getenv(
"ROS_PACKAGE_PATH");
2082 fprintf(cache,
"#ROS_PACKAGE_PATH=%s\n", (rpp ? rpp :
""));
2083 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
2086 fprintf(cache,
"%s\n", it->second->path_.c_str());
2088 if(fs::exists(cache_path))
2089 remove(cache_path.c_str());
2090 if(rename(tmp_cache_path, cache_path.c_str()) < 0)
2092 fprintf(stderr,
"[rospack] Error: failed to rename cache file %s to %s: %s\n",
2093 tmp_cache_path, cache_path.c_str(), strerror(errno));
2097 delete[] tmp_cache_dir;
2098 #if !defined(_MSC_VER) && !defined(__MINGW32__) 2099 delete[] tmp_cache_path;
2110 const char *user_cache_time_str = getenv(
"ROS_CACHE_TIMEOUT");
2111 if(user_cache_time_str)
2112 cache_max_age = atof(user_cache_time_str);
2113 if(cache_max_age == 0.0)
2116 if(stat(cache_path.c_str(), &s) == 0)
2118 double dt = difftime(time(NULL), s.st_mtime);
2121 if ((cache_max_age > 0.0) && (dt > cache_max_age))
2125 FILE* cache = fopen(cache_path.c_str(),
"r");
2130 char linebuf[30000];
2131 bool ros_package_path_ok =
false;
2132 const char* ros_package_path = getenv(
"ROS_PACKAGE_PATH");
2135 if(!fgets(linebuf,
sizeof(linebuf), cache))
2137 linebuf[strlen(linebuf)-1] = 0;
2138 if (linebuf[0] ==
'#')
2140 if(!strncmp(
"#ROS_PACKAGE_PATH=", linebuf, 18))
2142 if(!ros_package_path)
2144 if(!strlen(linebuf+18))
2145 ros_package_path_ok =
true;
2147 else if(!strcmp(linebuf+18, ros_package_path))
2148 ros_package_path_ok =
true;
2154 if(ros_package_path_ok)
2158 fseek(cache, 0, SEEK_SET);
2170 const std::string& instring,
2171 std::string& outstring)
2173 outstring = instring;
2174 for(std::string::size_type i = outstring.find(MANIFEST_PREFIX);
2175 i != std::string::npos;
2176 i = outstring.find(MANIFEST_PREFIX))
2178 outstring.replace(i, std::string(MANIFEST_PREFIX).length(),
2185 if (outstring.find_first_of(
"$`") == std::string::npos)
2200 std::string cmd = std::string(
"ret=\"") + outstring +
"\" && echo $ret";
2203 std::string token(
"\n");
2204 for (std::string::size_type s = cmd.find(token);
2205 s != std::string::npos;
2206 s = cmd.find(token, s))
2207 cmd.replace(s,token.length(),std::string(
" "));
2210 if(!(p = popen(cmd.c_str(),
"r")))
2212 std::string errmsg =
2213 std::string(
"failed to execute backquote expression ") +
2222 memset(buf,0,
sizeof(buf));
2227 while(fgets(buf + strlen(buf),
sizeof(buf)-strlen(buf)-1,p));
2228 }
while(ferror(p) && errno == EINTR);
2232 std::string errmsg =
2233 std::string(
"got non-zero exit status from executing backquote expression ") +
2241 buf[strlen(buf)-1] =
'\0';
2255 ROSPACK_CACHE_PREFIX,
2257 MANIFEST_TAG_PACKAGE)
2264 return "USAGE: rospack <command> [options] [package]\n" 2265 " Allowed commands:\n" 2267 " cflags-only-I [--deps-only] [package]\n" 2268 " cflags-only-other [--deps-only] [package]\n" 2269 " depends [package] (alias: deps)\n" 2270 " depends-indent [package] (alias: deps-indent)\n" 2271 " depends-manifests [package] (alias: deps-manifests)\n" 2272 " depends-msgsrv [package] (alias: deps-msgsrv)\n" 2273 " depends-on [package]\n" 2274 " depends-on1 [package]\n" 2275 " depends-why --target=<target> [package] (alias: deps-why)\n" 2276 " depends1 [package] (alias: deps1)\n" 2277 " export [--deps-only] --lang=<lang> --attrib=<attrib> [package]\n" 2280 " libs-only-L [--deps-only] [package]\n" 2281 " libs-only-l [--deps-only] [package]\n" 2282 " libs-only-other [--deps-only] [package]\n" 2284 " list-duplicates\n" 2286 " plugins --attrib=<attrib> [--top=<toppkg>] [package]\n" 2287 " profile [--length=<length>] [--zombie-only]\n" 2288 " rosdep [package] (alias: rosdeps)\n" 2289 " rosdep0 [package] (alias: rosdeps0)\n" 2293 " -q Quiets error reports.\n\n" 2294 " If [package] is omitted, the current working directory\n" 2295 " is used (if it contains a package.xml or manifest.xml).\n\n";
2308 ROSSTACK_CACHE_PREFIX,
2317 return "USAGE: rosstack [options] <command> [stack]\n" 2318 " Allowed commands:\n" 2321 " contents [stack]\n" 2324 " depends [stack] (alias: deps)\n" 2325 " depends-manifests [stack] (alias: deps-manifests)\n" 2326 " depends1 [stack] (alias: deps1)\n" 2327 " depends-indent [stack] (alias: deps-indent)\n" 2328 " depends-why --target=<target> [stack] (alias: deps-why)\n" 2329 " depends-on [stack]\n" 2330 " depends-on1 [stack]\n" 2331 " contains [package]\n" 2332 " contains-path [package]\n" 2333 " profile [--length=<length>] \n\n" 2334 " If [stack] is omitted, the current working directory\n" 2335 " is used (if it contains a stack.xml).\n\n";
2343 tinyxml2::XMLElement*
2346 tinyxml2::XMLElement* ele = stackage->
manifest_.RootElement();
2349 std::string errmsg = std::string(
"error parsing manifest of package ") +
2360 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 2361 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 2363 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL 2366 unsigned __int64 tmpres = 0;
2368 GetSystemTimeAsFileTime(&ft);
2369 tmpres |= ft.dwHighDateTime;
2371 tmpres |= ft.dwLowDateTime;
2373 tmpres -= DELTA_EPOCH_IN_MICROSECS;
2374 return static_cast<double>(tmpres) / 1e6;
2377 gettimeofday(&tod, NULL);
2378 return tod.tv_sec + 1e-6 * tod.tv_usec;
bool exports(const std::string &name, const std::string &lang, const std::string &attrib, bool deps_only, std::vector< std::string > &flags)
Compute exports declared in a package and its dependencies. Used by rosbuild.
virtual const char * usage()
Usage statement.
void addStackage(const std::string &path)
tinyxml2::XMLDocument manifest_
void gatherDepsFull(Stackage *stackage, bool direct, traversal_order_t order, int depth, boost::unordered_set< Stackage * > &deps_hash, std::vector< Stackage * > &deps, bool get_indented_deps, std::vector< std::string > &indented_deps, bool no_recursion_on_wet=false)
void gatherDeps(Stackage *stackage, bool direct, traversal_order_t order, std::vector< Stackage * > &deps, bool no_recursion_on_wet=false)
void computeDeps(Stackage *stackage, bool ignore_errors=false, bool ignore_missing=false)
static const char * DOTROS_NAME
bool depsMsgSrv(const std::string &name, bool direct, std::vector< std::string > &gens)
List the marker files in a packages's dependencies that indicate that those packages contain auto-gen...
bool depsDetail(const std::string &name, bool direct, std::vector< Stackage * > &deps)
Compute dependencies of a stackage (i.e., stackages that this stackages depends on), taking and returning stackage objects..
bool inStackage(std::string &name)
Is the current working directory a stackage?
static const char * SRV_GEN_GENERATED_DIR
virtual ~Rosstackage()
Destructor.
#define PyBytes_AsString
defined(WIN32)
std::vector< std::string > search_paths_
static const char * SRV_GEN_GENERATED_FILE
bool depsOnDetail(const std::string &name, bool direct, std::vector< Stackage * > &deps, bool ignore_missing=false)
Compute reverse dependencies of a stackage (i.e., stackages that depend on this stackage), taking and returning stackage objects. Forces crawl.
static const char * ROSPACK_MANIFEST_NAME
static const char * MANIFEST_ATTR_NAME
static const char * MANIFEST_TAG_EXPORT
static const char * MSG_GEN_GENERATED_FILE
tinyxml2::XMLElement * get_manifest_root(Stackage *stackage)
bool contents(const std::string &name, std::set< std::string > &packages)
Compute the packages that are contained in a stack.
bool reorder_paths(const std::string &paths, std::string &reordered)
Reorder the paths according to the workspace chaining.
virtual std::string get_manifest_type()
void listDuplicates(std::vector< std::string > &dups)
Identify duplicate stackages. Forces crawl.
void loadManifest(Stackage *stackage)
bool isStackage(const std::string &path)
bool deps(const std::string &name, bool direct, std::vector< std::string > &deps)
Compute dependencies of a stackage (i.e., stackages that this stackages depends on).
static const double DEFAULT_MAX_CACHE_AGE
boost::unordered_map< std::string, Stackage * > stackages_
virtual std::string get_manifest_type()
void setQuiet(bool quiet)
Control warning and error console output.
std::string manifest_name_
static const char * ROSPACK_NOSUBDIRS
void depsWhyDetail(Stackage *from, Stackage *to, std::list< std::list< Stackage * > > &acc_list)
boost::unordered_map< std::string, std::vector< std::string > > dups_
static const char * ROSSTACK_MANIFEST_NAME
bool rosdeps(const std::string &name, bool direct, std::set< std::string > &rosdeps)
Compute rosdep entries that are declared in manifest of a package and its dependencies. Used by rosmake.
std::string manifest_name_
DirectoryCrawlRecord(std::string path, double start_time, size_t start_num_pkgs)
virtual std::string get_manifest_type()
static const int MAX_DEPENDENCY_DEPTH
void listDuplicatesWithPaths(std::map< std::string, std::vector< std::string > > &dups)
Identify duplicate stackages and provide their paths. Forces crawl.
void list(std::set< std::pair< std::string, std::string > > &list)
List names and paths of all stackages.
static const char * MANIFEST_TAG_PACKAGE
static const char * MANIFEST_TAG_ROSDEP
static const char * MANIFEST_ATTR_TYPE
static const char * CATKIN_IGNORE
std::string getCacheHash()
std::string cache_prefix_
static const char * ROSPACK_CACHE_PREFIX
static const char * ROSPACKAGE_MANIFEST_NAME
bool expandExportString(Stackage *stackage, const std::string &instring, std::string &outstring)
std::string manifest_path_
bool cmpDirectoryCrawlRecord(DirectoryCrawlRecord *i, DirectoryCrawlRecord *j)
static const char * MANIFEST_TAG_STACK
bool contains(const std::string &name, std::string &stack, std::string &path)
Find the stack that contains a package.
static const char * ROSSTACK_CACHE_PREFIX
Exception(const std::string &what)
bool getSearchPathFromEnv(std::vector< std::string > &sp)
Helper method to construct a directory search path by looking at relevant environment variables...
void log(const std::string &level, const std::string &msg, bool append_errno)
bool depsManifests(const std::string &name, bool direct, std::vector< std::string > &manifests)
List the manifests of a stackage's dependencies. Used by rosbuild.
static const char * MANIFEST_ATTR_URL
Package crawler. Create one of these to operate on a package tree. Call public methods inherited from...
void _rosdeps(Stackage *stackage, std::set< std::string > &rosdeps, const char *tag_name)
static const std::string g_ros_os
std::vector< std::string > licenses_
bool depsOn(const std::string &name, bool direct, std::vector< std::string > &deps)
Compute reverse dependencies of a stackage (i.e., stackages that depend on this stackage). Forces crawl.
Stackage * findWithRecrawl(const std::string &name)
void update_wet_information()
The base class for package/stack ("stackage") crawlers. Users of the library should use the functiona...
std::vector< Stackage * > deps_
virtual const char * usage()
Usage statement.
static const int MAX_CRAWL_DEPTH
void crawl(std::vector< std::string > search_path, bool force)
Crawl the filesystem, accumulating a database of stackages. May read results from a cache file instea...
bool isSysPackage(const std::string &pkgname)
bool vcs(const std::string &name, bool direct, std::vector< std::string > &vcs)
Compute vcs entries that are declared in manifest of a package and its dependencies. Was used by Hudson build scripts; might not be needed.
void logError(const std::string &msg, bool append_errno=false)
Log a error (usually goes to stderr).
static const char * ROSSTACK_NAME
bool depsIndent(const std::string &name, bool direct, std::vector< std::string > &deps)
Generate indented list of a stackage's dependencies, including duplicates. Intended for visual debugg...
bool cpp_exports(const std::string &name, const std::string &type, const std::string &attrib, bool deps_only, std::vector< std::pair< std::string, bool > > &flags)
Compute cpp exports declared in a package and its dependencies. Used by rosbuild. ...
void _gatherDepsFull(Stackage *stackage, bool direct, traversal_order_t order, int depth, boost::unordered_set< Stackage * > &deps_hash, std::vector< Stackage * > &deps, bool get_indented_deps, std::vector< std::string > &indented_deps, bool no_recursion_on_wet, std::vector< std::string > &dep_chain)
bool profile(const std::vector< std::string > &search_path, bool zombie_only, int length, std::vector< std::string > &dirs)
Report on time taken to crawl for stackages. Intended for use in debugging misconfigured stackage tre...
bool find(const std::string &name, std::string &path)
Look for a stackage.
Stackage(const std::string &name, const std::string &path, const std::string &manifest_path, const std::string &manifest_name)
static const char * ROSPACK_NAME
double time_since_epoch()
#define PyUnicode_FromString
std::string getCachePath()
bool plugins(const std::string &name, const std::string &attrib, const std::string &top, std::vector< std::string > &flags)
Compute exported plugins declared in packages that depend on a package. Forces crawl. Used by rosbuild and roslib.
void computeDepsInternal(Stackage *stackage, bool ignore_errors, const std::string &depend_tag, bool ignore_missing=false)
bool depsWhy(const std::string &from, const std::string &to, std::string &output)
Compute all dependency chains from one stackage to another. Intended for visual debugging of dependen...
static const char * MSG_GEN_GENERATED_DIR
static const char * MANIFEST_TAG_VERSIONCONTROL
void crawlDetail(const std::string &path, bool force, int depth, bool collect_profile_data, std::vector< DirectoryCrawlRecord * > &profile_data, boost::unordered_set< std::string > &profile_hash)
void logWarn(const std::string &msg, bool append_errno=false)
Log a warning (usually goes to stderr).
Rosstackage(const std::string &manifest_name, const std::string &cache_prefix, const std::string &name, const std::string &tag)
Constructor, only used by derived classes.
bool exports_dry_package(Stackage *stackage, const std::string &lang, const std::string &attrib, std::vector< std::string > &flags)
Compute exports declared in a dry package.
static const char * MANIFEST_PREFIX