32 #include <boost/program_options.hpp> 33 #include <boost/algorithm/string.hpp> 39 namespace po = boost::program_options;
46 po::variables_map& vm);
56 bool quiet = (vm.count(
"quiet")==1);
61 bool package_given =
false;
62 bool deps_only =
false;
67 bool zombie_only =
false;
68 std::string length_str;
70 if(vm.count(
"command"))
71 command = vm[
"command"].as<std::string>();
73 if(vm.count(
"-h") && command.empty())
78 rp.
logError( std::string(
"no command given. Try '") + rp.
getName() +
" help'");
84 if((command ==
"profile") ||
85 (command ==
"depends-on") ||
86 (command ==
"depends-on1") ||
87 (command ==
"langs") ||
88 (command ==
"list-duplicates"))
91 if(vm.count(
"package"))
93 package = vm["package"].as<std::string>();
101 if(vm.count(
"deps-only"))
104 lang = vm[
"lang"].as<std::string>();
105 if(vm.count(
"attrib"))
106 attrib = vm[
"attrib"].as<std::string>();
108 top = vm[
"top"].as<std::string>();
109 if(vm.count(
"target"))
110 target = vm[
"target"].as<std::string>();
111 if(vm.count(
"zombie-only"))
113 if(vm.count(
"length"))
115 length_str = vm[
"length"].as<std::string>();
116 length = atoi(length_str.c_str());
127 if(command ==
"help" || vm.count(
"help"))
129 if(package_given || (command !=
"help" && vm.count(
"help"))) {
130 if (command ==
"help") {
131 command = vm[
"package"].as<std::string>();
133 output.append(
"Usage: rospack ");
134 output.append(command);
135 if(command ==
"help")
136 output.append(
"[command]\n\nPrint help message.");
137 else if(command ==
"find")
138 output.append(
"\n\nPrint absolute path to the package");
139 else if(command ==
"list")
140 output.append(
"\n\nPrint newline-separated list <package-name> <package-dir> for all packages.");
141 else if(command ==
"list-names")
142 output.append(
"\n\nPrint newline-separated list of packages names for all packages.");
143 else if(command ==
"list-duplicates")
144 output.append(
"\n\nPrint newline-separated list of names of packages that are found more than once during the search.");
145 else if(command ==
"langs")
146 output.append(
"\n\nPrint space-separated list of available language-specific client libraries.");
147 else if(command ==
"depends" || command ==
"deps")
148 output.append(
"[package]\n\nPrint newline-separated, ordered list of all dependencies of the package.");
149 else if(command ==
"depends1" || command ==
"deps1")
150 output.append(
"[package]\n\nPrint newline-separated, ordered list of immediate dependencies of the package.");
151 else if(command ==
"depends-manifest" || command ==
"deps-manifest")
152 output.append(
"[package]\n\nPrint space-separated, ordered list of manifest.xml files for all dependencies of the package. Used internally by rosbuild.");
153 else if(command ==
"depends-indent" || command ==
"deps-indent")
154 output.append(
"[package]\n\nPrint newline-separated, indented list of the entire dependency chain for the package.");
155 else if(command ==
"depends-why" || command ==
"deps-why")
156 output.append(
"--target=TARGET [package]\n\nPrint newline-separated presentation of all dependency chains from the package to TARGET. ");
157 else if(command ==
"depends-msgsrv" || command ==
"deps-msgsrv")
158 output.append(
"[package]\n\nPrint space-separated list of message-generation marker files for all dependencies of the package. Used internally by rosbuild.");
159 else if(command ==
"rosdep" || command ==
"rosdeps")
160 output.append(
"[package]\n\nPrint newline-separated list of all [rosdep] tags from the manifest.xml of the package and all of its dependencies.");
161 else if(command ==
"rosdep0" || command ==
"rosdeps0")
162 output.append(
"[package]\n\nPrint newline-separated list of all [rosdep] tags from the manifest.xml of just the package itself.");
163 else if(command ==
"vcs")
164 output.append(
"[package]\n\nPrint newline-separated list of all [versioncontrol] tags from the manifest.xml of the package and all of its dependencies.");
165 else if(command ==
"vcs0")
166 output.append(
"[package]\n\nPrint newline-separated list of all [versioncontrol] tags from the manifest.xml of just the package itself.");
167 else if(command ==
"depends-on")
168 output.append(
"[package]\n\nPrint newline-separated list of all packages that depend on the package. ");
169 else if(command ==
"depends-on1")
170 output.append(
"[package]\n\nPrint newline-separated list of all packages that directly depend on the package.");
171 else if(command ==
"export")
172 output.append(
"[--deps-only] --lang=<lang> --attrib=<attrib> [package]\n\nPrint Space-separated list of [export][LANGUAGE ATTRIBUTE=\"\"/][/export] values from the manifest.xml of the package and its dependencies.\n\nIf --deps-only is provided, then the package itself is excluded.");
173 else if(command ==
"plugins")
174 output.append(
"--attrib=<attrib> [--top=<toppkg>] [package]\n\nExamine packages that depend directly on the given package, giving name and the exported attribute with the name <attrib>\n\nIf --top=<toppkg> is given, then in addition to depending directly on the given package, to be scanned for exports, a package must also be a dependency of <toppkg>, or be <toppkg> itself.");
175 else if(command ==
"cflags-only-I")
176 output.append(
"[--deps-only] [package]\n\nPrint Space-separated list of [export][LANGUAGE ATTRIBUTE=\"\"/][/export] values from the manifest.xml of the package and its dependencies.\n\nIf --deps-only is provided, then the package itself is excluded.");
177 else if(command ==
"cflags-only-other")
178 output.append(
"[--deps-only] [package]\n\nPrint space-separated list of export/cpp/cflags that don't start with -I.\n\nIf --deps-only is provided, then the package itself is excluded.");
179 else if(command ==
"libs-only-L")
180 output.append(
"[--deps-only] [package]\n\nPrint space-separated list of export/cpp/libs that start with -L.\n\nIf --deps-only is provided, then the package itself is excluded.");
181 else if(command ==
"libs-only-l")
182 output.append(
"[--deps-only] [package]\n\nPrint space-separated list of export/cpp/libs that start with -l.\n\nIf --deps-only is provided, then the package itself is excluded.");
183 else if(command ==
"libs-only-other")
184 output.append(
"[--deps-only] [package]\n\nPrint space-separated list of export/cpp/libs that don't start with -l or -L.\n\nIf --deps-only is provided, then the package itself is excluded.");
185 else if(command ==
"profile")
186 output.append(
"[--length=<length>] [--zombie-only]\n\nForce a full crawl of package directories and report the directories that took the longest time to crawl.\n\n--length=N how many directories to display\n\n--zombie-only Only print directories that do not have any manifests.");
189 output.append(rp.
usage());
194 std::vector<std::string> search_path;
199 if(command ==
"profile")
201 if(package_given || target.size() || top.size() ||
202 deps_only || lang.size() || attrib.size())
204 rp.
logError(
"invalid option(s) given");
207 std::vector<std::string> dirs;
208 if(rp.
profile(search_path, zombie_only, length, dirs))
210 for(std::vector<std::string>::const_iterator it = dirs.begin();
213 output.append((*it) +
"\n");
218 rp.
crawl(search_path, force);
221 if(command ==
"find")
228 if(target.size() || top.size() || length_str.size() ||
229 zombie_only || deps_only || lang.size() || attrib.size())
231 rp.
logError(
"invalid option(s) given");
235 if(!rp.
find(package, path))
237 output.append(path +
"\n");
241 else if(command ==
"list")
243 if(package_given || target.size() || top.size() || length_str.size() ||
244 zombie_only || deps_only || lang.size() || attrib.size())
246 rp.
logError(
"invalid option(s) given");
249 std::set<std::pair<std::string, std::string> > list;
251 for(std::set<std::pair<std::string, std::string> >::const_iterator it = list.begin();
255 output.append(it->first +
" " + it->second +
"\n");
260 else if(command ==
"list-names")
262 if(package_given || target.size() || top.size() || length_str.size() ||
263 zombie_only || deps_only || lang.size() || attrib.size())
265 rp.
logError(
"invalid option(s) given");
268 std::set<std::pair<std::string, std::string> > list;
270 for(std::set<std::pair<std::string, std::string> >::const_iterator it = list.begin();
274 output.append(it->first +
"\n");
279 else if(command ==
"list-duplicates")
281 if(package_given || target.size() || top.size() || length_str.size() ||
282 zombie_only || deps_only || lang.size() || attrib.size())
284 rp.
logError(
"invalid option(s) given");
287 std::map<std::string, std::vector<std::string> > dups;
290 for(std::map<std::string, std::vector<std::string> >::const_iterator it = dups.begin();
294 output.append(it->first +
"\n");
295 for(std::vector<std::string>::const_iterator jt = it->second.begin();
296 jt != it->second.end();
299 output.append(
"- " + *jt +
"\n");
307 if(package_given || target.size() || top.size() || length_str.size() ||
308 zombie_only || deps_only || lang.size() || attrib.size())
310 rp.
logError(
"invalid option(s) given");
313 std::vector<std::string> deps;
314 if(!rp.
depsOn(
"roslang",
true, deps))
316 const char* ros_lang_disable;
317 if((ros_lang_disable = getenv(
"ROS_LANG_DISABLE")))
319 std::vector<std::string> disable_langs;
323 const char *path_delim =
";";
325 const char *path_delim = ":"; 327 boost::split(disable_langs, ros_lang_disable,
328 boost::is_any_of(path_delim),
329 boost::token_compress_on);
330 std::vector<std::string>::iterator it = deps.begin();
331 while(it != deps.end())
333 if(std::find(disable_langs.begin(), disable_langs.end(), *it) !=
340 for(std::vector<std::string>::const_iterator it = deps.begin();
344 if(it != deps.begin())
352 else if(command ==
"depends" || command ==
"deps" ||
353 command ==
"depends1" || command ==
"deps1")
360 if(target.size() || top.size() || length_str.size() ||
361 zombie_only || deps_only || lang.size() || attrib.size())
363 rp.
logError(
"invalid option(s) given");
366 std::vector<std::string> deps;
367 if(!rp.
deps(package, (command ==
"depends1" || command ==
"deps1"), deps))
369 for(std::vector<std::string>::const_iterator it = deps.begin();
372 output.append(*it +
"\n");
376 else if(command ==
"depends-manifests" || command ==
"deps-manifests")
383 if(target.size() || top.size() || length_str.size() ||
384 zombie_only || deps_only || lang.size() || attrib.size())
386 rp.
logError(
"invalid option(s) given");
389 std::vector<std::string> manifests;
392 for(std::vector<std::string>::const_iterator it = manifests.begin();
393 it != manifests.end();
396 if(it != manifests.begin())
405 (command ==
"depends-msgsrv" || command ==
"deps-msgsrv"))
412 if(target.size() || top.size() || length_str.size() ||
413 zombie_only || deps_only || lang.size() || attrib.size())
415 rp.
logError(
"invalid option(s) given");
418 std::vector<std::string> gens;
421 for(std::vector<std::string>::const_iterator it = gens.begin();
425 if(it != gens.begin())
433 else if(command ==
"depends-indent" || command ==
"deps-indent")
440 if(target.size() || top.size() || length_str.size() ||
441 zombie_only || deps_only || lang.size() || attrib.size())
443 rp.
logError(
"invalid option(s) given");
446 std::vector<std::string> deps;
449 for(std::vector<std::string>::const_iterator it = deps.begin();
452 output.append(*it +
"\n");
456 else if(command ==
"depends-why" || command ==
"deps-why")
458 if(!package.size() || !target.size())
463 if(top.size() || length_str.size() ||
464 zombie_only || deps_only || lang.size() || attrib.size())
466 rp.
logError(
"invalid option(s) given");
469 std::string why_output;
470 if(!rp.
depsWhy(package, target, why_output))
472 output.append(why_output);
478 (command ==
"rosdep" || command ==
"rosdeps" ||
479 command ==
"rosdep0" || command ==
"rosdeps0"))
486 if(target.size() || top.size() || length_str.size() ||
487 zombie_only || deps_only || lang.size() || attrib.size())
489 rp.
logError(
"invalid option(s) given");
492 std::set<std::string> rosdeps;
493 if(!rp.
rosdeps(package, (command ==
"rosdep0" || command ==
"rosdeps0"), rosdeps))
495 for(std::set<std::string>::const_iterator it = rosdeps.begin();
498 output.append(*it +
"\n");
504 (command ==
"vcs" || command ==
"vcs0"))
511 if(target.size() || top.size() || length_str.size() ||
512 zombie_only || deps_only || lang.size() || attrib.size())
514 rp.
logError(
"invalid option(s) given");
517 std::vector<std::string> vcs;
518 if(!rp.
vcs(package, (command ==
"vcs0"), vcs))
520 for(std::vector<std::string>::const_iterator it = vcs.begin();
523 output.append(*it +
"\n");
528 else if(command ==
"depends-on" || command ==
"depends-on1")
535 if(target.size() || top.size() || length_str.size() ||
536 zombie_only || deps_only || lang.size() || attrib.size())
538 rp.
logError(
"invalid option(s) given");
541 std::vector<std::string> deps;
542 if(!rp.
depsOn(package, (command ==
"depends-on1"), deps))
544 for(std::vector<std::string>::const_iterator it = deps.begin();
547 output.append(*it +
"\n");
553 if(!package.size() || !lang.size() || !attrib.size())
555 rp.
logError(
"no package / lang / attrib given");
558 if(target.size() || top.size() || length_str.size() || zombie_only)
560 rp.
logError(
"invalid option(s) given");
563 std::vector<std::string> flags;
564 if(!rp.
exports(package, lang, attrib, deps_only, flags))
566 for(std::vector<std::string>::const_iterator it = flags.begin();
570 if(it != flags.begin())
580 if(!package.size() || !attrib.size())
582 rp.
logError(
"no package / attrib given");
585 if(target.size() || length_str.size() || zombie_only)
587 rp.
logError(
"invalid option(s) given");
590 std::vector<std::string> flags;
591 if(!rp.
plugins(package, attrib, top, flags))
593 for(std::vector<std::string>::const_iterator it = flags.begin();
596 output.append(*it +
"\n");
607 if(target.size() || top.size() || length_str.size() || zombie_only)
609 rp.
logError(
"invalid option(s) given");
612 std::vector<std::pair<std::string, bool> > flags;
613 if(!rp.
cpp_exports(package,
"--cflags-only-I",
"cflags", deps_only, flags))
616 std::string dry_combined;
617 std::string wet_combined;
618 for(std::vector<std::pair<std::string, bool> >::const_iterator it = flags.begin();
622 std::string& combined = it->second ? wet_combined : dry_combined;
623 if(!combined.empty())
624 combined.append(
" ");
625 combined.append(it->first);
628 std::string dry_result;
630 output.append(dry_result);
632 std::string wet_result;
634 if(!dry_result.empty() && !wet_result.empty())
638 output.append(wet_result +
"\n");
649 if(target.size() || top.size() || length_str.size() || zombie_only)
651 rp.
logError(
"invalid option(s) given");
654 std::vector<std::pair<std::string, bool> > flags;
655 if(!rp.
cpp_exports(package,
"--cflags-only-other",
"cflags", deps_only, flags))
657 std::string combined;
658 for(std::vector<std::pair<std::string, bool> >::const_iterator it = flags.begin();
662 if(it != flags.begin())
663 combined.append(
" ");
664 combined.append(it->first);
668 output.append(result +
"\n");
679 if(target.size() || top.size() || length_str.size() || zombie_only)
681 rp.
logError(
"invalid option(s) given");
684 std::vector<std::pair<std::string, bool> > flags;
685 if(!rp.
cpp_exports(package,
"--libs-only-L",
"lflags", deps_only, flags))
688 std::string dry_combined;
689 std::string wet_combined;
690 for(std::vector<std::pair<std::string, bool> >::const_iterator it = flags.begin();
694 std::string& combined = it->second ? wet_combined : dry_combined;
695 if(!combined.empty())
696 combined.append(
" ");
697 combined.append(it->first);
700 std::string dry_result;
702 output.append(dry_result);
704 std::string wet_result;
706 if(!dry_result.empty() && !wet_result.empty())
710 output.append(wet_result +
"\n");
721 if(target.size() || top.size() || length_str.size() || zombie_only)
723 rp.
logError(
"invalid option(s) given");
726 std::vector<std::pair<std::string, bool> > flags;
727 if(!rp.
cpp_exports(package,
"--libs-only-l",
"lflags", deps_only, flags))
729 std::string combined;
730 for(std::vector<std::pair<std::string, bool> >::const_iterator it = flags.begin();
734 if(it != flags.begin())
735 combined.append(
" ");
736 combined.append(it->first);
740 output.append(result +
"\n");
751 if(target.size() || top.size() || length_str.size() || zombie_only)
753 rp.
logError(
"invalid option(s) given");
756 std::vector<std::pair<std::string, bool> > flags;
757 if(!rp.
cpp_exports(package,
"--libs-only-other",
"lflags", deps_only, flags))
759 std::string combined;
760 for(std::vector<std::pair<std::string, bool> >::const_iterator it = flags.begin();
764 if(it != flags.begin())
765 combined.append(
" ");
766 combined.append(it->first);
768 std::string intermediate;
772 output.append(result +
"\n");
783 if(target.size() || top.size() || length_str.size() ||
784 zombie_only || deps_only || lang.size() || attrib.size())
786 rp.
logError(
"invalid option(s) given");
790 std::set<std::string> packages;
792 for(std::set<std::string>::const_iterator it = packages.begin();
793 it != packages.end();
795 output.append(*it +
"\n");
800 ((command ==
"contains") || (command ==
"contains-path")))
807 if(target.size() || top.size() || length_str.size() ||
808 zombie_only || deps_only || lang.size() || attrib.size())
810 rp.
logError(
"invalid option(s) given");
813 std::string name, path;
814 if(!rp.
contains(package, name, path))
816 if(command ==
"contains")
817 output.append(name +
"\n");
819 output.append(path +
"\n");
824 rp.
logError(std::string(
"command ") + command +
" not implemented");
833 po::options_description desc(
"Allowed options");
835 (
"command", po::value<std::string>(),
"command")
836 (
"package", po::value<std::string>(),
"package")
837 (
"target", po::value<std::string>(),
"target")
838 (
"deps-only",
"deps-only")
839 (
"lang", po::value<std::string>(),
"lang")
840 (
"attrib", po::value<std::string>(),
"attrib")
841 (
"top", po::value<std::string>(),
"top")
842 (
"length", po::value<std::string>(),
"length")
843 (
"zombie-only",
"zombie-only")
846 (
"quiet,q",
"quiet");
848 po::positional_options_description pd;
849 pd.add(
"command", 1).add(
"package", 1);
852 po::store(po::command_line_parser(argc, argv).options(desc).positional(pd).run(), vm);
854 catch(boost::program_options::error e)
856 rp.
logError( std::string(
"failed to parse command-line options: ") + e.what());
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.
void parse_compiler_flags(const std::string &instring, const std::string &token, bool select, bool last, std::string &outstring)
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?
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.
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).
virtual std::string get_manifest_type()
void setQuiet(bool quiet)
Control warning and error console output.
bool parse_args(int argc, char **argv, rospack::Rosstackage &rp, po::variables_map &vm)
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.
bool rospack_run(int argc, char **argv, rospack::Rosstackage &rp, std::string &output)
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.
bool contains(const std::string &name, std::string &stack, std::string &path)
Find the stack that contains a package.
bool getSearchPathFromEnv(std::vector< std::string > &sp)
Helper method to construct a directory search path by looking at relevant environment variables...
virtual const char * usage()
Usage string, to be overridden by derived classes.
bool depsManifests(const std::string &name, bool direct, std::vector< std::string > &manifests)
List the manifests of a stackage's dependencies. Used by rosbuild.
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.
const std::string & getName()
Get the name of the tool that's in use (e.g., "rospack" or "rosstack")
The base class for package/stack ("stackage") crawlers. Users of the library should use the functiona...
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 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.
static const char * ROSPACK_NAME
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.
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...