main.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::application::AronArmemGenerator
17 * @author fabian.peller-konrad@kit.edu ( fabian dot peller-konrad at kit dot edu )
18 * @date 2020
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23// STD/STL
24#include <ctime>
25#include <filesystem>
26#include <iostream>
27
28// CXXOPTS
29#include "cxxopts.hpp"
30
31// ArmarX Executable
32//#include <ArmarXCore/core/application/Application.h>
33//#include <ArmarXCore/core/Component.h>
34//#include <ArmarXCore/core/logging/Logging.h>
35
36// Aron
39
40#include <RobotAPI/interface/aron.h>
43
44using namespace armarx;
45using namespace aron;
46
47/// Aron Code Generator Main Executable.
48/// This executable calls generates a aron code file out of an aron xml file.
49int
50main(int argc, char* argv[])
51{
52 try
53 {
54 cxxopts::Options options("AronArmemCodeGenerator",
55 "An application interface for the aron and armem code generation");
56
57 std::string input_default = "/path/to/some/xml/file.xml";
58 std::string output_default = "/path/to/some/output/folder/";
59
60 options.add_options("General")(
61 "v,verbose", "Enable verbose mode", cxxopts::value<bool>()->default_value("false"))(
62 "h,help", "Print usage");
63
64 options.add_options("IO")("i,input",
65 "XML file name",
66 cxxopts::value<std::string>()->default_value(input_default))(
67 "o,output",
68 "The output path",
69 cxxopts::value<std::string>()->default_value(output_default))(
70 "I,include", "include path", cxxopts::value<std::vector<std::string>>());
71
72 options.add_options("Generation")(
73 "f,force", "Enforce the generation", cxxopts::value<bool>()->default_value("false"));
74
75 auto result = options.parse(argc, argv);
76
77 if (result.count("help"))
78 {
79 std::cout << options.help() << std::endl;
80 exit(0);
81 }
82
83 bool verbose = result["v"].as<bool>();
84 bool force = result["f"].as<bool>();
85
86 std::string filename = result["i"].as<std::string>();
87 std::string output = result["o"].as<std::string>();
88
89 if (filename == input_default || output == output_default)
90 {
91 std::cout << options.help() << std::endl;
92 exit(0);
93 }
94
95 if (verbose)
96 {
97 std::cout << "Welcome to the AronCodeGenerator!" << std::endl;
98 std::cout << "Received the following parameters:" << std::endl;
99 std::cout << "- IO:" << std::endl;
100 std::cout << "-- Input: " << filename << std::endl;
101 std::cout << "-- Output: " << output << std::endl;
102 std::cout << "- Generation:" << std::endl;
103 std::cout << "-- Force: " << force << std::endl;
104 std::cout << std::endl;
105 }
106
107 if (verbose)
108 {
109 std::cout << "Generating a new cpp file out of <" + filename + ">" << std::endl;
110 }
111
112 std::filesystem::path input_file(filename);
113 std::filesystem::path output_folder(output);
114
115 std::vector<std::filesystem::path> includePaths;
116
117 if (result.count("I") > 0)
118 {
119 for (const auto& path : result["I"].as<std::vector<std::string>>())
120 {
121 includePaths.emplace_back(path);
122 }
123 }
124
125
126 if (!std::filesystem::exists(input_file) || !std::filesystem::is_regular_file(input_file))
127 {
128 std::cerr << "The input file does not exist or is not a regular file." << std::endl;
129 exit(1);
130 }
131
132 if (!std::filesystem::exists(output_folder) ||
133 !std::filesystem::is_directory(output_folder))
134 {
135 std::cerr << "The output folder does not exist or is not an directory." << std::endl;
136 exit(1);
137 }
138
139 if (input_file.extension().string() != ".xml")
140 {
141 std::cerr << "The file you passed has the wrong type." << std::endl;
142 exit(1);
143 }
144
145 if (verbose)
146 {
147 std::cout << "Parsing the XML file..." << std::endl;
148 }
149
151 reader.parseFile(input_file, includePaths);
152 if (verbose)
153 {
154 std::cout << "Parsing the XML file... done!" << std::endl;
155 std::cout << "--> Found " << reader.getGenerateObjects().size() << " types."
156 << std::endl;
157 std::cout << "--> They are: " << std::endl;
158 for (const auto& generateType : reader.getGenerateObjects())
159 {
160 std::cout << "----> " << generateType.typeName << std::endl;
161 }
162 }
163
164 codegenerator::cpp::Writer writer("AronTestSegment", reader.getCodeIncludes());
165
166 if (verbose)
167 {
168 std::cout << "Running the type class generator..." << std::endl;
169 }
170
173
174 if (verbose)
175 {
176 std::cout << "Running the type class generator... done!" << std::endl;
177 std::cout << "--> Found " << writer.getTypeClasses().size() << " type objects."
178 << std::endl;
179 std::cout << "--> They are: " << std::endl;
180 for (const auto& c : writer.getTypeClasses())
181 {
182 std::cout << "----> " << c->getName() << std::endl;
183 }
184 }
185
186 std::time_t current_time = std::time(0);
187 std::tm* now = std::localtime(&current_time);
188 std::string current_year = std::to_string(now->tm_year + 1900);
189
190 std::string fileDoc =
191 std::string("* This file is part of ArmarX. \n") + "* \n" + "* Copyright (C) 2012-" +
192 current_year + ", High Performance Humanoid Technologies (H2T), \n" +
193 "* Karlsruhe Institute of Technology (KIT), all rights reserved. \n" + "* \n" +
194 "* ArmarX is free software; you can redistribute it and/or modify \n" +
195 "* it under the terms of the GNU General Public License version 2 as \n" +
196 "* published by the Free Software Foundation. \n" + "* \n" +
197 "* ArmarX is distributed in the hope that it will be useful, but \n" +
198 "* WITHOUT ANY WARRANTY; without even the implied warranty of \n" +
199 "* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n" +
200 "* GNU General Public License for more details. \n" + "* \n" +
201 "* You should have received a copy of the GNU General Public License \n" +
202 "* along with this program. If not, see <http://www.gnu.org/licenses/>. \n" + "* \n" +
203 "* @copyright http://www.gnu.org/licenses/gpl-2.0.txt \n" +
204 "* GNU General Public License \n" +
205 "* *********************************************************************** \n" +
206 "* WARNING: This file is autogenerated. \n" + "* Original file: " + filename + " \n" +
207 "* Please do not edit since your changes may be overwritten on the next generation \n" +
208 "* If you have any questions please contact: Fabian Peller-Konrad (fabian dot "
209 "peller-konrad at kit dot edu) \n" +
210 "* ***********************************************************************";
211
212 auto w = CppWriterPtr(new CppWriter(true, fileDoc));
213 w->header.line();
214 w->header.line();
215
216 // Generate enums at top of generated header file
217 std::vector<MetaEnumPtr> enums = writer.getTypeEnums();
218 if (verbose)
219 {
220 std::cout << "Now exporting enums..." << std::endl;
221 }
222
223 w->body.line("/*************************************************************************");
224 w->body.line(" * ALL GENERATED ENUMS ***************************************************");
225 w->body.line(" ************************************************************************/");
226 MetaEnum::Write(enums, w);
227 w->body.line();
228 w->body.line();
229
230 std::string enum_file_generation_content = w->getString();
231
232 if (verbose)
233 {
234 std::cout << "Now exporting enums... done!" << std::endl;
235 }
236
237 if (enums.size() > 0 && enum_file_generation_content == "")
238 {
239 std::cerr << "\033[31m"
240 << "Error code 11 - Found error in code generation. Aborting!"
241 << "\033[0m" << std::endl;
242 exit(1);
243 }
244
245 // Generate all classes
246 std::vector<MetaClassPtr> classes = writer.getTypeClasses();
247 if (verbose)
248 {
249 std::cout << "Now exporting classes..." << std::endl;
250 }
251
252 w->body.line("/* ************************************************************************");
253 w->body.line(" * ALL GENERATED CLASSES *************************************************");
254 w->body.line(" * ***********************************************************************/");
255 CppClass::Write(classes, w);
256 w->body.line();
257 w->body.line();
258
259 std::string class_file_generation_content =
260 simox::alg::remove_prefix(w->getString(), enum_file_generation_content);
261
262 if (verbose)
263 {
264 std::cout << "Now exporting classes... done!" << std::endl;
265 }
266
267 if (classes.size() > 0 && class_file_generation_content == "")
268 {
269 std::cerr << "\033[31m"
270 << "Error code 21 - Found error in code generation. Aborting!"
271 << "\033[0m" << std::endl;
272 exit(1);
273 }
274
275 std::string new_file_full_content = w->getString();
276
277 std::string new_name_with_extension = input_file.filename().replace_extension("").string();
278 new_name_with_extension += ".aron.generated.h";
279 std::string output_file_path = output + "/" + new_name_with_extension;
280 std::filesystem::path output_file(output_file_path);
281
282 // check if file already exists
283 if (!force)
284 {
285 if (std::filesystem::exists(output_file))
286 {
287 std::ifstream ifs(output_file);
288 std::string file_content((std::istreambuf_iterator<char>(ifs)),
289 (std::istreambuf_iterator<char>()));
290
291 if (file_content == new_file_full_content)
292 {
293 if (verbose)
294 {
295 std::cout << "\033[31m"
296 << "Error code 31 - File content not changed for <" +
297 output_file.string() + ">"
298 << "\033[0m" << std::endl;
299 }
300 exit(0);
301 }
302 }
303 }
304
305 std::ofstream ofs;
306 ofs.open(output_file);
307 ofs << new_file_full_content;
308 ofs.close();
309
310 if (verbose)
311 {
312 std::cout << "\033[32m"
313 << "Finished generating <" + output_file.string() +
314 ">. The new file ist called <"
315 << output_file.string() << ">"
316 << "\033[0m" << std::endl;
317 }
318 }
319 catch (const cxxopts::OptionException& e)
320 {
321 std::cerr << "\033[31m"
322 << "Error code 01 - Error in parsing cxxopts options: " << e.what() << "\033[0m"
323 << std::endl;
324 exit(1);
325 }
326 exit(0);
327}
constexpr T c
static void Write(const std::vector< MetaClassPtr > &classes, const MetaWriterPtr &writer)
Definition MetaClass.cpp:40
static void Write(const std::vector< MetaEnumPtr > &classes, const MetaWriterPtr &writer)
Definition MetaEnum.cpp:44
std::vector< MetaEnumPtr > getTypeEnums() const
Definition CodeWriter.h:68
std::vector< MetaClassPtr > getTypeClasses() const
Definition CodeWriter.h:62
virtual void generateTypeObjects(const std::vector< typereader::GenerateObjectInfo > &) override
Definition Writer.cpp:274
virtual void generateTypeIntEnums(const std::vector< typereader::GenerateIntEnumInfo > &) override
Definition Writer.cpp:388
std::vector< typereader::GenerateObjectInfo > getGenerateObjects() const
Definition Reader.h:82
std::vector< std::string > getCodeIncludes() const
Definition Reader.h:58
std::vector< typereader::GenerateIntEnumInfo > getGenerateIntEnums() const
Definition Reader.h:88
void parseFile(const std::string &filename, const std::vector< std::filesystem::path > &includePaths={}) override
parse a filename
Definition Reader.cpp:141
virtual const char * what() const noexcept
Definition cxxopts.hpp:292
std::string help(const std::vector< std::string > &groups={}) const
Definition cxxopts.hpp:1854
OptionAdder add_options(std::string group="")
Definition cxxopts.hpp:1359
ParseResult parse(int &argc, char **&argv)
Definition cxxopts.hpp:1532
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< CppWriter > CppWriterPtr
Definition CppWriter.h:35
std::shared_ptr< Value > value()
Definition cxxopts.hpp:855