diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b8607bc7..5f7ab147e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,15 @@ project( AppBase ) cmake_minimum_required( VERSION 2.8.12 ) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") + +include( InstallDirectoryPermissions ) + file(GLOB HEADERS "include/appbase/*.hpp") set(CMAKE_EXPORT_COMPILE_COMMANDS "ON") -SET(BOOST_COMPONENTS) -LIST(APPEND BOOST_COMPONENTS thread +set(BOOST_COMPONENTS) +list(APPEND BOOST_COMPONENTS thread date_time filesystem system @@ -15,7 +19,7 @@ LIST(APPEND BOOST_COMPONENTS thread unit_test_framework locale) -FIND_PACKAGE(Boost 1.60 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) +find_package(Boost 1.60 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) set( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" ) if( APPLE ) @@ -48,13 +52,18 @@ target_link_libraries( appbase ${Boost_LIBRARIES}) target_include_directories( appbase PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ${Boost_INCLUDE_DIR}) -INSTALL( TARGETS +set_target_properties( appbase PROPERTIES PUBLIC_HEADER "${HEADERS}" ) + +set(CPACK_PACKAGING_INSTALL_PREFIX /) + +install( TARGETS appbase - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib + RUNTIME DESTINATION usr/bin + LIBRARY DESTINATION usr/lib + ARCHIVE DESTINATION usr/lib + PUBLIC_HEADER DESTINATION usr/include/appbase ) -INSTALL( FILES ${HEADERS} DESTINATION "include/appbase" ) +install_directory_permissions( DIRECTORY usr/include/appbase ) add_subdirectory( examples ) diff --git a/CMakeModules/InstallDirectoryPermissions.cmake b/CMakeModules/InstallDirectoryPermissions.cmake new file mode 100644 index 000000000..b13a80692 --- /dev/null +++ b/CMakeModules/InstallDirectoryPermissions.cmake @@ -0,0 +1,14 @@ +# Fix directory permissions after installation of header files (primarily). +macro(install_directory_permissions) + cmake_parse_arguments(ARG "" "DIRECTORY" "" ${ARGN}) + set(dir ${ARG_DIRECTORY}) + install(DIRECTORY DESTINATION ${dir} + DIRECTORY_PERMISSIONS OWNER_READ + OWNER_WRITE + OWNER_EXECUTE + GROUP_READ + GROUP_EXECUTE + WORLD_READ + WORLD_EXECUTE + ) +endmacro(install_directory_permissions) diff --git a/application.cpp b/application.cpp index 3fe9a99fc..d508f3341 100644 --- a/application.cpp +++ b/application.cpp @@ -22,7 +22,8 @@ class application_impl { options_description _app_options; options_description _cfg_options; - bfs::path _data_dir; + bfs::path _data_dir{"data-dir"}; + bfs::path _config_dir{"config-dir"}; bfs::path _logging_conf{"logging.json"}; uint64_t _version; @@ -43,6 +44,14 @@ uint64_t application::version() const { return my->_version; } +void application::set_default_data_dir(const bfs::path& data_dir) { + my->_data_dir = data_dir; +} + +void application::set_default_config_dir(const bfs::path& config_dir) { + my->_config_dir = config_dir; +} + bfs::path application::get_logging_conf() const { return my->_logging_conf; } @@ -81,8 +90,9 @@ void application::set_program_options() app_cli_opts.add_options() ("help,h", "Print this help message and exit.") ("version,v", "Print version information.") - ("data-dir,d", bpo::value()->default_value( "data-dir" ), "Directory containing configuration file config.ini") - ("config,c", bpo::value()->default_value( "config.ini" ), "Configuration file name relative to data-dir") + ("data-dir,d", bpo::value(), "Directory containing program runtime data") + ("config-dir", bpo::value(), "Directory containing configuration files such as config.ini") + ("config,c", bpo::value()->default_value( "config.ini" ), "Configuration file name relative to config-dir") ("logconf,l", bpo::value()->default_value( "logging.json" ), "Logging configuration file name/path for library users"); my->_cfg_options.add(app_cfg_opts); @@ -106,33 +116,34 @@ bool application::initialize_impl(int argc, char** argv, vector(); + if( options.count( "data-dir" ) ) { + bfs::path data_dir = options["data-dir"].as(); if( data_dir.is_relative() ) data_dir = bfs::current_path() / data_dir; + my->_data_dir = data_dir; } - my->_data_dir = data_dir; - bfs::path logconf = data_dir / "logging.json"; - if( options.count("logconf") ) - { - logconf = options["logconf"].as(); - if( logconf.is_relative() ) - logconf = data_dir / logconf; + if( options.count( "config-dir" ) ) { + bfs::path config_dir = options["config-dir"].as(); + if( config_dir.is_relative() ) + config_dir = bfs::current_path() / config_dir; + my->_config_dir = config_dir; } + + bfs::path logconf = options["logconf"].as(); + if( logconf.is_relative() ) + logconf = my->_config_dir / logconf; my->_logging_conf = logconf; - bfs::path config_file_name = data_dir / "config.ini"; + bfs::path config_file_name = my->_config_dir / "config.ini"; if( options.count( "config" ) ) { config_file_name = options["config"].as(); if( config_file_name.is_relative() ) - config_file_name = data_dir / config_file_name; + config_file_name = my->_config_dir / config_file_name; } if(!bfs::exists(config_file_name)) { - if(config_file_name.compare(data_dir / "config.ini") != 0) + if(config_file_name.compare(my->_config_dir / "config.ini") != 0) { cout << "Config file " << config_file_name << " missing." << std::endl; return false; @@ -208,23 +219,23 @@ void application::write_default_config(const bfs::path& cfg_file) { for(const boost::shared_ptr od : my->_cfg_options.options()) { if(!od->description().empty()) - out_cfg << "# " << od->description() << "\n"; + out_cfg << "# " << od->description() << std::endl; boost::any store; if(!od->semantic()->apply_default(store)) - out_cfg << "# " << od->long_name() << " = \n"; + out_cfg << "# " << od->long_name() << " = " << std::endl; else { auto example = od->format_parameter(); if(example.empty()) // This is a boolean switch - out_cfg << od->long_name() << " = " << "false\n"; + out_cfg << od->long_name() << " = " << "false" << std::endl; else { // The string is formatted "arg (=)" example.erase(0, 6); example.erase(example.length()-1); - out_cfg << od->long_name() << " = " << example << "\n"; + out_cfg << od->long_name() << " = " << example << std::endl; } } - out_cfg << "\n"; + out_cfg << std::endl; } out_cfg.close(); } @@ -245,8 +256,12 @@ abstract_plugin& application::get_plugin(const string& name)const { return *ptr; } -bfs::path application::data_dir()const { +bfs::path application::data_dir() const { return my->_data_dir; } +bfs::path application::config_dir() const { + return my->_config_dir; +} + } /// namespace appbase diff --git a/include/appbase/application.hpp b/include/appbase/application.hpp index fbe4b3d09..1e79c2501 100644 --- a/include/appbase/application.hpp +++ b/include/appbase/application.hpp @@ -23,6 +23,28 @@ namespace appbase { * @return Version output with -v/--version */ uint64_t version() const; + /** @brief Set default data directory + * + * @param data_dir Default data directory to use if not specified + * on the command line. + */ + void set_default_data_dir(const bfs::path& data_dir = "data-dir"); + /** @brief Get data directory + * + * @return Data directory, possibly from command line + */ + bfs::path data_dir() const; + /** @brief Set default config directory + * + * @param config_dir Default configuration directory to use if not + * specified on the command line. + */ + void set_default_config_dir(const bfs::path& config_dir = "etc"); + /** @brief Get config directory + * + * @return Config directory, possibly from command line + */ + bfs::path config_dir() const; /** @brief Get logging configuration path. * * @return Logging configuration location from command line @@ -78,9 +100,6 @@ namespace appbase { return *ptr; } - bfs::path data_dir()const; - - boost::asio::io_service& get_io_service() { return *io_serv; } protected: template