32 #include <boost/algorithm/string.hpp> 33 #include <boost/filesystem.hpp> 34 #include <boost/functional/hash.hpp> 44 #define snprintf _snprintf 45 #define pclose _pclose 47 #define PATH_MAX MAX_PATH 48 #if defined(__MINGW32__) 55 #include <sys/types.h> 75 #if PY_VERSION_HEX < 0x03000000 76 #undef PyBytes_AsString 77 #undef PyUnicode_AsUTF8 78 #undef PyUnicode_FromString 79 #define PyBytes_AsString PyString_AsString 80 #define PyUnicode_AsUTF8 PyString_AsString 81 #define PyUnicode_FromString PyString_FromString 89 namespace fs = boost::filesystem;
122 static const std::string
g_ros_os =
"osx";
125 static const std::string g_ros_os =
"win32";
127 static const std::string g_ros_os =
"linux";
135 : std::runtime_error(what)
162 const std::string& path,
163 const std::string& manifest_path,
164 const std::string& manifest_name) :
167 manifest_path_(manifest_path),
168 manifest_name_(manifest_name),
169 manifest_loaded_(false),
170 deps_computed_(false),
171 is_metapackage_(false)
178 assert(is_wet_package_);
179 assert(manifest_loaded_);
182 for(TiXmlElement* el = root->FirstChildElement(
"name"); el; el = el->NextSiblingElement(
"name"))
184 name_ = el->GetText();
188 std::string tagname_license =
"license";
189 for(TiXmlElement* el = root->FirstChildElement(tagname_license); el; el = el->NextSiblingElement(tagname_license ))
191 licenses_.push_back(el->GetText());
194 for(TiXmlElement* 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 #if BOOST_VERSION < 106500 262 for(std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
264 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
279 log(
"Warning", msg, append_errno);
285 log(
"Error", msg, append_errno);
291 char* rpp = getenv(
"ROS_PACKAGE_PATH");
297 const char *path_delim =
";";
299 const char *path_delim = ":"; 302 std::vector<std::string> rpp_strings;
303 boost::split(rpp_strings, rpp,
304 boost::is_any_of(path_delim),
305 boost::token_compress_on);
306 for(std::vector<std::string>::const_iterator it = rpp_strings.begin();
307 it != rpp_strings.end();
327 if(!fs::is_directory(path))
330 catch(fs::filesystem_error& e)
332 logWarn(std::string(
"error while looking at ") + path +
": " + e.what());
338 for(fs::directory_iterator dit = fs::directory_iterator(path);
339 dit != fs::directory_iterator();
342 if(!fs::is_regular_file(dit->path()))
353 catch(fs::filesystem_error& e)
355 logWarn(std::string(
"error while crawling ") + path +
": " + e.what());
387 std::vector<DirectoryCrawlRecord*> dummy;
389 #if BOOST_VERSION < 106500 390 std::tr1::unordered_set<std::string> dummy2;
392 boost::unordered_set<std::string> dummy2;
394 for(std::vector<std::string>::const_iterator p =
search_paths_.begin();
413 for(fs::path path = fs::current_path();
415 path = path.parent_path())
419 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 420 name = fs::path(path).filename();
423 name = fs::path(path).filename().string();
431 catch(fs::filesystem_error& e)
455 std::set<std::string>& packages)
458 #if BOOST_VERSION < 106500 459 std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
461 boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
465 std::vector<std::string> search_paths;
466 search_paths.push_back(it->second->path_);
467 rp2.
crawl(search_paths,
true);
468 std::set<std::pair<std::string, std::string> > names_paths;
469 rp2.
list(names_paths);
470 for(std::set<std::pair<std::string, std::string> >::const_iterator iit = names_paths.begin();
471 iit != names_paths.end();
473 packages.insert(iit->first);
478 logError(std::string(
"stack ") + name +
" not found");
489 #if BOOST_VERSION < 106500 490 for(std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
492 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
497 std::vector<std::string> search_paths;
498 search_paths.push_back(it->second->path_);
499 rp2.
crawl(search_paths,
true);
500 std::set<std::pair<std::string, std::string> > names_paths;
501 rp2.
list(names_paths);
502 for(std::set<std::pair<std::string, std::string> >::const_iterator iit = names_paths.begin();
503 iit != names_paths.end();
506 if(iit->first == name)
509 path = it->second->path_;
515 logError(std::string(
"stack containing package ") + name +
" not found");
522 #if BOOST_VERSION < 106500 523 for(std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
525 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
530 std::pair<std::string, std::string> item;
531 item.first = it->first;
532 item.second = it->second->path_;
540 dups.resize(
dups_.size());
542 #if BOOST_VERSION < 106500 543 for(std::tr1::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
545 for(boost::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
559 #if BOOST_VERSION < 106500 560 for(std::tr1::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
562 for(boost::unordered_map<std::string, std::vector<std::string> >::const_iterator it =
dups_.begin();
567 dups[it->first].resize(it->second.size());
569 for(std::vector<std::string>::const_iterator jt = it->second.begin();
570 jt != it->second.end();
573 dups[it->first][j] = *jt;
581 std::vector<std::string>&
deps)
583 std::vector<Stackage*> stackages;
597 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
598 it != stackages.end();
600 deps.push_back((*it)->name_);
606 std::vector<std::string>&
deps)
608 std::vector<Stackage*> stackages;
611 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
612 it != stackages.end();
614 deps.push_back((*it)->name_);
620 std::vector<std::string>&
deps)
628 std::vector<Stackage*> deps_vec;
629 #if BOOST_VERSION < 106500 630 std::tr1::unordered_set<Stackage*> deps_hash;
632 boost::unordered_set<Stackage*> deps_hash;
634 std::vector<std::string> indented_deps;
636 for(std::vector<std::string>::const_iterator it = indented_deps.begin();
637 it != indented_deps.end();
651 const std::string& to,
661 std::list<std::list<Stackage*> > acc_list;
671 output.append(std::string(
"Dependency chains from ") +
672 from +
" to " + to +
":\n");
673 for(std::list<std::list<Stackage*> >::const_iterator it = acc_list.begin();
674 it != acc_list.end();
678 for(std::list<Stackage*>::const_iterator iit = it->begin();
682 if(iit != it->begin())
683 output.append(
"-> ");
684 output.append((*iit)->name_ +
" ");
693 std::vector<std::string>& manifests)
701 std::vector<Stackage*> deps_vec;
703 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
704 it != deps_vec.end();
706 manifests.push_back((*it)->manifest_path_);
718 std::set<std::string>&
rosdeps)
726 std::vector<Stackage*> deps_vec;
728 deps_vec.push_back(stackage);
731 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
732 it != deps_vec.end();
737 _rosdeps(*it, rosdeps, MANIFEST_TAG_ROSDEP);
742 _rosdeps(*it, rosdeps,
"build_depend");
743 _rosdeps(*it, rosdeps,
"buildtool_depend");
744 _rosdeps(*it, rosdeps,
"run_depend");
746 _rosdeps(*it, rosdeps,
"build_export_depend");
747 _rosdeps(*it, rosdeps,
"buildtool_export_depend");
748 _rosdeps(*it, rosdeps,
"exec_depend");
750 _rosdeps(*it, rosdeps,
"doc_depend");
751 _rosdeps(*it, rosdeps,
"test_depend");
767 for(TiXmlElement* ele = root->FirstChildElement(tag_name);
769 ele = ele->NextSiblingElement(tag_name))
774 if((att_str = ele->Attribute(MANIFEST_ATTR_NAME)))
776 rosdeps.insert(std::string(
"name: ") + att_str);
781 const char* dep_pkgname = ele->GetText();
784 rosdeps.insert(std::string(
"name: ") + dep_pkgname);
792 std::vector<std::string>&
vcs)
800 std::vector<Stackage*> deps_vec;
802 deps_vec.push_back(stackage);
805 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
806 it != deps_vec.end();
810 for(TiXmlElement* ele = root->FirstChildElement(MANIFEST_TAG_VERSIONCONTROL);
812 ele = ele->NextSiblingElement(MANIFEST_TAG_VERSIONCONTROL))
816 if((att_str = ele->Attribute(MANIFEST_ATTR_TYPE)))
818 result.append(
"type: ");
819 result.append(att_str);
821 if((att_str = ele->Attribute(MANIFEST_ATTR_URL)))
823 result.append(
"\turl: ");
824 result.append(att_str);
826 vcs.push_back(result);
840 const std::string& attrib,
bool deps_only,
841 std::vector<std::pair<std::string, bool> >& flags)
847 static bool init_py =
false;
848 static PyObject* pName;
849 static PyObject* pModule;
850 static PyObject* pDict;
851 static PyObject* pFunc;
856 std::vector<Stackage*> deps_vec;
858 deps_vec.push_back(stackage);
860 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
861 it != deps_vec.end();
864 if(!(*it)->is_wet_package_)
866 std::vector<std::string> dry_flags;
871 for(std::vector<std::string>::const_iterator it = dry_flags.begin(); it != dry_flags.end(); ++it)
873 flags.push_back(std::pair<std::string, bool>(*it,
false));
879 PyGILState_STATE gstate = PyGILState_Ensure();
885 pModule = PyImport_Import(pName);
889 PyGILState_Release(gstate);
890 std::string errmsg =
"could not find python module 'rosdep2.rospack'. is rosdep up-to-date (at least 0.10.4)?";
893 pDict = PyModule_GetDict(pModule);
894 pFunc = PyDict_GetItemString(pDict,
"call_pkg_config");
897 if(!PyCallable_Check(pFunc))
900 PyGILState_Release(gstate);
901 std::string errmsg =
"could not find python function 'rosdep2.rospack.call_pkg_config'. is rosdep up-to-date (at least 0.10.7)?";
905 PyObject* pArgs = PyTuple_New(2);
907 PyTuple_SetItem(pArgs, 0, pOpt);
909 PyTuple_SetItem(pArgs, 1, pPkg);
910 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
916 PyGILState_Release(gstate);
917 std::string errmsg =
"could not call python function 'rosdep2.rospack.call_pkg_config'";
920 if(pValue == Py_None)
923 std::string errmsg =
"python function 'rosdep2.rospack.call_pkg_config' could not call 'pkg-config " + type +
" " + (*it)->name_ +
"' without errors";
927 flags.push_back(std::pair<std::string, bool>(
PyBytes_AsString(pValue),
true));
937 PyGILState_Release(gstate);
952 static bool init_py =
false;
953 static PyObject* pName;
954 static PyObject* pModule;
955 static PyObject* pFunc;
958 PyGILState_STATE gstate = PyGILState_Ensure();
964 pModule = PyImport_Import(pName);
968 PyGILState_Release(gstate);
969 std::string errmsg =
"could not find python module 'catkin_pkg.rospack'. is catkin_pkg up-to-date (at least 0.1.8)?";
972 PyObject* pDict = PyModule_GetDict(pModule);
973 pFunc = PyDict_GetItemString(pDict,
"reorder_paths");
976 if(!PyCallable_Check(pFunc))
979 PyGILState_Release(gstate);
980 std::string errmsg =
"could not find python function 'catkin_pkg.rospack.reorder_paths'. is catkin_pkg up-to-date (at least 0.1.8)?";
985 PyObject* pArgs = PyTuple_New(1);
987 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
993 PyGILState_Release(gstate);
994 std::string errmsg =
"could not call python function 'catkin_pkg.rospack.reorder_paths'";
1008 PyGILState_Release(gstate);
1015 const std::string& attrib,
bool deps_only,
1016 std::vector<std::string>& flags)
1024 std::vector<Stackage*> deps_vec;
1026 deps_vec.push_back(stackage);
1028 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1029 it != deps_vec.end();
1048 const std::string& attrib,
1049 std::vector<std::string>& flags)
1052 for(TiXmlElement* ele = root->FirstChildElement(MANIFEST_TAG_EXPORT);
1054 ele = ele->NextSiblingElement(MANIFEST_TAG_EXPORT))
1056 bool os_match =
false;
1057 const char *best_match = NULL;
1058 for(TiXmlElement* ele2 = ele->FirstChildElement(lang);
1060 ele2 = ele2->NextSiblingElement(lang))
1063 if ((os_str = ele2->Attribute(
"os")))
1065 if(g_ros_os == std::string(os_str))
1068 logWarn(std::string(
"ignoring duplicate ") + lang +
" tag with os=" + os_str +
" in export block");
1071 best_match = ele2->Attribute(attrib.c_str());
1079 best_match = ele2->Attribute(attrib.c_str());
1081 logWarn(std::string(
"ignoring duplicate ") + lang +
" tag in export block");
1087 std::string expanded_str;
1090 flags.push_back(expanded_str);
1096 if((lang ==
"cpp") && (attrib ==
"cflags"))
1100 if(fs::is_regular_file(msg_gen / MSG_GEN_GENERATED_FILE))
1102 msg_gen /= fs::path(
"cpp") /
"include";
1103 flags.push_back(std::string(
"-I" + msg_gen.string()));
1105 if(fs::is_regular_file(srv_gen / SRV_GEN_GENERATED_FILE))
1107 srv_gen /= fs::path(
"cpp") /
"include";
1108 flags.push_back(std::string(
"-I" + srv_gen.string()));
1116 const std::string& top,
1117 std::vector<std::string>& flags)
1120 std::vector<Stackage*> stackages;
1124 #if BOOST_VERSION < 106500 1125 std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
1127 boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.find(name);
1132 stackages.push_back(it->second);
1138 std::vector<Stackage*> top_deps;
1141 #if BOOST_VERSION < 106500 1142 std::tr1::unordered_set<Stackage*> top_deps_set;
1144 boost::unordered_set<Stackage*> top_deps_set;
1146 for(std::vector<Stackage*>::iterator it = top_deps.begin();
1147 it != top_deps.end();
1149 top_deps_set.insert(*it);
1150 std::vector<Stackage*>::iterator it = stackages.begin();
1151 while(it != stackages.end())
1153 if((*it)->name_ != top &&
1154 (top_deps_set.find(*it) == top_deps_set.end()))
1155 it = stackages.erase(it);
1161 for(std::vector<Stackage*>::const_iterator it = stackages.begin();
1162 it != stackages.end();
1166 for(TiXmlElement* ele = root->FirstChildElement(MANIFEST_TAG_EXPORT);
1168 ele = ele->NextSiblingElement(MANIFEST_TAG_EXPORT))
1170 for(TiXmlElement* ele2 = ele->FirstChildElement(name);
1172 ele2 = ele2->NextSiblingElement(name))
1174 const char *att_str;
1175 if((att_str = ele2->Attribute(attrib.c_str())))
1177 std::string expanded_str;
1180 flags.push_back((*it)->name_ +
" " + expanded_str);
1190 std::vector<std::string>& gens)
1198 std::vector<Stackage*> deps_vec;
1200 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1201 it != deps_vec.end();
1204 fs::path msg_gen = fs::path((*it)->path_) /
1205 MSG_GEN_GENERATED_DIR /
1207 fs::path srv_gen = fs::path((*it)->path_) /
1208 SRV_GEN_GENERATED_DIR /
1210 if(fs::is_regular_file(msg_gen))
1211 gens.push_back(msg_gen.string());
1212 if(fs::is_regular_file(srv_gen))
1213 gens.push_back(srv_gen.string());
1230 const std::string& msg,
1235 fprintf(stderr,
"[%s] %s: %s",
1236 name_.c_str(), level.c_str(), msg.c_str());
1238 fprintf(stderr,
": %s", strerror(errno));
1239 fprintf(stderr,
"\n");
1262 std::vector<Stackage*>&
deps)
1268 logError(std::string(
"no such package ") + name);
1275 std::vector<Stackage*> deps_vec;
1277 for(std::vector<Stackage*>::const_iterator it = deps_vec.begin();
1278 it != deps_vec.end();
1280 deps.push_back(*it);
1293 std::list<std::list<Stackage*> >& acc_list)
1296 for(std::vector<Stackage*>::const_iterator it = from->
deps_.begin();
1297 it != from->
deps_.end();
1300 if((*it)->name_ == to->
name_)
1302 std::list<Stackage*> acc;
1303 acc.push_back(from);
1305 acc_list.push_back(acc);
1309 std::list<std::list<Stackage*> > l;
1311 for(std::list<std::list<Stackage*> >::iterator iit = l.begin();
1315 iit->push_front(from);
1316 acc_list.push_back(*iit);
1324 std::vector<Stackage*>&
deps,
bool ignore_missing)
1330 logError(std::string(
"no such package ") + name);
1335 #if BOOST_VERSION < 106500 1336 for(std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
1338 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
1344 std::vector<Stackage*> deps_vec;
1346 for(std::vector<Stackage*>::const_iterator iit = deps_vec.begin();
1347 iit != deps_vec.end();
1350 if((*iit)->name_ == name)
1352 deps.push_back(it->second);
1370 std::vector<std::string>& dirs)
1373 std::vector<DirectoryCrawlRecord*> dcrs;
1374 #if BOOST_VERSION < 106500 1375 std::tr1::unordered_set<std::string> dcrs_hash;
1377 boost::unordered_set<std::string> dcrs_hash;
1379 for(std::vector<std::string>::const_iterator p = search_path.begin();
1380 p != search_path.end();
1389 snprintf(buf,
sizeof(buf),
"%.6f", total);
1390 dirs.push_back(std::string(
"Full tree crawl took ") + buf +
" seconds.");
1391 dirs.push_back(
"Directories marked with (*) contain no manifest. You may");
1392 dirs.push_back(
"want to delete these directories.");
1393 dirs.push_back(
"To get just of list of directories without manifests,");
1394 dirs.push_back(
"re-run the profile with --zombie-only");
1395 dirs.push_back(
"-------------------------------------------------------------");
1398 std::reverse(dcrs.begin(), dcrs.end());
1400 for(std::vector<DirectoryCrawlRecord*>::const_iterator it = dcrs.begin();
1408 if(length < 0 || i < length)
1409 dirs.push_back((*it)->path_);
1416 snprintf(buf,
sizeof(buf),
"%.6f", (*it)->crawl_time_);
1417 if(length < 0 || i < length)
1418 dirs.push_back(std::string(buf) +
" " +
1419 ((*it)->zombie_ ?
"* " :
" ") +
1433 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 1434 std::string name = fs::path(path).filename();
1437 std::string name = fs::path(path).filename().string();
1443 if(fs::is_regular_file(dry_manifest_path))
1447 else if(fs::is_regular_file(wet_manifest_path))
1470 std::vector<std::string> dups;
1486 bool collect_profile_data,
1487 std::vector<DirectoryCrawlRecord*>& profile_data,
1488 #
if BOOST_VERSION < 106500
1489 std::tr1::unordered_set<std::string>& profile_hash)
1491 boost::unordered_set<std::string>& profile_hash)
1494 if(depth > MAX_CRAWL_DEPTH)
1495 throw Exception(
"maximum depth exceeded during crawl");
1499 if(!fs::is_directory(path))
1502 catch(fs::filesystem_error& e)
1504 logWarn(std::string(
"error while looking at ") + path +
": " + e.what());
1511 if(fs::is_regular_file(catkin_ignore))
1514 catch(fs::filesystem_error& e)
1516 logWarn(std::string(
"error while looking for ") + catkin_ignore.string() +
": " + e.what());
1528 if(fs::is_regular_file(nosubdirs))
1531 catch(fs::filesystem_error& e)
1533 logWarn(std::string(
"error while looking for ") + nosubdirs.string() +
": " + e.what());
1542 if(fs::is_regular_file(rospack_manifest))
1545 catch(fs::filesystem_error& e)
1547 logWarn(std::string(
"error while looking for ") + rospack_manifest.string() +
": " + e.what());
1551 if(collect_profile_data)
1553 if(profile_hash.find(path) == profile_hash.end())
1558 profile_data.push_back(dcr);
1559 profile_hash.insert(path);
1565 for(fs::directory_iterator dit = fs::directory_iterator(path);
1566 dit != fs::directory_iterator();
1569 if(fs::is_directory(dit->path()))
1571 #if !defined(BOOST_FILESYSTEM_VERSION) || (BOOST_FILESYSTEM_VERSION == 2) 1572 std::string name = dit->path().filename();
1575 std::string name = dit->path().filename().string();
1578 if(name.size() == 0 || name[0] ==
'.')
1582 collect_profile_data, profile_data, profile_hash);
1586 catch(fs::filesystem_error& e)
1588 logWarn(std::string(
"error while crawling ") + path +
": " + e.what());
1591 if(collect_profile_data && dcr != NULL)
1597 if(
stackages_.size() == dcr->start_num_pkgs_)
1598 dcr->zombie_ =
true;
1610 std::string errmsg = std::string(
"error parsing manifest of package ") +
1657 TiXmlNode *dep_node = NULL;
1658 const char* dep_pkgname;
1659 while((dep_node = root->IterateChildren(depend_tag, dep_node)))
1661 TiXmlElement *dep_ele = dep_node->ToElement();
1664 dep_pkgname = dep_ele->Attribute(
tag_.c_str());
1668 dep_pkgname = dep_ele->GetText();
1674 std::string errmsg = std::string(
"bad depend syntax (no 'package/stack' attribute) in manifest ") + stackage->
name_ +
" at " + stackage->
manifest_path_;
1678 else if(dep_pkgname == stackage->
name_)
1695 stackage->
deps_.push_back(dep);
1699 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'";
1706 if (std::find(stackage->
deps_.begin(), stackage->
deps_.end(), dep) == stackage->
deps_.end())
1708 stackage->
deps_.push_back(dep);
1718 static bool initialized =
false;
1729 static std::map<std::string, bool> cache;
1730 if(cache.find(pkgname) != cache.end())
1732 return cache.find(pkgname)->second;
1736 PyGILState_STATE gstate = PyGILState_Ensure();
1738 static PyObject* pModule = 0;
1739 static PyObject* pDict = 0;
1743 pModule = PyImport_Import(pName);
1748 PyGILState_Release(gstate);
1749 std::string errmsg =
"could not find python module 'rosdep2.rospack'. is rosdep up-to-date (at least 0.10.4)?";
1752 pDict = PyModule_GetDict(pModule);
1755 static PyObject* pView = 0;
1758 PyObject* pFunc = PyDict_GetItemString(pDict,
"init_rospack_interface");
1759 if(!PyCallable_Check(pFunc))
1762 PyGILState_Release(gstate);
1763 std::string errmsg =
"could not find python function 'rosdep2.rospack.init_rospack_interface'. is rosdep up-to-date (at least 0.10.4)?";
1766 pView = PyObject_CallObject(pFunc, NULL);
1770 PyGILState_Release(gstate);
1771 std::string errmsg =
"could not call python function 'rosdep2.rospack.init_rospack_interface'";
1775 static bool rospack_view_not_empty =
false;
1776 if(!rospack_view_not_empty)
1778 PyObject* pFunc = PyDict_GetItemString(pDict,
"is_view_empty");
1779 if(!PyCallable_Check(pFunc))
1782 PyGILState_Release(gstate);
1783 std::string errmsg =
"could not find python function 'rosdep2.rospack.is_view_empty'. is rosdep up-to-date (at least 0.10.8)?";
1786 PyObject* pArgs = PyTuple_New(1);
1787 PyTuple_SetItem(pArgs, 0, pView);
1788 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
1791 if(PyObject_IsTrue(pValue))
1794 PyGILState_Release(gstate);
1795 std::string errmsg =
"the rosdep view is empty: call 'sudo rosdep init' and 'rosdep update'";
1798 rospack_view_not_empty =
true;
1801 PyObject* pFunc = PyDict_GetItemString(pDict,
"is_system_dependency");
1802 if(!PyCallable_Check(pFunc))
1805 PyGILState_Release(gstate);
1806 std::string errmsg =
"could not call python function 'rosdep2.rospack.is_system_dependency'. is rosdep up-to-date (at least 0.10.4)?";
1810 PyObject* pArgs = PyTuple_New(2);
1811 PyTuple_SetItem(pArgs, 0, pView);
1813 PyTuple_SetItem(pArgs, 1, pDep);
1814 PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
1818 bool value = PyObject_IsTrue(pValue);
1828 PyGILState_Release(gstate);
1830 cache[pkgname] = value;
1838 std::vector<Stackage*>&
deps,
1839 bool no_recursion_on_wet)
1841 #if BOOST_VERSION < 106500 1842 std::tr1::unordered_set<Stackage*> deps_hash;
1844 boost::unordered_set<Stackage*> deps_hash;
1846 std::vector<std::string> indented_deps;
1848 deps_hash, deps,
false, indented_deps, no_recursion_on_wet);
1854 #
if BOOST_VERSION < 106500
1855 std::tr1::unordered_set<Stackage*>& deps_hash,
1857 boost::unordered_set<Stackage*>& deps_hash,
1859 std::vector<Stackage*>&
deps,
1860 bool get_indented_deps,
1861 std::vector<std::string>& indented_deps,
1862 bool no_recursion_on_wet,
1863 std::vector<std::string>& dep_chain)
1872 for(std::vector<Stackage*>::const_iterator it = stackage->
deps_.begin();
1873 it != stackage->
deps_.end();
1875 deps.push_back(*it);
1879 if(depth > MAX_DEPENDENCY_DEPTH) {
1881 for(std::vector<std::string>::const_iterator it = dep_chain.begin();
1882 it != dep_chain.end();
1885 std::vector<std::string>::const_iterator begin = dep_chain.begin();
1886 std::vector<std::string>::const_iterator cycle_begin = std::find(begin, it, *it);
1887 if(cycle_begin != it) {
1889 for(std::vector<std::string>::const_iterator jt = cycle_begin; jt != it; ++jt) {
1890 if(jt != cycle_begin) cycle +=
", ";
1896 throw Exception(std::string(
"maximum dependency depth exceeded (likely circular dependency") + cycle +
")");
1899 for(std::vector<Stackage*>::const_iterator it = stackage->
deps_.begin();
1900 it != stackage->
deps_.end();
1903 if(get_indented_deps)
1905 std::string indented_dep;
1906 for(
int i=0; i<depth; i++)
1907 indented_dep.append(
" ");
1908 indented_dep.append((*it)->name_);
1909 indented_deps.push_back(indented_dep);
1912 bool first = (deps_hash.find(*it) == deps_hash.end());
1915 deps_hash.insert(*it);
1919 deps.push_back(*it);
1921 if(!(*it)->is_wet_package_ || !no_recursion_on_wet)
1926 dep_chain.push_back((*it)->name_);
1928 get_indented_deps, indented_deps,
1929 no_recursion_on_wet, dep_chain);
1930 dep_chain.pop_back();
1935 deps.push_back(*it);
1944 #
if BOOST_VERSION < 106500
1945 std::tr1::unordered_set<Stackage*>& deps_hash,
1947 boost::unordered_set<Stackage*>& deps_hash,
1949 std::vector<Stackage*>&
deps,
1950 bool get_indented_deps,
1951 std::vector<std::string>& indented_deps,
1952 bool no_recursion_on_wet)
1954 std::vector<std::string> dep_chain;
1955 dep_chain.push_back(stackage->
name_);
1962 no_recursion_on_wet,
1969 fs::path cache_path;
1971 char* ros_home = getenv(
"ROS_HOME");
1973 cache_path = ros_home;
1980 char* home_drive = getenv(
"HOMEDRIVE");
1981 char* home_path = getenv(
"HOMEPATH");
1982 if(home_drive && home_path)
1983 cache_path = fs::path(home_drive) / fs::path(home_path) / fs::path(DOTROS_NAME);
1986 struct passwd* passwd_ent;
1988 if((passwd_ent = getpwuid(geteuid())))
1989 home_path = passwd_ent->pw_dir;
1991 home_path = getenv(
"HOME");
1993 cache_path = fs::path(home_path) / fs::path(DOTROS_NAME);
2000 if(!fs::is_directory(cache_path))
2002 fs::create_directory(cache_path);
2005 catch(fs::filesystem_error& e)
2007 logWarn(std::string(
"cannot create rospack cache directory ") +
2008 cache_path.string() +
": " + e.what());
2011 return cache_path.string();
2018 char* rpp = getenv(
"ROS_PACKAGE_PATH");
2020 boost::hash<std::string> hash_func;
2021 value = hash_func(rpp);
2024 snprintf(buffer, 21,
"%020lu", value);
2037 char linebuf[30000];
2040 if (!fgets(linebuf,
sizeof(linebuf), cache))
2042 if (linebuf[0] ==
'#')
2044 char* newline_pos = strchr(linebuf,
'\n');
2064 if(!cache_path.size())
2066 logWarn(
"no location available to write cache file. Try setting ROS_HOME or HOME.");
2070 size_t len = cache_path.size() + 1;
2071 char *tmp_cache_dir =
new char[len];
2072 strncpy(tmp_cache_dir, cache_path.c_str(), len);
2073 #if defined(_MSC_VER) 2075 char tmp_cache_path[PATH_MAX];
2076 char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
2077 _splitpath_s(tmp_cache_dir, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME,
2079 char full_dir[_MAX_DRIVE + _MAX_DIR];
2080 _makepath_s(full_dir, _MAX_DRIVE + _MAX_DIR, drive, dir, NULL, NULL);
2081 snprintf(tmp_cache_path,
sizeof(tmp_cache_path),
"%s\\.rospack_cache.XXXXXX", full_dir);
2082 #elif defined(__MINGW32__) 2083 char tmp_cache_path[PATH_MAX];
2084 char* temp_name = tempnam(dirname(tmp_cache_dir),
".rospack_cache.");
2085 snprintf(tmp_cache_path,
sizeof(tmp_cache_path), temp_name);
2088 char *temp_dirname = dirname(tmp_cache_dir);
2089 len = strlen(temp_dirname) + 22 + 1;
2090 char *tmp_cache_path =
new char[len];
2091 snprintf(tmp_cache_path, len,
"%s/.rospack_cache.XXXXXX", temp_dirname);
2093 #if defined(__MINGW32__) 2096 int fd = open(tmp_cache_path, O_RDWR | O_EXCL | _O_CREAT, 0644);
2099 logWarn(std::string(
"unable to create temporary cache file ") +
2100 tmp_cache_path,
true);
2104 FILE *cache = fdopen(fd,
"w");
2105 #elif defined(WIN32) 2106 if (_mktemp_s(tmp_cache_path, PATH_MAX) != 0)
2109 "[rospack] Unable to generate temporary cache file name: %u",
2114 FILE *cache = fopen(tmp_cache_path,
"w");
2116 int fd = mkstemp(tmp_cache_path);
2119 fprintf(stderr,
"[rospack] Unable to create temporary cache file %s: %s\n",
2120 tmp_cache_path, strerror(errno));
2124 FILE *cache = fdopen(fd,
"w");
2128 fprintf(stderr,
"[rospack] Unable open cache file %s: %s\n",
2129 tmp_cache_path, strerror(errno));
2133 char *rpp = getenv(
"ROS_PACKAGE_PATH");
2134 fprintf(cache,
"#ROS_PACKAGE_PATH=%s\n", (rpp ? rpp :
""));
2135 #if BOOST_VERSION < 106500 2136 for(std::tr1::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
2138 for(boost::unordered_map<std::string, Stackage*>::const_iterator it =
stackages_.begin();
2142 fprintf(cache,
"%s\n", it->second->path_.c_str());
2144 if(fs::exists(cache_path))
2145 remove(cache_path.c_str());
2146 if(rename(tmp_cache_path, cache_path.c_str()) < 0)
2148 fprintf(stderr,
"[rospack] Error: failed to rename cache file %s to %s: %s\n",
2149 tmp_cache_path, cache_path.c_str(), strerror(errno));
2153 delete[] tmp_cache_dir;
2154 #if !defined(_MSC_VER) && !defined(__MINGW32__) 2155 delete[] tmp_cache_path;
2166 const char *user_cache_time_str = getenv(
"ROS_CACHE_TIMEOUT");
2167 if(user_cache_time_str)
2168 cache_max_age = atof(user_cache_time_str);
2169 if(cache_max_age == 0.0)
2172 if(stat(cache_path.c_str(), &s) == 0)
2174 double dt = difftime(time(NULL), s.st_mtime);
2177 if ((cache_max_age > 0.0) && (dt > cache_max_age))
2181 FILE* cache = fopen(cache_path.c_str(),
"r");
2186 char linebuf[30000];
2187 bool ros_package_path_ok =
false;
2188 const char* ros_package_path = getenv(
"ROS_PACKAGE_PATH");
2191 if(!fgets(linebuf,
sizeof(linebuf), cache))
2193 linebuf[strlen(linebuf)-1] = 0;
2194 if (linebuf[0] ==
'#')
2196 if(!strncmp(
"#ROS_PACKAGE_PATH=", linebuf, 18))
2198 if(!ros_package_path)
2200 if(!strlen(linebuf+18))
2201 ros_package_path_ok =
true;
2203 else if(!strcmp(linebuf+18, ros_package_path))
2204 ros_package_path_ok =
true;
2210 if(ros_package_path_ok)
2214 fseek(cache, 0, SEEK_SET);
2226 const std::string& instring,
2227 std::string& outstring)
2229 outstring = instring;
2230 for(std::string::size_type i = outstring.find(MANIFEST_PREFIX);
2231 i != std::string::npos;
2232 i = outstring.find(MANIFEST_PREFIX))
2234 outstring.replace(i, std::string(MANIFEST_PREFIX).length(),
2241 if (outstring.find_first_of(
"$`") == std::string::npos)
2256 std::string cmd = std::string(
"ret=\"") + outstring +
"\" && echo $ret";
2259 std::string token(
"\n");
2260 for (std::string::size_type s = cmd.find(token);
2261 s != std::string::npos;
2262 s = cmd.find(token, s))
2263 cmd.replace(s,token.length(),std::string(
" "));
2266 if(!(p = popen(cmd.c_str(),
"r")))
2268 std::string errmsg =
2269 std::string(
"failed to execute backquote expression ") +
2278 memset(buf,0,
sizeof(buf));
2283 while(fgets(buf + strlen(buf),
sizeof(buf)-strlen(buf)-1,p));
2284 }
while(ferror(p) && errno == EINTR);
2288 std::string errmsg =
2289 std::string(
"got non-zero exit status from executing backquote expression ") +
2297 buf[strlen(buf)-1] =
'\0';
2311 ROSPACK_CACHE_PREFIX,
2313 MANIFEST_TAG_PACKAGE)
2320 return "USAGE: rospack <command> [options] [package]\n" 2321 " Allowed commands:\n" 2323 " cflags-only-I [--deps-only] [package]\n" 2324 " cflags-only-other [--deps-only] [package]\n" 2325 " depends [package] (alias: deps)\n" 2326 " depends-indent [package] (alias: deps-indent)\n" 2327 " depends-manifests [package] (alias: deps-manifests)\n" 2328 " depends-msgsrv [package] (alias: deps-msgsrv)\n" 2329 " depends-on [package]\n" 2330 " depends-on1 [package]\n" 2331 " depends-why --target=<target> [package] (alias: deps-why)\n" 2332 " depends1 [package] (alias: deps1)\n" 2333 " export [--deps-only] --lang=<lang> --attrib=<attrib> [package]\n" 2336 " libs-only-L [--deps-only] [package]\n" 2337 " libs-only-l [--deps-only] [package]\n" 2338 " libs-only-other [--deps-only] [package]\n" 2340 " list-duplicates\n" 2342 " plugins --attrib=<attrib> [--top=<toppkg>] [package]\n" 2343 " profile [--length=<length>] [--zombie-only]\n" 2344 " rosdep [package] (alias: rosdeps)\n" 2345 " rosdep0 [package] (alias: rosdeps0)\n" 2349 " -q Quiets error reports.\n\n" 2350 " If [package] is omitted, the current working directory\n" 2351 " is used (if it contains a package.xml or manifest.xml).\n\n";
2364 ROSSTACK_CACHE_PREFIX,
2373 return "USAGE: rosstack [options] <command> [stack]\n" 2374 " Allowed commands:\n" 2377 " contents [stack]\n" 2380 " depends [stack] (alias: deps)\n" 2381 " depends-manifests [stack] (alias: deps-manifests)\n" 2382 " depends1 [stack] (alias: deps1)\n" 2383 " depends-indent [stack] (alias: deps-indent)\n" 2384 " depends-why --target=<target> [stack] (alias: deps-why)\n" 2385 " depends-on [stack]\n" 2386 " depends-on1 [stack]\n" 2387 " contains [package]\n" 2388 " contains-path [package]\n" 2389 " profile [--length=<length>] \n\n" 2390 " If [stack] is omitted, the current working directory\n" 2391 " is used (if it contains a stack.xml).\n\n";
2402 TiXmlElement* ele = stackage->
manifest_.RootElement();
2405 std::string errmsg = std::string(
"error parsing manifest of package ") +
2416 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 2417 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 2419 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL 2422 unsigned __int64 tmpres = 0;
2424 GetSystemTimeAsFileTime(&ft);
2425 tmpres |= ft.dwHighDateTime;
2427 tmpres |= ft.dwLowDateTime;
2429 tmpres -= DELTA_EPOCH_IN_MICROSECS;
2430 return static_cast<double>(tmpres) / 1e6;
2433 gettimeofday(&tod, NULL);
2434 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)
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
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 gatherDepsFull(Stackage *stackage, bool direct, traversal_order_t order, int depth, std::tr1::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 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
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)
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.
void _gatherDepsFull(Stackage *stackage, bool direct, traversal_order_t order, int depth, std::tr1::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)
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
std::tr1::unordered_map< std::string, std::vector< std::string > > dups_
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...
TiXmlElement * get_manifest_root(Stackage *stackage)
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...
std::tr1::unordered_map< std::string, Stackage * > stackages_
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 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.
void crawlDetail(const std::string &path, bool force, int depth, bool collect_profile_data, std::vector< DirectoryCrawlRecord * > &profile_data, std::tr1::unordered_set< std::string > &profile_hash)
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