27int main(
int argc,
char** argv)
31 std::cerr <<
"create_node_manifest: Missing inputs! The program requires: \n\t1.) the yaml "
32 "node manifest files (separated by ';').\n\t2.) Build information for nodes supposed to be "
33 "registered during build time (List of '<class_name>@<library_build_path>' "
34 "separated by ';').\n\t3.) The name of the package that provides the build targets.\n\t4.) Output "
35 "file for the complete node plugin manifest.\n\t";
36 std::cerr <<
"Usage: create_node_manifest <manifest_files> <build_infos> <build_package_name> "
43 std::vector<std::string> manifest_files;
46 manifest_files.push_back(std::filesystem::absolute(path).
string());
49 const std::string build_package_name = argv[3];
50 const std::filesystem::path output_file{ std::filesystem::absolute(argv[4]) };
53 if (manifest_files.empty())
55 throw std::runtime_error(
"Argument manifest_files must not be empty");
57 if (output_file.empty())
59 throw std::runtime_error(
"Argument output_file must not be empty.");
63 if (output_file.extension() !=
".yaml")
65 throw std::runtime_error(
"Output file '" + output_file.string() +
"' has wrong extension. Must be '.yaml'.");
69 std::map<std::string, std::string> build_lib_paths;
70 for (
const auto& build_info : build_infos)
73 if (parts.size() != 2)
75 throw std::runtime_error(
"Invalid build info entry ('" + build_info +
"').");
77 const std::string& class_name = parts[0];
78 const std::string& build_path = parts[1];
79 if (build_lib_paths.find(class_name) != build_lib_paths.end())
81 throw std::runtime_error(
"Node class '" + class_name +
"' is specified multiple times in build infos.");
83 build_lib_paths[class_name] = build_path;
87 auto all_but_build_package =
89 all_but_build_package.erase(build_package_name);
98 for (
const auto& [node_name, params] : output_manifest.getInternalMap())
102 output_manifest[node_name] =
NodeManifest({ { node_name, params } }).autoComplete(loader)[node_name];
106 if (build_lib_paths.find(params.class_name) == build_lib_paths.end())
108 throw std::runtime_error(
"Node '" + node_name +
"' (Class '" + params.class_name +
109 "') cannot be found. It's not being built by this package (" + build_package_name +
110 ") and is also not provided by any other package. For a node to be discoverable, "
111 "one must register it using auto_apms_behavior_tree_register_nodes() in the "
112 "CMakeLists.txt of a ROS 2 package.");
115 output_manifest[node_name].library = build_lib_paths[params.class_name];
116 output_manifest[node_name].package = build_package_name;
121 output_manifest.toFile(output_file);
124 std::set<std::string> paths;
125 for (
const auto& [node_name, params] : output_manifest.getInternalMap())
127 const auto& path = params.library;
128 if (
const auto& [_, success] = paths.insert(path); success)
130 std::cout << path <<
';';
134 catch (
const std::exception& e)
136 std::cerr <<
"ERROR (create_node_manifest): " << e.what() <<
"\n";
std::vector< std::string > splitString(const std::string &str, const std::string &delimiter, bool preserve_empty=true)
Split a string into multiple tokens using a specific delimiter string (Delimiter may consist of multi...