35 #include <boost/algorithm/string/predicate.hpp>
36 #include <boost/filesystem/operations.hpp>
37 #include <boost/program_options.hpp>
57 using log4cpp::Priority;
70 const string& parent_project_version,
71 const string& parent_project_name,
72 const string& parent_project_vcs_version,
73 const string& parent_module_version,
74 const string& parent_module_name,
76 const Priority::Value& elements_loglevel):
77 m_program_ptr(move(program_ptr)),
78 m_parent_project_version(move(parent_project_version)),
79 m_parent_project_name(move(parent_project_name)),
80 m_parent_project_vcs_version(move(parent_project_vcs_version)),
81 m_parent_module_version(move(parent_module_version)),
82 m_parent_module_name(move(parent_module_name)),
83 m_search_dirs(move(search_dirs)),
85 m_elements_loglevel(move(elements_loglevel)) {
104 const string& module_name) {
109 conf_name.replace_extension(
"conf");
113 if (default_config_file.empty()) {
114 log.warn() <<
"The " << conf_name <<
" default configuration file cannot be found in:";
116 log.warn() <<
" " << loc;
118 if (not module_name.
empty()) {
119 conf_name =
Path::Item {module_name} / conf_name;
120 log.warn() <<
"Trying " << conf_name <<
".";
125 if (default_config_file.empty()) {
126 log.debug() <<
"Couldn't find " << conf_name <<
" default configuration file.";
128 log.debug() <<
"Found " << conf_name <<
" default configuration file at " << default_config_file;
131 return default_config_file;
138 return full_path.filename();
145 return full_path.parent_path();
148 template<
class charT>
150 const boost::program_options::basic_parsed_options<charT>& cmd_parsed_options) {
152 for (
const auto& o : cmd_parsed_options.options) {
153 if (o.string_key ==
"config-file") {
154 if (o.value.size() != 1) {
155 cerr <<
"Wrong usage of the --config-file option" << endl;
156 exit(
static_cast<int>(ExitCode::USAGE));
159 if (not boost::filesystem::exists(conf_file)) {
160 cerr <<
"The " << conf_file
161 <<
" configuration file doesn't exist!" << endl;
173 int argc,
char* argv[]) {
179 using boost::program_options::value;
180 using boost::program_options::store;
181 using boost::program_options::command_line_parser;
182 using boost::program_options::collect_unrecognized;
183 using boost::program_options::include_positional;
184 using boost::program_options::notify;
185 using boost::program_options::parse_config_file;
190 string default_log_level =
"INFO";
198 cmd_only_generic_options.add_options()
199 (
"version",
"Print version string")
200 (
"help",
"Produce help message")
202 value<Path::Item>()->default_value(default_config_file),
203 "Name of a configuration file");
207 cmd_and_file_generic_options.add_options()
208 (
"log-level", value<string>()->default_value(default_log_level),
209 "Log level: FATAL, ERROR, WARN, INFO (default), DEBUG")
211 value<Path::Item>(),
"Name of a log file");
216 for (
auto o : cmd_only_generic_options.options()) {
217 all_generic_options.add(o);
219 for (
auto o : cmd_and_file_generic_options.options()) {
220 all_generic_options.add(o);
225 auto specific_options =
m_program_ptr->defineSpecificProgramOptions();
226 auto program_arguments =
m_program_ptr->defineProgramArguments();
228 all_specific_options.add(specific_options)
229 .add(program_arguments.first);
233 all_cmd_and_file_options.add(cmd_and_file_generic_options)
234 .add(all_specific_options);
238 help_options.add(all_generic_options).add(all_specific_options);
241 auto cmd_parsed_options = command_line_parser(argc, argv)
242 .options(cmd_only_generic_options)
243 .allow_unregistered().run();
247 store(cmd_parsed_options, var_map);
250 if (var_map.count(
"help") > 0) {
251 cout << help_options << endl;
252 exit(
static_cast<int>(ExitCode::OK));
256 if (var_map.count(
"version") > 0) {
258 exit(
static_cast<int>(ExitCode::OK));
263 auto config_file = var_map.at(
"config-file").as<
Path::Item>();
267 auto leftover_cmd_options = collect_unrecognized(cmd_parsed_options.options,
272 auto parsed_cmdline_options = command_line_parser(leftover_cmd_options)
273 .options(all_cmd_and_file_options)
274 .positional(program_arguments.second)
277 store(parsed_cmdline_options, var_map);
280 if (not config_file.empty() and boost::filesystem::exists(config_file)) {
283 auto parsed_cfgfile_options = parse_config_file(ifs,
284 all_cmd_and_file_options);
285 store(parsed_cfgfile_options, var_map);
290 if (boost::starts_with(
e.what(),
"unrecognised option") or
291 boost::starts_with(
e.what(),
"too many positional options")) {
306 log.log(
m_elements_loglevel,
"##########################################################");
307 log.log(
m_elements_loglevel,
"##########################################################");
316 log.log(
m_elements_loglevel,
"##########################################################");
320 log.log(
m_elements_loglevel,
"##########################################################");
321 log.log(
m_elements_loglevel,
"##########################################################");
331 log.log(
m_elements_loglevel,
"##########################################################");
338 stringstream log_message {};
343 if (v.second.value().type() ==
typeid(
string)) {
344 log_message << v.first <<
" = " << v.second.as<
string>();
346 }
else if (v.second.value().type() ==
typeid(double)) {
347 log_message << v.first <<
" = " << v.second.as<
double>();
349 }
else if (v.second.value().type() ==
typeid(int64_t)) {
350 log_message << v.first <<
" = " << v.second.as<int64_t>();
352 }
else if (v.second.value().type() ==
typeid(int)) {
353 log_message << v.first <<
" = " << v.second.as<
int>();
355 }
else if (v.second.value().type() ==
typeid(bool)) {
356 log_message << v.first <<
" = " << v.second.as<
bool>();
358 }
else if (v.second.value().type() ==
typeid(
Path::Item)) {
359 log_message << v.first <<
" = "
362 }
else if (v.second.value().type() ==
typeid(
vector<int>)) {
364 stringstream vecContent {};
365 for (
const auto& i : intVec) {
366 vecContent <<
" " << i;
368 log_message << v.first <<
" = {" << vecContent.str() <<
" }";
372 stringstream vecContent {};
373 for (
const auto& i : intVec) {
374 vecContent <<
" " << i;
376 log_message << v.first <<
" = {" << vecContent.str() <<
" }";
380 stringstream vecContent {};
381 for (
const auto& i : intVec) {
382 vecContent <<
" " << i;
384 log_message << v.first <<
" = {" << vecContent.str() <<
" }";
387 log_message <<
"Option " << v.first <<
" of type "
388 << v.second.value().type().name() <<
" not supported in logging !"
402 log.debug() <<
"##########################################################";
404 log.debug() <<
"# Environment of the Run";
405 log.debug() <<
"# ---------------------------";
409 log.debug() << v.second <<
": " <<
m_env[v.second];
423 local_search_paths.
begin(),
425 return boost::filesystem::complete(s);
431 if (local_search_paths[0] != this_parent_path) {
432 auto b = local_search_paths.
begin();
433 local_search_paths.
insert(b, this_parent_path);
440 if (
m_env[v.second].exists()) {
460 auto exit_code =
e.exitCode();
461 log.fatal() <<
"# Elements Exception : " <<
e.what();
466 string logging_level;
470 throw Exception(
"Required option log-level is not provided!",
492 log.debug() <<
"# Exit Code: " << int(c);
521 ExitCode exit_code {ExitCode::NOT_OK};
525 log.fatal() <<
"Crash detected";
526 log.fatal() <<
"This is the back trace:";
528 log.fatal() << level;
536 log.fatal() <<
"# Elements Exception : " << exc1.
what();
543 log.fatal() <<
"# Standard Exception : " << exc2.
what();
547 log.fatal() <<
"# An exception of unknown type occurred, "
548 <<
"i.e., an exception not deriving from std::exception ";