250 {
251 set_program_options();
252
253 bpo::variables_map& options = my->_options;
254 try {
255 bpo::parsed_options parsed = bpo::command_line_parser(argc,
argv).options(my->_app_options).run();
256 bpo::store(parsed, options);
257 vector<string> positionals = bpo::collect_unrecognized(parsed.options, bpo::include_positional);
258 if(!positionals.empty())
259 BOOST_THROW_EXCEPTION(std::runtime_error("Unknown option '" + positionals[0] + "' passed as command line argument"));
260 } catch( const boost::program_options::unknown_option& e ) {
261 BOOST_THROW_EXCEPTION(std::runtime_error("Unknown option '" + e.get_option_name() + "' passed as command line argument"));
262 }
263
264 if( options.count( "help" ) ) {
265 cout << my->_app_options << std::endl;
266 return false;
267 }
268
269 if( options.count( "version" ) ) {
271 return false;
272 }
273
274 if( options.count( "full-version" ) ) {
276 return false;
277 }
278
279 if( options.count( "print-default-config" ) ) {
280 print_default_config(cout);
281 return false;
282 }
283
284 if( options.count( "data-dir" ) ) {
285
286
287
288
289 auto workaround = options["data-dir"].as<std::string>();
294 }
295
296 if( options.count( "config-dir" ) ) {
297 auto workaround = options["config-dir"].as<std::string>();
302 }
303
304 auto workaround = options["logconf"].as<std::string>();
305 bfs::path logconf = workaround;
306 if( logconf.is_relative() )
307 logconf = my->_config_dir / logconf;
308 my->_logging_conf = logconf;
309
310 workaround = options["config"].as<std::string>();
311 my->_config_file_name = workaround;
312 if( my->_config_file_name.is_relative() )
313 my->_config_file_name = my->_config_dir / my->_config_file_name;
314
315 if(!bfs::exists(my->_config_file_name)) {
316 if(my->_config_file_name.compare(my->_config_dir / "config.ini") != 0)
317 {
318 cout << "Config file " << my->_config_file_name << " missing." << std::endl;
319 return false;
320 }
321 write_default_config(my->_config_file_name);
322 }
323
324 std::vector< bpo::basic_option<char> > opts_from_config;
325 try {
326 bpo::parsed_options parsed_opts_from_config = bpo::parse_config_file<char>(my->_config_file_name.make_preferred().string().c_str(), my->_cfg_options, false);
327 bpo::store(parsed_opts_from_config, options);
328 opts_from_config = parsed_opts_from_config.options;
329 } catch( const boost::program_options::unknown_option& e ) {
330 BOOST_THROW_EXCEPTION(std::runtime_error(
"Unknown option '" + e.get_option_name() +
"' inside the config file " +
full_config_file_path().
string()));
331 }
332
333 std::vector<string> set_but_default_list;
334
335 for(const boost::shared_ptr<bpo::option_description>& od_ptr : my->_cfg_options.options()) {
336 boost::any default_val, config_val;
337 if(!od_ptr->semantic()->apply_default(default_val))
338 continue;
339
340 if(my->_any_compare_map.find(default_val.type()) == my->_any_compare_map.end()) {
341 std::cerr << "APPBASE: Developer -- the type " << default_val.type().name() << " is not registered with appbase," << std::endl;
342 std::cerr << " add a register_config_type<>() in your plugin's ctor" << std::endl;
343 return false;
344 }
345
346 for(const bpo::basic_option<char>& opt : opts_from_config) {
347 if(opt.string_key != od_ptr->long_name())
348 continue;
349
350 od_ptr->semantic()->parse(config_val, opt.value, true);
351 if(my->_any_compare_map.at(default_val.type())(default_val, config_val))
352 set_but_default_list.push_back(opt.string_key);
353 break;
354 }
355 }
356 if(set_but_default_list.size()) {
357 std::cerr << "APPBASE: Warning: The following configuration items in the config.ini file are redundantly set to" << std::endl;
358 std::cerr << " their default value:" << std::endl;
359 std::cerr << " ";
360 size_t chars_on_line = 0;
361 for(auto it = set_but_default_list.cbegin(); it != set_but_default_list.end(); ++it) {
362 std::cerr << *it;
363 if(it + 1 != set_but_default_list.end())
364 std::cerr << ", ";
365 if((chars_on_line += it->size()) > 65) {
366 std::cerr << std::endl << " ";
367 chars_on_line = 0;
368 }
369 }
370 std::cerr << std::endl;
371 std::cerr << " Explicit values will override future changes to application defaults. Consider commenting out or" << std::endl;
372 std::cerr << " removing these items." << std::endl;
373 }
374
375 if(options.count("plugin") > 0)
376 {
377 auto plugins = options.at("plugin").as<std::vector<std::string>>();
378 for(auto& arg : plugins)
379 {
380 vector<string> names;
381 boost::split(names, arg, boost::is_any_of(" \t,"));
382 for(
const std::string&
name : names)
384 }
385 }
386 try {
387 for (
auto plugin : autostart_plugins)
389 plugin->initialize(options);
390
391 bpo::notify(options);
392 } catch (...) {
393 std::cerr << "Failed to initialize\n";
394 return false;
395 }
396
397 return true;
398}
@ registered
the plugin is constructed but doesn't do anything
bfs::path data_dir() const
Get data directory.
bfs::path full_config_file_path() const
Get full config.ini path.
string version_string() const
Get version string; generated from git describe if available.
bfs::path config_dir() const
Get config directory.
Plugin & get_plugin() const
string full_version_string() const
Get full version string; same as version_string() unless set differently.