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 tinyxml2::XMLElement* el = root->FirstChildElement(
"name");
184 name_ = el->GetText();
186 std::string tagname_license =
"license";
187 for(el = root->FirstChildElement(tagname_license.c_str()); el; el = el->NextSiblingElement(tagname_license.c_str()))
189 licenses_.push_back(el->GetText());
192 for(el = root->FirstChildElement(
"export"); el; el = el->NextSiblingElement(
"export"))
194 if(el->FirstChildElement(
"metapackage"))
196 is_metapackage_ =
true;
204 return manifest_name_ == MANIFEST_TAG_STACK || (is_wet_package_ && is_metapackage_);
209 return manifest_name_ == MANIFEST_TAG_PACKAGE || (is_wet_package_ && !is_metapackage_);
224 size_t start_num_pkgs) :
227 start_time_(start_time),
229 start_num_pkgs_(start_num_pkgs) {}
241 const std::string& cache_prefix,
242 const std::string& name,
243 const std::string& tag) :
244 manifest_name_(manifest_name),
245 cache_prefix_(cache_prefix),
259 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
273 log(
"Warning", msg, append_errno);
279 log(
"Error", msg, append_errno);
285 char* rpp = getenv(
"ROS_PACKAGE_PATH");
291 const char *path_delim =
";";
293 const char *path_delim = ":"; 296 std::vector<std::string> rpp_strings;
297 boost::split(rpp_strings, rpp,
298 boost::is_any_of(path_delim),
299 boost::token_compress_on);
300 for(std::vector<std::string>::const_iterator it = rpp_strings.begin();
301 it != rpp_strings.end();
321 if(!fs::is_directory(path))
324 catch(fs::filesystem_error& e)
326 logWarn(std::string(
"error while looking at ") + path +
": " + e.what());
332 for(fs::directory_iterator dit = fs::directory_iterator(path);
333 dit != fs::directory_iterator();
336 if(!fs::is_regular_file(dit->path()))
347 catch(fs::filesystem_error& e)
351 if(e.code().value() != EACCES)
353 logWarn(std::string(
"error while crawling ") + path +
": " + e.what() +
"; " + e.code().message());
386 std::vector<DirectoryCrawlRecord*> dummy;
387 boost::unordered_set<std::string> dummy2;
388 for(std::vector<std::string>::const_iterator p =
search_paths_.begin();
407 for(fs::path path = fs::current_path();
409 path = path.parent_path())
413 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 414 name = fs::path(path).filename();
417 name = fs::path(path).filename().string();
425 catch(fs::filesystem_error& e)
449 std::set<std::string>& packages)
452 boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
455 std::vector<std::string> search_paths;
456 search_paths.push_back(it->second->path_);
457 rp2.
crawl(search_paths,
true);
458 std::set<std::pair<std::string, std::string> > names_paths;
459 rp2.
list(names_paths);
460 for(std::set<std::pair<std::string, std::string> >::const_iterator iit = names_paths.begin();
461 iit != names_paths.end();
463 packages.insert(iit->first);
468 logError(std::string(
"stack ") + name +
" not found");
479 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
483 std::vector<std::string> search_paths;
484 search_paths.push_back(it->second->path_);
485 rp2.
crawl(search_paths,
true);
486 std::set<std::pair<std::string, std::string> > names_paths;
487 rp2.
list(names_paths);
488 for(std::set<std::pair<std::string, std::string> >::const_iterator iit = names_paths.begin();
489 iit != names_paths.end();
492 if(iit->first == name)
495 path = it->second->path_;
501 logError(std::string(
"stack containing package ") + name +
" not found");
508 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
512 std::pair<std::string, std::string> item;
513 item.first = it->first;
514 item.second = it->second->path_;
522 dups.resize(
dups_.size());
524 for(boost::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
537 for(boost::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
541 dups[it->first].resize(it->second.size());
543 for(std::vector<std::string>::const_iterator jt = it->second.begin();
544 jt != it->second.end();
547 dups[it->first][j] = *jt;
555 std::vector<std::string>&
deps)
557 std::vector<Stackage*> stackages;
571 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
572 it != stackages.end();
574 deps.push_back((*it)->name_);
580 std::vector<std::string>&
deps)
582 std::vector<Stackage*> stackages;
585 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
586 it != stackages.end();
588 deps.push_back((*it)->name_);
594 std::vector<std::string>&
deps)
602 std::vector<Stackage*> deps_vec;
603 boost::unordered_set<Stackage*> deps_hash;
604 std::vector<std::string> indented_deps;
606 for(std::vector<std::string>::const_iterator it = indented_deps.begin();
607 it != indented_deps.end();
621 const std::string& to,
631 std::list<std::list<Stackage*> > acc_list;
641 output.append(std::string(
"Dependency chains from ") +
642 from +
" to " + to +
":\n");
643 for(std::list<std::list<Stackage*> >::const_iterator it = acc_list.begin();
644 it != acc_list.end();
648 for(std::list<Stackage*>::const_iterator iit = it->begin();
652 if(iit != it->begin())
653 output.append(
"-> ");
654 output.append((*iit)->name_ +
" ");
663 std::vector<std::string>& manifests)
671 std::vector<Stackage*> deps_vec;
673 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
674 it != deps_vec.end();
676 manifests.push_back((*it)->manifest_path_);
688 std::set<std::string>&
rosdeps)
696 std::vector<Stackage*> deps_vec;
698 deps_vec.push_back(stackage);
701 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
702 it != deps_vec.end();
707 _rosdeps(*it, rosdeps, MANIFEST_TAG_ROSDEP);
712 _rosdeps(*it, rosdeps,
"build_depend");
713 _rosdeps(*it, rosdeps,
"buildtool_depend");
714 _rosdeps(*it, rosdeps,
"run_depend");
716 _rosdeps(*it, rosdeps,
"build_export_depend");
717 _rosdeps(*it, rosdeps,
"buildtool_export_depend");
718 _rosdeps(*it, rosdeps,
"exec_depend");
720 _rosdeps(*it, rosdeps,
"doc_depend");
721 _rosdeps(*it, rosdeps,
"test_depend");
737 for(tinyxml2::XMLElement* ele = root->FirstChildElement(tag_name);
739 ele = ele->NextSiblingElement(tag_name))
744 if((att_str = ele->Attribute(MANIFEST_ATTR_NAME)))
746 rosdeps.insert(std::string(
"name: ") + att_str);
751 const char* dep_pkgname = ele->GetText();
754 rosdeps.insert(std::string(
"name: ") + dep_pkgname);
762 std::vector<std::string>&
vcs)
770 std::vector<Stackage*> deps_vec;
772 deps_vec.push_back(stackage);
775 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
776 it != deps_vec.end();
780 for(tinyxml2::XMLElement* ele = root->FirstChildElement(MANIFEST_TAG_VERSIONCONTROL);
782 ele = ele->NextSiblingElement(MANIFEST_TAG_VERSIONCONTROL))
786 if((att_str = ele->Attribute(MANIFEST_ATTR_TYPE)))
788 result.append(
"type: ");
789 result.append(att_str);
791 if((att_str = ele->Attribute(MANIFEST_ATTR_URL)))
793 result.append(
"\turl: ");
794 result.append(att_str);
796 vcs.push_back(result);
810 const std::string& attrib,
bool deps_only,
811 std::vector<std::pair<std::string, bool> >& flags)
817 static bool init_py =
false;
818 static PyObject* pName;
819 static PyObject* pModule;
820 static PyObject* pDict;
821 static PyObject* pFunc;
826 std::vector<Stackage*> deps_vec;
828 deps_vec.push_back(stackage);
830 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
831 it != deps_vec.end();
834 if(!(*it)->is_wet_package_)
836 std::vector<std::string> dry_flags;
841 for(std::vector<std::string>::const_iterator it = dry_flags.begin(); it != dry_flags.end(); ++it)
843 flags.push_back(std::pair<std::string, bool>(*it,
false));
849 PyGILState_STATE gstate = PyGILState_Ensure();
855 pModule = PyImport_Import(pName);
859 PyGILState_Release(gstate);
860 std::string errmsg =
"could not find python module 'rosdep2.rospack'. is rosdep up-to-date (at least 0.10.4)?";
863 pDict = PyModule_GetDict(pModule);
864 pFunc = PyDict_GetItemString(pDict,
"call_pkg_config");
867 if(!PyCallable_Check(pFunc))
870 PyGILState_Release(gstate);
871 std::string errmsg =
"could not find python function 'rosdep2.rospack.call_pkg_config'. is rosdep up-to-date (at least 0.10.7)?";
875 PyObject* pArgs = PyTuple_New(2);
877 PyTuple_SetItem(pArgs, 0, pOpt);
879 PyTuple_SetItem(pArgs, 1, pPkg);
880 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
886 PyGILState_Release(gstate);
887 std::string errmsg =
"could not call python function 'rosdep2.rospack.call_pkg_config'";
890 if(pValue == Py_None)
893 std::string errmsg =
"python function 'rosdep2.rospack.call_pkg_config' could not call 'pkg-config " + type +
" " + (*it)->name_ +
"' without errors";
897 flags.push_back(std::pair<std::string, bool>(
PyBytes_AsString(pValue),
true));
907 PyGILState_Release(gstate);
922 static bool init_py =
false;
923 static PyObject* pName;
924 static PyObject* pModule;
925 static PyObject* pFunc;
928 PyGILState_STATE gstate = PyGILState_Ensure();
934 pModule = PyImport_Import(pName);
938 PyGILState_Release(gstate);
939 std::string errmsg =
"could not find python module 'catkin_pkg.rospack'. is catkin_pkg up-to-date (at least 0.1.8)?";
942 PyObject* pDict = PyModule_GetDict(pModule);
943 pFunc = PyDict_GetItemString(pDict,
"reorder_paths");
946 if(!PyCallable_Check(pFunc))
949 PyGILState_Release(gstate);
950 std::string errmsg =
"could not find python function 'catkin_pkg.rospack.reorder_paths'. is catkin_pkg up-to-date (at least 0.1.8)?";
955 PyObject* pArgs = PyTuple_New(1);
957 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
963 PyGILState_Release(gstate);
964 std::string errmsg =
"could not call python function 'catkin_pkg.rospack.reorder_paths'";
978 PyGILState_Release(gstate);
985 const std::string& attrib,
bool deps_only,
986 std::vector<std::string>& flags)
994 std::vector<Stackage*> deps_vec;
996 deps_vec.push_back(stackage);
998 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
999 it != deps_vec.end();
1018 const std::string& attrib,
1019 std::vector<std::string>& flags)
1022 for(tinyxml2::XMLElement* ele = root->FirstChildElement(MANIFEST_TAG_EXPORT);
1024 ele = ele->NextSiblingElement(MANIFEST_TAG_EXPORT))
1026 bool os_match =
false;
1027 const char *best_match = NULL;
1028 for(tinyxml2::XMLElement* ele2 = ele->FirstChildElement(lang.c_str());
1030 ele2 = ele2->NextSiblingElement(lang.c_str()))
1033 if ((os_str = ele2->Attribute(
"os")))
1035 if(g_ros_os == std::string(os_str))
1038 logWarn(std::string(
"ignoring duplicate ") + lang +
" tag with os=" + os_str +
" in export block");
1041 best_match = ele2->Attribute(attrib.c_str());
1049 best_match = ele2->Attribute(attrib.c_str());
1051 logWarn(std::string(
"ignoring duplicate ") + lang +
" tag in export block");
1057 std::string expanded_str;
1060 flags.push_back(expanded_str);
1066 if((lang ==
"cpp") && (attrib ==
"cflags"))
1070 if(fs::is_regular_file(msg_gen / MSG_GEN_GENERATED_FILE))
1072 msg_gen /= fs::path(
"cpp") /
"include";
1073 flags.push_back(std::string(
"-I" + msg_gen.string()));
1075 if(fs::is_regular_file(srv_gen / SRV_GEN_GENERATED_FILE))
1077 srv_gen /= fs::path(
"cpp") /
"include";
1078 flags.push_back(std::string(
"-I" + srv_gen.string()));
1086 const std::string& top,
1087 std::vector<std::string>& flags)
1090 std::vector<Stackage*> stackages;
1094 boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
1098 stackages.push_back(it->second);
1104 std::vector<Stackage*> top_deps;
1107 boost::unordered_set<Stackage*> top_deps_set;
1108 for(std::vector<Stackage*>::iterator it = top_deps.begin();
1109 it != top_deps.end();
1111 top_deps_set.insert(*it);
1112 std::vector<Stackage*>::iterator it = stackages.begin();
1113 while(it != stackages.end())
1115 if((*it)->name_ != top &&
1116 (top_deps_set.find(*it) == top_deps_set.end()))
1117 it = stackages.erase(it);
1123 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
1124 it != stackages.end();
1128 for(tinyxml2::XMLElement* ele = root->FirstChildElement(MANIFEST_TAG_EXPORT);
1130 ele = ele->NextSiblingElement(MANIFEST_TAG_EXPORT))
1132 for(tinyxml2::XMLElement* ele2 = ele->FirstChildElement(name.c_str());
1134 ele2 = ele2->NextSiblingElement(name.c_str()))
1136 const char *att_str;
1137 if((att_str = ele2->Attribute(attrib.c_str())))
1139 std::string expanded_str;
1142 flags.push_back((*it)->name_ +
" " + expanded_str);
1152 std::vector<std::string>& gens)
1160 std::vector<Stackage*> deps_vec;
1162 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1163 it != deps_vec.end();
1166 fs::path msg_gen = fs::path((*it)->path_) /
1167 MSG_GEN_GENERATED_DIR /
1169 fs::path srv_gen = fs::path((*it)->path_) /
1170 SRV_GEN_GENERATED_DIR /
1172 if(fs::is_regular_file(msg_gen))
1173 gens.push_back(msg_gen.string());
1174 if(fs::is_regular_file(srv_gen))
1175 gens.push_back(srv_gen.string());
1192 const std::string& msg,
1197 fprintf(stderr,
"[%s] %s: %s",
1198 name_.c_str(), level.c_str(), msg.c_str());
1200 fprintf(stderr,
": %s", strerror(errno));
1201 fprintf(stderr,
"\n");
1224 std::vector<Stackage*>&
deps)
1230 logError(std::string(
"no such package ") + name);
1237 std::vector<Stackage*> deps_vec;
1239 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1240 it != deps_vec.end();
1242 deps.push_back(*it);
1255 std::list<std::list<Stackage*> >& acc_list)
1258 for(std::vector<Stackage*>::const_iterator it = from->
deps_.begin();
1259 it != from->
deps_.end();
1262 if((*it)->name_ == to->
name_)
1264 std::list<Stackage*> acc;
1265 acc.push_back(from);
1267 acc_list.push_back(acc);
1271 std::list<std::list<Stackage*> > l;
1273 for(std::list<std::list<Stackage*> >::iterator iit = l.begin();
1277 iit->push_front(from);
1278 acc_list.push_back(*iit);
1286 std::vector<Stackage*>&
deps,
bool ignore_missing)
1292 logError(std::string(
"no such package ") + name);
1297 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
1302 std::vector<Stackage*> deps_vec;
1304 for(std::vector<Stackage*>::const_iterator iit = deps_vec.begin();
1305 iit != deps_vec.end();
1308 if((*iit)->name_ == name)
1310 deps.push_back(it->second);
1328 std::vector<std::string>& dirs)
1331 std::vector<DirectoryCrawlRecord*> dcrs;
1332 boost::unordered_set<std::string> dcrs_hash;
1333 for(std::vector<std::string>::const_iterator p = search_path.begin();
1334 p != search_path.end();
1343 snprintf(buf,
sizeof(buf),
"%.6f", total);
1344 dirs.push_back(std::string(
"Full tree crawl took ") + buf +
" seconds.");
1345 dirs.push_back(
"Directories marked with (*) contain no manifest. You may");
1346 dirs.push_back(
"want to delete these directories.");
1347 dirs.push_back(
"To get just of list of directories without manifests,");
1348 dirs.push_back(
"re-run the profile with --zombie-only");
1349 dirs.push_back(
"-------------------------------------------------------------");
1352 std::reverse(dcrs.begin(), dcrs.end());
1354 for(std::vector<DirectoryCrawlRecord*>::const_iterator it = dcrs.begin();
1362 if(length < 0 || i < length)
1363 dirs.push_back((*it)->path_);
1370 snprintf(buf,
sizeof(buf),
"%.6f", (*it)->crawl_time_);
1371 if(length < 0 || i < length)
1372 dirs.push_back(std::string(buf) +
" " +
1373 ((*it)->zombie_ ?
"* " :
" ") +
1387 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 1388 std::string name = fs::path(path).filename();
1391 std::string name = fs::path(path).filename().string();
1397 if(fs::is_regular_file(dry_manifest_path))
1401 else if(fs::is_regular_file(wet_manifest_path))
1427 std::vector<std::string> dups;
1443 bool collect_profile_data,
1444 std::vector<DirectoryCrawlRecord*>& profile_data,
1445 boost::unordered_set<std::string>& profile_hash)
1447 if(depth > MAX_CRAWL_DEPTH)
1448 throw Exception(
"maximum depth exceeded during crawl");
1452 if(!fs::is_directory(path))
1455 catch(fs::filesystem_error& e)
1457 logWarn(std::string(
"error while looking at ") + path +
": " + e.what());
1464 if(fs::is_regular_file(catkin_ignore))
1467 catch(fs::filesystem_error& e)
1469 logWarn(std::string(
"error while looking for ") + catkin_ignore.string() +
": " + e.what());
1481 if(fs::is_regular_file(nosubdirs))
1484 catch(fs::filesystem_error& e)
1486 logWarn(std::string(
"error while looking for ") + nosubdirs.string() +
": " + e.what());
1495 if(fs::is_regular_file(rospack_manifest))
1498 catch(fs::filesystem_error& e)
1500 logWarn(std::string(
"error while looking for ") + rospack_manifest.string() +
": " + e.what());
1504 if(collect_profile_data)
1506 if(profile_hash.find(path) == profile_hash.end())
1511 profile_data.push_back(dcr);
1512 profile_hash.insert(path);
1518 for(fs::directory_iterator dit = fs::directory_iterator(path);
1519 dit != fs::directory_iterator();
1522 if(fs::is_directory(dit->path()))
1524 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 1525 std::string name = dit->path().filename();
1528 std::string name = dit->path().filename().string();
1531 if(name.size() == 0 || name[0] ==
'.')
1535 collect_profile_data, profile_data, profile_hash);
1539 catch(fs::filesystem_error& e)
1543 if(e.code().value() != EACCES)
1545 logWarn(std::string(
"error while crawling ") + path +
": " + e.what());
1549 if(collect_profile_data && dcr != NULL)
1555 if(
stackages_.size() == dcr->start_num_pkgs_)
1556 dcr->zombie_ =
true;
1568 std::string errmsg = std::string(
"error parsing manifest of package ") +
1612 tinyxml2::XMLElement* root;
1615 const char* dep_pkgname;
1616 for(tinyxml2::XMLElement *dep_ele = root->FirstChildElement(depend_tag.c_str());
1618 dep_ele = dep_ele->NextSiblingElement(depend_tag.c_str()))
1622 dep_pkgname = dep_ele->Attribute(
tag_.c_str());
1626 dep_pkgname = dep_ele->GetText();
1632 std::string errmsg = std::string(
"bad depend syntax (no 'package/stack' attribute) in manifest ") + stackage->
name_ +
" at " + stackage->
manifest_path_;
1636 else if(dep_pkgname == stackage->
name_)
1653 stackage->
deps_.push_back(dep);
1657 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'";
1664 if (std::find(stackage->
deps_.begin(), stackage->
deps_.end(), dep) == stackage->
deps_.end())
1666 stackage->
deps_.push_back(dep);
1676 static bool initialized =
false;
1687 static std::map<std::string, bool> cache;
1688 if(cache.find(pkgname) != cache.end())
1690 return cache.find(pkgname)->second;
1694 PyGILState_STATE gstate = PyGILState_Ensure();
1696 static PyObject* pModule = 0;
1697 static PyObject* pDict = 0;
1701 pModule = PyImport_Import(pName);
1706 PyGILState_Release(gstate);
1707 std::string errmsg =
"could not find python module 'rosdep2.rospack'. is rosdep up-to-date (at least 0.10.4)?";
1710 pDict = PyModule_GetDict(pModule);
1713 static PyObject* pView = 0;
1716 PyObject* pFunc = PyDict_GetItemString(pDict,
"init_rospack_interface");
1717 if(!PyCallable_Check(pFunc))
1720 PyGILState_Release(gstate);
1721 std::string errmsg =
"could not find python function 'rosdep2.rospack.init_rospack_interface'. is rosdep up-to-date (at least 0.10.4)?";
1724 pView = PyObject_CallObject(pFunc, NULL);
1728 PyGILState_Release(gstate);
1729 std::string errmsg =
"could not call python function 'rosdep2.rospack.init_rospack_interface'";
1733 static bool rospack_view_not_empty =
false;
1734 if(!rospack_view_not_empty)
1736 PyObject* pFunc = PyDict_GetItemString(pDict,
"is_view_empty");
1737 if(!PyCallable_Check(pFunc))
1740 PyGILState_Release(gstate);
1741 std::string errmsg =
"could not find python function 'rosdep2.rospack.is_view_empty'. is rosdep up-to-date (at least 0.10.8)?";
1744 PyObject* pArgs = PyTuple_New(1);
1745 PyTuple_SetItem(pArgs, 0, pView);
1746 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
1749 if(PyObject_IsTrue(pValue))
1752 PyGILState_Release(gstate);
1753 std::string errmsg =
"the rosdep view is empty: call 'sudo rosdep init' and 'rosdep update'";
1756 rospack_view_not_empty =
true;
1759 PyObject* pFunc = PyDict_GetItemString(pDict,
"is_system_dependency");
1760 if(!PyCallable_Check(pFunc))
1763 PyGILState_Release(gstate);
1764 std::string errmsg =
"could not call python function 'rosdep2.rospack.is_system_dependency'. is rosdep up-to-date (at least 0.10.4)?";
1768 PyObject* pArgs = PyTuple_New(2);
1769 PyTuple_SetItem(pArgs, 0, pView);
1771 PyTuple_SetItem(pArgs, 1, pDep);
1772 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
1776 bool value = PyObject_IsTrue(pValue);
1786 PyGILState_Release(gstate);
1788 cache[pkgname] = value;
1796 std::vector<Stackage*>&
deps,
1797 bool no_recursion_on_wet)
1799 boost::unordered_set<Stackage*> deps_hash;
1800 std::vector<std::string> indented_deps;
1802 deps_hash, deps,
false, indented_deps, no_recursion_on_wet);
1808 boost::unordered_set<Stackage*>& deps_hash,
1809 std::vector<Stackage*>&
deps,
1810 bool get_indented_deps,
1811 std::vector<std::string>& indented_deps,
1812 bool no_recursion_on_wet,
1813 std::vector<std::string>& dep_chain)
1822 for(std::vector<Stackage*>::const_iterator it = stackage->
deps_.begin();
1823 it != stackage->
deps_.end();
1825 deps.push_back(*it);
1829 if(depth > MAX_DEPENDENCY_DEPTH) {
1831 for(std::vector<std::string>::const_iterator it = dep_chain.begin();
1832 it != dep_chain.end();
1835 std::vector<std::string>::const_iterator begin = dep_chain.begin();
1836 std::vector<std::string>::const_iterator cycle_begin = std::find(begin, it, *it);
1837 if(cycle_begin != it) {
1839 for(std::vector<std::string>::const_iterator jt = cycle_begin; jt != it; ++jt) {
1840 if(jt != cycle_begin) cycle +=
", ";
1846 throw Exception(std::string(
"maximum dependency depth exceeded (likely circular dependency") + cycle +
")");
1849 for(std::vector<Stackage*>::const_iterator it = stackage->
deps_.begin();
1850 it != stackage->
deps_.end();
1853 if(get_indented_deps)
1855 std::string indented_dep;
1856 for(
int i=0; i<depth; i++)
1857 indented_dep.append(
" ");
1858 indented_dep.append((*it)->name_);
1859 indented_deps.push_back(indented_dep);
1862 bool first = (deps_hash.find(*it) == deps_hash.end());
1865 deps_hash.insert(*it);
1869 deps.push_back(*it);
1871 if(!(*it)->is_wet_package_ || !no_recursion_on_wet)
1876 dep_chain.push_back((*it)->name_);
1878 get_indented_deps, indented_deps,
1879 no_recursion_on_wet, dep_chain);
1880 dep_chain.pop_back();
1885 deps.push_back(*it);
1894 boost::unordered_set<Stackage*>& deps_hash,
1895 std::vector<Stackage*>&
deps,
1896 bool get_indented_deps,
1897 std::vector<std::string>& indented_deps,
1898 bool no_recursion_on_wet)
1900 std::vector<std::string> dep_chain;
1901 dep_chain.push_back(stackage->
name_);
1908 no_recursion_on_wet,
1915 fs::path cache_path;
1917 char* ros_home = getenv(
"ROS_HOME");
1919 cache_path = ros_home;
1926 char* home_drive = getenv(
"HOMEDRIVE");
1927 char* home_path = getenv(
"HOMEPATH");
1928 if(home_drive && home_path)
1929 cache_path = fs::path(home_drive) / fs::path(home_path) / fs::path(DOTROS_NAME);
1932 struct passwd* passwd_ent;
1934 if((passwd_ent = getpwuid(geteuid())))
1935 home_path = passwd_ent->pw_dir;
1937 home_path = getenv(
"HOME");
1939 cache_path = fs::path(home_path) / fs::path(DOTROS_NAME);
1946 if(!fs::is_directory(cache_path))
1948 fs::create_directory(cache_path);
1951 catch(fs::filesystem_error& e)
1953 logWarn(std::string(
"cannot create rospack cache directory ") +
1954 cache_path.string() +
": " + e.what());
1957 return cache_path.string();
1964 char* rpp = getenv(
"ROS_PACKAGE_PATH");
1966 boost::hash<std::string> hash_func;
1967 value = hash_func(rpp);
1970 snprintf(buffer, 21,
"%020lu", value);
1983 char linebuf[30000];
1986 if (!fgets(linebuf,
sizeof(linebuf), cache))
1988 if (linebuf[0] ==
'#')
1990 char* newline_pos = strchr(linebuf,
'\n');
2010 if(!cache_path.size())
2012 logWarn(
"no location available to write cache file. Try setting ROS_HOME or HOME.");
2016 size_t len = cache_path.size() + 1;
2017 char *tmp_cache_dir =
new char[len];
2018 strncpy(tmp_cache_dir, cache_path.c_str(), len);
2019 #if defined(_MSC_VER) 2021 char tmp_cache_path[PATH_MAX];
2022 char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
2023 _splitpath_s(tmp_cache_dir, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME,
2025 char full_dir[_MAX_DRIVE + _MAX_DIR];
2026 _makepath_s(full_dir, _MAX_DRIVE + _MAX_DIR, drive, dir, NULL, NULL);
2027 snprintf(tmp_cache_path,
sizeof(tmp_cache_path),
"%s\\.rospack_cache.XXXXXX", full_dir);
2028 #elif defined(__MINGW32__) 2029 char tmp_cache_path[PATH_MAX];
2030 char* temp_name = tempnam(dirname(tmp_cache_dir),
".rospack_cache.");
2031 snprintf(tmp_cache_path,
sizeof(tmp_cache_path), temp_name);
2034 char *temp_dirname = dirname(tmp_cache_dir);
2035 len = strlen(temp_dirname) + 22 + 1;
2036 char *tmp_cache_path =
new char[len];
2037 snprintf(tmp_cache_path, len,
"%s/.rospack_cache.XXXXXX", temp_dirname);
2039 #if defined(__MINGW32__) 2042 int fd = open(tmp_cache_path, O_RDWR | O_EXCL | _O_CREAT, 0644);
2045 logWarn(std::string(
"unable to create temporary cache file ") +
2046 tmp_cache_path,
true);
2050 FILE *cache = fdopen(fd,
"w");
2051 #elif defined(WIN32) 2052 if (_mktemp_s(tmp_cache_path, PATH_MAX) != 0)
2055 "[rospack] Unable to generate temporary cache file name: %u",
2060 FILE *cache = fopen(tmp_cache_path,
"w");
2062 mode_t mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
2063 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)
2117 FILE* cache = fopen(cache_path.c_str(),
"r");
2122 if(fstat(fileno(cache), &s) == -1)
2128 double dt = difftime(time(NULL), s.st_mtime);
2131 if ((cache_max_age > 0.0) && (dt > cache_max_age))
2138 char linebuf[30000];
2139 bool ros_package_path_ok =
false;
2140 const char* ros_package_path = getenv(
"ROS_PACKAGE_PATH");
2143 if(!fgets(linebuf,
sizeof(linebuf), cache))
2145 linebuf[strlen(linebuf)-1] = 0;
2146 if (linebuf[0] ==
'#')
2148 if(!strncmp(
"#ROS_PACKAGE_PATH=", linebuf, 18))
2150 if(!ros_package_path)
2152 if(!strlen(linebuf+18))
2153 ros_package_path_ok =
true;
2155 else if(!strcmp(linebuf+18, ros_package_path))
2156 ros_package_path_ok =
true;
2162 if(ros_package_path_ok)
2166 fseek(cache, 0, SEEK_SET);
2178 const std::string& instring,
2179 std::string& outstring)
2181 outstring = instring;
2182 for(std::string::size_type i = outstring.find(MANIFEST_PREFIX);
2183 i != std::string::npos;
2184 i = outstring.find(MANIFEST_PREFIX))
2186 outstring.replace(i, std::string(MANIFEST_PREFIX).length(),
2193 if (outstring.find_first_of(
"$`") == std::string::npos)
2208 std::string cmd = std::string(
"ret=\"") + outstring +
"\" && echo $ret";
2211 std::string token(
"\n");
2212 for (std::string::size_type s = cmd.find(token);
2213 s != std::string::npos;
2214 s = cmd.find(token, s))
2215 cmd.replace(s,token.length(),std::string(
" "));
2218 if(!(p = popen(cmd.c_str(),
"r")))
2220 std::string errmsg =
2221 std::string(
"failed to execute backquote expression ") +
2230 memset(buf,0,
sizeof(buf));
2235 while(fgets(buf + strlen(buf),
sizeof(buf)-strlen(buf)-1,p));
2236 }
while(ferror(p) && errno == EINTR);
2240 std::string errmsg =
2241 std::string(
"got non-zero exit status from executing backquote expression ") +
2249 buf[strlen(buf)-1] =
'\0';
2263 ROSPACK_CACHE_PREFIX,
2265 MANIFEST_TAG_PACKAGE)
2272 return "USAGE: rospack <command> [options] [package]\n" 2273 " Allowed commands:\n" 2275 " cflags-only-I [--deps-only] [package]\n" 2276 " cflags-only-other [--deps-only] [package]\n" 2277 " depends [package] (alias: deps)\n" 2278 " depends-indent [package] (alias: deps-indent)\n" 2279 " depends-manifests [package] (alias: deps-manifests)\n" 2280 " depends-msgsrv [package] (alias: deps-msgsrv)\n" 2281 " depends-on [package]\n" 2282 " depends-on1 [package]\n" 2283 " depends-why --target=<target> [package] (alias: deps-why)\n" 2284 " depends1 [package] (alias: deps1)\n" 2285 " export [--deps-only] --lang=<lang> --attrib=<attrib> [package]\n" 2288 " libs-only-L [--deps-only] [package]\n" 2289 " libs-only-l [--deps-only] [package]\n" 2290 " libs-only-other [--deps-only] [package]\n" 2292 " list-duplicates\n" 2294 " plugins --attrib=<attrib> [--top=<toppkg>] [package]\n" 2295 " profile [--length=<length>] [--zombie-only]\n" 2296 " rosdep [package] (alias: rosdeps)\n" 2297 " rosdep0 [package] (alias: rosdeps0)\n" 2301 " -q Quiets error reports.\n\n" 2302 " If [package] is omitted, the current working directory\n" 2303 " is used (if it contains a package.xml or manifest.xml).\n\n";
2316 ROSSTACK_CACHE_PREFIX,
2325 return "USAGE: rosstack [options] <command> [stack]\n" 2326 " Allowed commands:\n" 2329 " contents [stack]\n" 2332 " depends [stack] (alias: deps)\n" 2333 " depends-manifests [stack] (alias: deps-manifests)\n" 2334 " depends1 [stack] (alias: deps1)\n" 2335 " depends-indent [stack] (alias: deps-indent)\n" 2336 " depends-why --target=<target> [stack] (alias: deps-why)\n" 2337 " depends-on [stack]\n" 2338 " depends-on1 [stack]\n" 2339 " contains [package]\n" 2340 " contains-path [package]\n" 2341 " profile [--length=<length>] \n\n" 2342 " If [stack] is omitted, the current working directory\n" 2343 " is used (if it contains a stack.xml).\n\n";
2351 tinyxml2::XMLElement*
2354 tinyxml2::XMLElement* ele = stackage->
manifest_.RootElement();
2357 std::string errmsg = std::string(
"error parsing manifest of package ") +
2368 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 2369 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 2371 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL 2374 unsigned __int64 tmpres = 0;
2376 GetSystemTimeAsFileTime(&ft);
2377 tmpres |= ft.dwHighDateTime;
2379 tmpres |= ft.dwLowDateTime;
2381 tmpres -= DELTA_EPOCH_IN_MICROSECS;
2382 return static_cast<double>(tmpres) / 1e6;
2385 gettimeofday(&tod, NULL);
2386 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 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 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_
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)
static const char * SRV_GEN_GENERATED_FILE
static const char * ROSPACK_MANIFEST_NAME
static const char * MANIFEST_ATTR_NAME
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 * 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 depsWhyDetail(Stackage *from, Stackage *to, std::list< std::list< Stackage *> > &acc_list)
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
boost::unordered_map< std::string, std::vector< std::string > > dups_
static const char * ROSSTACK_MANIFEST_NAME
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 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 gatherDeps(Stackage *stackage, bool direct, traversal_order_t order, std::vector< Stackage *> &deps, bool no_recursion_on_wet=false)
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 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 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. ...
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