diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index 9f16c6f3..f679c7b9 100644 --- a/nano/lib/CMakeLists.txt +++ b/nano/lib/CMakeLists.txt @@ -90,7 +90,8 @@ target_link_libraries( ipc_flatbuffers_lib ${CRYPTOPP_LIBRARY} ${CMAKE_DL_LIBS} - Boost::boost) + Boost::boost + Boost::program_options) if(NANO_STACKTRACE_BACKTRACE) target_link_libraries(nano_lib backtrace) diff --git a/nano/lib/utility.cpp b/nano/lib/utility.cpp index 64111b4c..f33b21a8 100644 --- a/nano/lib/utility.cpp +++ b/nano/lib/utility.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -196,3 +197,23 @@ void assert_internal (char const * check_expr, char const * func, char const * f abort (); } + +// Issue #3748 +void nano::sort_options_description (const boost::program_options::options_description & source, boost::program_options::options_description & target) +{ + // Grab all of the options, get the option display name, stick it in a map using the display name as + // the key (the map will sort) and the value as the option itself. + const auto & options = source.options (); + std::map> sorted_options; + for (const auto & option : options) + { + auto pair = std::make_pair (option->canonical_display_name (2), option); + sorted_options.insert (pair); + } + + // Rebuild for display purposes only. + for (const auto & option_pair : sorted_options) + { + target.add (option_pair.second); + } +} diff --git a/nano/lib/utility.hpp b/nano/lib/utility.hpp index eb0d1e71..b547e532 100644 --- a/nano/lib/utility.hpp +++ b/nano/lib/utility.hpp @@ -22,6 +22,11 @@ namespace system { class error_code; } + +namespace program_options +{ + class options_description; +} } void assert_internal (char const * check_expr, char const * func, char const * file, unsigned int line, bool is_release_assert, std::string_view error = ""); @@ -203,4 +208,7 @@ constexpr TARGET_TYPE narrow_cast (SOURCE_TYPE const & val) debug_assert (val == static_cast (res)); return res; } + +// Issue #3748 +void sort_options_description (const boost::program_options::options_description & source, boost::program_options::options_description & target); } diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index 399cd5a8..02414350 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -2033,7 +2033,11 @@ int main (int argc, char * const * argv) } else { - std::cout << description << std::endl; + // Issue #3748 + // Regardless how the options were added, output the options in alphabetical order so they are easy to find. + boost::program_options::options_description sorted_description ("Command line options"); + nano::sort_options_description (description, sorted_description); + std::cout << sorted_description << std::endl; result = -1; } } diff --git a/nano/nano_rpc/entry.cpp b/nano/nano_rpc/entry.cpp index 8c8032cd..49f5bc88 100644 --- a/nano/nano_rpc/entry.cpp +++ b/nano/nano_rpc/entry.cpp @@ -156,7 +156,11 @@ int main (int argc, char * const * argv) } else { - std::cout << description << std::endl; + // Issue #3748 + // Regardless how the options were added, output the options in alphabetical order so they are easy to find. + boost::program_options::options_description sorted_description ("Command line options"); + nano::sort_options_description (description, sorted_description); + std::cout << sorted_description << std::endl; } return 1;