From d32c0b36bf4b739cd71792048b03b2efe51c4c50 Mon Sep 17 00:00:00 2001 From: Volker Christian Date: Tue, 23 Sep 2025 21:38:01 +0200 Subject: [PATCH 1/2] Recursive needs processing The current way needs relations are checked in void App::_process_requirements() is missleading. Assume you have an application 'test' with a CLI11 config system configuring following needs relations between some subcommands: app ---> sub1 ---> sub11 | |-> sub12 |-> sub2 A) Current needs processing gives: ./test -> test requires sub1 // OK for the user ./test sub1 -> test requires sub2 // OK for the user ./test sub1 sub2 -> sub1 requires sub11 // Confuses the user ./test sub1 sub2 sub11 -> ready for execution B) Recursive needs processing gives: ./test -> test requires sub1 // OK ./test sub1 -> sub1 requires sub11 // Much more intuitive for the user ./test sub1 sub2 -> sub1 requires sub11 // Makes sense: sub1 configuration is not compleate yet ./test sub1 sub11 -> test requires sub2 // OK, sub1 configuration is compleate ./test sub1 sub11 sub2 -> ready for execution --- include/CLI/impl/App_inl.hpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/include/CLI/impl/App_inl.hpp b/include/CLI/impl/App_inl.hpp index 614805dde..d5b7a7e1f 100644 --- a/include/CLI/impl/App_inl.hpp +++ b/include/CLI/impl/App_inl.hpp @@ -1317,10 +1317,22 @@ CLI11_INLINE void App::_process_requirements() { missing_need = opt->get_name(); } } + for(const auto &subc : need_subcommands_) { // Process subcommands given on the commandline first + if (subc->count() > 0) { + subc->_process_requirements(); + } + } for(const auto &subc : need_subcommands_) { - if(subc->count_all() == 0) { - missing_needed = true; - missing_need = subc->get_display_name(); + if (subc->count() == 0) { + try { + subc->_process_requirements(); + } catch (const CLI::RequiresError&) { + throw RequiresError(get_display_name(), subc->name_); + } + if(subc->count_all() == 0) { + missing_needed = true; + missing_need = subc->get_display_name(); + } } } if(missing_needed) { @@ -1402,7 +1414,7 @@ CLI11_INLINE void App::_process_requirements() { } } } - if(sub->count() > 0 || sub->name_.empty()) { + if(sub->count() > 0 || sub->name_.empty() && need_subcommands_.find(sub.get()) == need_subcommands_.end()) { sub->_process_requirements(); } From 57fea316407b21e8da2320fb054a94bc1f76ca69 Mon Sep 17 00:00:00 2001 From: Volker Christian Date: Wed, 1 Oct 2025 13:35:22 +0200 Subject: [PATCH 2/2] Fix condition logic --- include/CLI/impl/App_inl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/CLI/impl/App_inl.hpp b/include/CLI/impl/App_inl.hpp index d5b7a7e1f..06258477f 100644 --- a/include/CLI/impl/App_inl.hpp +++ b/include/CLI/impl/App_inl.hpp @@ -1414,7 +1414,7 @@ CLI11_INLINE void App::_process_requirements() { } } } - if(sub->count() > 0 || sub->name_.empty() && need_subcommands_.find(sub.get()) == need_subcommands_.end()) { + if((sub->count() > 0 || sub->name_.empty()) && need_subcommands_.find(sub.get()) == need_subcommands_.end()) { sub->_process_requirements(); }