From c3cc8407914359a28de6604e63ad1685c5906a98 Mon Sep 17 00:00:00 2001 From: hwinkel Date: Sat, 5 Aug 2023 13:41:10 +0200 Subject: [PATCH] initial commit --- .drone.yml | 42 + .gitignore | 3 + CMakeLists.txt | 58 + cmake/Jenkinsfile | 59 + cmake/Jenkinsfile:Zone.Identifier | 0 cmake/Modules/CheckParent.cmake | 1 + .../Modules/CheckParent.cmake:Zone.Identifier | 0 cmake/Modules/CppCheck.cmake | 28 + cmake/Modules/FindGMP.cmake | 76 + cmake/Modules/FindValgrind.cmake | 25 + cmake/Modules/Findsodium.cmake | 269 + cmake/Modules/GenerateCccc.cmake | 47 + cmake/Modules/GenerateCppCheck.cmake | 74 + cmake/Modules/ProcessDOXYGEN.cmake | 23 + cmake/Modules/ProcessGIT.cmake | 17 + cmake/Modules/add_my_test.cmake | 22 + cmake/Modules/c++-standards.cmake | 66 + cmake/Modules/code-coverage.cmake | 588 + cmake/Modules/codecheck.cmake | 83 + cmake/Modules/compdb.cmake | 23 + cmake/Modules/compiler-options.cmake | 46 + cmake/Modules/defaultIncludes.cmake | 15 + cmake/Modules/defaultOptions.cmake | 9 + cmake/Modules/doxygen.cmake | 134 + cmake/Modules/protobuf.cmake | 34 + cmake/Modules/sanitizers.cmake | 87 + cmake/Modules/tools.cmake | 64 + cmake/Modules/xslt.cmake | 43 + cmake/Toolchains/Toolchain-mingw64.cmake | 27 + docs/Doxyfile.in | 23 + include/kubecontrol/kubecontrol.hpp | 0 libs/CLI11/.all-contributorsrc | 483 + libs/CLI11/.appveyor.yml | 39 + libs/CLI11/.ci/azure-build.yml | 23 + libs/CLI11/.ci/azure-cmake.yml | 17 + libs/CLI11/.ci/azure-test.yml | 9 + libs/CLI11/.clang-format | 86 + libs/CLI11/.clang-tidy | 80 + libs/CLI11/.cmake-format.yaml | 6 + libs/CLI11/.codecov.yml | 3 + libs/CLI11/.editorconfig | 13 + libs/CLI11/.github/CONTRIBUTING.md | 103 + .../.github/actions/quick_cmake/action.yml | 25 + libs/CLI11/.github/codecov.yml | 7 + libs/CLI11/.github/dependabot.yml | 7 + libs/CLI11/.github/labeler_merged.yml | 4 + libs/CLI11/.github/workflows/build.yml | 59 + libs/CLI11/.github/workflows/pr_merged.yml | 15 + libs/CLI11/.github/workflows/tests.yml | 250 + libs/CLI11/.gitignore | 15 + libs/CLI11/.pre-commit-config.yaml | 88 + libs/CLI11/.remarkrc | 7 + libs/CLI11/CHANGELOG.md | 1009 + libs/CLI11/CLI11.CPack.Description.txt | 1 + libs/CLI11/CLI11.hpp.in | 83 + libs/CLI11/CMakeLists.txt | 233 + libs/CLI11/CPPLINT.cfg | 13 + libs/CLI11/LICENSE | 25 + libs/CLI11/README.md | 1767 ++ libs/CLI11/azure-pipelines.yml | 139 + libs/CLI11/book/.gitignore | 20 + libs/CLI11/book/CMakeLists.txt | 7 + libs/CLI11/book/README.md | 94 + libs/CLI11/book/SUMMARY.md | 15 + libs/CLI11/book/book.json | 12 + libs/CLI11/book/chapters/advanced-topics.md | 152 + .../book/chapters/an-advanced-example.md | 39 + libs/CLI11/book/chapters/basics.md | 39 + libs/CLI11/book/chapters/config.md | 340 + libs/CLI11/book/chapters/flags.md | 167 + libs/CLI11/book/chapters/formatting.md | 86 + libs/CLI11/book/chapters/installation.md | 114 + libs/CLI11/book/chapters/internals.md | 54 + libs/CLI11/book/chapters/options.md | 459 + libs/CLI11/book/chapters/subcommands.md | 194 + libs/CLI11/book/chapters/toolkits.md | 40 + libs/CLI11/book/chapters/validators.md | 66 + libs/CLI11/book/code/CMakeLists.txt | 32 + libs/CLI11/book/code/flags.cpp | 36 + libs/CLI11/book/code/geet.cpp | 50 + libs/CLI11/book/code/intro.cpp | 15 + libs/CLI11/book/code/simplest.cpp | 11 + libs/CLI11/cmake/CLI11.pc.in | 9 + libs/CLI11/cmake/CLI11ConfigVersion.cmake.in | 13 + libs/CLI11/cmake/CLI11GeneratePkgConfig.cmake | 3 + libs/CLI11/cmake/CLI11Warnings.cmake | 37 + libs/CLI11/cmake/CodeCoverage.cmake | 243 + libs/CLI11/conanfile.py | 49 + libs/CLI11/docs/.gitignore | 2 + libs/CLI11/docs/CLI11.svg | 114 + libs/CLI11/docs/CLI11_100.png | Bin 0 -> 3355 bytes libs/CLI11/docs/CLI11_300.png | Bin 0 -> 9957 bytes libs/CLI11/docs/CMakeLists.txt | 11 + libs/CLI11/docs/Doxyfile | 2475 +++ libs/CLI11/docs/mainpage.md | 24 + libs/CLI11/examples/CMakeLists.txt | 251 + libs/CLI11/examples/callback_passthrough.cpp | 28 + libs/CLI11/examples/config_app.cpp | 50 + libs/CLI11/examples/custom_parse.cpp | 39 + libs/CLI11/examples/digit_args.cpp | 21 + libs/CLI11/examples/enum.cpp | 33 + libs/CLI11/examples/enum_ostream.cpp | 50 + libs/CLI11/examples/formatter.cpp | 37 + libs/CLI11/examples/groups.cpp | 39 + libs/CLI11/examples/inter_argument_order.cpp | 51 + libs/CLI11/examples/json.cpp | 123 + libs/CLI11/examples/modhelp.cpp | 35 + libs/CLI11/examples/nested.cpp | 30 + libs/CLI11/examples/option_groups.cpp | 46 + libs/CLI11/examples/positional_arity.cpp | 46 + libs/CLI11/examples/positional_validation.cpp | 37 + libs/CLI11/examples/prefix_command.cpp | 35 + libs/CLI11/examples/ranges.cpp | 41 + libs/CLI11/examples/retired.cpp | 46 + libs/CLI11/examples/shapes.cpp | 56 + libs/CLI11/examples/simple.cpp | 38 + libs/CLI11/examples/subcom_help.cpp | 21 + .../examples/subcom_in_files/CMakeLists.txt | 1 + .../examples/subcom_in_files/subcommand_a.cpp | 37 + .../examples/subcom_in_files/subcommand_a.hpp | 23 + .../subcom_in_files/subcommand_main.cpp | 26 + libs/CLI11/examples/subcom_partitioned.cpp | 46 + libs/CLI11/examples/subcommands.cpp | 35 + libs/CLI11/examples/testEXE.cpp | 26 + libs/CLI11/examples/validators.cpp | 25 + libs/CLI11/include/CLI/App.hpp | 1404 ++ libs/CLI11/include/CLI/CLI.hpp | 36 + libs/CLI11/include/CLI/Config.hpp | 48 + libs/CLI11/include/CLI/ConfigFwd.hpp | 185 + libs/CLI11/include/CLI/Error.hpp | 354 + libs/CLI11/include/CLI/Formatter.hpp | 25 + libs/CLI11/include/CLI/FormatterFwd.hpp | 189 + libs/CLI11/include/CLI/Macros.hpp | 75 + libs/CLI11/include/CLI/Option.hpp | 807 + libs/CLI11/include/CLI/Split.hpp | 48 + libs/CLI11/include/CLI/StringTools.hpp | 234 + libs/CLI11/include/CLI/Timer.hpp | 135 + libs/CLI11/include/CLI/TypeTools.hpp | 1588 ++ libs/CLI11/include/CLI/Validators.hpp | 908 + libs/CLI11/include/CLI/Version.hpp | 16 + libs/CLI11/include/CLI/impl/App_inl.hpp | 2103 ++ libs/CLI11/include/CLI/impl/Config_inl.hpp | 394 + libs/CLI11/include/CLI/impl/Formatter_inl.hpp | 291 + libs/CLI11/include/CLI/impl/Option_inl.hpp | 653 + libs/CLI11/include/CLI/impl/Split_inl.hpp | 139 + .../include/CLI/impl/StringTools_inl.hpp | 260 + .../CLI11/include/CLI/impl/Validators_inl.hpp | 346 + libs/CLI11/meson.build | 23 + libs/CLI11/meson_options.txt | 1 + libs/CLI11/scripts/ExtractVersion.py | 17 + libs/CLI11/scripts/MakeSingleHeader.py | 158 + libs/CLI11/scripts/check_style.sh | 10 + libs/CLI11/scripts/check_style_docker.sh | 14 + libs/CLI11/scripts/clang-format-pre-commit | 36 + libs/CLI11/scripts/mdlint_style.rb | 9 + libs/CLI11/src/CMakeLists.txt | 120 + libs/CLI11/src/Precompile.cpp | 13 + libs/CLI11/subprojects/catch2.wrap | 11 + libs/CLI11/test_package/CMakeLists.txt | 16 + libs/CLI11/test_package/conanfile.py | 21 + libs/CLI11/test_package/example.cpp | 20 + libs/CLI11/tests/.syntastic_cpp_config | 1 + libs/CLI11/tests/AppTest.cpp | 2462 +++ libs/CLI11/tests/BoostOptionTypeTest.cpp | 126 + libs/CLI11/tests/CMakeLists.txt | 219 + libs/CLI11/tests/ComplexTypeTest.cpp | 191 + libs/CLI11/tests/ConfigFileTest.cpp | 2989 +++ libs/CLI11/tests/CreationTest.cpp | 777 + libs/CLI11/tests/DeprecatedTest.cpp | 14 + libs/CLI11/tests/FormatterTest.cpp | 211 + libs/CLI11/tests/HelpTest.cpp | 1285 ++ libs/CLI11/tests/HelpersTest.cpp | 1343 ++ libs/CLI11/tests/NewParseTest.cpp | 495 + libs/CLI11/tests/OptionGroupTest.cpp | 803 + libs/CLI11/tests/OptionTypeTest.cpp | 1142 + libs/CLI11/tests/OptionalTest.cpp | 357 + libs/CLI11/tests/SetTest.cpp | 729 + libs/CLI11/tests/SimpleTest.cpp | 34 + libs/CLI11/tests/StringParseTest.cpp | 117 + libs/CLI11/tests/SubcommandTest.cpp | 1986 ++ libs/CLI11/tests/TimerTest.cpp | 70 + libs/CLI11/tests/TransformTest.cpp | 971 + libs/CLI11/tests/TrueFalseTest.cpp | 29 + libs/CLI11/tests/WindowsTest.cpp | 19 + libs/CLI11/tests/app_helper.hpp | 69 + libs/CLI11/tests/catch.hpp | 9 + libs/CLI11/tests/informational.cpp | 56 + libs/CLI11/tests/link_test_1.cpp | 10 + libs/CLI11/tests/link_test_2.cpp | 17 + libs/CLI11/tests/main.cpp | 8 + libs/CLI11/tests/meson.build | 78 + libs/CLI11/tests/mesonTest/README.md | 10 + libs/CLI11/tests/mesonTest/main.cpp | 17 + libs/CLI11/tests/mesonTest/meson.build | 5 + libs/Catch2/.clang-format | 25 + libs/Catch2/.conan/build.py | 94 + .../Catch2/.conan/test_package/CMakeLists.txt | 11 + libs/Catch2/.conan/test_package/conanfile.py | 19 + .../.conan/test_package/test_package.cpp | 15 + libs/Catch2/.gitattributes | 22 + libs/Catch2/.github/FUNDING.yml | 1 + .../.github/ISSUE_TEMPLATE/bug_report.md | 29 + .../.github/ISSUE_TEMPLATE/feature_request.md | 14 + libs/Catch2/.github/pull_request_template.md | 28 + libs/Catch2/.gitignore | 31 + libs/Catch2/.travis.yml | 335 + libs/Catch2/BUILD.bazel | 17 + libs/Catch2/CMake/Catch2Config.cmake.in | 10 + libs/Catch2/CMake/FindGcov.cmake | 157 + libs/Catch2/CMake/FindLcov.cmake | 354 + libs/Catch2/CMake/Findcodecov.cmake | 258 + libs/Catch2/CMake/MiscFunctions.cmake | 26 + libs/Catch2/CMake/catch2.pc.in | 10 + libs/Catch2/CMake/llvm-cov-wrapper | 56 + libs/Catch2/CMakeLists.txt | 259 + libs/Catch2/CODE_OF_CONDUCT.md | 46 + libs/Catch2/LICENSE.txt | 23 + libs/Catch2/README.md | 37 + libs/Catch2/WORKSPACE | 0 libs/Catch2/appveyor.yml | 101 + libs/Catch2/artwork/catch2-c-logo.png | Bin 0 -> 10636 bytes libs/Catch2/artwork/catch2-hand-logo.png | Bin 0 -> 33761 bytes libs/Catch2/artwork/catch2-logo-small.png | Bin 0 -> 20939 bytes libs/Catch2/codecov.yml | 25 + libs/Catch2/conanfile.py | 30 + libs/Catch2/contrib/Catch.cmake | 206 + libs/Catch2/contrib/CatchAddTests.cmake | 135 + .../contrib/ParseAndAddCatchTests.cmake | 252 + libs/Catch2/contrib/gdbinit | 16 + libs/Catch2/contrib/lldbinit | 16 + libs/Catch2/docs/Readme.md | 41 + libs/Catch2/docs/assertions.md | 201 + libs/Catch2/docs/benchmarks.md | 254 + libs/Catch2/docs/ci-and-misc.md | 112 + libs/Catch2/docs/cmake-integration.md | 291 + libs/Catch2/docs/command-line.md | 421 + libs/Catch2/docs/commercial-users.md | 22 + libs/Catch2/docs/configuration.md | 275 + libs/Catch2/docs/contributing.md | 231 + libs/Catch2/docs/deprecations.md | 144 + libs/Catch2/docs/event-listeners.md | 75 + libs/Catch2/docs/generators.md | 219 + libs/Catch2/docs/limitations.md | 201 + libs/Catch2/docs/list-of-examples.md | 49 + libs/Catch2/docs/logging.md | 159 + libs/Catch2/docs/matchers.md | 207 + libs/Catch2/docs/opensource-users.md | 126 + libs/Catch2/docs/other-macros.md | 154 + libs/Catch2/docs/own-main.md | 131 + libs/Catch2/docs/release-notes.md | 1316 ++ libs/Catch2/docs/release-process.md | 73 + libs/Catch2/docs/reporters.md | 47 + libs/Catch2/docs/slow-compiles.md | 106 + libs/Catch2/docs/test-cases-and-sections.md | 275 + libs/Catch2/docs/test-fixtures.md | 143 + libs/Catch2/docs/tostring.md | 132 + libs/Catch2/docs/tutorial.md | 279 + libs/Catch2/docs/why-catch.md | 46 + libs/Catch2/examples/000-CatchMain.cpp | 15 + libs/Catch2/examples/010-TestCase.cpp | 36 + libs/Catch2/examples/020-TestCase-1.cpp | 35 + libs/Catch2/examples/020-TestCase-2.cpp | 33 + .../Catch2/examples/030-Asn-Require-Check.cpp | 74 + libs/Catch2/examples/100-Fix-Section.cpp | 69 + libs/Catch2/examples/110-Fix-ClassFixture.cpp | 63 + .../120-Bdd-ScenarioGivenWhenThen.cpp | 73 + libs/Catch2/examples/200-Rpt-CatchMain.cpp | 27 + .../examples/207-Rpt-TeamCityReporter.cpp | 171 + .../examples/210-Evt-EventListeners.cpp | 422 + .../Catch2/examples/231-Cfg-OutputStreams.cpp | 56 + libs/Catch2/examples/300-Gen-OwnGenerator.cpp | 59 + .../examples/301-Gen-MapTypeConversion.cpp | 58 + libs/Catch2/examples/302-Gen-Table.cpp | 54 + .../310-Gen-VariablesInGenerators.cpp | 33 + .../Catch2/examples/311-Gen-CustomCapture.cpp | 41 + libs/Catch2/examples/CMakeLists.txt | 158 + libs/Catch2/include/catch.hpp | 496 + libs/Catch2/include/catch_with_main.hpp | 14 + libs/Catch2/include/external/clara.hpp | 1268 ++ .../internal/benchmark/catch_benchmark.hpp | 122 + .../benchmark/catch_benchmarking_all.hpp | 29 + .../internal/benchmark/catch_chronometer.hpp | 71 + .../internal/benchmark/catch_clock.hpp | 40 + .../internal/benchmark/catch_constructor.hpp | 79 + .../internal/benchmark/catch_environment.hpp | 38 + .../internal/benchmark/catch_estimate.hpp | 31 + .../benchmark/catch_execution_plan.hpp | 59 + .../internal/benchmark/catch_optimizer.hpp | 68 + .../catch_outlier_classification.hpp | 29 + .../benchmark/catch_sample_analysis.hpp | 50 + .../benchmark/detail/catch_analyse.hpp | 78 + .../detail/catch_benchmark_function.hpp | 105 + .../detail/catch_complete_invoke.hpp | 68 + .../benchmark/detail/catch_estimate_clock.hpp | 115 + .../benchmark/detail/catch_measure.hpp | 35 + .../benchmark/detail/catch_repeat.hpp | 37 + .../detail/catch_run_for_at_least.hpp | 65 + .../internal/benchmark/detail/catch_stats.cpp | 224 + .../internal/benchmark/detail/catch_stats.hpp | 160 + .../benchmark/detail/catch_timing.hpp | 33 + libs/Catch2/include/internal/catch_approx.cpp | 88 + libs/Catch2/include/internal/catch_approx.h | 132 + .../internal/catch_assertionhandler.cpp | 122 + .../include/internal/catch_assertionhandler.h | 88 + .../include/internal/catch_assertioninfo.h | 31 + .../internal/catch_assertionresult.cpp | 104 + .../include/internal/catch_assertionresult.h | 59 + .../Catch2/include/internal/catch_capture.hpp | 159 + .../internal/catch_capture_matchers.cpp | 24 + .../include/internal/catch_capture_matchers.h | 88 + libs/Catch2/include/internal/catch_clara.h | 38 + .../include/internal/catch_commandline.cpp | 230 + .../include/internal/catch_commandline.h | 20 + libs/Catch2/include/internal/catch_common.cpp | 43 + libs/Catch2/include/internal/catch_common.h | 92 + .../internal/catch_compiler_capabilities.h | 378 + libs/Catch2/include/internal/catch_config.cpp | 86 + libs/Catch2/include/internal/catch_config.hpp | 133 + .../catch_config_uncaught_exceptions.hpp | 44 + .../include/internal/catch_console_colour.cpp | 243 + .../include/internal/catch_console_colour.h | 69 + .../Catch2/include/internal/catch_context.cpp | 70 + libs/Catch2/include/internal/catch_context.h | 64 + .../include/internal/catch_debug_console.cpp | 41 + .../include/internal/catch_debug_console.h | 17 + .../include/internal/catch_debugger.cpp | 122 + libs/Catch2/include/internal/catch_debugger.h | 65 + .../include/internal/catch_decomposer.cpp | 24 + .../include/internal/catch_decomposer.h | 259 + .../include/internal/catch_default_main.hpp | 47 + .../Catch2/include/internal/catch_enforce.cpp | 40 + libs/Catch2/include/internal/catch_enforce.h | 53 + .../internal/catch_enum_values_registry.cpp | 75 + .../internal/catch_enum_values_registry.h | 35 + .../include/internal/catch_errno_guard.cpp | 15 + .../include/internal/catch_errno_guard.h | 22 + .../catch_exception_translator_registry.cpp | 89 + .../catch_exception_translator_registry.h | 30 + .../internal/catch_external_interfaces.h | 20 + .../internal/catch_fatal_condition.cpp | 244 + .../include/internal/catch_fatal_condition.h | 68 + .../include/internal/catch_generators.cpp | 32 + .../include/internal/catch_generators.hpp | 219 + .../internal/catch_generators_generic.hpp | 242 + .../internal/catch_generators_specific.hpp | 175 + libs/Catch2/include/internal/catch_impl.hpp | 33 + .../internal/catch_interfaces_capture.cpp | 5 + .../internal/catch_interfaces_capture.h | 100 + .../internal/catch_interfaces_config.cpp | 5 + .../internal/catch_interfaces_config.h | 92 + .../catch_interfaces_enum_values_registry.h | 46 + .../internal/catch_interfaces_exception.cpp | 6 + .../internal/catch_interfaces_exception.h | 88 + .../catch_interfaces_generatortracker.h | 39 + .../catch_interfaces_registry_hub.cpp | 6 + .../internal/catch_interfaces_registry_hub.h | 61 + .../internal/catch_interfaces_reporter.cpp | 114 + .../internal/catch_interfaces_reporter.h | 272 + .../internal/catch_interfaces_runner.cpp | 5 + .../internal/catch_interfaces_runner.h | 19 + .../catch_interfaces_tag_alias_registry.h | 28 + .../internal/catch_interfaces_testcase.cpp | 6 + .../internal/catch_interfaces_testcase.h | 38 + .../include/internal/catch_leak_detector.cpp | 37 + .../include/internal/catch_leak_detector.h | 18 + libs/Catch2/include/internal/catch_list.cpp | 173 + libs/Catch2/include/internal/catch_list.h | 38 + .../include/internal/catch_matchers.cpp | 28 + libs/Catch2/include/internal/catch_matchers.h | 174 + .../internal/catch_matchers_exception.cpp | 30 + .../internal/catch_matchers_exception.hpp | 36 + .../internal/catch_matchers_floating.cpp | 237 + .../internal/catch_matchers_floating.h | 70 + .../internal/catch_matchers_generic.cpp | 9 + .../internal/catch_matchers_generic.hpp | 58 + .../internal/catch_matchers_string.cpp | 118 + .../include/internal/catch_matchers_string.h | 80 + .../include/internal/catch_matchers_vector.h | 180 + .../Catch2/include/internal/catch_message.cpp | 142 + libs/Catch2/include/internal/catch_message.h | 99 + libs/Catch2/include/internal/catch_meta.hpp | 50 + libs/Catch2/include/internal/catch_objc.hpp | 215 + .../include/internal/catch_objc_arc.hpp | 51 + libs/Catch2/include/internal/catch_option.hpp | 73 + .../internal/catch_output_redirect.cpp | 147 + .../include/internal/catch_output_redirect.h | 116 + libs/Catch2/include/internal/catch_platform.h | 30 + .../include/internal/catch_polyfills.cpp | 31 + .../include/internal/catch_polyfills.hpp | 15 + .../include/internal/catch_preprocessor.hpp | 237 + .../catch_random_number_generator.cpp | 73 + .../internal/catch_random_number_generator.h | 58 + .../internal/catch_reenable_warnings.h | 21 + .../include/internal/catch_registry_hub.cpp | 99 + .../internal/catch_reporter_registrars.hpp | 78 + .../internal/catch_reporter_registry.cpp | 34 + .../internal/catch_reporter_registry.h | 37 + .../include/internal/catch_result_type.cpp | 27 + .../include/internal/catch_result_type.h | 55 + .../include/internal/catch_run_context.cpp | 595 + .../include/internal/catch_run_context.h | 159 + .../Catch2/include/internal/catch_section.cpp | 38 + libs/Catch2/include/internal/catch_section.h | 51 + .../include/internal/catch_section_info.cpp | 19 + .../include/internal/catch_section_info.h | 42 + .../Catch2/include/internal/catch_session.cpp | 317 + libs/Catch2/include/internal/catch_session.h | 62 + .../include/internal/catch_singletons.cpp | 36 + .../include/internal/catch_singletons.hpp | 44 + .../catch_startup_exception_registry.cpp | 28 + .../catch_startup_exception_registry.h | 29 + libs/Catch2/include/internal/catch_stream.cpp | 187 + libs/Catch2/include/internal/catch_stream.h | 51 + .../include/internal/catch_string_manip.cpp | 109 + .../include/internal/catch_string_manip.h | 45 + .../include/internal/catch_stringref.cpp | 50 + .../Catch2/include/internal/catch_stringref.h | 104 + .../internal/catch_suppress_warnings.h | 27 + .../include/internal/catch_tag_alias.cpp | 5 + .../Catch2/include/internal/catch_tag_alias.h | 26 + .../catch_tag_alias_autoregistrar.cpp | 16 + .../internal/catch_tag_alias_autoregistrar.h | 26 + .../internal/catch_tag_alias_registry.cpp | 58 + .../internal/catch_tag_alias_registry.h | 31 + .../include/internal/catch_test_case_info.cpp | 186 + .../include/internal/catch_test_case_info.h | 90 + .../catch_test_case_registry_impl.cpp | 176 + .../internal/catch_test_case_registry_impl.h | 71 + .../internal/catch_test_case_tracker.cpp | 254 + .../internal/catch_test_case_tracker.h | 180 + .../include/internal/catch_test_registry.cpp | 37 + .../include/internal/catch_test_registry.h | 402 + .../include/internal/catch_test_spec.cpp | 99 + .../Catch2/include/internal/catch_test_spec.h | 94 + .../internal/catch_test_spec_parser.cpp | 240 + .../include/internal/catch_test_spec_parser.h | 79 + libs/Catch2/include/internal/catch_text.h | 17 + libs/Catch2/include/internal/catch_timer.cpp | 74 + libs/Catch2/include/internal/catch_timer.h | 30 + .../include/internal/catch_to_string.hpp | 28 + .../include/internal/catch_tostring.cpp | 265 + libs/Catch2/include/internal/catch_tostring.h | 675 + libs/Catch2/include/internal/catch_totals.cpp | 61 + libs/Catch2/include/internal/catch_totals.h | 41 + .../internal/catch_uncaught_exceptions.cpp | 25 + .../internal/catch_uncaught_exceptions.h | 15 + .../include/internal/catch_user_interfaces.h | 18 + .../Catch2/include/internal/catch_version.cpp | 44 + libs/Catch2/include/internal/catch_version.h | 39 + .../internal/catch_wildcard_pattern.cpp | 47 + .../include/internal/catch_wildcard_pattern.h | 38 + .../include/internal/catch_windows_h_proxy.h | 39 + .../include/internal/catch_xmlwriter.cpp | 334 + .../Catch2/include/internal/catch_xmlwriter.h | 116 + .../reporters/catch_reporter_automake.hpp | 62 + .../reporters/catch_reporter_bases.cpp | 84 + .../reporters/catch_reporter_bases.hpp | 285 + .../reporters/catch_reporter_compact.cpp | 290 + .../reporters/catch_reporter_compact.h | 39 + .../reporters/catch_reporter_console.cpp | 700 + .../reporters/catch_reporter_console.h | 89 + .../reporters/catch_reporter_junit.cpp | 300 + .../include/reporters/catch_reporter_junit.h | 62 + .../reporters/catch_reporter_listening.cpp | 164 + .../reporters/catch_reporter_listening.h | 63 + .../reporters/catch_reporter_sonarqube.hpp | 181 + .../include/reporters/catch_reporter_tap.hpp | 254 + .../reporters/catch_reporter_teamcity.hpp | 219 + .../include/reporters/catch_reporter_xml.cpp | 281 + .../include/reporters/catch_reporter_xml.h | 68 + libs/Catch2/misc/CMakeLists.txt | 11 + .../misc/appveyorBuildConfigurationScript.bat | 22 + .../misc/appveyorMergeCoverageScript.py | 9 + libs/Catch2/misc/appveyorTestRunScript.bat | 15 + libs/Catch2/misc/coverage-helper.cpp | 142 + libs/Catch2/misc/installOpenCppCoverage.ps1 | 19 + libs/Catch2/projects/CMakeLists.txt | 492 + .../Catch2/projects/ExtraTests/CMakeLists.txt | 201 + libs/Catch2/projects/ExtraTests/ToDo.txt | 11 + .../ExtraTests/X01-PrefixedMacros.cpp | 85 + .../ExtraTests/X02-DisabledMacros.cpp | 35 + .../X03-DisabledExceptions-DefaultHandler.cpp | 23 + .../X04-DisabledExceptions-CustomHandler.cpp | 33 + .../ExtraTests/X10-FallbackStringifier.cpp | 23 + .../ExtraTests/X11-DisableStringification.cpp | 16 + .../ExtraTests/X12-CustomDebugBreakMacro.cpp | 17 + .../ExtraTests/X20-BenchmarkingMacros.cpp | 125 + .../ExtraTests/X90-WindowsHeaderInclusion.cpp | 12 + .../Baselines/automake.std.approved.txt | 168 + .../Baselines/compact.sw.approved.txt | 1904 ++ .../Baselines/console.std.approved.txt | 1425 ++ .../Baselines/console.sw.approved.txt | 14186 ++++++++++++ .../Baselines/console.swa4.approved.txt | 936 + .../SelfTest/Baselines/junit.sw.approved.txt | 1773 ++ .../Baselines/sonarqube.sw.approved.txt | 1777 ++ .../SelfTest/Baselines/xml.sw.approved.txt | 16775 +++++++++++++++ .../CompileTimePerfTests/10.tests.cpp | 13 + .../CompileTimePerfTests/100.tests.cpp | 13 + .../CompileTimePerfTests/All.tests.cpp | 15 + .../IntrospectiveTests/CmdLine.tests.cpp | 582 + .../IntrospectiveTests/Details.tests.cpp | 23 + .../GeneratorsImpl.tests.cpp | 355 + .../InternalBenchmark.tests.cpp | 405 + .../IntrospectiveTests/PartTracker.tests.cpp | 253 + .../RandomNumberGeneration.tests.cpp | 45 + .../IntrospectiveTests/String.tests.cpp | 150 + .../IntrospectiveTests/StringManip.tests.cpp | 67 + .../SelfTest/IntrospectiveTests/Tag.tests.cpp | 54 + .../IntrospectiveTests/ToString.tests.cpp | 53 + .../SelfTest/IntrospectiveTests/Xml.tests.cpp | 114 + .../SelfTest/Misc/invalid-test-names.input | 1 + .../SelfTest/Misc/plain-old-tests.input | 2 + .../Misc/special-characters-in-file.input | 1 + .../SurrogateCpps/catch_console_colour.cpp | 3 + .../SelfTest/SurrogateCpps/catch_debugger.cpp | 2 + .../catch_interfaces_reporter.cpp | 2 + .../SelfTest/SurrogateCpps/catch_option.cpp | 3 + .../SelfTest/SurrogateCpps/catch_stream.cpp | 3 + .../SurrogateCpps/catch_test_case_tracker.cpp | 2 + .../SurrogateCpps/catch_test_spec.cpp | 3 + .../SurrogateCpps/catch_xmlwriter.cpp | 4 + libs/Catch2/projects/SelfTest/TestMain.cpp | 34 + .../SelfTest/TimingTests/Sleep.tests.cpp | 23 + .../SelfTest/UsageTests/Approx.tests.cpp | 222 + .../SelfTest/UsageTests/BDD.tests.cpp | 110 + .../SelfTest/UsageTests/Benchmark.tests.cpp | 144 + .../SelfTest/UsageTests/Class.tests.cpp | 137 + .../SelfTest/UsageTests/Compilation.tests.cpp | 269 + .../SelfTest/UsageTests/Condition.tests.cpp | 347 + .../UsageTests/Decomposition.tests.cpp | 39 + .../UsageTests/EnumToString.tests.cpp | 99 + .../SelfTest/UsageTests/Exception.tests.cpp | 210 + .../SelfTest/UsageTests/Generators.tests.cpp | 271 + .../SelfTest/UsageTests/Matchers.tests.cpp | 678 + .../SelfTest/UsageTests/Message.tests.cpp | 284 + .../SelfTest/UsageTests/Misc.tests.cpp | 493 + .../UsageTests/ToStringByte.tests.cpp | 15 + .../UsageTests/ToStringChrono.tests.cpp | 44 + .../UsageTests/ToStringGeneral.tests.cpp | 210 + .../UsageTests/ToStringOptional.tests.cpp | 23 + .../UsageTests/ToStringPair.tests.cpp | 30 + .../UsageTests/ToStringTuple.tests.cpp | 47 + .../UsageTests/ToStringVariant.tests.cpp | 91 + .../UsageTests/ToStringVector.tests.cpp | 86 + .../UsageTests/ToStringWhich.tests.cpp | 193 + .../SelfTest/UsageTests/Tricky.tests.cpp | 429 + .../UsageTests/VariadicMacros.tests.cpp | 29 + .../projects/SelfTest/WarnAboutNoTests.cmake | 19 + .../projects/TestScripts/testRandomOrder.py | 59 + .../OCTest/OCTest.xcodeproj/project.pbxproj | 294 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../XCode/OCTest/OCTest/CatchOCTestCase.h | 25 + .../XCode/OCTest/OCTest/CatchOCTestCase.mm | 87 + .../projects/XCode/OCTest/OCTest/Main.mm | 2 + .../projects/XCode/OCTest/OCTest/OCTest.1 | 79 + .../projects/XCode/OCTest/OCTest/OCTest.mm | 28 + .../projects/XCode/OCTest/OCTest/TestObj.h | 28 + .../projects/XCode/OCTest/OCTest/TestObj.m | 25 + .../projects/XCode/OCTest/catch_objc_impl.mm | 69 + libs/Catch2/scripts/approvalTests.py | 217 + libs/Catch2/scripts/approve.py | 33 + libs/Catch2/scripts/benchmarkCompile.py | 148 + libs/Catch2/scripts/benchmarkRunner.py | 56 + libs/Catch2/scripts/developBuild.py | 10 + libs/Catch2/scripts/embed.py | 63 + libs/Catch2/scripts/embedClara.py | 27 + .../extractFeaturesFromReleaseNotes.py | 94 + libs/Catch2/scripts/fixWhitespace.py | 52 + libs/Catch2/scripts/generateSingleHeader.py | 151 + libs/Catch2/scripts/majorRelease.py | 10 + libs/Catch2/scripts/minorRelease.py | 10 + libs/Catch2/scripts/patchRelease.py | 10 + libs/Catch2/scripts/releaseCommon.py | 168 + libs/Catch2/scripts/releaseNotes.py | 65 + libs/Catch2/scripts/scriptCommon.py | 31 + libs/Catch2/scripts/updateDocumentToC.py | 449 + libs/Catch2/scripts/updateWandbox.py | 53 + libs/Catch2/single_include/catch2/catch.hpp | 17970 ++++++++++++++++ .../catch2/catch_reporter_automake.hpp | 62 + .../catch2/catch_reporter_sonarqube.hpp | 181 + .../catch2/catch_reporter_tap.hpp | 254 + .../catch2/catch_reporter_teamcity.hpp | 219 + libs/Catch2/src/catch_with_main.cpp | 2 + libs/Catch2/third_party/clara.hpp | 1267 ++ src/kubecontrol/kubecontrol.cpp | 0 test/test_kubecontrol.cpp | 32 + 587 files changed, 140234 insertions(+) create mode 100644 .drone.yml create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 cmake/Jenkinsfile create mode 100644 cmake/Jenkinsfile:Zone.Identifier create mode 100644 cmake/Modules/CheckParent.cmake create mode 100644 cmake/Modules/CheckParent.cmake:Zone.Identifier create mode 100644 cmake/Modules/CppCheck.cmake create mode 100644 cmake/Modules/FindGMP.cmake create mode 100644 cmake/Modules/FindValgrind.cmake create mode 100644 cmake/Modules/Findsodium.cmake create mode 100644 cmake/Modules/GenerateCccc.cmake create mode 100644 cmake/Modules/GenerateCppCheck.cmake create mode 100644 cmake/Modules/ProcessDOXYGEN.cmake create mode 100644 cmake/Modules/ProcessGIT.cmake create mode 100644 cmake/Modules/add_my_test.cmake create mode 100644 cmake/Modules/c++-standards.cmake create mode 100644 cmake/Modules/code-coverage.cmake create mode 100644 cmake/Modules/codecheck.cmake create mode 100644 cmake/Modules/compdb.cmake create mode 100644 cmake/Modules/compiler-options.cmake create mode 100644 cmake/Modules/defaultIncludes.cmake create mode 100644 cmake/Modules/defaultOptions.cmake create mode 100644 cmake/Modules/doxygen.cmake create mode 100644 cmake/Modules/protobuf.cmake create mode 100644 cmake/Modules/sanitizers.cmake create mode 100644 cmake/Modules/tools.cmake create mode 100644 cmake/Modules/xslt.cmake create mode 100644 cmake/Toolchains/Toolchain-mingw64.cmake create mode 100644 docs/Doxyfile.in create mode 100644 include/kubecontrol/kubecontrol.hpp create mode 100644 libs/CLI11/.all-contributorsrc create mode 100644 libs/CLI11/.appveyor.yml create mode 100644 libs/CLI11/.ci/azure-build.yml create mode 100644 libs/CLI11/.ci/azure-cmake.yml create mode 100644 libs/CLI11/.ci/azure-test.yml create mode 100644 libs/CLI11/.clang-format create mode 100644 libs/CLI11/.clang-tidy create mode 100644 libs/CLI11/.cmake-format.yaml create mode 100644 libs/CLI11/.codecov.yml create mode 100644 libs/CLI11/.editorconfig create mode 100644 libs/CLI11/.github/CONTRIBUTING.md create mode 100644 libs/CLI11/.github/actions/quick_cmake/action.yml create mode 100644 libs/CLI11/.github/codecov.yml create mode 100644 libs/CLI11/.github/dependabot.yml create mode 100644 libs/CLI11/.github/labeler_merged.yml create mode 100644 libs/CLI11/.github/workflows/build.yml create mode 100644 libs/CLI11/.github/workflows/pr_merged.yml create mode 100644 libs/CLI11/.github/workflows/tests.yml create mode 100644 libs/CLI11/.gitignore create mode 100644 libs/CLI11/.pre-commit-config.yaml create mode 100644 libs/CLI11/.remarkrc create mode 100644 libs/CLI11/CHANGELOG.md create mode 100644 libs/CLI11/CLI11.CPack.Description.txt create mode 100644 libs/CLI11/CLI11.hpp.in create mode 100644 libs/CLI11/CMakeLists.txt create mode 100644 libs/CLI11/CPPLINT.cfg create mode 100644 libs/CLI11/LICENSE create mode 100644 libs/CLI11/README.md create mode 100644 libs/CLI11/azure-pipelines.yml create mode 100644 libs/CLI11/book/.gitignore create mode 100644 libs/CLI11/book/CMakeLists.txt create mode 100644 libs/CLI11/book/README.md create mode 100644 libs/CLI11/book/SUMMARY.md create mode 100644 libs/CLI11/book/book.json create mode 100644 libs/CLI11/book/chapters/advanced-topics.md create mode 100644 libs/CLI11/book/chapters/an-advanced-example.md create mode 100644 libs/CLI11/book/chapters/basics.md create mode 100644 libs/CLI11/book/chapters/config.md create mode 100644 libs/CLI11/book/chapters/flags.md create mode 100644 libs/CLI11/book/chapters/formatting.md create mode 100644 libs/CLI11/book/chapters/installation.md create mode 100644 libs/CLI11/book/chapters/internals.md create mode 100644 libs/CLI11/book/chapters/options.md create mode 100644 libs/CLI11/book/chapters/subcommands.md create mode 100644 libs/CLI11/book/chapters/toolkits.md create mode 100644 libs/CLI11/book/chapters/validators.md create mode 100644 libs/CLI11/book/code/CMakeLists.txt create mode 100644 libs/CLI11/book/code/flags.cpp create mode 100644 libs/CLI11/book/code/geet.cpp create mode 100644 libs/CLI11/book/code/intro.cpp create mode 100644 libs/CLI11/book/code/simplest.cpp create mode 100644 libs/CLI11/cmake/CLI11.pc.in create mode 100644 libs/CLI11/cmake/CLI11ConfigVersion.cmake.in create mode 100644 libs/CLI11/cmake/CLI11GeneratePkgConfig.cmake create mode 100644 libs/CLI11/cmake/CLI11Warnings.cmake create mode 100644 libs/CLI11/cmake/CodeCoverage.cmake create mode 100644 libs/CLI11/conanfile.py create mode 100644 libs/CLI11/docs/.gitignore create mode 100644 libs/CLI11/docs/CLI11.svg create mode 100644 libs/CLI11/docs/CLI11_100.png create mode 100644 libs/CLI11/docs/CLI11_300.png create mode 100644 libs/CLI11/docs/CMakeLists.txt create mode 100644 libs/CLI11/docs/Doxyfile create mode 100644 libs/CLI11/docs/mainpage.md create mode 100644 libs/CLI11/examples/CMakeLists.txt create mode 100644 libs/CLI11/examples/callback_passthrough.cpp create mode 100644 libs/CLI11/examples/config_app.cpp create mode 100644 libs/CLI11/examples/custom_parse.cpp create mode 100644 libs/CLI11/examples/digit_args.cpp create mode 100644 libs/CLI11/examples/enum.cpp create mode 100644 libs/CLI11/examples/enum_ostream.cpp create mode 100644 libs/CLI11/examples/formatter.cpp create mode 100644 libs/CLI11/examples/groups.cpp create mode 100644 libs/CLI11/examples/inter_argument_order.cpp create mode 100644 libs/CLI11/examples/json.cpp create mode 100644 libs/CLI11/examples/modhelp.cpp create mode 100644 libs/CLI11/examples/nested.cpp create mode 100644 libs/CLI11/examples/option_groups.cpp create mode 100644 libs/CLI11/examples/positional_arity.cpp create mode 100644 libs/CLI11/examples/positional_validation.cpp create mode 100644 libs/CLI11/examples/prefix_command.cpp create mode 100644 libs/CLI11/examples/ranges.cpp create mode 100644 libs/CLI11/examples/retired.cpp create mode 100644 libs/CLI11/examples/shapes.cpp create mode 100644 libs/CLI11/examples/simple.cpp create mode 100644 libs/CLI11/examples/subcom_help.cpp create mode 100644 libs/CLI11/examples/subcom_in_files/CMakeLists.txt create mode 100644 libs/CLI11/examples/subcom_in_files/subcommand_a.cpp create mode 100644 libs/CLI11/examples/subcom_in_files/subcommand_a.hpp create mode 100644 libs/CLI11/examples/subcom_in_files/subcommand_main.cpp create mode 100644 libs/CLI11/examples/subcom_partitioned.cpp create mode 100644 libs/CLI11/examples/subcommands.cpp create mode 100644 libs/CLI11/examples/testEXE.cpp create mode 100644 libs/CLI11/examples/validators.cpp create mode 100644 libs/CLI11/include/CLI/App.hpp create mode 100644 libs/CLI11/include/CLI/CLI.hpp create mode 100644 libs/CLI11/include/CLI/Config.hpp create mode 100644 libs/CLI11/include/CLI/ConfigFwd.hpp create mode 100644 libs/CLI11/include/CLI/Error.hpp create mode 100644 libs/CLI11/include/CLI/Formatter.hpp create mode 100644 libs/CLI11/include/CLI/FormatterFwd.hpp create mode 100644 libs/CLI11/include/CLI/Macros.hpp create mode 100644 libs/CLI11/include/CLI/Option.hpp create mode 100644 libs/CLI11/include/CLI/Split.hpp create mode 100644 libs/CLI11/include/CLI/StringTools.hpp create mode 100644 libs/CLI11/include/CLI/Timer.hpp create mode 100644 libs/CLI11/include/CLI/TypeTools.hpp create mode 100644 libs/CLI11/include/CLI/Validators.hpp create mode 100644 libs/CLI11/include/CLI/Version.hpp create mode 100644 libs/CLI11/include/CLI/impl/App_inl.hpp create mode 100644 libs/CLI11/include/CLI/impl/Config_inl.hpp create mode 100644 libs/CLI11/include/CLI/impl/Formatter_inl.hpp create mode 100644 libs/CLI11/include/CLI/impl/Option_inl.hpp create mode 100644 libs/CLI11/include/CLI/impl/Split_inl.hpp create mode 100644 libs/CLI11/include/CLI/impl/StringTools_inl.hpp create mode 100644 libs/CLI11/include/CLI/impl/Validators_inl.hpp create mode 100644 libs/CLI11/meson.build create mode 100644 libs/CLI11/meson_options.txt create mode 100644 libs/CLI11/scripts/ExtractVersion.py create mode 100644 libs/CLI11/scripts/MakeSingleHeader.py create mode 100644 libs/CLI11/scripts/check_style.sh create mode 100644 libs/CLI11/scripts/check_style_docker.sh create mode 100644 libs/CLI11/scripts/clang-format-pre-commit create mode 100644 libs/CLI11/scripts/mdlint_style.rb create mode 100644 libs/CLI11/src/CMakeLists.txt create mode 100644 libs/CLI11/src/Precompile.cpp create mode 100644 libs/CLI11/subprojects/catch2.wrap create mode 100644 libs/CLI11/test_package/CMakeLists.txt create mode 100644 libs/CLI11/test_package/conanfile.py create mode 100644 libs/CLI11/test_package/example.cpp create mode 100644 libs/CLI11/tests/.syntastic_cpp_config create mode 100644 libs/CLI11/tests/AppTest.cpp create mode 100644 libs/CLI11/tests/BoostOptionTypeTest.cpp create mode 100644 libs/CLI11/tests/CMakeLists.txt create mode 100644 libs/CLI11/tests/ComplexTypeTest.cpp create mode 100644 libs/CLI11/tests/ConfigFileTest.cpp create mode 100644 libs/CLI11/tests/CreationTest.cpp create mode 100644 libs/CLI11/tests/DeprecatedTest.cpp create mode 100644 libs/CLI11/tests/FormatterTest.cpp create mode 100644 libs/CLI11/tests/HelpTest.cpp create mode 100644 libs/CLI11/tests/HelpersTest.cpp create mode 100644 libs/CLI11/tests/NewParseTest.cpp create mode 100644 libs/CLI11/tests/OptionGroupTest.cpp create mode 100644 libs/CLI11/tests/OptionTypeTest.cpp create mode 100644 libs/CLI11/tests/OptionalTest.cpp create mode 100644 libs/CLI11/tests/SetTest.cpp create mode 100644 libs/CLI11/tests/SimpleTest.cpp create mode 100644 libs/CLI11/tests/StringParseTest.cpp create mode 100644 libs/CLI11/tests/SubcommandTest.cpp create mode 100644 libs/CLI11/tests/TimerTest.cpp create mode 100644 libs/CLI11/tests/TransformTest.cpp create mode 100644 libs/CLI11/tests/TrueFalseTest.cpp create mode 100644 libs/CLI11/tests/WindowsTest.cpp create mode 100644 libs/CLI11/tests/app_helper.hpp create mode 100644 libs/CLI11/tests/catch.hpp create mode 100644 libs/CLI11/tests/informational.cpp create mode 100644 libs/CLI11/tests/link_test_1.cpp create mode 100644 libs/CLI11/tests/link_test_2.cpp create mode 100644 libs/CLI11/tests/main.cpp create mode 100644 libs/CLI11/tests/meson.build create mode 100644 libs/CLI11/tests/mesonTest/README.md create mode 100644 libs/CLI11/tests/mesonTest/main.cpp create mode 100644 libs/CLI11/tests/mesonTest/meson.build create mode 100644 libs/Catch2/.clang-format create mode 100644 libs/Catch2/.conan/build.py create mode 100644 libs/Catch2/.conan/test_package/CMakeLists.txt create mode 100644 libs/Catch2/.conan/test_package/conanfile.py create mode 100644 libs/Catch2/.conan/test_package/test_package.cpp create mode 100644 libs/Catch2/.gitattributes create mode 100644 libs/Catch2/.github/FUNDING.yml create mode 100644 libs/Catch2/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 libs/Catch2/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 libs/Catch2/.github/pull_request_template.md create mode 100644 libs/Catch2/.gitignore create mode 100644 libs/Catch2/.travis.yml create mode 100644 libs/Catch2/BUILD.bazel create mode 100644 libs/Catch2/CMake/Catch2Config.cmake.in create mode 100644 libs/Catch2/CMake/FindGcov.cmake create mode 100644 libs/Catch2/CMake/FindLcov.cmake create mode 100644 libs/Catch2/CMake/Findcodecov.cmake create mode 100644 libs/Catch2/CMake/MiscFunctions.cmake create mode 100644 libs/Catch2/CMake/catch2.pc.in create mode 100644 libs/Catch2/CMake/llvm-cov-wrapper create mode 100644 libs/Catch2/CMakeLists.txt create mode 100644 libs/Catch2/CODE_OF_CONDUCT.md create mode 100644 libs/Catch2/LICENSE.txt create mode 100644 libs/Catch2/README.md create mode 100644 libs/Catch2/WORKSPACE create mode 100644 libs/Catch2/appveyor.yml create mode 100644 libs/Catch2/artwork/catch2-c-logo.png create mode 100644 libs/Catch2/artwork/catch2-hand-logo.png create mode 100644 libs/Catch2/artwork/catch2-logo-small.png create mode 100644 libs/Catch2/codecov.yml create mode 100644 libs/Catch2/conanfile.py create mode 100644 libs/Catch2/contrib/Catch.cmake create mode 100644 libs/Catch2/contrib/CatchAddTests.cmake create mode 100644 libs/Catch2/contrib/ParseAndAddCatchTests.cmake create mode 100644 libs/Catch2/contrib/gdbinit create mode 100644 libs/Catch2/contrib/lldbinit create mode 100644 libs/Catch2/docs/Readme.md create mode 100644 libs/Catch2/docs/assertions.md create mode 100644 libs/Catch2/docs/benchmarks.md create mode 100644 libs/Catch2/docs/ci-and-misc.md create mode 100644 libs/Catch2/docs/cmake-integration.md create mode 100644 libs/Catch2/docs/command-line.md create mode 100644 libs/Catch2/docs/commercial-users.md create mode 100644 libs/Catch2/docs/configuration.md create mode 100644 libs/Catch2/docs/contributing.md create mode 100644 libs/Catch2/docs/deprecations.md create mode 100644 libs/Catch2/docs/event-listeners.md create mode 100644 libs/Catch2/docs/generators.md create mode 100644 libs/Catch2/docs/limitations.md create mode 100644 libs/Catch2/docs/list-of-examples.md create mode 100644 libs/Catch2/docs/logging.md create mode 100644 libs/Catch2/docs/matchers.md create mode 100644 libs/Catch2/docs/opensource-users.md create mode 100644 libs/Catch2/docs/other-macros.md create mode 100644 libs/Catch2/docs/own-main.md create mode 100644 libs/Catch2/docs/release-notes.md create mode 100644 libs/Catch2/docs/release-process.md create mode 100644 libs/Catch2/docs/reporters.md create mode 100644 libs/Catch2/docs/slow-compiles.md create mode 100644 libs/Catch2/docs/test-cases-and-sections.md create mode 100644 libs/Catch2/docs/test-fixtures.md create mode 100644 libs/Catch2/docs/tostring.md create mode 100644 libs/Catch2/docs/tutorial.md create mode 100644 libs/Catch2/docs/why-catch.md create mode 100644 libs/Catch2/examples/000-CatchMain.cpp create mode 100644 libs/Catch2/examples/010-TestCase.cpp create mode 100644 libs/Catch2/examples/020-TestCase-1.cpp create mode 100644 libs/Catch2/examples/020-TestCase-2.cpp create mode 100644 libs/Catch2/examples/030-Asn-Require-Check.cpp create mode 100644 libs/Catch2/examples/100-Fix-Section.cpp create mode 100644 libs/Catch2/examples/110-Fix-ClassFixture.cpp create mode 100644 libs/Catch2/examples/120-Bdd-ScenarioGivenWhenThen.cpp create mode 100644 libs/Catch2/examples/200-Rpt-CatchMain.cpp create mode 100644 libs/Catch2/examples/207-Rpt-TeamCityReporter.cpp create mode 100644 libs/Catch2/examples/210-Evt-EventListeners.cpp create mode 100644 libs/Catch2/examples/231-Cfg-OutputStreams.cpp create mode 100644 libs/Catch2/examples/300-Gen-OwnGenerator.cpp create mode 100644 libs/Catch2/examples/301-Gen-MapTypeConversion.cpp create mode 100644 libs/Catch2/examples/302-Gen-Table.cpp create mode 100644 libs/Catch2/examples/310-Gen-VariablesInGenerators.cpp create mode 100644 libs/Catch2/examples/311-Gen-CustomCapture.cpp create mode 100644 libs/Catch2/examples/CMakeLists.txt create mode 100644 libs/Catch2/include/catch.hpp create mode 100644 libs/Catch2/include/catch_with_main.hpp create mode 100644 libs/Catch2/include/external/clara.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_benchmark.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_benchmarking_all.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_chronometer.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_clock.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_constructor.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_environment.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_estimate.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_execution_plan.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_optimizer.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_outlier_classification.hpp create mode 100644 libs/Catch2/include/internal/benchmark/catch_sample_analysis.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_analyse.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_benchmark_function.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_complete_invoke.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_estimate_clock.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_measure.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_repeat.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_run_for_at_least.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_stats.cpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_stats.hpp create mode 100644 libs/Catch2/include/internal/benchmark/detail/catch_timing.hpp create mode 100644 libs/Catch2/include/internal/catch_approx.cpp create mode 100644 libs/Catch2/include/internal/catch_approx.h create mode 100644 libs/Catch2/include/internal/catch_assertionhandler.cpp create mode 100644 libs/Catch2/include/internal/catch_assertionhandler.h create mode 100644 libs/Catch2/include/internal/catch_assertioninfo.h create mode 100644 libs/Catch2/include/internal/catch_assertionresult.cpp create mode 100644 libs/Catch2/include/internal/catch_assertionresult.h create mode 100644 libs/Catch2/include/internal/catch_capture.hpp create mode 100644 libs/Catch2/include/internal/catch_capture_matchers.cpp create mode 100644 libs/Catch2/include/internal/catch_capture_matchers.h create mode 100644 libs/Catch2/include/internal/catch_clara.h create mode 100644 libs/Catch2/include/internal/catch_commandline.cpp create mode 100644 libs/Catch2/include/internal/catch_commandline.h create mode 100644 libs/Catch2/include/internal/catch_common.cpp create mode 100644 libs/Catch2/include/internal/catch_common.h create mode 100644 libs/Catch2/include/internal/catch_compiler_capabilities.h create mode 100644 libs/Catch2/include/internal/catch_config.cpp create mode 100644 libs/Catch2/include/internal/catch_config.hpp create mode 100644 libs/Catch2/include/internal/catch_config_uncaught_exceptions.hpp create mode 100644 libs/Catch2/include/internal/catch_console_colour.cpp create mode 100644 libs/Catch2/include/internal/catch_console_colour.h create mode 100644 libs/Catch2/include/internal/catch_context.cpp create mode 100644 libs/Catch2/include/internal/catch_context.h create mode 100644 libs/Catch2/include/internal/catch_debug_console.cpp create mode 100644 libs/Catch2/include/internal/catch_debug_console.h create mode 100644 libs/Catch2/include/internal/catch_debugger.cpp create mode 100644 libs/Catch2/include/internal/catch_debugger.h create mode 100644 libs/Catch2/include/internal/catch_decomposer.cpp create mode 100644 libs/Catch2/include/internal/catch_decomposer.h create mode 100644 libs/Catch2/include/internal/catch_default_main.hpp create mode 100644 libs/Catch2/include/internal/catch_enforce.cpp create mode 100644 libs/Catch2/include/internal/catch_enforce.h create mode 100644 libs/Catch2/include/internal/catch_enum_values_registry.cpp create mode 100644 libs/Catch2/include/internal/catch_enum_values_registry.h create mode 100644 libs/Catch2/include/internal/catch_errno_guard.cpp create mode 100644 libs/Catch2/include/internal/catch_errno_guard.h create mode 100644 libs/Catch2/include/internal/catch_exception_translator_registry.cpp create mode 100644 libs/Catch2/include/internal/catch_exception_translator_registry.h create mode 100644 libs/Catch2/include/internal/catch_external_interfaces.h create mode 100644 libs/Catch2/include/internal/catch_fatal_condition.cpp create mode 100644 libs/Catch2/include/internal/catch_fatal_condition.h create mode 100644 libs/Catch2/include/internal/catch_generators.cpp create mode 100644 libs/Catch2/include/internal/catch_generators.hpp create mode 100644 libs/Catch2/include/internal/catch_generators_generic.hpp create mode 100644 libs/Catch2/include/internal/catch_generators_specific.hpp create mode 100644 libs/Catch2/include/internal/catch_impl.hpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_capture.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_capture.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_config.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_config.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_enum_values_registry.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_exception.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_exception.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_generatortracker.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_registry_hub.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_registry_hub.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_reporter.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_reporter.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_runner.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_runner.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_tag_alias_registry.h create mode 100644 libs/Catch2/include/internal/catch_interfaces_testcase.cpp create mode 100644 libs/Catch2/include/internal/catch_interfaces_testcase.h create mode 100644 libs/Catch2/include/internal/catch_leak_detector.cpp create mode 100644 libs/Catch2/include/internal/catch_leak_detector.h create mode 100644 libs/Catch2/include/internal/catch_list.cpp create mode 100644 libs/Catch2/include/internal/catch_list.h create mode 100644 libs/Catch2/include/internal/catch_matchers.cpp create mode 100644 libs/Catch2/include/internal/catch_matchers.h create mode 100644 libs/Catch2/include/internal/catch_matchers_exception.cpp create mode 100644 libs/Catch2/include/internal/catch_matchers_exception.hpp create mode 100644 libs/Catch2/include/internal/catch_matchers_floating.cpp create mode 100644 libs/Catch2/include/internal/catch_matchers_floating.h create mode 100644 libs/Catch2/include/internal/catch_matchers_generic.cpp create mode 100644 libs/Catch2/include/internal/catch_matchers_generic.hpp create mode 100644 libs/Catch2/include/internal/catch_matchers_string.cpp create mode 100644 libs/Catch2/include/internal/catch_matchers_string.h create mode 100644 libs/Catch2/include/internal/catch_matchers_vector.h create mode 100644 libs/Catch2/include/internal/catch_message.cpp create mode 100644 libs/Catch2/include/internal/catch_message.h create mode 100644 libs/Catch2/include/internal/catch_meta.hpp create mode 100644 libs/Catch2/include/internal/catch_objc.hpp create mode 100644 libs/Catch2/include/internal/catch_objc_arc.hpp create mode 100644 libs/Catch2/include/internal/catch_option.hpp create mode 100644 libs/Catch2/include/internal/catch_output_redirect.cpp create mode 100644 libs/Catch2/include/internal/catch_output_redirect.h create mode 100644 libs/Catch2/include/internal/catch_platform.h create mode 100644 libs/Catch2/include/internal/catch_polyfills.cpp create mode 100644 libs/Catch2/include/internal/catch_polyfills.hpp create mode 100644 libs/Catch2/include/internal/catch_preprocessor.hpp create mode 100644 libs/Catch2/include/internal/catch_random_number_generator.cpp create mode 100644 libs/Catch2/include/internal/catch_random_number_generator.h create mode 100644 libs/Catch2/include/internal/catch_reenable_warnings.h create mode 100644 libs/Catch2/include/internal/catch_registry_hub.cpp create mode 100644 libs/Catch2/include/internal/catch_reporter_registrars.hpp create mode 100644 libs/Catch2/include/internal/catch_reporter_registry.cpp create mode 100644 libs/Catch2/include/internal/catch_reporter_registry.h create mode 100644 libs/Catch2/include/internal/catch_result_type.cpp create mode 100644 libs/Catch2/include/internal/catch_result_type.h create mode 100644 libs/Catch2/include/internal/catch_run_context.cpp create mode 100644 libs/Catch2/include/internal/catch_run_context.h create mode 100644 libs/Catch2/include/internal/catch_section.cpp create mode 100644 libs/Catch2/include/internal/catch_section.h create mode 100644 libs/Catch2/include/internal/catch_section_info.cpp create mode 100644 libs/Catch2/include/internal/catch_section_info.h create mode 100644 libs/Catch2/include/internal/catch_session.cpp create mode 100644 libs/Catch2/include/internal/catch_session.h create mode 100644 libs/Catch2/include/internal/catch_singletons.cpp create mode 100644 libs/Catch2/include/internal/catch_singletons.hpp create mode 100644 libs/Catch2/include/internal/catch_startup_exception_registry.cpp create mode 100644 libs/Catch2/include/internal/catch_startup_exception_registry.h create mode 100644 libs/Catch2/include/internal/catch_stream.cpp create mode 100644 libs/Catch2/include/internal/catch_stream.h create mode 100644 libs/Catch2/include/internal/catch_string_manip.cpp create mode 100644 libs/Catch2/include/internal/catch_string_manip.h create mode 100644 libs/Catch2/include/internal/catch_stringref.cpp create mode 100644 libs/Catch2/include/internal/catch_stringref.h create mode 100644 libs/Catch2/include/internal/catch_suppress_warnings.h create mode 100644 libs/Catch2/include/internal/catch_tag_alias.cpp create mode 100644 libs/Catch2/include/internal/catch_tag_alias.h create mode 100644 libs/Catch2/include/internal/catch_tag_alias_autoregistrar.cpp create mode 100644 libs/Catch2/include/internal/catch_tag_alias_autoregistrar.h create mode 100644 libs/Catch2/include/internal/catch_tag_alias_registry.cpp create mode 100644 libs/Catch2/include/internal/catch_tag_alias_registry.h create mode 100644 libs/Catch2/include/internal/catch_test_case_info.cpp create mode 100644 libs/Catch2/include/internal/catch_test_case_info.h create mode 100644 libs/Catch2/include/internal/catch_test_case_registry_impl.cpp create mode 100644 libs/Catch2/include/internal/catch_test_case_registry_impl.h create mode 100644 libs/Catch2/include/internal/catch_test_case_tracker.cpp create mode 100644 libs/Catch2/include/internal/catch_test_case_tracker.h create mode 100644 libs/Catch2/include/internal/catch_test_registry.cpp create mode 100644 libs/Catch2/include/internal/catch_test_registry.h create mode 100644 libs/Catch2/include/internal/catch_test_spec.cpp create mode 100644 libs/Catch2/include/internal/catch_test_spec.h create mode 100644 libs/Catch2/include/internal/catch_test_spec_parser.cpp create mode 100644 libs/Catch2/include/internal/catch_test_spec_parser.h create mode 100644 libs/Catch2/include/internal/catch_text.h create mode 100644 libs/Catch2/include/internal/catch_timer.cpp create mode 100644 libs/Catch2/include/internal/catch_timer.h create mode 100644 libs/Catch2/include/internal/catch_to_string.hpp create mode 100644 libs/Catch2/include/internal/catch_tostring.cpp create mode 100644 libs/Catch2/include/internal/catch_tostring.h create mode 100644 libs/Catch2/include/internal/catch_totals.cpp create mode 100644 libs/Catch2/include/internal/catch_totals.h create mode 100644 libs/Catch2/include/internal/catch_uncaught_exceptions.cpp create mode 100644 libs/Catch2/include/internal/catch_uncaught_exceptions.h create mode 100644 libs/Catch2/include/internal/catch_user_interfaces.h create mode 100644 libs/Catch2/include/internal/catch_version.cpp create mode 100644 libs/Catch2/include/internal/catch_version.h create mode 100644 libs/Catch2/include/internal/catch_wildcard_pattern.cpp create mode 100644 libs/Catch2/include/internal/catch_wildcard_pattern.h create mode 100644 libs/Catch2/include/internal/catch_windows_h_proxy.h create mode 100644 libs/Catch2/include/internal/catch_xmlwriter.cpp create mode 100644 libs/Catch2/include/internal/catch_xmlwriter.h create mode 100644 libs/Catch2/include/reporters/catch_reporter_automake.hpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_bases.cpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_bases.hpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_compact.cpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_compact.h create mode 100644 libs/Catch2/include/reporters/catch_reporter_console.cpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_console.h create mode 100644 libs/Catch2/include/reporters/catch_reporter_junit.cpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_junit.h create mode 100644 libs/Catch2/include/reporters/catch_reporter_listening.cpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_listening.h create mode 100644 libs/Catch2/include/reporters/catch_reporter_sonarqube.hpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_tap.hpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_teamcity.hpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_xml.cpp create mode 100644 libs/Catch2/include/reporters/catch_reporter_xml.h create mode 100644 libs/Catch2/misc/CMakeLists.txt create mode 100644 libs/Catch2/misc/appveyorBuildConfigurationScript.bat create mode 100644 libs/Catch2/misc/appveyorMergeCoverageScript.py create mode 100644 libs/Catch2/misc/appveyorTestRunScript.bat create mode 100644 libs/Catch2/misc/coverage-helper.cpp create mode 100644 libs/Catch2/misc/installOpenCppCoverage.ps1 create mode 100644 libs/Catch2/projects/CMakeLists.txt create mode 100644 libs/Catch2/projects/ExtraTests/CMakeLists.txt create mode 100644 libs/Catch2/projects/ExtraTests/ToDo.txt create mode 100644 libs/Catch2/projects/ExtraTests/X01-PrefixedMacros.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X02-DisabledMacros.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X03-DisabledExceptions-DefaultHandler.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X10-FallbackStringifier.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X11-DisableStringification.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X12-CustomDebugBreakMacro.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X20-BenchmarkingMacros.cpp create mode 100644 libs/Catch2/projects/ExtraTests/X90-WindowsHeaderInclusion.cpp create mode 100644 libs/Catch2/projects/SelfTest/Baselines/automake.std.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/compact.sw.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/console.std.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/console.sw.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/console.swa4.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/junit.sw.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/sonarqube.sw.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/Baselines/xml.sw.approved.txt create mode 100644 libs/Catch2/projects/SelfTest/CompileTimePerfTests/10.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/CompileTimePerfTests/100.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/CompileTimePerfTests/All.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/CmdLine.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/Details.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/RandomNumberGeneration.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/String.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/StringManip.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/Tag.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/ToString.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/IntrospectiveTests/Xml.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/Misc/invalid-test-names.input create mode 100644 libs/Catch2/projects/SelfTest/Misc/plain-old-tests.input create mode 100644 libs/Catch2/projects/SelfTest/Misc/special-characters-in-file.input create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_debugger.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_option.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_stream.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp create mode 100644 libs/Catch2/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp create mode 100644 libs/Catch2/projects/SelfTest/TestMain.cpp create mode 100644 libs/Catch2/projects/SelfTest/TimingTests/Sleep.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Approx.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/BDD.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Benchmark.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Class.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Compilation.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Condition.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Decomposition.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/EnumToString.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Exception.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Generators.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Matchers.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Message.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Misc.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringByte.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringChrono.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringOptional.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringPair.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringTuple.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringVector.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/Tricky.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/UsageTests/VariadicMacros.tests.cpp create mode 100644 libs/Catch2/projects/SelfTest/WarnAboutNoTests.cmake create mode 100644 libs/Catch2/projects/TestScripts/testRandomOrder.py create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/CatchOCTestCase.h create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/Main.mm create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/OCTest.1 create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/OCTest.mm create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/TestObj.h create mode 100644 libs/Catch2/projects/XCode/OCTest/OCTest/TestObj.m create mode 100644 libs/Catch2/projects/XCode/OCTest/catch_objc_impl.mm create mode 100644 libs/Catch2/scripts/approvalTests.py create mode 100644 libs/Catch2/scripts/approve.py create mode 100644 libs/Catch2/scripts/benchmarkCompile.py create mode 100644 libs/Catch2/scripts/benchmarkRunner.py create mode 100644 libs/Catch2/scripts/developBuild.py create mode 100644 libs/Catch2/scripts/embed.py create mode 100644 libs/Catch2/scripts/embedClara.py create mode 100644 libs/Catch2/scripts/extractFeaturesFromReleaseNotes.py create mode 100644 libs/Catch2/scripts/fixWhitespace.py create mode 100644 libs/Catch2/scripts/generateSingleHeader.py create mode 100644 libs/Catch2/scripts/majorRelease.py create mode 100644 libs/Catch2/scripts/minorRelease.py create mode 100644 libs/Catch2/scripts/patchRelease.py create mode 100644 libs/Catch2/scripts/releaseCommon.py create mode 100644 libs/Catch2/scripts/releaseNotes.py create mode 100644 libs/Catch2/scripts/scriptCommon.py create mode 100644 libs/Catch2/scripts/updateDocumentToC.py create mode 100644 libs/Catch2/scripts/updateWandbox.py create mode 100644 libs/Catch2/single_include/catch2/catch.hpp create mode 100644 libs/Catch2/single_include/catch2/catch_reporter_automake.hpp create mode 100644 libs/Catch2/single_include/catch2/catch_reporter_sonarqube.hpp create mode 100644 libs/Catch2/single_include/catch2/catch_reporter_tap.hpp create mode 100644 libs/Catch2/single_include/catch2/catch_reporter_teamcity.hpp create mode 100644 libs/Catch2/src/catch_with_main.cpp create mode 100644 libs/Catch2/third_party/clara.hpp create mode 100644 src/kubecontrol/kubecontrol.cpp create mode 100644 test/test_kubecontrol.cpp diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..a0b0e23 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,42 @@ +kind: pipeline +type: kubernetes +name: default-build + +steps: + - name: build + image: kmaster.ti.unibw-hamburg.de:30808/debianbullseye + commands: + - mkdir -p build && cd build + - CC=clang-11 CXX=clang++-11 cmake -DCMAKE_BUILD_TYPE=DEBUG .. + - make -j + - make test + + - name: CodeChecker + image: kmaster.ti.unibw-hamburg.de:30808/drone-ftewa-codechecker + pull: always + settings: + CODECHECKER_URL: "http://codechecker:8001" + CODECHECKER_PRODUCT: "Kubecontrol" + CODECHECKER_USER: + from_secret: CODECHECKER_USER_SECRET + CODECHECKER_PASS: + from_secret: CODECHECKER_PASS_SECRET + when: + event: + include: + - push + - pull_request + +--- +kind: secret +name: CODECHECKER_USER_SECRET +get: + path: codechecker-client + name: username + +--- +kind: secret +name: CODECHECKER_PASS_SECRET +get: + path: codechecker-client + name: password \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c3f2257 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +.clangd +compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d20b0ff --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required (VERSION 3.1 FATAL_ERROR) +project (Ship VERSION 0.1.0 LANGUAGES CXX C) +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) +include(defaultOptions) + +IF(NOT TARGET Catch2) + add_subdirectory(libs/Catch2 EXCLUDE_FROM_ALL) + include(libs/Catch2/contrib/Catch.cmake) +ENDIF() + + + +IF (NOT TARGET CLI11) + set(CLI11_TESTING OFF CACHE BOOL "disable testing") + add_subdirectory(libs/CLI11 EXCLUDE_FROM_ALL) +ENDIF() + + +# build with CC=clang-15 CXX=clang++-15 cmake -D CMAKE_BUILD_TYPE=DEBUG .. + + +add_library(kubecontrol STATIC + libs/kubecontrol/kubecontrol.hpp + src/kubecontrol/kubecontrol.cpp + + ) + + +target_link_libraries(kubecontrol +EntityLibrary + +loguru +) +target_include_directories(kubecontrol PUBLIC + $ + $ + src) + + + + +# +# Everything TEST related +# +option(TEST_KUBECONTROL_LIBRARY "Turn running of application template specific tests off" ON) + +IF (${TEST_ENTITIY_LIBRARY}) + + + +# add_executable(test_SensorClass tests/test_SensorClass.cpp) +# target_link_libraries(test_SensorClass Catch2::Catch2 EntityLibrary loguru) +# catch_discover_tests(test_SensorClass) + + + + +ENDIF() diff --git a/cmake/Jenkinsfile b/cmake/Jenkinsfile new file mode 100644 index 0000000..865fd8a --- /dev/null +++ b/cmake/Jenkinsfile @@ -0,0 +1,59 @@ +@Library('ftewa-jenkins-library@main') _ + +@NonCPS +def getPipelineJobNames() { + Hudson.instance.getAllItems(org.jenkinsci.plugins.workflow.job.WorkflowJob)*.fullName +} + +@NonCPS +def triggerJobs() { + def jobs = getPipelineJobNames(); + + for (job in jobs) + { + echo "Trigger ${job}" + if (job.contains("Integration")) + { + build job: job, + parameters: [ + string(name: 'REPO_NAME', value: "cmake"), + string(name: 'TAG', value: "main") + ], + wait: false + + } + } +} + +pipeline { + agent { + kubernetes { + //workspaceVolume: dynamicPVC(accessModes: 'ReadWriteOnce', requestsSize: '20G', storageClassName: 'csi-rbd-sc') + yaml libraryResource("files/pod-build.yml") + defaultContainer 'clang-build' + } + } // agent + options { + // Only keep the 1 most recent builds + buildDiscarder(logRotator(numToKeepStr: "1")) + } + + +stages { + + stage("Build") + { + + steps { + echo "build" + triggerJobs() + } + + + + + + } // stage("Build") + + } +} diff --git a/cmake/Jenkinsfile:Zone.Identifier b/cmake/Jenkinsfile:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/cmake/Modules/CheckParent.cmake b/cmake/Modules/CheckParent.cmake new file mode 100644 index 0000000..c33bfd5 --- /dev/null +++ b/cmake/Modules/CheckParent.cmake @@ -0,0 +1 @@ +get_directory_property(hasParent PARENT_DIRECTORY) diff --git a/cmake/Modules/CheckParent.cmake:Zone.Identifier b/cmake/Modules/CheckParent.cmake:Zone.Identifier new file mode 100644 index 0000000..e69de29 diff --git a/cmake/Modules/CppCheck.cmake b/cmake/Modules/CppCheck.cmake new file mode 100644 index 0000000..1161f52 --- /dev/null +++ b/cmake/Modules/CppCheck.cmake @@ -0,0 +1,28 @@ +option(CPPCHECK "Turns cppcheck processing on if executable is found." OFF) + +find_program(CPPCHECK_PATH NAMES cppcheck) + +# export compile commands to json file to be used by cppcheck +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) +set(CPPCHECK_COMPILE_COMMANDS "${CMAKE_BINARY_DIR}/compile_commands.json") + +# output directory for codecheck analysis +set(CPPCHECK_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/cppcheck_results) + +if(CPPCHECK AND CPPCHECK_PATH AND NOT CPPCHECK_ADDED) + + set(CPPCHECK_ADDED ON) + + if (NOT TARGET cppcheck) + + add_custom_target(cppcheck + COMMAND rm -rf ${CPPCHECK_OUTPUT_DIRECTORY}\; + mkdir -p ${CPPCHECK_OUTPUT_DIRECTORY}\; + ${CPPCHECK_PATH} + --project=${CPPCHECK_COMPILE_COMMANDS} + --plist-output=${CPPCHECK_OUTPUT_DIRECTORY} + --enable=all + --inline-suppr + ) + endif() +endif() diff --git a/cmake/Modules/FindGMP.cmake b/cmake/Modules/FindGMP.cmake new file mode 100644 index 0000000..96d4a55 --- /dev/null +++ b/cmake/Modules/FindGMP.cmake @@ -0,0 +1,76 @@ +# Try to find the GMP library +# https://gmplib.org/ +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(GMP 6.0.0) +# to require version 6.0.0 to newer of GMP. +# +# Once done this will define +# +# GMP_FOUND - system has GMP lib with correct version +# GMP_INCLUDES - the GMP include directory +# GMP_LIBRARIES - the GMP library +# GMP_VERSION - GMP version +# +# Copyright (c) 2016 Jack Poulson, +# Redistribution and use is allowed according to the terms of the BSD license. + +find_path(GMP_INCLUDES NAMES gmp.h PATHS $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR}) + +# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified +if(NOT GMP_FIND_VERSION) + if(NOT GMP_FIND_VERSION_MAJOR) + set(GMP_FIND_VERSION_MAJOR 5) + endif() + if(NOT GMP_FIND_VERSION_MINOR) + set(GMP_FIND_VERSION_MINOR 1) + endif() + if(NOT GMP_FIND_VERSION_PATCH) + set(GMP_FIND_VERSION_PATCH 0) + endif() + set(GMP_FIND_VERSION + "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") +endif() + +message("GMP_INCLUDES=${GMP_INCLUDES}") +if(GMP_INCLUDES) + # Since the GMP version macros may be in a file included by gmp.h of the form + # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. + file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h") + foreach(gmp_header_filename ${GMP_HEADERS}) + file(READ "${gmp_header_filename}" _gmp_version_header) + string(REGEX MATCH + "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match + "${_gmp_version_header}") + if(_gmp_major_version_match) + set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" + _gmp_minor_version_match "${_gmp_version_header}") + set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" + _gmp_patchlevel_version_match "${_gmp_version_header}") + set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") + set(GMP_VERSION + ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) + endif() + endforeach() + + # Check whether found version exists and exceeds the minimum requirement + if(NOT GMP_VERSION) + set(GMP_VERSION_OK FALSE) + message(STATUS "GMP version was not detected") + elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) + set(GMP_VERSION_OK FALSE) + message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, " + "but at least version ${GMP_FIND_VERSION} is required") + else() + set(GMP_VERSION_OK TRUE) + endif() +endif() + +find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${LIB_INSTALL_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GMP DEFAULT_MSG + GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) +mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) diff --git a/cmake/Modules/FindValgrind.cmake b/cmake/Modules/FindValgrind.cmake new file mode 100644 index 0000000..bb1205d --- /dev/null +++ b/cmake/Modules/FindValgrind.cmake @@ -0,0 +1,25 @@ +# Find Valgrind. +# +# This module defines: +# VALGRIND_INCLUDE_DIR, where to find valgrind/memcheck.h, etc. +# VALGRIND_PROGRAM, the valgrind executable. +# VALGRIND_FOUND, If false, do not try to use valgrind. +# +# If you have valgrind installed in a non-standard place, you can define +# VALGRIND_PREFIX to tell cmake where it is. +# +# NOTE: Copied from the opencog project, where it is distributed under the +# terms of the New BSD License. + +message(STATUS "Valgrind Prefix: ${VALGRIND_PREFIX}") + +find_path(VALGRIND_INCLUDE_DIR valgrind/memcheck.h + /usr/include /usr/local/include ${VALGRIND_PREFIX}/include) +find_program(VALGRIND_PROGRAM NAMES valgrind PATH + /usr/bin /usr/local/bin ${VALGRIND_PREFIX}/bin) + +find_package_handle_standard_args(VALGRIND DEFAULT_MSG + VALGRIND_INCLUDE_DIR + VALGRIND_PROGRAM) + +mark_as_advanced(VALGRIND_INCLUDE_DIR VALGRIND_PROGRAM) diff --git a/cmake/Modules/Findsodium.cmake b/cmake/Modules/Findsodium.cmake new file mode 100644 index 0000000..9d306d1 --- /dev/null +++ b/cmake/Modules/Findsodium.cmake @@ -0,0 +1,269 @@ +# Written in 2016 by Henrik Steffen Gaßmann +# +# To the extent possible under law, the author(s) have dedicated all +# copyright and related and neighboring rights to this software to the +# public domain worldwide. This software is distributed without any warranty. +# +# You should have received a copy of the CC0 Public Domain Dedication +# along with this software. If not, see +# +# http://creativecommons.org/publicdomain/zero/1.0/ +# +######################################################################## +# Tries to find the local libsodium installation. +# +# On Windows the sodium_DIR environment variable is used as a default +# hint which can be overridden by setting the corresponding cmake variable. +# +# Once done the following variables will be defined: +# +# sodium_FOUND +# sodium_INCLUDE_DIR +# sodium_LIBRARY_DEBUG +# sodium_LIBRARY_RELEASE +# +# +# Furthermore an imported "sodium" target is created. +# + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" + OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set(_GCC_COMPATIBLE 1) +endif() + +# static library option +option(sodium_USE_STATIC_LIBS "enable to statically link against sodium") +if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST)) + unset(sodium_LIBRARY CACHE) + unset(sodium_LIBRARY_DEBUG CACHE) + unset(sodium_LIBRARY_RELEASE CACHE) + unset(sodium_DLL_DEBUG CACHE) + unset(sodium_DLL_RELEASE CACHE) + set(sodium_USE_STATIC_LIBS_LAST ${sodium_USE_STATIC_LIBS} CACHE INTERNAL "internal change tracking variable") +endif() + + +######################################################################## +# UNIX +if (UNIX) + # import pkg-config + find_package(PkgConfig QUIET) + if (PKG_CONFIG_FOUND) + pkg_check_modules(sodium_PKG QUIET libsodium) + endif() + + if(sodium_USE_STATIC_LIBS) + set(XPREFIX sodium_PKG_STATIC) + else() + set(XPREFIX sodium_PKG) + endif() + + find_path(sodium_INCLUDE_DIR sodium.h + HINTS ${${XPREFIX}_INCLUDE_DIRS} + ) + find_library(sodium_LIBRARY_DEBUG NAMES ${${XPREFIX}_LIBRARIES} sodium + HINTS ${${XPREFIX}_LIBRARY_DIRS} + ) + find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES} sodium + HINTS ${${XPREFIX}_LIBRARY_DIRS} + ) + + +######################################################################## +# Windows +elseif (WIN32) + set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory") + mark_as_advanced(sodium_DIR) + + find_path(sodium_INCLUDE_DIR sodium.h + HINTS ${sodium_DIR} + PATH_SUFFIXES include + ) + + if (MSVC) + # detect target architecture + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.c" [=[ + #if defined _M_IX86 + #error ARCH_VALUE x86_32 + #elif defined _M_X64 + #error ARCH_VALUE x86_64 + #endif + #error ARCH_VALUE unknown + ]=]) + try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/arch.c" + OUTPUT_VARIABLE _COMPILATION_LOG + ) + string(REGEX REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*" "\\1" _TARGET_ARCH "${_COMPILATION_LOG}") + + # construct library path + if (_TARGET_ARCH STREQUAL "x86_32") + string(APPEND _PLATFORM_PATH "Win32") + elseif(_TARGET_ARCH STREQUAL "x86_64") + string(APPEND _PLATFORM_PATH "x64") + else() + message(FATAL_ERROR "the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake.") + endif() + string(APPEND _PLATFORM_PATH "/$$CONFIG$$") + + if (MSVC_VERSION LESS 1900) + math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60") + else() + math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50") + endif() + string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}") + + if (sodium_USE_STATIC_LIBS) + string(APPEND _PLATFORM_PATH "/static") + else() + string(APPEND _PLATFORM_PATH "/dynamic") + endif() + + string(REPLACE "$$CONFIG$$" "Debug" _DEBUG_PATH_SUFFIX "${_PLATFORM_PATH}") + string(REPLACE "$$CONFIG$$" "Release" _RELEASE_PATH_SUFFIX "${_PLATFORM_PATH}") + + find_library(sodium_LIBRARY_DEBUG libsodium.lib + HINTS ${sodium_DIR} + PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} + ) + find_library(sodium_LIBRARY_RELEASE libsodium.lib + HINTS ${sodium_DIR} + PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} + ) + if (NOT sodium_USE_STATIC_LIBS) + set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") + find_library(sodium_DLL_DEBUG libsodium + HINTS ${sodium_DIR} + PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} + ) + find_library(sodium_DLL_RELEASE libsodium + HINTS ${sodium_DIR} + PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} + ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK}) + endif() + + elseif(_GCC_COMPATIBLE) + if (sodium_USE_STATIC_LIBS) + find_library(sodium_LIBRARY_DEBUG libsodium.a + HINTS ${sodium_DIR} + PATH_SUFFIXES lib + ) + find_library(sodium_LIBRARY_RELEASE libsodium.a + HINTS ${sodium_DIR} + PATH_SUFFIXES lib + ) + else() + find_library(sodium_LIBRARY_DEBUG libsodium.dll.a + HINTS ${sodium_DIR} + PATH_SUFFIXES lib + ) + find_library(sodium_LIBRARY_RELEASE libsodium.dll.a + HINTS ${sodium_DIR} + PATH_SUFFIXES lib + ) + + file(GLOB _DLL + LIST_DIRECTORIES false + RELATIVE "${sodium_DIR}/bin" + "${sodium_DIR}/bin/libsodium*.dll" + ) + find_library(sodium_DLL_DEBUG ${_DLL} libsodium + HINTS ${sodium_DIR} + PATH_SUFFIXES bin + ) + find_library(sodium_DLL_RELEASE ${_DLL} libsodium + HINTS ${sodium_DIR} + PATH_SUFFIXES bin + ) + endif() + else() + message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") + endif() + + +######################################################################## +# unsupported +else() + message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") +endif() + + +######################################################################## +# common stuff + +# extract sodium version +if (sodium_INCLUDE_DIR) + set(_VERSION_HEADER "${_INCLUDE_DIR}/sodium/version.h") + if (EXISTS _VERSION_HEADER) + file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT) + string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_VERSION_STRING[ \t]*\"([^\n]*)\".*" "\\1" + sodium_VERSION "${_VERSION_HEADER_CONTENT}") + set(sodium_VERSION "${sodium_VERSION}" PARENT_SCOPE) + endif() +endif() + +# communicate results +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(sodium + REQUIRED_VARS + sodium_LIBRARY_RELEASE + sodium_LIBRARY_DEBUG + sodium_INCLUDE_DIR + VERSION_VAR + sodium_VERSION +) + +# mark file paths as advanced +mark_as_advanced(sodium_INCLUDE_DIR) +mark_as_advanced(sodium_LIBRARY_DEBUG) +mark_as_advanced(sodium_LIBRARY_RELEASE) +if (WIN32) + mark_as_advanced(sodium_DLL_DEBUG) + mark_as_advanced(sodium_DLL_RELEASE) +endif() + +# create imported target +if(sodium_USE_STATIC_LIBS) + set(_LIB_TYPE STATIC) +else() + set(_LIB_TYPE SHARED) +endif() +add_library(sodium ${_LIB_TYPE} IMPORTED) + +set_target_properties(sodium PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${sodium_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" +) + +if (sodium_USE_STATIC_LIBS) + set_target_properties(sodium PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "SODIUM_STATIC" + IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" + IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" + ) +else() + if (UNIX) + set_target_properties(sodium PROPERTIES + IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" + IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" + ) + elseif (WIN32) + set_target_properties(sodium PROPERTIES + IMPORTED_IMPLIB "${sodium_LIBRARY_RELEASE}" + IMPORTED_IMPLIB_DEBUG "${sodium_LIBRARY_DEBUG}" + ) + if (NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND")) + set_target_properties(sodium PROPERTIES + IMPORTED_LOCATION_DEBUG "${sodium_DLL_DEBUG}" + ) + endif() + if (NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND")) + set_target_properties(sodium PROPERTIES + IMPORTED_LOCATION_RELWITHDEBINFO "${sodium_DLL_RELEASE}" + IMPORTED_LOCATION_MINSIZEREL "${sodium_DLL_RELEASE}" + IMPORTED_LOCATION_RELEASE "${sodium_DLL_RELEASE}" + ) + endif() + endif() +endif() diff --git a/cmake/Modules/GenerateCccc.cmake b/cmake/Modules/GenerateCccc.cmake new file mode 100644 index 0000000..9c6f1e3 --- /dev/null +++ b/cmake/Modules/GenerateCccc.cmake @@ -0,0 +1,47 @@ +INCLUDE(CheckParent) +# search for CCCC binary +FIND_PROGRAM(CCCC cccc ) + +# +# check if the GENERATE_CCCC function has already been defined +# +get_property(_GENERATE_CCCC GLOBAL PROPERTY _GENERATE_CCCC) +IF (NOT _GENERATE_CCCC) + +# set that we have defined GENERATE_CCCC +set_property(GLOBAL PROPERTY _GENERATE_CCCC "YES") + + + FUNCTION(GENERATE_CCCC) + IF(CCCC) + CMAKE_PARSE_ARGUMENTS(ARG "" "" "TARGETS" ${ARGN}) + get_property(_ccccfiles GLOBAL PROPERTY _ccccfiles) + foreach(_target ${ARG_TARGETS}) + get_target_property(_sources ${_target} SOURCES) + get_target_property(_source_dir ${_target} SOURCE_DIR) + + foreach(_source ${_sources}) + set(_fullsource "${_source_dir}/${_source}") + list(APPEND _ccccfiles "${_fullsource}") + endforeach() + endforeach() + set_property(GLOBAL PROPERTY _ccccfiles ${_ccccfiles}) + ENDIF() + ENDFUNCTION() + + FUNCTION(RESET_CCCC) + set_property(GLOBAL PROPERTY _ccccfiles "") + ENDFUNCTION() + + FUNCTION(GENERATE_CCCC_TARGET) + IF (NOT hasParent AND CCCC) + get_property(_targetccccfiles GLOBAL PROPERTY _ccccfiles) + + ADD_CUSTOM_TARGET(cccc + COMMAND ${CCCC} --outdir=cccc ${_targetccccfiles} + COMMENT "Generating cccc result") + ENDIF() + ENDFUNCTION() + + +ENDIF() diff --git a/cmake/Modules/GenerateCppCheck.cmake b/cmake/Modules/GenerateCppCheck.cmake new file mode 100644 index 0000000..a33ec73 --- /dev/null +++ b/cmake/Modules/GenerateCppCheck.cmake @@ -0,0 +1,74 @@ +INCLUDE(CheckParent) +find_program(CPPCHECK NAMES cppcheck) + +# +# check if the GENERATE_CPPCHECK function has already been defined +# +get_property(_GENERATE_CPPCHECK GLOBAL PROPERTY _GENERATE_CPPCHECK) +IF (NOT _GENERATE_CPPCHECK) + + # set that we have defined GENERATE_CCCC + set_property(GLOBAL PROPERTY _GENERATE_CPPCHECK "YES") + + FUNCTION(GENERATE_CPPCHECK) + IF(NOT TARGET cppcheck) + IF(CPPCHECK) + CMAKE_PARSE_ARGUMENTS(ARG "" "" "TARGETS" ${ARGN}) + get_property(_cppcheckfiles GLOBAL PROPERTY _cppcheckfiles) + get_property(_cppcheckincludedirs GLOBAL PROPERTY _cppcheckincludedirs) + + foreach(_target ${ARG_TARGETS}) + get_target_property(_sources ${_target} SOURCES) + get_target_property(_source_dir ${_target} SOURCE_DIR) + get_target_property(_include_dir ${_target} INCLUDE_DIRECTORIES) + string(REPLACE "$<" ";" _include_dirs ${_include_dir}) + + foreach(_dir ${_include_dirs}) + list(APPEND _cppcheckincludedirs -I${_include_dir}) + endforeach() + + foreach(_source ${_sources}) + set(_fullsource "${_source_dir}/${_source}") + list(APPEND _cppcheckfiles ${_fullsource}) + endforeach() + endforeach() + set_property(GLOBAL PROPERTY _cppcheckfiles ${_cppcheckfiles}) + set_property(GLOBAL PROPERTY _cppcheckincludedirs ${_cppcheckincludedirs}) + ENDIF() + ENDIF() + ENDFUNCTION() + + FUNCTION(RESET_CPPCHECK) + set_property(GLOBAL PROPERTY _cppcheckfiles "") + set_property(GLOBAL PROPERTY _cppcheckincludedirs "") + ENDFUNCTION() + + + FUNCTION(GENERATE_CPPCHECK_TARGET) + IF ( NOT hasParent AND CPPCHECK) + message("generate cppcheck target") + get_property(_targetcppcheckfiles GLOBAL PROPERTY _cppcheckfiles) + get_property(_targetcppcheckincludedirs GLOBAL PROPERTY _cppcheckincludedirs) + + add_custom_target(cppcheck + COMMAND + ${CPPCHECK} + --xml + --xml-version=2 + --enable=all + --inconclusive + --force + --inline-suppr + ${_targetcppcheckincludedirs} + ${_targetcppcheckfiles} + 2> cppcheck.xml + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT + "cppcheck: Running cppcheck on target ${_targetname}..." + VERBATIM) + + ENDIF() + ENDFUNCTION() + +ENDIF() diff --git a/cmake/Modules/ProcessDOXYGEN.cmake b/cmake/Modules/ProcessDOXYGEN.cmake new file mode 100644 index 0000000..a49dcb9 --- /dev/null +++ b/cmake/Modules/ProcessDOXYGEN.cmake @@ -0,0 +1,23 @@ +INCLUDE(CheckParent) + +IF(NOT hasParent) + find_package(Doxygen) + + + IF (DOXYGEN_FOUND) + # set input and output files + set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in) + set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + + # request to configure the file + configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) + + # note the option ALL which allows to build the docs together with the application + add_custom_target( doxygen + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM ) + ENDIF() + +ENDIF() diff --git a/cmake/Modules/ProcessGIT.cmake b/cmake/Modules/ProcessGIT.cmake new file mode 100644 index 0000000..c2c6d13 --- /dev/null +++ b/cmake/Modules/ProcessGIT.cmake @@ -0,0 +1,17 @@ +if (GIT_FOUND) + execute_process( + COMMAND git rev-parse --abbrev-ref HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +# Get the latest abbreviated commit hash of the working branch +execute_process( + COMMAND git log -1 --format=%h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +endif() diff --git a/cmake/Modules/add_my_test.cmake b/cmake/Modules/add_my_test.cmake new file mode 100644 index 0000000..d5a90f0 --- /dev/null +++ b/cmake/Modules/add_my_test.cmake @@ -0,0 +1,22 @@ +get_property(_ADD_MY_TEST GLOBAL PROPERTY _ADD_MY_TEST) +IF (NOT _ADD_MY_TEST) + + # set that we have defined GENERATE_CCCC + set_property(GLOBAL PROPERTY _ADD_MY_TEST "YES") + + + FUNCTION(ADD_MY_TEST) + CMAKE_PARSE_ARGUMENTS(ARG "" "TEST" "SOURCES;LIBS" ${ARGN}) + get_property(_mytests GLOBAL PROPERTY _mytests) + + list(APPEND _mytests "${ARG_TEST}") + + add_executable(${ARG_TEST} ${ARG_SOURCES}) + target_link_libraries(${ARG_TEST} ${ARG_LIBS}) + add_test(${ARG_TEST} ${ARG_TEST}) + + set_property(GLOBAL PROPERTY _mytests ${_mytests}) + ENDFUNCTION() + + +ENDIF() diff --git a/cmake/Modules/c++-standards.cmake b/cmake/Modules/c++-standards.cmake new file mode 100644 index 0000000..87a894f --- /dev/null +++ b/cmake/Modules/c++-standards.cmake @@ -0,0 +1,66 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# Set the compiler standard to C++11 +macro(cxx_11) + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) + + if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("/std:c++11" _cpp_latest_flag_supported) + if(_cpp_latest_flag_supported) + add_compile_options("/std:c++11") + endif() + endif() +endmacro() + +# Set the compiler standard to C++14 +macro(cxx_14) + set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) + + if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("/std:c++14" _cpp_latest_flag_supported) + if(_cpp_latest_flag_supported) + add_compile_options("/std:c++14") + endif() + endif() +endmacro() + +# Set the compiler standard to C++17 +macro(cxx_17) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) + + if(MSVC_VERSION GREATER_EQUAL "1900" AND CMAKE_VERSION LESS 3.10) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("/std:c++17" _cpp_latest_flag_supported) + if(_cpp_latest_flag_supported) + add_compile_options("/std:c++17") + endif() + endif() +endmacro() + +# Set the compiler standard to C++20 +macro(cxx_20) + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) +endmacro() diff --git a/cmake/Modules/code-coverage.cmake b/cmake/Modules/code-coverage.cmake new file mode 100644 index 0000000..6f1a917 --- /dev/null +++ b/cmake/Modules/code-coverage.cmake @@ -0,0 +1,588 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# USAGE: To enable any code coverage instrumentation/targets, the single CMake +# option of `CODE_COVERAGE` needs to be set to 'ON', either by GUI, ccmake, or +# on the command line. +# +# From this point, there are two primary methods for adding instrumentation to +# targets: 1 - A blanket instrumentation by calling `add_code_coverage()`, where +# all targets in that directory and all subdirectories are automatically +# instrumented. 2 - Per-target instrumentation by calling +# `target_code_coverage()`, where the target is given and thus only +# that target is instrumented. This applies to both libraries and executables. +# +# To add coverage targets, such as calling `make ccov` to generate the actual +# coverage information for perusal or consumption, call +# `target_code_coverage()` on an *executable* target. +# +# Example 1: All targets instrumented +# +# In this case, the coverage information reported will will be that of the +# `theLib` library target and `theExe` executable. +# +# 1a: Via global command +# +# ~~~ +# add_code_coverage() # Adds instrumentation to all targets +# +# add_library(theLib lib.cpp) +# +# add_executable(theExe main.cpp) +# target_link_libraries(theExe PRIVATE theLib) +# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target (instrumentation already added via global anyways) for generating code coverage reports. +# ~~~ +# +# 1b: Via target commands +# +# ~~~ +# add_library(theLib lib.cpp) +# target_code_coverage(theLib) # As a library target, adds coverage instrumentation but no targets. +# +# add_executable(theExe main.cpp) +# target_link_libraries(theExe PRIVATE theLib) +# target_code_coverage(theExe) # As an executable target, adds the 'ccov-theExe' target and instrumentation for generating code coverage reports. +# ~~~ +# +# Example 2: Target instrumented, but with regex pattern of files to be excluded +# from report +# +# ~~~ +# add_executable(theExe main.cpp non_covered.cpp) +# target_code_coverage(theExe EXCLUDE non_covered.cpp test/*) # As an executable target, the reports will exclude the non-covered.cpp file, and any files in a test/ folder. +# ~~~ +# +# Example 3: Target added to the 'ccov' and 'ccov-all' targets +# +# ~~~ +# add_code_coverage_all_targets(EXCLUDE test/*) # Adds the 'ccov-all' target set and sets it to exclude all files in test/ folders. +# +# add_executable(theExe main.cpp non_covered.cpp) +# target_code_coverage(theExe AUTO ALL EXCLUDE non_covered.cpp test/*) # As an executable target, adds to the 'ccov' and ccov-all' targets, and the reports will exclude the non-covered.cpp file, and any files in a test/ folder. +# ~~~ + +# Options +option( + CODE_COVERAGE + "Builds targets with code coverage instrumentation. (Requires GCC or Clang)" + OFF) + +# Programs +find_program(LLVM_COV_PATH NAMES llvm-cov llvm-cov-8 llvm-cov-7 llvm-cov-6) +find_program(LLVM_PROFDATA_PATH NAMES llvm-profdata llvm-profdata-8 llvm-profdata-7 llvm-profdata-6) +find_program(LCOV_PATH lcov) +find_program(GENHTML_PATH genhtml) + +# Variables +set(CMAKE_COVERAGE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/ccov) + +# Common initialization/checks +if(CODE_COVERAGE AND NOT CODE_COVERAGE_ADDED) + set(CODE_COVERAGE_ADDED ON) + + # Common Targets + add_custom_target(ccov-preprocessing + COMMAND ${CMAKE_COMMAND} + -E + make_directory + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY} + DEPENDS ccov-clean) + + if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + # Messages + message(STATUS "Building with llvm Code Coverage Tools") + + if(NOT LLVM_COV_PATH) + message(FATAL_ERROR "llvm-cov not found! Aborting.") + else() + # Version number checking for 'EXCLUDE' compatability + execute_process(COMMAND ${LLVM_COV_PATH} --version + OUTPUT_VARIABLE LLVM_COV_VERSION_CALL_OUTPUT) + string(REGEX MATCH + "[0-9]+\\.[0-9]+\\.[0-9]+" + LLVM_COV_VERSION + ${LLVM_COV_VERSION_CALL_OUTPUT}) + + if(LLVM_COV_VERSION VERSION_LESS "7.0.0") + message( + WARNING + "target_code_coverage()/add_code_coverage_all_targets() 'EXCLUDE' option only available on llvm-cov >= 7.0.0" + ) + endif() + endif() + + # Targets + add_custom_target(ccov-clean + COMMAND rm -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND rm -f + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list) + + # Used to get the shared object file list before doing the main all-processing + add_custom_target(ccov-libs + COMMAND ; + COMMENT "libs ready for coverage report.") + + elseif(CMAKE_COMPILER_IS_GNUCXX) + # Messages + message(STATUS "Building with lcov Code Coverage Tools") + + if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} upper_build_type) + if(NOT ${upper_build_type} STREQUAL "DEBUG") + message( + WARNING + "Code coverage results with an optimized (non-Debug) build may be misleading" + ) + endif() + else() + message( + WARNING + "Code coverage results with an optimized (non-Debug) build may be misleading" + ) + endif() + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() + + # Targets + add_custom_target(ccov-clean + COMMAND ${LCOV_PATH} + --directory + ${CMAKE_BINARY_DIR} + --zerocounters) + + else() + message(FATAL_ERROR "Code coverage requires Clang or GCC. Aborting.") + endif() +endif() + +# Adds code coverage instrumentation to a library, or instrumentation/targets +# for an executable target. +# ~~~ +# EXECUTABLE ADDED TARGETS: +# GCOV/LCOV: +# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-${TARGET_NAME} : Generates HTML code coverage report for the associated named target. +# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. +# +# LLVM-COV: +# ccov : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-report : Generates HTML code coverage report for every target added with 'AUTO' parameter. +# ccov-${TARGET_NAME} : Generates HTML code coverage report. +# ccov-report-${TARGET_NAME} : Prints to command line summary per-file coverage information. +# ccov-show-${TARGET_NAME} : Prints to command line detailed per-line coverage information. +# ccov-all : Generates HTML code coverage report, merging every target added with 'ALL' parameter into a single detailed report. +# ccov-all-report : Prints summary per-file coverage information for every target added with ALL' parameter to the command line. +# +# Required: +# TARGET_NAME - Name of the target to generate code coverage for. +# Optional: +# AUTO - Adds the target to the 'ccov' target so that it can be run in a batch with others easily. Effective on executable targets. +# ALL - Adds the target to the 'ccov-all' and 'ccov-all-report' targets, which merge several executable targets coverage data to a single report. Effective on executable targets. +# EXTERNAL - For GCC's lcov, allows the profiling of 'external' files from the processing directory +# EXCLUDE - Excludes files of the patterns provided from coverage. **These do not copy to the 'all' targets.** +# OBJECTS - For executables ONLY, if the provided targets are shared libraries, adds coverage information to the output +# ~~~ +function(target_code_coverage TARGET_NAME) + # Argument parsing + set(options AUTO ALL EXTERNAL) + set(multi_value_keywords EXCLUDE OBJECTS) + cmake_parse_arguments(target_code_coverage + "${options}" + "" + "${multi_value_keywords}" + ${ARGN}) + + if(CODE_COVERAGE) + + # Add code coverage instrumentation to the target's linker command + if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + target_compile_options( + ${TARGET_NAME} + PRIVATE -fprofile-instr-generate -fcoverage-mapping) + set_property(TARGET ${TARGET_NAME} + APPEND_STRING + PROPERTY LINK_FLAGS "-fprofile-instr-generate ") + set_property(TARGET ${TARGET_NAME} + APPEND_STRING + PROPERTY LINK_FLAGS "-fcoverage-mapping ") + elseif(CMAKE_COMPILER_IS_GNUCXX) + target_compile_options(${TARGET_NAME} + PRIVATE -fprofile-arcs -ftest-coverage) + target_link_libraries(${TARGET_NAME} PRIVATE gcov) + endif() + + # Targets + get_target_property(target_type ${TARGET_NAME} TYPE) + + # Add shared library to processing for 'all' targets + if(target_type STREQUAL "SHARED_LIBRARY" AND target_code_coverage_ALL) + if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + add_custom_target( + ccov-run-${TARGET_NAME} + COMMAND echo + "-object=$" + >> + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + DEPENDS ccov-preprocessing ${TARGET_NAME}) + + if(NOT TARGET ccov-libs) + message( + FATAL_ERROR + "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." + ) + endif() + + add_dependencies(ccov-libs ccov-run-${TARGET_NAME}) + endif() + endif() + + # For executables add targets to run and produce output + if(target_type STREQUAL "EXECUTABLE") + if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + + # If there are shared objects to also work with, generate the string to add them here + foreach(SO_TARGET ${target_code_coverage_OBJECTS}) + # Check to see if the target is a shared object + if(TARGET ${SO_TARGET}) + get_target_property(SO_TARGET_TYPE ${SO_TARGET} TYPE) + if(${SO_TARGET_TYPE} STREQUAL "SHARED_LIBRARY") + set(SO_OBJECTS ${SO_OBJECTS} -object=$) + endif() + endif() + endforeach() + + # Run the executable, generating raw profile data + add_custom_target( + ccov-run-${TARGET_NAME} + COMMAND LLVM_PROFILE_FILE=${TARGET_NAME}.profraw + $ + COMMAND echo + "-object=$" + >> + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list + COMMAND echo + "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.profraw " + >> + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list + DEPENDS ccov-preprocessing ccov-libs ${TARGET_NAME}) + + # Merge the generated profile data so llvm-cov can process it + add_custom_target(ccov-processing-${TARGET_NAME} + COMMAND ${LLVM_PROFDATA_PATH} + merge + -sparse + ${TARGET_NAME}.profraw + -o + ${TARGET_NAME}.profdata + DEPENDS ccov-run-${TARGET_NAME}) + + # Ignore regex only works on LLVM >= 7 + if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") + foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} + -ignore-filename-regex='${EXCLUDE_ITEM}') + endforeach() + endif() + + # Print out details of the coverage information to the command line + add_custom_target(ccov-show-${TARGET_NAME} + COMMAND ${LLVM_COV_PATH} + show + $ + ${SO_OBJECTS} + -instr-profile=${TARGET_NAME}.profdata + -show-line-counts-or-regions + ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${TARGET_NAME}) + + # Print out a summary of the coverage information to the command line + add_custom_target(ccov-report-${TARGET_NAME} + COMMAND ${LLVM_COV_PATH} + report + $ + ${SO_OBJECTS} + -instr-profile=${TARGET_NAME}.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${TARGET_NAME}) + + # Generates HTML output of the coverage information for perusal + add_custom_target( + ccov-${TARGET_NAME} + COMMAND ${LLVM_COV_PATH} + show + $ + ${SO_OBJECTS} + -instr-profile=${TARGET_NAME}.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME} + -format="html" + ${EXCLUDE_REGEX} + DEPENDS ccov-processing-${TARGET_NAME}) + + elseif(CMAKE_COMPILER_IS_GNUCXX) + set(COVERAGE_INFO + "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}.info") + + # Run the executable, generating coverage information + add_custom_target(ccov-run-${TARGET_NAME} + COMMAND $ + DEPENDS ccov-preprocessing ${TARGET_NAME}) + + # Generate exclusion string for use + foreach(EXCLUDE_ITEM ${target_code_coverage_EXCLUDE}) + set(EXCLUDE_REGEX + ${EXCLUDE_REGEX} + --remove + ${COVERAGE_INFO} + '${EXCLUDE_ITEM}') + endforeach() + + if(EXCLUDE_REGEX) + set(EXCLUDE_COMMAND + ${LCOV_PATH} + ${EXCLUDE_REGEX} + --output-file + ${COVERAGE_INFO}) + else() + set(EXCLUDE_COMMAND ;) + endif() + + if(NOT ${target_code_coverage_EXTERNAL}) + set(EXTERNAL_OPTION --no-external) + endif() + + # Generates HTML output of the coverage information for perusal + add_custom_target( + ccov-${TARGET_NAME} + COMMAND ${CMAKE_COMMAND} + -E + remove + ${COVERAGE_INFO} + COMMAND ${LCOV_PATH} + --directory + ${CMAKE_BINARY_DIR} + --zerocounters + COMMAND $ + COMMAND ${LCOV_PATH} + --directory + ${CMAKE_BINARY_DIR} + --base-directory + ${CMAKE_SOURCE_DIR} + --capture + ${EXTERNAL_OPTION} + --output-file + ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + COMMAND ${GENHTML_PATH} + -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME} + ${COVERAGE_INFO} + DEPENDS ccov-preprocessing ${TARGET_NAME}) + endif() + + add_custom_command( + TARGET ccov-${TARGET_NAME} POST_BUILD + COMMAND ; + COMMENT + "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/${TARGET_NAME}/index.html in your browser to view the coverage report." + ) + + # AUTO + if(target_code_coverage_AUTO) + if(NOT TARGET ccov) + add_custom_target(ccov) + endif() + add_dependencies(ccov ccov-${TARGET_NAME}) + + if(NOT CMAKE_COMPILER_IS_GNUCXX) + if(NOT TARGET ccov-report) + add_custom_target(ccov-report) + endif() + add_dependencies(ccov-report ccov-report-${TARGET_NAME}) + endif() + endif() + + # ALL + if(target_code_coverage_ALL) + if(NOT TARGET ccov-all-processing) + message( + FATAL_ERROR + "Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'." + ) + endif() + + add_dependencies(ccov-all-processing ccov-run-${TARGET_NAME}) + endif() + endif() + endif() +endfunction() + +# Adds code coverage instrumentation to all targets in the current directory and +# any subdirectories. To add coverage instrumentation to only specific targets, +# use `target_code_coverage`. +function(add_code_coverage) + if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + add_compile_options(-fprofile-instr-generate -fcoverage-mapping) + add_link_options(-fprofile-instr-generate -fcoverage-mapping) + elseif(CMAKE_COMPILER_IS_GNUCXX) + add_compile_options(-fprofile-arcs -ftest-coverage) + link_libraries(gcov) + endif() +endfunction() + +# Adds the 'ccov-all' type targets that calls all targets added via +# `target_code_coverage` with the `ALL` parameter, but merges all the coverage +# data from them into a single large report instead of the numerous smaller +# reports. +# ~~~ +# Optional: +# EXCLUDE - Excludes files of the regex patterns provided from coverage. +# ~~~ +function(add_code_coverage_all_targets) + # Argument parsing + set(multi_value_keywords EXCLUDE) + cmake_parse_arguments(add_code_coverage_all_targets + "" + "" + "${multi_value_keywords}" + ${ARGN}) + + if(CODE_COVERAGE) + if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + + # Merge the profile data for all of the run executables + add_custom_target( + ccov-all-processing + COMMAND ${LLVM_PROFDATA_PATH} + merge + -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -sparse + `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/profraw.list`) + + # Regex exclude only available for LLVM >= 7 + if(LLVM_COV_VERSION VERSION_GREATER_EQUAL "7.0.0") + foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) + set(EXCLUDE_REGEX ${EXCLUDE_REGEX} + -ignore-filename-regex='${EXCLUDE_ITEM}') + endforeach() + endif() + + # Print summary of the code coverage information to the command line + add_custom_target( + ccov-all-report + COMMAND + ${LLVM_COV_PATH} + report + `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + + # Export coverage information so continuous integration tools (e.g. Jenkins) can consume it + add_custom_target( + ccov-all-export + COMMAND + ${LLVM_COV_PATH} + export + `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -format="text" + ${EXCLUDE_REGEX} > ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/coverage.json + DEPENDS ccov-all-processing) + + # Generate HTML output of all added targets for perusal + add_custom_target( + ccov-all + COMMAND + ${LLVM_COV_PATH} + show + `cat + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/binaries.list` + -instr-profile=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.profdata + -show-line-counts-or-regions + -output-dir=${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + -format="html" + ${EXCLUDE_REGEX} + DEPENDS ccov-all-processing) + + elseif(CMAKE_COMPILER_IS_GNUCXX) + set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged.info") + + # Nothing required for gcov + add_custom_target(ccov-all-processing COMMAND ;) + + # Exclusion regex string creation + foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE}) + set(EXCLUDE_REGEX + ${EXCLUDE_REGEX} + --remove + ${COVERAGE_INFO} + '${EXCLUDE_ITEM}') + endforeach() + + if(EXCLUDE_REGEX) + set(EXCLUDE_COMMAND + ${LCOV_PATH} + ${EXCLUDE_REGEX} + --output-file + ${COVERAGE_INFO}) + else() + set(EXCLUDE_COMMAND ;) + endif() + + # Generates HTML output of all targets for perusal + add_custom_target(ccov-all + COMMAND ${LCOV_PATH} + --directory + ${CMAKE_BINARY_DIR} + --capture + --output-file + ${COVERAGE_INFO} + COMMAND ${EXCLUDE_COMMAND} + COMMAND ${GENHTML_PATH} + -o + ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged + ${COVERAGE_INFO} + COMMAND ${CMAKE_COMMAND} + -E + remove + ${COVERAGE_INFO} + DEPENDS ccov-all-processing) + + endif() + + add_custom_command( + TARGET ccov-all POST_BUILD + COMMAND ; + COMMENT + "Open ${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/all-merged/index.html in your browser to view the coverage report." + ) + endif() +endfunction() diff --git a/cmake/Modules/codecheck.cmake b/cmake/Modules/codecheck.cmake new file mode 100644 index 0000000..621aec0 --- /dev/null +++ b/cmake/Modules/codecheck.cmake @@ -0,0 +1,83 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +option(CODECHECKER "Turns on codecheck processing if it is found." OFF) +option(CODECHECKER_STORE "Store results on central codechecker server" OFF) +option(CODECHECKER_RUN "Name of the codechecker run" "run-1") +option(CODECHECKER_BRANCH "Name of the branch codecheker is run for" "unknown") +option(CODECHECKER_URL "URL and product link to codechecker server" "http://localhost:8001/Default") +option(CODECHECK_TRIM_PATH "beginning of the path to be removed when storing" "/tmp") + +find_program(CODECHECKER_PATH + NAME CodeChecker + PATHS ~/bin/ + /usr/bin/ + /usr/local/bin +) + +if (CODECHECKER_PATH ) + message(STATUS "CodeChecker found") +else() + message(STATUS "CodeChecker not found") +endif() + +# export compile commands to json file to be used by atom c++ ide (clangd) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) +set(CODECHECKER_COMPILE_COMMANDS "${CMAKE_BINARY_DIR}/compile_commands.json") + +# check if a skip file exists +if(EXISTS ${CMAKE_SOURCE_DIR}/codecheck.skip) + set(CODECHECKER_SKIP "-i${CMAKE_SOURCE_DIR}/codecheck.skip") +endif() + + +# output directory for codecheck analysis +set(CODECHECKER_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/codechecker_results) + +# html output directory +set(CODECHECKER_HTML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/codechecker_html) + +# Common initialization/checks +if(CODECHECKER AND CODECHECKER_PATH AND NOT CODECHECKER_ADDED) + set(CODECHECKER_ADDED ON) + + IF(NOT TARGET codechecker) + + add_custom_target(codechecker + COMMAND ${CODECHECKER_PATH} + analyze + ${CODECHECKER_SKIP} + -j 4 + -o ${CODECHECKER_OUTPUT_DIRECTORY} + ${CODECHECKER_COMPILE_COMMANDS} + ) + + add_custom_target(codechecker-clean + COMMAND rm -rf ${CODECHECKER_OUTPUT_DIRECTORY} + ) + + + add_custom_target(codechecker-html + COMMAND ${CODECHECKER_PATH} + parse + ${CODECHECKER_OUTPUT_DIRECTORY} + -e html + -o ${CODECHECKER_HTML_OUTPUT_DIRECTORY} + ) + + if (CODECHECKER_STORE) + add_custom_target(codechecker-store + COMMAND ${CODECHECKER_PATH} + store + --trim-path-prefix \"${CODECHECK_TRIM_PATH}\" + --tag \"${CODECHECKER_BRANCH}\" + -n \"${CODECHECKER_RUN}\" + --url ${CODECHECKER_URL} + ${CODECHECKER_OUTPUT_DIRECTORY} + ) + endif() + +endif() +endif() diff --git a/cmake/Modules/compdb.cmake b/cmake/Modules/compdb.cmake new file mode 100644 index 0000000..a169208 --- /dev/null +++ b/cmake/Modules/compdb.cmake @@ -0,0 +1,23 @@ +find_program(COMPDB_PATH + NAME compdb + PATHS ~/.local/bin/ + /bin + /sbin + /usr/bin + /usr/sbin + /usr/local/bin + /usr/local/sbin + ) + + + +if (COMPDB_PATH) + IF(NOT TARGET COMPD) + add_custom_target(COMPD + ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${COMPDB_PATH} -p ${CMAKE_CURRENT_BINARY_DIR} list >compile_commands.json + ) + endif() +endif() diff --git a/cmake/Modules/compiler-options.cmake b/cmake/Modules/compiler-options.cmake new file mode 100644 index 0000000..1d8a146 --- /dev/null +++ b/cmake/Modules/compiler-options.cmake @@ -0,0 +1,46 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +option(ENABLE_ALL_WARNINGS "Compile with all warnings for the major compilers." + OFF) +option(ENABLE_EFFECTIVE_CXX "Enable Effective C++ warnings." OFF) + +if(ENABLE_ALL_WARNINGS) + if(CMAKE_COMPILER_IS_GNUCXX) + # GCC + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + elseif("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + # Clang + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + elseif(MSVC) + # MSVC + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + endif() +endif() + +if(ENABLE_EFFECTIVE_CXX) + if(CMAKE_COMPILER_IS_GNUCXX) + # GCC + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++") + elseif("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang" + OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + # Clang + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++") + endif() +endif() diff --git a/cmake/Modules/defaultIncludes.cmake b/cmake/Modules/defaultIncludes.cmake new file mode 100644 index 0000000..2c38764 --- /dev/null +++ b/cmake/Modules/defaultIncludes.cmake @@ -0,0 +1,15 @@ +include(c++-standards) +include(compiler-options) +include(sanitizers) +include(codecheck) +include(CppCheck) +include(code-coverage) +include(tools) +include(GNUInstallDirs) +include(CTest) +include(doxygen) +include(ProcessGIT) +include(CheckParent) +include(add_my_test) +include(TestBigEndian) +include(compdb) diff --git a/cmake/Modules/defaultOptions.cmake b/cmake/Modules/defaultOptions.cmake new file mode 100644 index 0000000..2e1ffd2 --- /dev/null +++ b/cmake/Modules/defaultOptions.cmake @@ -0,0 +1,9 @@ +include(defaultIncludes) +find_package(Git) + +enable_testing() +cxx_20() +build_docs(PROCESS_DOXYFILE DOXYFILE_PATH "docs/Doxyfile.in" ) + +add_code_coverage_all_targets(EXCLUDE ${PROJECT_SOURCE_DIR}/libs/* ${PROJECT_SOURCE_DIR}/test/*) +TEST_BIG_ENDIAN(IS_BIG_ENDIAN) diff --git a/cmake/Modules/doxygen.cmake b/cmake/Modules/doxygen.cmake new file mode 100644 index 0000000..f231472 --- /dev/null +++ b/cmake/Modules/doxygen.cmake @@ -0,0 +1,134 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +find_package(Doxygen) + +option(BUILD_DOCUMENTATION "Build API documentation using Doxygen. (make doc)" + ${DOXYGEN_FOUND}) + +# Builds doxygen documentation with a default 'Doxyfile.in' or with a specified +# one, and can make the results installable (under the `doc` install target) +# +# This can only be used once per project, as each target generated is as +# `doc-${PROJECT_NAME}` unless TARGET_NAME is specified. +# ~~~ +# Optional Arguments: +# +# ADD_TO_DOC +# If specified, adds this generated target to be a dependency of the more general +# `doc` target. +# +# INSTALLABLE +# Adds the generated documentation to the generic `install` target, under the +# `documentation` installation group. +# +# PROCESS_DOXYFILE +# If set, then will process the found Doxyfile through the CMAKE `configure_file` +# function for macro replacements before using it. (@ONLY) +# +# TARGET_NAME +# The name to give the doc target. (Default: doc-${PROJECT_NAME}) +# +# OUTPUT_DIR +# The directory to place the generated output. (Default: ${CMAKE_CURRENT_BINARY_DIR}/doc) +# +# INSTALL_PATH +# The path to install the documenttation under. (if not specified, defaults to +# 'share/${PROJECT_NAME}) +# +# DOXYFILE_PATH +# The given doxygen file to use/process. (Defaults to'${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile') +# ~~~ +function(build_docs) + set(OPTIONS ADD_TO_DOC INSTALLABLE PROCESS_DOXYFILE) + set(SINGLE_VALUE_KEYWORDS + TARGET_NAME + INSTALL_PATH + DOXYFILE_PATH + OUTPUT_DIR) + set(MULTI_VALUE_KEYWORDS) + cmake_parse_arguments(build_docs + "${OPTIONS}" + "${SINGLE_VALUE_KEYWORDS}" + "${MULTI_VALUE_KEYWORDS}" + ${ARGN}) + + if(BUILD_DOCUMENTATION) + if(NOT DOXYGEN_FOUND) + message(FATAL_ERROR "Doxygen is needed to build the documentation.") + endif() + + if(NOT build_docs_DOXYFILE_PATH) + set(DOXYFILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile") + elseif(EXISTS "${build_docs_DOXYFILE_PATH}") + set(DOXYFILE_PATH "${build_docs_DOXYFILE_PATH}") + else() + set(DOXYFILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${build_docs_DOXYFILE_PATH}") + endif() + + if(NOT EXISTS "${DOXYFILE_PATH}") + message( + SEND_ERROR + "Could not find Doxyfile to use for procesing documentation at: ${DOXYFILE_PATH}" + ) + return() + endif() + + if(build_docs_PROCESS_DOXYFILE) + set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") + configure_file("${DOXYFILE_PATH}" "${DOXYFILE}" @ONLY) + else() + set(DOXYFILE "${DOXYFILE_PATH}") + endif() + + if(build_docs_OUTPUT_DIR) + set(OUT_DIR "${build_docs_OUTPUT_DIR}") + else() + set(OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc") + endif() + + file(MAKE_DIRECTORY "${OUT_DIR}") + + if(build_docs_TARGET_NAME) + set(TARGET_NAME ${build_docs_TARGET_NAME}) + else() + set(TARGET_NAME doc-${PROJECT_NAME}) + endif() + + IF(NOT TARGET ${TARGET_NAME}) + add_custom_target(${TARGET_NAME} + COMMAND ${DOXYGEN_EXECUTABLE} "${DOXYFILE}" + WORKING_DIRECTORY "${OUT_DIR}" + VERBATIM) + ENDIF() + + if(build_docs_ADD_TO_DOC) + if(NOT TARGET doc) + add_custom_target(doc) + endif() + + add_dependencies(doc ${TARGET_NAME}) + endif() + + if(build_docs_INSTALLABLE) + if(NOT build_docs_INSTALL_PATH) + set(build_docs_INSTALL_PATH share/${PROJECT_NAME}) + endif() + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/ + COMPONENT documentation + DESTINATION ${build_docs_INSTALL_PATH}) + endif() + endif() +endfunction() diff --git a/cmake/Modules/protobuf.cmake b/cmake/Modules/protobuf.cmake new file mode 100644 index 0000000..e2fd5f4 --- /dev/null +++ b/cmake/Modules/protobuf.cmake @@ -0,0 +1,34 @@ +function(protobuf_generate_cpp) + set(OPTIONS) + set(SINGLE_VALUE_KEYWORDS + PROTO_PATH + CPP_PATH + HPP_PATH + ) + set(MULTI_VALUE_KEYWORDS) + cmake_parse_arguments(protobuf + "${OPTIONS}" + "${SINGLE_VALUE_KEYWORDS}" + "${MULTI_VALUE_KEYWORDS}" + ${ARGN}) + + FILE(GLOB PROTO_FILES ${protobuf_PROTO_PATH}/*.proto) + set(PROTOC ${CMAKE_BINARY_DIR}/libs/protobuf/protoc) + # set(PROTOC protoc) + + FOREACH(proto ${PROTO_FILES}) + FILE(TO_NATIVE_PATH ${proto} proto_native) + get_filename_component(protoFILENAME ${proto} NAME_WLE ) + get_filename_component(protoDIR ${proto} DIRECTORY) + + + add_custom_command( + OUTPUT "${protoDIR}/${protoFILENAME}.pb.cc" + DEPENDS "${protoDIR}/${protoFILENAME}.proto" + COMMAND ${PROTOC} --cpp_out=${protoDIR} --proto_path=${protoDIR} --proto_path="${CMAKE_SOURCE_DIR}/libs/protobuf/src" "${protoDIR}/${protoFILENAME}.proto" + ) + + ENDFOREACH(proto) + + +endfunction() diff --git a/cmake/Modules/sanitizers.cmake b/cmake/Modules/sanitizers.cmake new file mode 100644 index 0000000..f26947f --- /dev/null +++ b/cmake/Modules/sanitizers.cmake @@ -0,0 +1,87 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +set( + USE_SANITIZER + "" + CACHE + STRING + "Compile with a sanitizer. Options are: Address, Memory, MemoryWithOrigins, Undefined, Thread, Leak, 'Address;Undefined'" + ) + +function(append value) + foreach(variable ${ARGN}) + set(${variable} "${${variable}} ${value}" PARENT_SCOPE) + endforeach(variable) +endfunction() + +if(USE_SANITIZER) + append("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + if(UNIX) + + if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + append("-O1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() + + if(USE_SANITIZER MATCHES "([Aa]ddress);([Uu]ndefined)" + OR USE_SANITIZER MATCHES "([Uu]ndefined);([Aa]ddress)") + message(STATUS "Building with Address, Undefined sanitizers") + append("-fsanitize=address,undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif("${USE_SANITIZER}" MATCHES "([Aa]ddress)") + # Optional: -fno-optimize-sibling-calls -fsanitize-address-use-after-scope + message(STATUS "Building with Address sanitizer") + append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif(USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)") + # Optional: -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 + append("-fsanitize=memory" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + if(USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)") + message(STATUS "Building with MemoryWithOrigins sanitizer") + append("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + else() + message(STATUS "Building with Memory sanitizer") + endif() + elseif(USE_SANITIZER MATCHES "([Uu]ndefined)") + message(STATUS "Building with Undefined sanitizer") + append("-fsanitize=undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + if(EXISTS "${BLACKLIST_FILE}") + append("-fsanitize-blacklist=${BLACKLIST_FILE}" CMAKE_C_FLAGS + CMAKE_CXX_FLAGS) + endif() + elseif(USE_SANITIZER MATCHES "([Tt]hread)") + message(STATUS "Building with Thread sanitizer") + append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif(USE_SANITIZER MATCHES "([Ll]eak)") + message(STATUS "Building with Leak sanitizer") + append("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + else() + message( + FATAL_ERROR "Unsupported value of USE_SANITIZER: ${USE_SANITIZER}") + endif() + elseif(MSVC) + if(USE_SANITIZER MATCHES "([Aa]ddress)") + message(STATUS "Building with Address sanitizer") + append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + else() + message( + FATAL_ERROR + "This sanitizer not yet supported in the MSVC environment: ${USE_SANITIZER}" + ) + endif() + else() + message(FATAL_ERROR "USE_SANITIZER is not supported on this platform.") + endif() + +endif() diff --git a/cmake/Modules/tools.cmake b/cmake/Modules/tools.cmake new file mode 100644 index 0000000..6d03f21 --- /dev/null +++ b/cmake/Modules/tools.cmake @@ -0,0 +1,64 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +option(CLANG_TIDY "Turns on clang-tidy processing if it is found." OFF) +option(IWYU "Turns on include-what-you-use processing if it is found." OFF) + +# Adds clang-tidy checks to the compilation, with the given arguments being used +# as the options set. +macro(clang_tidy) + if(CLANG_TIDY AND CLANG_TIDY_EXE) + set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} ${ARGN}) + endif() +endmacro() + +# Adds include_what_you_use to the compilation, with the given arguments being +# used as the options set. +macro(include_what_you_use) + if(IWYU AND IWYU_EXE) + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "${IWYU_EXE};${ARGN}") + endif() +endmacro() + +find_program(CLANG_TIDY_EXE NAMES clang-tidy clang-tidy-8 clang-tidy-7 clang-tidy-6) +if(CLANG_TIDY_EXE) + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + if(NOT CLANG_TIDY) + message(STATUS "clang-tidy NOT ENABLED via 'CLANG_TIDY' variable!") + set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it + endif() +elseif(CLANG_TIDY) + message(SEND_ERROR "Cannot enable clang-tidy, as executable not found!") + set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it +else() + message(STATUS "clang-tidy not found!") + set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it +endif() + +find_program(IWYU_EXE NAMES "include-what-you-use") +if(IWYU_EXE) + message(STATUS "include-what-you-use found: ${IWYU_EXE}") + if(NOT IWYU) + message(STATUS "include-what-you-use NOT ENABLED via 'IWYU' variable!") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it + endif() +elseif(IWYU) + message( + SEND_ERROR "Cannot enable include-what-you-use, as executable not found!") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it +else() + message(STATUS "include-what-you-use not found!") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE "" CACHE STRING "" FORCE) # delete it +endif() diff --git a/cmake/Modules/xslt.cmake b/cmake/Modules/xslt.cmake new file mode 100644 index 0000000..9a60337 --- /dev/null +++ b/cmake/Modules/xslt.cmake @@ -0,0 +1,43 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# + +IF(NOT CMAKE_SET_XSLT) + +set(CMAKE_SET_XSLT true) + +find_program(CMAKE_XSLTPROC NAME xsltproc HINTS ${CMAKE_SYSTEM_PROGRAM_PATH}) + +if (CMAKE_XSLTPROC) + message(STATUS "XSLTPROC found") +else() + message(FATAL_ERROR "XSLTPROC not found") +endif() + +function(xslt_generate) + set(OPTIONS ) + set(SINGLE_VALUE_KEYWORDS OUT_FILE XML_FILE XSL_FILE) + set(MULTI_VALUE_KEYWORDS) + cmake_parse_arguments(XSLT + "${OPTIONS}" + "${SINGLE_VALUE_KEYWORDS}" + "${MULTI_VALUE_KEYWORDS}" + ${ARGN}) + + + message(STATUS "generating ${CMAKE_XSLTPROC} --nonet -o ${XSLT_OUT_FILE} ${XSLT_XSL_FILE} ${XSLT_XML_FILE} ") + execute_process( + COMMAND ${CMAKE_XSLTPROC} --nonet -o ${XSLT_OUT_FILE} ${XSLT_XSL_FILE} ${XSLT_XML_FILE} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE OUT + ERROR_VARIABLE ERR + ) + + message(STATUS ${OUT}) + message(STATUS ${ERR}) + +endfunction() + +ENDIF() diff --git a/cmake/Toolchains/Toolchain-mingw64.cmake b/cmake/Toolchains/Toolchain-mingw64.cmake new file mode 100644 index 0000000..434c229 --- /dev/null +++ b/cmake/Toolchains/Toolchain-mingw64.cmake @@ -0,0 +1,27 @@ +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix) +SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix) + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(WINE_FOUND wine) + +if(WINE_FOUND) + message(STATUS "WINE found") + SET(CMAKE_CROSSCOMPILING_EMULATOR wine) +endif() + +if (CMAKE_CROSSCOMPILING) + message(STATUS "Crosscompiling for ${CMAKE_SYSTEM_NAME}") +endif() diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..f2ebb78 --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,23 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = @PROJECT_NAME@ +PROJECT_NUMBER = "@GIT_BRANCH@ @GIT_COMMIT_HASH@" +PROJECT_BRIEF = "library implementing a floats to libcms gateway" +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doxygen/ +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +MULTILINE_CPP_IS_BRIEF = NO +TAB_SIZE = 4 +MARKDOWN_SUPPORT = YES +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/README.md @CMAKE_CURRENT_SOURCE_DIR@/src/ @CMAKE_CURRENT_SOURCE_DIR@/tests/ @CMAKE_CURRENT_SOURCE_DIR@/docs @CMAKE_CURRENT_SOURCE_DIR@/include +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.hpp *.cpp *.md +USE_MDFILE_AS_MAINPAGE = README.md +RECURSIVE = YES diff --git a/include/kubecontrol/kubecontrol.hpp b/include/kubecontrol/kubecontrol.hpp new file mode 100644 index 0000000..e69de29 diff --git a/libs/CLI11/.all-contributorsrc b/libs/CLI11/.all-contributorsrc new file mode 100644 index 0000000..7de6785 --- /dev/null +++ b/libs/CLI11/.all-contributorsrc @@ -0,0 +1,483 @@ +{ + "projectName": "CLI11", + "projectOwner": "CLIUtils", + "repoType": "github", + "repoHost": "https://github.com", + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": true, + "commitConvention": "atom", + "contributors": [ + { + "login": "henryiii", + "name": "Henry Schreiner", + "avatar_url": "https://avatars1.githubusercontent.com/u/4616906?v=4", + "profile": "http://iscinumpy.gitlab.io", + "contributions": [ + "bug", + "doc", + "code" + ] + }, + { + "login": "phlptp", + "name": "Philip Top", + "avatar_url": "https://avatars0.githubusercontent.com/u/20667153?v=4", + "profile": "https://github.com/phlptp", + "contributions": [ + "bug", + "doc", + "code" + ] + }, + { + "login": "cbachhuber", + "name": "Christoph Bachhuber", + "avatar_url": "https://avatars0.githubusercontent.com/u/27212661?v=4", + "profile": "https://www.linkedin.com/in/cbachhuber/", + "contributions": [ + "example", + "code" + ] + }, + { + "login": "lambdafu", + "name": "Marcus Brinkmann", + "avatar_url": "https://avatars1.githubusercontent.com/u/1138455?v=4", + "profile": "https://lambdafu.net/", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "SkyToGround", + "name": "Jonas Nilsson", + "avatar_url": "https://avatars1.githubusercontent.com/u/58835?v=4", + "profile": "https://github.com/SkyToGround", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "dvj", + "name": "Doug Johnston", + "avatar_url": "https://avatars2.githubusercontent.com/u/77217?v=4", + "profile": "https://github.com/dvj", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "lczech", + "name": "Lucas Czech", + "avatar_url": "https://avatars0.githubusercontent.com/u/4741887?v=4", + "profile": "http://lucas-czech.de", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "rafiw", + "name": "Rafi Wiener", + "avatar_url": "https://avatars3.githubusercontent.com/u/3034707?v=4", + "profile": "https://github.com/rafiw", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "mensinda", + "name": "Daniel Mensinger", + "avatar_url": "https://avatars3.githubusercontent.com/u/3407462?v=4", + "profile": "https://github.com/mensinda", + "contributions": [ + "platform" + ] + }, + { + "login": "jbriales", + "name": "Jesus Briales", + "avatar_url": "https://avatars1.githubusercontent.com/u/6850478?v=4", + "profile": "https://github.com/jbriales", + "contributions": [ + "code", + "bug" + ] + }, + { + "login": "seanfisk", + "name": "Sean Fisk", + "avatar_url": "https://avatars0.githubusercontent.com/u/410322?v=4", + "profile": "https://seanfisk.com/", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "fpeng1985", + "name": "fpeng1985", + "avatar_url": "https://avatars1.githubusercontent.com/u/87981?v=4", + "profile": "https://github.com/fpeng1985", + "contributions": [ + "code" + ] + }, + { + "login": "almikhayl", + "name": "almikhayl", + "avatar_url": "https://avatars2.githubusercontent.com/u/6747040?v=4", + "profile": "https://github.com/almikhayl", + "contributions": [ + "code", + "platform" + ] + }, + { + "login": "andrew-hardin", + "name": "Andrew Hardin", + "avatar_url": "https://avatars0.githubusercontent.com/u/16496326?v=4", + "profile": "https://github.com/andrew-hardin", + "contributions": [ + "code" + ] + }, + { + "login": "SX91", + "name": "Anton", + "avatar_url": "https://avatars2.githubusercontent.com/u/754754?v=4", + "profile": "https://github.com/SX91", + "contributions": [ + "code" + ] + }, + { + "login": "helmesjo", + "name": "Fred Helmesjö", + "avatar_url": "https://avatars0.githubusercontent.com/u/2501070?v=4", + "profile": "https://github.com/helmesjo", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "skannan89", + "name": "Kannan", + "avatar_url": "https://avatars0.githubusercontent.com/u/11918764?v=4", + "profile": "https://github.com/skannan89", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "kraj", + "name": "Khem Raj", + "avatar_url": "https://avatars3.githubusercontent.com/u/465279?v=4", + "profile": "http://himvis.com", + "contributions": [ + "code" + ] + }, + { + "login": "mogigoma", + "name": "Mak Kolybabi", + "avatar_url": "https://avatars2.githubusercontent.com/u/130862?v=4", + "profile": "https://www.mogigoma.com/", + "contributions": [ + "doc" + ] + }, + { + "login": "msoeken", + "name": "Mathias Soeken", + "avatar_url": "https://avatars0.githubusercontent.com/u/1998245?v=4", + "profile": "http://msoeken.github.io", + "contributions": [ + "doc" + ] + }, + { + "login": "nathanhourt", + "name": "Nathan Hourt", + "avatar_url": "https://avatars2.githubusercontent.com/u/271977?v=4", + "profile": "https://github.com/nathanhourt", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "pleroux0", + "name": "Paul le Roux", + "avatar_url": "https://avatars2.githubusercontent.com/u/39619854?v=4", + "profile": "https://github.com/pleroux0", + "contributions": [ + "code", + "platform" + ] + }, + { + "login": "chfast", + "name": "Paweł Bylica", + "avatar_url": "https://avatars1.githubusercontent.com/u/573380?v=4", + "profile": "https://github.com/chfast", + "contributions": [ + "platform" + ] + }, + { + "login": "peterazmanov", + "name": "Peter Azmanov", + "avatar_url": "https://avatars0.githubusercontent.com/u/15322318?v=4", + "profile": "https://github.com/peterazmanov", + "contributions": [ + "code" + ] + }, + { + "login": "delpinux", + "name": "Stéphane Del Pino", + "avatar_url": "https://avatars0.githubusercontent.com/u/35096584?v=4", + "profile": "https://github.com/delpinux", + "contributions": [ + "code" + ] + }, + { + "login": "metopa", + "name": "Viacheslav Kroilov", + "avatar_url": "https://avatars2.githubusercontent.com/u/3974178?v=4", + "profile": "https://github.com/metopa", + "contributions": [ + "code" + ] + }, + { + "login": "ChristosT", + "name": "christos", + "avatar_url": "https://avatars0.githubusercontent.com/u/6725596?v=4", + "profile": "http://cs.odu.edu/~ctsolakis", + "contributions": [ + "code" + ] + }, + { + "login": "deining", + "name": "deining", + "avatar_url": "https://avatars3.githubusercontent.com/u/18169566?v=4", + "profile": "https://github.com/deining", + "contributions": [ + "doc" + ] + }, + { + "login": "elszon", + "name": "elszon", + "avatar_url": "https://avatars0.githubusercontent.com/u/2971495?v=4", + "profile": "https://github.com/elszon", + "contributions": [ + "code" + ] + }, + { + "login": "ncihnegn", + "name": "ncihnegn", + "avatar_url": "https://avatars3.githubusercontent.com/u/12021721?v=4", + "profile": "https://github.com/ncihnegn", + "contributions": [ + "code" + ] + }, + { + "login": "nurelin", + "name": "nurelin", + "avatar_url": "https://avatars3.githubusercontent.com/u/5276274?v=4", + "profile": "https://github.com/nurelin", + "contributions": [ + "code" + ] + }, + { + "login": "ryan4729", + "name": "ryan4729", + "avatar_url": "https://avatars3.githubusercontent.com/u/40183301?v=4", + "profile": "https://github.com/ryan4729", + "contributions": [ + "test" + ] + }, + { + "login": "slurps-mad-rips", + "name": "Isabella Muerte", + "avatar_url": "https://avatars0.githubusercontent.com/u/63051?v=4", + "profile": "https://izzys.casa", + "contributions": [ + "platform" + ] + }, + { + "login": "KOLANICH", + "name": "KOLANICH", + "avatar_url": "https://avatars1.githubusercontent.com/u/240344?v=4", + "profile": "https://github.com/KOLANICH", + "contributions": [ + "platform" + ] + }, + { + "login": "jgerityneurala", + "name": "James Gerity", + "avatar_url": "https://avatars2.githubusercontent.com/u/57360646?v=4", + "profile": "https://github.com/jgerityneurala", + "contributions": [ + "doc" + ] + }, + { + "login": "jsoref", + "name": "Josh Soref", + "avatar_url": "https://avatars0.githubusercontent.com/u/2119212?v=4", + "profile": "https://github.com/jsoref", + "contributions": [ + "tool" + ] + }, + { + "login": "geir-t", + "name": "geir-t", + "avatar_url": "https://avatars3.githubusercontent.com/u/35292136?v=4", + "profile": "https://github.com/geir-t", + "contributions": [ + "platform" + ] + }, + { + "login": "certik", + "name": "Ondřej Čertík", + "avatar_url": "https://avatars3.githubusercontent.com/u/20568?v=4", + "profile": "https://ondrejcertik.com/", + "contributions": [ + "bug" + ] + }, + { + "login": "samhocevar", + "name": "Sam Hocevar", + "avatar_url": "https://avatars2.githubusercontent.com/u/245089?v=4", + "profile": "http://sam.hocevar.net/", + "contributions": [ + "code" + ] + }, + { + "login": "rcurtin", + "name": "Ryan Curtin", + "avatar_url": "https://avatars0.githubusercontent.com/u/1845039?v=4", + "profile": "http://www.ratml.org/", + "contributions": [ + "doc" + ] + }, + { + "login": "mbhall88", + "name": "Michael Hall", + "avatar_url": "https://avatars3.githubusercontent.com/u/20403931?v=4", + "profile": "https://mbh.sh", + "contributions": [ + "doc" + ] + }, + { + "login": "ferdymercury", + "name": "ferdymercury", + "avatar_url": "https://avatars3.githubusercontent.com/u/10653970?v=4", + "profile": "https://github.com/ferdymercury", + "contributions": [ + "doc" + ] + }, + { + "login": "jakoblover", + "name": "Jakob Lover", + "avatar_url": "https://avatars0.githubusercontent.com/u/14160441?v=4", + "profile": "https://github.com/jakoblover", + "contributions": [ + "code" + ] + }, + { + "login": "ZeeD26", + "name": "Dominik Steinberger", + "avatar_url": "https://avatars2.githubusercontent.com/u/2487468?v=4", + "profile": "https://github.com/ZeeD26", + "contributions": [ + "code" + ] + }, + { + "login": "dfleury2", + "name": "D. Fleury", + "avatar_url": "https://avatars1.githubusercontent.com/u/4805384?v=4", + "profile": "https://github.com/dfleury2", + "contributions": [ + "code" + ] + }, + { + "login": "dbarowy", + "name": "Dan Barowy", + "avatar_url": "https://avatars3.githubusercontent.com/u/573142?v=4", + "profile": "https://github.com/dbarowy", + "contributions": [ + "doc" + ] + }, + { + "login": "paddy-hack", + "name": "Olaf Meeuwissen", + "avatar_url": "https://avatars.githubusercontent.com/u/6804372?v=4", + "profile": "https://github.com/paddy-hack", + "contributions": [ + "code" + ] + }, + { + "login": "dryleev", + "name": "dryleev", + "avatar_url": "https://avatars.githubusercontent.com/u/83670813?v=4", + "profile": "https://github.com/dryleev", + "contributions": [ + "code" + ] + }, + { + "login": "AnticliMaxtic", + "name": "Max", + "avatar_url": "https://avatars.githubusercontent.com/u/43995389?v=4", + "profile": "https://github.com/AnticliMaxtic", + "contributions": [ + "code" + ] + }, + { + "login": "alexdewar", + "name": "Alex Dewar", + "avatar_url": "https://avatars.githubusercontent.com/u/23149834?v=4", + "profile": "https://profiles.sussex.ac.uk/p281168-alex-dewar/publications", + "contributions": [ + "code" + ] + } + ], + "contributorsPerLine": 7, + "skipCi": true +} diff --git a/libs/CLI11/.appveyor.yml b/libs/CLI11/.appveyor.yml new file mode 100644 index 0000000..08bba18 --- /dev/null +++ b/libs/CLI11/.appveyor.yml @@ -0,0 +1,39 @@ +version: 2.3.1.{build} + +branches: + only: + - main + - v1 + +install: + - git submodule update --init --recursive + - py -3 --version + - set PATH=C:\Python38-x64;C:\Python38-x64\Scripts;%PATH% + - cmake --version + - python --version + - python -m pip --version + - python -m pip install conan + - conan user + - conan --version + +build_script: + - mkdir build + - cd build + - ps: + cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE_TESTS=ON + -DCMAKE_BUILD_TYPE=Debug -DCMAKE_GENERATOR="Visual Studio 14 2015" + - ps: cmake --build . + - cd .. + - ps: set CTEST_OUTPUT_ON_FAILURE=1 + - conan create . CLIUtils/CLI11 + +test_script: + - cd build + - ps: ctest --output-on-failure -C Debug + +notifications: + - provider: Webhook + url: https://webhooks.gitter.im/e/0185e91c5d989a476d7b + on_build_success: false + on_build_failure: true + on_build_status_changed: true diff --git a/libs/CLI11/.ci/azure-build.yml b/libs/CLI11/.ci/azure-build.yml new file mode 100644 index 0000000..04ee5d6 --- /dev/null +++ b/libs/CLI11/.ci/azure-build.yml @@ -0,0 +1,23 @@ +steps: + # Needed on GCC 4.8 docker image for some reason + - script: mkdir build + displayName: "Make build directory" + + - task: CMake@1 + inputs: + cmakeArgs: + .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=$(cli11.single) + -DCMAKE_CXX_STANDARD=$(cli11.std) + -DCLI11_SINGLE_FILE_TESTS=$(cli11.single) + -DCMAKE_BUILD_TYPE=$(cli11.build_type) $(cli11.options) + displayName: "Configure" + + - script: cmake --build . -- -j2 --keep-going + displayName: "Build Unix" + workingDirectory: build + condition: ne( variables['Agent.OS'], 'Windows_NT' ) + + - script: cmake --build . + displayName: "Build Windows" + workingDirectory: build + condition: eq( variables['Agent.OS'], 'Windows_NT' ) diff --git a/libs/CLI11/.ci/azure-cmake.yml b/libs/CLI11/.ci/azure-cmake.yml new file mode 100644 index 0000000..a2f3d98 --- /dev/null +++ b/libs/CLI11/.ci/azure-cmake.yml @@ -0,0 +1,17 @@ +steps: + # Note that silkeh/clang does not include ca-certificates, so check the shasum for verification + - bash: | + wget --no-check-certificate "https://cmake.org/files/v3.14/cmake-3.14.3-Linux-x86_64.tar.gz" + echo "29faa62fb3a0b6323caa3d9557e1a5f1205614c0d4c5c2a9917f16a74f7eff68 cmake-3.14.3-Linux-x86_64.tar.gz" | shasum -sca 256 + displayName: Download CMake + + - task: ExtractFiles@1 + inputs: + archiveFilePatterns: "cmake*.tar.gz" + destinationFolder: "cmake_program" + displayName: Extract CMake + + - bash: + echo + "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.14.3-Linux-x86_64/bin" + displayName: Add CMake to PATH diff --git a/libs/CLI11/.ci/azure-test.yml b/libs/CLI11/.ci/azure-test.yml new file mode 100644 index 0000000..c9dc9a2 --- /dev/null +++ b/libs/CLI11/.ci/azure-test.yml @@ -0,0 +1,9 @@ +steps: + - script: ctest --output-on-failure -C $(cli11.build_type) -T test + displayName: "Test" + workingDirectory: build + + - task: PublishTestResults@2 + inputs: + testResultsFormat: "cTest" + testResultsFiles: "**/Test.xml" diff --git a/libs/CLI11/.clang-format b/libs/CLI11/.clang-format new file mode 100644 index 0000000..6a5d106 --- /dev/null +++ b/libs/CLI11/.clang-format @@ -0,0 +1,86 @@ +Language: Cpp +BasedOnStyle: LLVM +# AccessModifierOffset: -2 +# AlignAfterOpenBracket: Align +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +# AlignEscapedNewlinesLeft: false +# AlignOperands: true +# AlignTrailingComments: true +# AllowAllParametersOfDeclarationOnNextLine: true +# AllowShortBlocksOnASingleLine: false +# AllowShortCaseLabelsOnASingleLine: false +# AllowShortFunctionsOnASingleLine: All +# AllowShortIfStatementsOnASingleLine: false +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +# AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +BinPackArguments: false +BinPackParameters: false +# BraceWrapping: +# AfterClass: false +# AfterControlStatement: false +# AfterEnum: false +# AfterFunction: false +# AfterNamespace: false +# AfterObjCDeclaration: false +# AfterStruct: false +# AfterUnion: false +# BeforeCatch: false +# BeforeElse: false +# IndentBraces: false +# BreakBeforeBinaryOperators: None +# BreakBeforeBraces: Attach +# BreakBeforeTernaryOperators: true +# BreakConstructorInitializersBeforeComma: false +# BreakAfterJavaFieldAnnotations: false +# BreakStringLiterals: true +ColumnLimit: 120 +# CommentPragmas: '^ IWYU pragma:' +# ConstructorInitializerAllOnOneLineOrOnePerLine: false +# ConstructorInitializerIndentWidth: 4 +# ContinuationIndentWidth: 4 +# Cpp11BracedListStyle: true +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +# IncludeIsMainRegex: '$' +# IndentCaseLabels: false +IndentWidth: 4 +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true +# KeepEmptyLinesAtTheStartOfBlocks: true +# MacroBlockBegin: '' +# MacroBlockEnd: '' +# MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# ObjCBlockIndentWidth: 2 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +# PointerAlignment: Right +# ReflowComments: true +SortIncludes: true +# SpaceAfterCStyleCast: false +# SpaceAfterTemplateKeyword: true +# SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +# SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +# SpacesInAngles: false +# SpacesInContainerLiterals: true +# SpacesInCStyleCastParentheses: false +# SpacesInParentheses: false +# SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never diff --git a/libs/CLI11/.clang-tidy b/libs/CLI11/.clang-tidy new file mode 100644 index 0000000..82450d1 --- /dev/null +++ b/libs/CLI11/.clang-tidy @@ -0,0 +1,80 @@ +# Checks that will be implemented in future PRs: +# performance-unnecessary-value-param, hints to ~110 issues. Be careful with implementing the suggested changes of this one, as auto-fixes may break the code +# bugprone-forwarding-reference-overload probably should be enabled and fixed. +# clang-diagnostic-float-equal can be fixed by using _a from Catch::literals +# bugprone-exception-escape due to main being a bit simple in examples +# modernize-avoid-c-arrays trips up in TEMPLATE_TEST_CASE catch macro +# modernize-return-braced-init-list triggers on lambdas ? +# modernize-make-unique requires C++14 +# readability-avoid-const-params-in-decls Affected by the pre-compile split + +Checks: | + *bugprone*, + -bugprone-easily-swappable-parameters, + -bugprone-forwarding-reference-overload, + -bugprone-exception-escape, + clang-analyzer-optin.cplusplus.VirtualCall, + clang-analyzer-optin.performance.Padding, + -clang-diagnostic-float-equal, + cppcoreguidelines-init-variables, + cppcoreguidelines-prefer-member-initializer, + cppcoreguidelines-pro-type-static-cast-downcast, + cppcoreguidelines-slicing, + google-*, + -google-runtime-references, + llvm-include-order, + llvm-namespace-comment, + misc-definitions-in-headers, + misc-misplaced-const, + misc-non-copyable-objects, + misc-static-assert, + misc-throw-by-value-catch-by-reference, + misc-throw-by-value-catch-by-reference, + misc-uniqueptr-reset-release, + misc-unused-parameters, + modernize*, + -modernize-use-trailing-return-type, + -modernize-concat-nested-namespaces, + -modernize-return-braced-init-list, + -modernize-make-unique, + *performance*, + -performance-unnecessary-value-param, + -performance-inefficient-string-concatenation, + readability-const-return-type, + readability-container-size-empty, + readability-delete-null-pointer, + readability-else-after-return, + readability-implicit-bool-conversion, + readability-inconsistent-declaration-parameter-name, + readability-make-member-function-const, + readability-misplaced-array-index, + readability-non-const-parameter, + readability-qualified-auto, + readability-redundant-function-ptr-dereference, + readability-redundant-smartptr-get, + readability-redundant-string-cstr, + readability-simplify-subscript-expr, + readability-static-accessed-through-instance, + readability-static-definition-in-anonymous-namespace, + readability-string-compare, + readability-suspicious-call-argument, + readability-uniqueptr-delete-release, + +CheckOptions: + - key: google-readability-braces-around-statements.ShortStatementLines + value: "3" + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: true + - key: performance-inefficient-string-concatenation.StrictMode + value: true + - key: performance-unnecessary-value-param.AllowedTypes + value: "exception_ptr$;" + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: true + - key: modernize-use-nodiscard.ReplacementString + value: "CLI11_NODISCARD" + +HeaderFilterRegex: "CLI.*hpp" + +FormatStyle: file +# WarningsAsErrors: "*" diff --git a/libs/CLI11/.cmake-format.yaml b/libs/CLI11/.cmake-format.yaml new file mode 100644 index 0000000..543ddf1 --- /dev/null +++ b/libs/CLI11/.cmake-format.yaml @@ -0,0 +1,6 @@ +format: + line_width: 99 + +# Causes a few issues - can be solved later, possibly. +markup: + enable_markup: false diff --git a/libs/CLI11/.codecov.yml b/libs/CLI11/.codecov.yml new file mode 100644 index 0000000..185bbad --- /dev/null +++ b/libs/CLI11/.codecov.yml @@ -0,0 +1,3 @@ +ignore: + - "tests" + - "examples" diff --git a/libs/CLI11/.editorconfig b/libs/CLI11/.editorconfig new file mode 100644 index 0000000..3c6f665 --- /dev/null +++ b/libs/CLI11/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = space +insert_final_newline = true +end_of_line = lf +trim_trailing_whitespace = true + +[*.cpp,*.hpp,*.py] +indent_size = 4 + +[*.yml] +indent_size = 2 diff --git a/libs/CLI11/.github/CONTRIBUTING.md b/libs/CLI11/.github/CONTRIBUTING.md new file mode 100644 index 0000000..7d37634 --- /dev/null +++ b/libs/CLI11/.github/CONTRIBUTING.md @@ -0,0 +1,103 @@ +# Contributing + +Thanks for considering to write a Pull Request (PR) for CLI11! Here are a few +guidelines to get you started: + +Make sure you are comfortable with the license; all contributions are licensed +under the original license. + +## Adding functionality + +Make sure any new functions you add are are: + +- Documented by `///` documentation for Doxygen +- Mentioned in the instructions in the README, though brief mentions are okay +- Explained in your PR (or previously explained in an Issue mentioned in the PR) +- Completely covered by tests + +In general, make sure the addition is well thought out and does not increase the +complexity of CLI11 needlessly. + +## Things you should know + +- Once you make the PR, tests will run to make sure your code works on all + supported platforms +- The test coverage is also measured, and that should remain 100% +- Formatting should be done with pre-commit, otherwise the format check will not + pass. However, it is trivial to apply this to your PR, so don't worry about + this check. If you do want to run it, see below. +- Everything must pass clang-tidy as well, run with + `-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy)"` (if you set + `"$(which clang-tidy) -fix"`, make sure you use a single threaded build + process, or just build one example target). +- Your changes must also conform to most of the + [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) + rules checked by [cpplint](https://github.com/cpplint/cpplint). For unused + cpplint filters and justifications, see [CPPLINT.cfg](/CPPLINT.cfg). + +## Pre-commit + +Format is handled by pre-commit. You should install it (or use +[pipx](https://pypa.github.io/pipx/)): + +```bash +python3 -m pip install pre-commit +``` + +Then, you can run it on the items you've added to your staging area, or all +files: + +```bash +pre-commit run +# OR +pre-commit run --all-files +``` + +And, if you want to always use it, you can install it as a git hook (hence the +name, pre-commit): + +```bash +pre-commit install +``` + +## For developers releasing to Conan.io + +This is now done by the CI system on tagged releases. Previously, the steps to +make a Conan.io release were: + +```bash +conan remove '*' # optional, I like to be clean +conan create . cliutils/stable +conan upload "*" -r cli11 --all +``` + +Here I've assumed that the remote is `cli11`. + +## For maintainers: remember to add contributions + +In a commit to a PR, just add +"`@all-contributors please add for `" or similar (see +). Use `code` for code, `bug` if an issue was +submitted, `platform` for packaging stuff, and `doc` for documentation updates. + +To run locally, do: + +```bash +yarn add --dev all-contributors-cli +yarn all-contributors add username code,bug +``` + +## For maintainers: Making a release + +Remember to replace the emoji in the readme, being careful not to replace the +ones in all-contributors if any overlap. + +Steps: + +- Update changelog if needed +- Update the version in `.appveyor.yml` and `include/CLI/Version.hpp`. +- Find and replace in README (new minor/major release only): + - Replace " 🆕" and "🆕 " with "" (ignores the description line) + - Check for `\/\/$` (vi syntax) to catch leftover `// 🆕` + - Replace "🚧" with "🆕" (manually ignore the description line) +- Make a release in the GitHub UI, use a name such as "Version X.Y(.Z): Title" diff --git a/libs/CLI11/.github/actions/quick_cmake/action.yml b/libs/CLI11/.github/actions/quick_cmake/action.yml new file mode 100644 index 0000000..811f73f --- /dev/null +++ b/libs/CLI11/.github/actions/quick_cmake/action.yml @@ -0,0 +1,25 @@ +name: Quick CMake config +description: "Runs CMake 3.4+ (if already setup)" +inputs: + args: + description: "Other arguments" + required: false + default: "" + cmake-version: + description: "The CMake version to run" + required: true + +runs: + using: composite + steps: + - name: CMake ${{ inputs.cmake-version }} + uses: jwlawson/actions-setup-cmake@v1.12 + with: + cmake-version: "${{ inputs.cmake-version }}" + - run: | + mkdir -p build-tmp + touch build-tmp/tmp + rm -r build-tmp/* + (cd build-tmp && cmake .. ${{ inputs.args }}) + rm -r build-tmp + shell: bash diff --git a/libs/CLI11/.github/codecov.yml b/libs/CLI11/.github/codecov.yml new file mode 100644 index 0000000..a0b0667 --- /dev/null +++ b/libs/CLI11/.github/codecov.yml @@ -0,0 +1,7 @@ +codecov: + notify: + after_n_builds: 4 +coverage: + status: + project: + informational: true diff --git a/libs/CLI11/.github/dependabot.yml b/libs/CLI11/.github/dependabot.yml new file mode 100644 index 0000000..2c7d170 --- /dev/null +++ b/libs/CLI11/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/libs/CLI11/.github/labeler_merged.yml b/libs/CLI11/.github/labeler_merged.yml new file mode 100644 index 0000000..96e1ca7 --- /dev/null +++ b/libs/CLI11/.github/labeler_merged.yml @@ -0,0 +1,4 @@ +needs changelog: + - all: ["!CHANGELOG.md"] +needs README: + - all: ["!README.md"] diff --git a/libs/CLI11/.github/workflows/build.yml b/libs/CLI11/.github/workflows/build.yml new file mode 100644 index 0000000..625502c --- /dev/null +++ b/libs/CLI11/.github/workflows/build.yml @@ -0,0 +1,59 @@ +name: Build +on: + push: + branches: + - main + - v* + tags: + - "*" + pull_request: + +jobs: + single-header: + name: Single header + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: Prepare CMake config + run: cmake -S . -B build -DCLI11_SINGLE_FILE=ON + + - name: Make package + run: cmake --build build --target package_source + + - name: Copy source packages + run: | + mkdir -p CLI11-Source + cp build/CLI11-*-Source.* CLI11-Source + cp build/CLI11-*-Source.* . + + - name: Make header + run: cmake --build build --target CLI11-generate-single-file + + - name: Copy file to main folder + run: cp build/include/CLI11.hpp CLI11.hpp + + - uses: actions/upload-artifact@v3 + with: + name: CLI11.hpp + path: CLI11.hpp + + - uses: actions/upload-artifact@v3 + with: + name: CLI11-Source + path: CLI11-Source + + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: | + CLI11.hpp + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/libs/CLI11/.github/workflows/pr_merged.yml b/libs/CLI11/.github/workflows/pr_merged.yml new file mode 100644 index 0000000..56f6f74 --- /dev/null +++ b/libs/CLI11/.github/workflows/pr_merged.yml @@ -0,0 +1,15 @@ +name: PR merged +on: + pull_request_target: + types: [closed] + +jobs: + label-merged: + name: Changelog needed + runs-on: ubuntu-latest + if: github.event.pull_request.merged == true + steps: + - uses: actions/labeler@main + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/labeler_merged.yml diff --git a/libs/CLI11/.github/workflows/tests.yml b/libs/CLI11/.github/workflows/tests.yml new file mode 100644 index 0000000..febc813 --- /dev/null +++ b/libs/CLI11/.github/workflows/tests.yml @@ -0,0 +1,250 @@ +name: Tests +on: + push: + branches: + - main + - v* + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + coverage: + name: Coverage + runs-on: ubuntu-latest + strategy: + matrix: + std: ["11", "14", "17", "20"] + precompile: ["ON", "OFF"] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Get LCov + run: | + wget https://github.com/linux-test-project/lcov/releases/download/v1.16/lcov-1.16.tar.gz + tar -xzf lcov-1.16.tar.gz + cd lcov-1.16 + sudo make install + + - name: Configure + run: | + cmake -S . -B build \ + -DCMAKE_CXX_STANDARD=${{matrix.std}} \ + -DCLI11_SINGLE_FILE_TESTS=OFF \ + -DCLI11_EXAMPLES=OFF \ + -DCLI11_PRECOMPILED=${{matrix.precompile}} \ + -DCMAKE_BUILD_TYPE=Coverage + + - name: Build + run: cmake --build build -j4 + + - name: Test + run: cmake --build build --target CLI11_coverage + + - name: Prepare coverage + run: | + lcov --directory . --capture --output-file coverage.info + lcov --remove coverage.info '*/tests/*' '*/examples/*' '/usr/*' --output-file coverage.info + lcov --list coverage.info + working-directory: build + + - uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: true + working-directory: build + + clang-tidy: + name: Clang-Tidy + runs-on: ubuntu-latest + container: silkeh/clang:14 + steps: + - uses: actions/checkout@v3 + + - name: Configure + run: > + cmake -S . -B build -DCMAKE_CXX_STANDARD=17 + -DCMAKE_CXX_CLANG_TIDY="$(which + clang-tidy);--use-color;--warnings-as-errors=*" + + - name: Build + run: cmake --build build -j4 -- --keep-going + + cuda-build: + name: CUDA build only + runs-on: ubuntu-latest + container: nvidia/cuda:10.2-devel-ubuntu18.04 + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - name: Add wget + run: apt-get update && apt-get install -y wget + - name: Get cmake + uses: jwlawson/actions-setup-cmake@v1.13 + - name: Configure + run: cmake -S . -B build -DCLI11_CUDA_TESTS=ON + - name: Build + run: cmake --build build -j2 + + boost-build: + name: Boost build + runs-on: ubuntu-latest + container: zouzias/boost:1.76.0 + steps: + - uses: actions/checkout@v1 + with: + submodules: true + - name: Add deps + run: apt-get update && apt-get install make + - name: Get CMake + uses: jwlawson/actions-setup-cmake@v1.13 + - name: Configure + run: cmake -S . -B build -DCLI11_BOOST=ON + - name: Build + run: cmake --build build -j2 + - name: Run tests + run: ctest --output-on-failure + working-directory: build + + meson-build: + name: Meson build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Prepare commands + run: | + pipx install meson + pipx install ninja + + - name: Configure + run: meson setup build-meson . -Dtests=true + + - name: Build + run: meson compile -C build-meson + + cmake-config: + name: CMake config check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Check CMake 3.4 + with: + cmake-version: "3.4" + uses: ./.github/actions/quick_cmake + + - name: Check CMake 3.5 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.5" + if: success() || failure() + + - name: Check CMake 3.6 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.6" + if: success() || failure() + + - name: Check CMake 3.7 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.7" + if: success() || failure() + + - name: Check CMake 3.8 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.8" + if: success() || failure() + + - name: Check CMake 3.9 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.9" + if: success() || failure() + + - name: Check CMake 3.10 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.10" + if: success() || failure() + + - name: Check CMake 3.11 (full) + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.11" + args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON + if: success() || failure() + + - name: Check CMake 3.12 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.12" + if: success() || failure() + + - name: Check CMake 3.13 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.13" + if: success() || failure() + + - name: Check CMake 3.14 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.14" + if: success() || failure() + + - name: Check CMake 3.15 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.15" + if: success() || failure() + + - name: Check CMake 3.16 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.16" + if: success() || failure() + + - name: Check CMake 3.17 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.17" + if: success() || failure() + + - name: Check CMake 3.18 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.18" + if: success() || failure() + + - name: Check CMake 3.19 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.19" + if: success() || failure() + + - name: Check CMake 3.20 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.20" + if: success() || failure() + + - name: Check CMake 3.21 (full) + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.21" + args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON + if: success() || failure() + + - name: Check CMake 3.22 (full) + uses: ./.github/actions/quick_cmake + with: + cmake-version: "3.22" + args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON + if: success() || failure() diff --git a/libs/CLI11/.gitignore b/libs/CLI11/.gitignore new file mode 100644 index 0000000..cc1b9d0 --- /dev/null +++ b/libs/CLI11/.gitignore @@ -0,0 +1,15 @@ +a.out* +*.swp +/*build* +/test_package/build +/Makefile +/CMakeFiles/* +/cmake_install.cmake +/*.kdev4 +/html/* +!/meson.build + +/node_modules/* +/package.json +/yarn.lock +/CLI11.hpp diff --git a/libs/CLI11/.pre-commit-config.yaml b/libs/CLI11/.pre-commit-config.yaml new file mode 100644 index 0000000..14d633d --- /dev/null +++ b/libs/CLI11/.pre-commit-config.yaml @@ -0,0 +1,88 @@ +ci: + autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" + autofix_commit_msg: "style: pre-commit.ci fixes" + +repos: + - repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + - id: end-of-file-fixer + - id: mixed-line-ending + - id: trailing-whitespace + + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v15.0.4 + hooks: + - id: clang-format + types_or: [c++, c, cuda] + + - repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.13 + hooks: + - id: cmake-format + additional_dependencies: [pyyaml] + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.0.0-alpha.4" + hooks: + - id: prettier + types_or: [yaml, markdown, html, css, scss, javascript, json] + args: [--prose-wrap=always] + + - repo: https://github.com/markdownlint/markdownlint + rev: v0.12.0 + hooks: + - id: markdownlint + args: ["--style=scripts/mdlint_style.rb"] + # Uncomment on macOS - Apple has deprecated Ruby, so macOS is stuck on 2.6 + # language_version: 3.1.2 + + # - repo: local + # hooks: + # - id: remarklint + # name: remarklint + # language: node + # entry: remark + # types: [markdown] + # args: ["--frail", "--quiet"] + # additional_dependencies: + # [ + # remark, + # remark-lint, + # remark-cli, + # remark-preset-lint-recommended, + # remark-lint-list-item-indent, + # remark-lint-no-undefined-references, + # ] + + - repo: local + hooks: + - id: disallow-caps + name: Disallow improper capitalization + language: pygrep + entry: PyBind|Numpy|Cmake|CCache|PyTest|Github + exclude: .pre-commit-config.yaml + + - repo: local + hooks: + - id: avoid-msvc-macro + name: Avoid MSVC <=2017 min/max macro (use extra parens) + language: pygrep + entry: \b(min|max)\( + exclude: .pre-commit-config.yaml + + - repo: https://github.com/codespell-project/codespell + rev: v2.2.2 + hooks: + - id: codespell + args: ["-L", "atleast,ans,doub,inout"] diff --git a/libs/CLI11/.remarkrc b/libs/CLI11/.remarkrc new file mode 100644 index 0000000..73cad83 --- /dev/null +++ b/libs/CLI11/.remarkrc @@ -0,0 +1,7 @@ +{ + "plugins": [ + "remark-preset-lint-recommended", + ["remark-lint-list-item-indent", "space"], + ["remark-lint-no-undefined-references", {"allow": ["^1"]}] + ] +} diff --git a/libs/CLI11/CHANGELOG.md b/libs/CLI11/CHANGELOG.md new file mode 100644 index 0000000..e20369f --- /dev/null +++ b/libs/CLI11/CHANGELOG.md @@ -0,0 +1,1009 @@ +# Changelog + +## Version 2.3: Precompilation Support + +This version adds a pre-compiled mode to CLI11, which allows you to precompile +the library, saving time on incremental rebuilds, making CLI11 more competitive +on compile time with classic compiled CLI libraries. The header-only mode is +still default, and is not yet distributed via binaries. + +- Add `CLI11_PRECOMPILED` as an option. [#762][] +- Bugfix: Include `` in `FormatterFwd` [#727][] +- Bugfix: Add missing `Macros.hpp` to `Error.hpp` [#755][] +- Bugfix: Fix subcommand callback trigger [#733][] +- Bugfix: Variable rename to avoid warning [#734][] +- Bugfix: `split_program_name` single file name error [#740][] +- Bugfix: Better support for min/max overrides on MSVC [#741][] +- Bugfix: Support MSVC 2022 [#748][] +- Bugfix: Support negated flag in config file [#775][] +- Bugfix: Better errors for some confusing config file situations [#781][] +- Backend: Restore coverage testing (lost with Travis CI) [#747][] + +[#727]: https://github.com/CLIUtils/CLI11/pull/727 +[#733]: https://github.com/CLIUtils/CLI11/pull/733 +[#734]: https://github.com/CLIUtils/CLI11/pull/734 +[#740]: https://github.com/CLIUtils/CLI11/pull/740 +[#741]: https://github.com/CLIUtils/CLI11/pull/741 +[#747]: https://github.com/CLIUtils/CLI11/pull/747 +[#748]: https://github.com/CLIUtils/CLI11/pull/748 +[#755]: https://github.com/CLIUtils/CLI11/pull/755 +[#762]: https://github.com/CLIUtils/CLI11/pull/762 +[#775]: https://github.com/CLIUtils/CLI11/pull/775 +[#781]: https://github.com/CLIUtils/CLI11/pull/781 + +### Version 2.3.1: Missing implementation + +A function implementation was missing after the pre-compile move, missed due to +the fact we lost 100% after losing coverage checking. We are working on filling +out 100% coverage again to ensure this doesn't happen again! + +- Bugfix: `App::get_option_group` implementation missing [#793][] +- Bugfix: Fix spacing when setting an empty footer [#796][] +- Bugfix: Address Klocwork static analysis checking issues [#785][] + +[#785]: https://github.com/CLIUtils/CLI11/pull/785 +[#793]: https://github.com/CLIUtils/CLI11/pull/793 +[#796]: https://github.com/CLIUtils/CLI11/pull/796 + +## Version 2.2: Option and Configuration Flexibility + +New features include support for output of an empty vector, a summing option +policy that can be applied more broadly, and an option to validate optional +arguments to discriminate from positional arguments. A new validator to check +for files on a default path is included to allow one or more default paths for +configuration files or other file arguments. A number of bug fixes and code +cleanup for various build configurations. Clean up of some error outputs and +extension of existing capability to new types or situations. + +There is a possible minor breaking change in behavior of certain types which +wrapped an integer, such as `std::atomic` or `std::optional` when used +in a flag. The default behavior is now as a single argument value vs. summing +all the arguments. The default summing behavior is now restricted to pure +integral types, int64_t, int, uint32_t, etc. Use the new `sum` multi option +policy to revert to the older behavior. The summing behavior on wrapper types +was not originally intended. + +- Add `MultiOptionPolicy::Sum` and refactor the `add_flag` to fix a bug when + using `std::optional` as type. [#709][] +- Add support for an empty vector result in TOML and as a default string. + [#660][] +- Add `.validate_optional_arguments()` to support discriminating positional + arguments from vector option arguments. [#668][] +- Add `CLI::FileOnDefaultPath` to check for files on a specified default path. + [#698][] +- Change default value display in help messages from `=XXXX` to `[XXXXX]` to + make it clearer. [#666][] +- Modify the Range Validator to support additional types and clean up the error + output. [#690][] +- Bugfix: The trigger on parse modifier did not work on positional argument.s + [#713][] +- Bugfix: The single header file generation was missing custom namespace + generation. [#707][] +- Bugfix: Clean up File Error handling in the argument processing. [#678][] +- Bugfix: Fix a stack overflow error if nameless commands had fallthrough. + [#665][] +- Bugfix: A subcommand callback could be executed multiple times if it was a + member of an option group. [#666][] +- Bugfix: Fix an issue with vectors of multi argument types where partial + argument sets did not result in an error. [#661][] +- Bugfix: Fix an issue with type the template matching on C++20 and add some CI + builds for C++20. [#663][] +- Bugfix: Fix typo in C++20 detection on MSVC. [#706][] +- Bugfix: An issue where the detection of RTTI being disabled on certain MSVC + platforms did not disable the use of dynamic cast calls. [#666][] +- Bugfix: Resolve strict-overflow warning on some GCC compilers. [#666][] +- Backend: Add additional tests concerning the use of aliases for option groups + in config files. [#666][] +- Build: Add support for testing in meson and cleanup symbolic link generation. + [#701][], [#697][] +- Build: Support building in WebAssembly. [#679][] + +[#660]: https://github.com/CLIUtils/CLI11/pull/660 +[#661]: https://github.com/CLIUtils/CLI11/pull/661 +[#663]: https://github.com/CLIUtils/CLI11/pull/663 +[#665]: https://github.com/CLIUtils/CLI11/pull/665 +[#666]: https://github.com/CLIUtils/CLI11/pull/666 +[#668]: https://github.com/CLIUtils/CLI11/pull/668 +[#678]: https://github.com/CLIUtils/CLI11/pull/678 +[#679]: https://github.com/CLIUtils/CLI11/pull/679 +[#690]: https://github.com/CLIUtils/CLI11/pull/690 +[#697]: https://github.com/CLIUtils/CLI11/pull/697 +[#698]: https://github.com/CLIUtils/CLI11/pull/698 +[#701]: https://github.com/CLIUtils/CLI11/pull/701 +[#706]: https://github.com/CLIUtils/CLI11/pull/706 +[#707]: https://github.com/CLIUtils/CLI11/pull/707 +[#709]: https://github.com/CLIUtils/CLI11/pull/709 +[#713]: https://github.com/CLIUtils/CLI11/pull/713 + +## Version 2.1: Names and callbacks + +The name restrictions for options and subcommands are now much looser, allowing +a wider variety of characters than before, even spaces can be used (use quotes +to include a space in most shells). The default configuration parser was +improved, allowing your configuration to sit in a larger file. And option +callbacks have a few new settings, allowing them to be run even if the option is +not passed, or every time the option is parsed. + +- Option/subcommand name restrictions have been relaxed. Most characters are now + allowed. [#627][] +- The config parser can accept streams, specify a specific section, and inline + comment characters are supported [#630][] +- `force_callback` & `trigger_on_parse` added, allowing a callback to always run + on parse even if not present or every time the option is parsed [#631][] +- Bugfix(cmake): Only add `CONFIGURE_DEPENDS` if CLI11 is the main project + [#633][] +- Bugfix(cmake): Ensure the cmake/pkg-config files install to a arch independent + path [#635][] +- Bugfix: The single header file generation was missing the include guard. + [#620][] + +[#620]: https://github.com/CLIUtils/CLI11/pull/620 +[#627]: https://github.com/CLIUtils/CLI11/pull/627 +[#630]: https://github.com/CLIUtils/CLI11/pull/630 +[#631]: https://github.com/CLIUtils/CLI11/pull/631 +[#633]: https://github.com/CLIUtils/CLI11/pull/633 +[#635]: https://github.com/CLIUtils/CLI11/pull/635 + +### Version 2.1.1: Quick Windows fix + +- A collision with `min`/`max` macros on Windows has been fixed. [#642][] +- Tests pass with Boost again [#646][] +- Running the pre-commit hooks in development no longer requires docker for + clang-format [#647][] + +[#642]: https://github.com/CLIUtils/CLI11/pull/642 +[#646]: https://github.com/CLIUtils/CLI11/pull/646 +[#647]: https://github.com/CLIUtils/CLI11/pull/647 + +## Version 2.1.2: Better subproject builds + +- Use `main` for the main branch of the repository [#657][] +- Bugfix(cmake): Enforce at least C++11 when using CMake target [#656][] +- Build: Don't run doxygen and CTest includes if a submodule [#656][] +- Build: Avoid a warning on CMake 3.22 [#656][] +- Build: Support compiling the tests with an external copy of Catch2 [#653][] + +[#653]: https://github.com/CLIUtils/CLI11/pull/653 +[#656]: https://github.com/CLIUtils/CLI11/pull/656 +[#657]: https://github.com/CLIUtils/CLI11/pull/657 + +## Version 2.0: Simplification + +This version focuses on cleaning up deprecated functionality, and some minor +default changes. The config processing is TOML compliant now. Atomics and +complex numbers are directly supported, along with other container improvements. +A new version flag option has finally been added. Subcommands are significantly +improved with new features and bugfixes for corner cases. This release contains +a lot of backend cleanup, including a complete overhaul of the testing system +and single file generation system. + +- Built-in config format is TOML compliant now [#435][] + - Support multiline TOML [#528][] + - Support for configurable quotes [#599][] + - Support short/positional options in config mode [#443][] +- More powerful containers, support for `%%` separator [#423][] +- Support atomic types [#520][] and complex types natively [#423][] +- Add a type validator `CLI::TypeValidator` [#526][] +- Add a version flag easily [#452][], with help message [#601][] +- Support `->silent()` on subcommands. [#529][] +- Add alias section to help for subcommands [#545][] +- Allow quotes to specify a program name [#605][] +- Backend: redesigned MakeSingleFiles to have a higher level of manual control, + to support future features. [#546][] +- Backend: moved testing from GTest to Catch2 [#574][] +- Bugfix: avoid duplicated and missed calls to the final callback [#584][] +- Bugfix: support embedded newlines in more places [#592][] +- Bugfix: avoid listing helpall as a required flag [#530][] +- Bugfix: avoid a clash with WINDOWS define [#563][] +- Bugfix: the help flag didn't get processed when a config file was required + [#606][] +- Bugfix: fix description of non-configurable subcommands in config [#604][] +- Build: support pkg-config [#523][] + +> ### Converting from CLI11 1.9 +> +> - Removed deprecated set commands, use validators instead. [#565][] +> - The final "defaulted" bool has been removed, use `->capture_default_str()` +> instead. Use `app.option_defaults()->always_capture_default()` to set this +> for all future options. [#597][] +> - Use `add_option` on a complex number instead of `add_complex`, which has +> been removed. + +[#423]: https://github.com/CLIUtils/CLI11/pull/423 +[#435]: https://github.com/CLIUtils/CLI11/pull/435 +[#443]: https://github.com/CLIUtils/CLI11/pull/443 +[#452]: https://github.com/CLIUtils/CLI11/pull/452 +[#520]: https://github.com/CLIUtils/CLI11/pull/520 +[#523]: https://github.com/CLIUtils/CLI11/pull/523 +[#526]: https://github.com/CLIUtils/CLI11/pull/526 +[#528]: https://github.com/CLIUtils/CLI11/pull/528 +[#529]: https://github.com/CLIUtils/CLI11/pull/529 +[#530]: https://github.com/CLIUtils/CLI11/pull/530 +[#545]: https://github.com/CLIUtils/CLI11/pull/545 +[#546]: https://github.com/CLIUtils/CLI11/pull/546 +[#563]: https://github.com/CLIUtils/CLI11/pull/563 +[#565]: https://github.com/CLIUtils/CLI11/pull/565 +[#574]: https://github.com/CLIUtils/CLI11/pull/574 +[#584]: https://github.com/CLIUtils/CLI11/pull/584 +[#592]: https://github.com/CLIUtils/CLI11/pull/592 +[#597]: https://github.com/CLIUtils/CLI11/pull/597 +[#599]: https://github.com/CLIUtils/CLI11/pull/599 +[#601]: https://github.com/CLIUtils/CLI11/pull/601 +[#604]: https://github.com/CLIUtils/CLI11/pull/604 +[#605]: https://github.com/CLIUtils/CLI11/pull/605 +[#606]: https://github.com/CLIUtils/CLI11/pull/606 + +## Version 1.9: Config files and cleanup + +Config file handling was revamped to fix common issues, and now supports reading +[TOML](https://github.com/toml-lang/toml). + +Adding options is significantly more powerful with support for things like +`std::tuple` and `std::array`, including with transforms. Several new +configuration options were added to facilitate a wider variety of apps. GCC 4.7 +is no longer supported. + +- Config files refactored, supports TOML (may become default output in 2.0) + [#362][] +- Added two template parameter form of `add_option`, allowing `std::optional` to + be supported without a special import [#285][] +- `string_view` now supported in reasonable places [#300][], [#285][] +- `immediate_callback`, `final_callback`, and `parse_complete_callback` added to + support controlling the App callback order [#292][], [#313][] +- Multiple positional arguments maintain order if `positionals_at_end` is set. + [#306][] +- Pair/tuple/array now supported, and validators indexed to specific components + in the objects [#307][], [#310][] +- Footer callbacks supported [#309][] +- Subcommands now support needs (including nameless subcommands) [#317][] +- More flexible type size, more useful `add_complex` [#325][], [#370][] +- Added new validators `CLI::NonNegativeNumber` and `CLI::PositiveNumber` + [#342][] +- Transform now supports arrays [#349][] +- Option groups can be hidden [#356][] +- Add `CLI::deprecate_option` and `CLI::retire_option` functions [#358][] +- More flexible and safer Option `default_val` [#387][] +- Backend: Cleaner type traits [#286][] +- Backend: File checking updates [#341][] +- Backend: Using pre-commit to format, checked in GitHub Actions [#336][] +- Backend: Clang-tidy checked again, CMake option now `CL11_CLANG_TIDY` [#390][] +- Backend: Warning cleanup, more checks from klocwork [#350][], Effective C++ + [#354][], clang-tidy [#360][], CUDA NVCC [#365][], cross compile [#373][], + sign conversion [#382][], and cpplint [#400][] +- Docs: CLI11 Tutorial now hosted in the same repository [#304][], [#318][], + [#374][] +- Bugfix: Fixed undefined behavior in `checked_multiply` [#290][] +- Bugfix: `->check()` was adding the name to the wrong validator [#320][] +- Bugfix: Resetting config option works properly [#301][] +- Bugfix: Hidden flags were showing up in error printout [#333][] +- Bugfix: Enum conversion no longer broken if stream operator added [#348][] +- Build: The meson build system supported [#299][] +- Build: GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is + now required. [#160][] +- Build: Restructured significant portions of CMake build system [#394][] + +> ### Converting from CLI11 1.8 +> +> - Some deprecated methods dropped +> - `add_set*` should be replaced with `->check`/`->transform` and +> `CLI::IsMember` since 1.8 +> - `get_defaultval` was replaced by `get_default_str` in 1.8 +> - The true/false 4th argument to `add_option` is expected to be removed in +> 2.0, use `->capture_default_str()` since 1.8 + +[#160]: https://github.com/CLIUtils/CLI11/pull/160 +[#285]: https://github.com/CLIUtils/CLI11/pull/285 +[#286]: https://github.com/CLIUtils/CLI11/pull/286 +[#290]: https://github.com/CLIUtils/CLI11/pull/290 +[#292]: https://github.com/CLIUtils/CLI11/pull/292 +[#299]: https://github.com/CLIUtils/CLI11/pull/299 +[#300]: https://github.com/CLIUtils/CLI11/pull/300 +[#301]: https://github.com/CLIUtils/CLI11/pull/301 +[#304]: https://github.com/CLIUtils/CLI11/pull/304 +[#306]: https://github.com/CLIUtils/CLI11/pull/306 +[#307]: https://github.com/CLIUtils/CLI11/pull/307 +[#309]: https://github.com/CLIUtils/CLI11/pull/309 +[#310]: https://github.com/CLIUtils/CLI11/pull/310 +[#313]: https://github.com/CLIUtils/CLI11/pull/313 +[#317]: https://github.com/CLIUtils/CLI11/pull/317 +[#318]: https://github.com/CLIUtils/CLI11/pull/318 +[#320]: https://github.com/CLIUtils/CLI11/pull/320 +[#325]: https://github.com/CLIUtils/CLI11/pull/325 +[#333]: https://github.com/CLIUtils/CLI11/pull/333 +[#336]: https://github.com/CLIUtils/CLI11/pull/336 +[#341]: https://github.com/CLIUtils/CLI11/pull/341 +[#342]: https://github.com/CLIUtils/CLI11/pull/342 +[#348]: https://github.com/CLIUtils/CLI11/pull/348 +[#349]: https://github.com/CLIUtils/CLI11/pull/349 +[#350]: https://github.com/CLIUtils/CLI11/pull/350 +[#354]: https://github.com/CLIUtils/CLI11/pull/354 +[#356]: https://github.com/CLIUtils/CLI11/pull/356 +[#358]: https://github.com/CLIUtils/CLI11/pull/358 +[#360]: https://github.com/CLIUtils/CLI11/pull/360 +[#362]: https://github.com/CLIUtils/CLI11/pull/362 +[#365]: https://github.com/CLIUtils/CLI11/pull/365 +[#370]: https://github.com/CLIUtils/CLI11/pull/370 +[#373]: https://github.com/CLIUtils/CLI11/pull/373 +[#374]: https://github.com/CLIUtils/CLI11/pull/374 +[#382]: https://github.com/CLIUtils/CLI11/pull/382 +[#387]: https://github.com/CLIUtils/CLI11/pull/387 +[#390]: https://github.com/CLIUtils/CLI11/pull/390 +[#394]: https://github.com/CLIUtils/CLI11/pull/394 +[#400]: https://github.com/CLIUtils/CLI11/pull/400 + +### Version 1.9.1: Backporting fixes + +This is a patch version that backports fixes from the development of 2.0. + +- Support relative inclusion [#475][] +- Fix cases where spaces in paths could break CMake support [#471][] +- Fix an issue with string conversion [#421][] +- Cross-compiling improvement for Conan.io [#430][] +- Fix option group default propagation [#450][] +- Fix for C++20 [#459][] +- Support compiling with RTTI off [#461][] + +[#421]: https://github.com/CLIUtils/CLI11/pull/421 +[#430]: https://github.com/CLIUtils/CLI11/pull/430 +[#450]: https://github.com/CLIUtils/CLI11/pull/450 +[#459]: https://github.com/CLIUtils/CLI11/pull/459 +[#461]: https://github.com/CLIUtils/CLI11/pull/461 +[#471]: https://github.com/CLIUtils/CLI11/pull/471 +[#475]: https://github.com/CLIUtils/CLI11/pull/475 + +## Version 1.8: Transformers, default strings, and flags + +Set handling has been completely replaced by a new backend that works as a +Validator or Transformer. This provides a single interface instead of the 16 +different functions in App. It also allows ordered collections to be used, +custom functions for filtering, and better help and error messages. You can also +use a collection of pairs (like `std::map`) to transform the match into an +output. Also new are inverted flags, which can cancel or reduce the count of +flags, and can also support general flag types. A new `add_option_fn` lets you +more easily program CLI11 options with the types you choose. Vector options now +support a custom separator. Apps can now be composed with unnamed subcommand +support. The final bool "defaults" flag when creating options has been replaced +by `->capture_default_str()` (ending an old limitation in construction made this +possible); the old method is still available but may be removed in future +versions. + +- Replaced default help capture: `.add_option("name", value, "", True)` becomes + `.add_option("name", value)->capture_default_str()` [#242][] +- Added `.always_capture_default()` [#242][] +- New `CLI::IsMember` validator replaces set validation [#222][] +- `IsMember` also supports container of pairs, transform allows modification of + result [#228][] +- Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue` + [#253][] +- Much more powerful flags with different values [#211][], general types + [#235][] +- `add_option` now supports bool due to unified bool handling [#211][] +- Support for composable unnamed subcommands [#216][] +- Reparsing is better supported with `.remaining_for_passthrough()` [#265][] +- Custom vector separator using `->delimiter(char)` [#209][], [#221][], [#240][] +- Validators added for IP4 addresses and positive numbers [#210][] and numbers + [#262][] +- Minimum required Boost for optional Optionals has been corrected to 1.61 + [#226][] +- Positionals can stop options from being parsed with `app.positionals_at_end()` + [#223][] +- Added `validate_positionals` [#262][] +- Positional parsing is much more powerful [#251][], duplicates supported + [#247][] +- Validators can be negated with `!` [#230][], and now handle tname functions + [#228][] +- Better enum support and streaming helper [#233][] and [#228][] +- Cleanup for shadow warnings [#232][] +- Better alignment on multiline descriptions [#269][] +- Better support for aarch64 [#266][] +- Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise, + `CLI11_TESTING` must be used [#277][] +- Drop auto-detection of experimental optional and boost::optional; must be + enabled explicitly (too fragile) [#277][] [#279][] + +> ### Converting from CLI11 1.7 +> +> - `.add_option(..., true)` should be replaced by +> `.add_option(...)->capture_default_str()` or +> `app.option_defaults()->always_capture_default()` can be used +> - `app.add_set("--name", value, {"choice1", "choice2"})` should become +> `app.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))` +> - The `_ignore_case` version of this can be replaced by adding +> `CLI::ignore_case` to the argument list in `IsMember` +> - The `_ignore_underscore` version of this can be replaced by adding +> `CLI::ignore_underscore` to the argument list in `IsMember` +> - The `_ignore_case_underscore` version of this can be replaced by adding both +> functions listed above to the argument list in `IsMember` +> - If you want an exact match to the original choice after one of the modifier +> functions matches, use `->transform` instead of `->check` +> - The `_mutable` versions of this can be replaced by passing a pointer or +> shared pointer into `IsMember` +> - An error with sets now produces a `ValidationError` instead of a +> `ConversionError` + +[#209]: https://github.com/CLIUtils/CLI11/pull/209 +[#210]: https://github.com/CLIUtils/CLI11/pull/210 +[#211]: https://github.com/CLIUtils/CLI11/pull/211 +[#216]: https://github.com/CLIUtils/CLI11/pull/216 +[#221]: https://github.com/CLIUtils/CLI11/pull/221 +[#222]: https://github.com/CLIUtils/CLI11/pull/222 +[#223]: https://github.com/CLIUtils/CLI11/pull/223 +[#226]: https://github.com/CLIUtils/CLI11/pull/226 +[#228]: https://github.com/CLIUtils/CLI11/pull/228 +[#230]: https://github.com/CLIUtils/CLI11/pull/230 +[#232]: https://github.com/CLIUtils/CLI11/pull/232 +[#233]: https://github.com/CLIUtils/CLI11/pull/233 +[#235]: https://github.com/CLIUtils/CLI11/pull/235 +[#240]: https://github.com/CLIUtils/CLI11/pull/240 +[#242]: https://github.com/CLIUtils/CLI11/pull/242 +[#247]: https://github.com/CLIUtils/CLI11/pull/247 +[#251]: https://github.com/CLIUtils/CLI11/pull/251 +[#253]: https://github.com/CLIUtils/CLI11/pull/253 +[#262]: https://github.com/CLIUtils/CLI11/pull/262 +[#265]: https://github.com/CLIUtils/CLI11/pull/265 +[#266]: https://github.com/CLIUtils/CLI11/pull/266 +[#269]: https://github.com/CLIUtils/CLI11/pull/269 +[#277]: https://github.com/CLIUtils/CLI11/pull/277 +[#279]: https://github.com/CLIUtils/CLI11/pull/279 + +## Version 1.7: Parse breakup + +The parsing procedure now maps much more sensibly to complex, nested subcommand +structures. Each phase of the parsing happens on all subcommands before moving +on with the next phase of the parse. This allows several features, like required +environment variables, to work properly even through subcommand boundaries. +Passing the same subcommand multiple times is better supported. Several new +features were added as well, including Windows style option support, parsing +strings directly, and ignoring underscores in names. Adding a set that you plan +to change later must now be done with `add_mutable_set`. + +- Support Windows style options with `->allow_windows_style_options`. [#187][] + On by default on Windows. [#190][] +- Added `parse(string)` to split up and parse a command-line style string + directly. [#186][] +- Added `ignore_underscore` and related functions, to ignore underscores when + matching names. [#185][] +- The default INI Config will now add quotes to strings with spaces [#195][] +- The default message now will mention the help-all flag also if present + [#197][] +- Added `->description` to set Option descriptions [#199][] +- Mutating sets (introduced in Version 1.6) now have a clear add method, + `add_mutable_set*`, since the set reference should not expire [#200][] +- Subcommands now track how many times they were parsed in a parsing process. + `count()` with no arguments will return the number of times a subcommand was + encountered. [#178][] +- Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and + `requirements`; all subcommands complete a phase before moving on. [#178][] +- Calling parse multiple times is now officially supported without `clear` + (automatic). [#178][] +- Dropped the mostly undocumented `short_circuit` property, as help flag parsing + is a bit more complex, and the default callback behavior of options now works + properly. [#179][] +- Use the standard `BUILD_TESTING` over `CLI11_TESTING` if defined [#183][] +- Cleanup warnings [#191][] +- Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and + `set_type_name`. Use without the `set_` instead. [#192][] + +> ### Converting from CLI11 1.6 +> +> - `->short_circuit()` is no longer needed, just remove it if you were using +> it - raising an exception will happen in the proper place now without it. +> - `->add_set*` becomes `->add_mutable_set*` if you were using the editable set +> feature +> - `footer`, `name`, `callback`, and `type_name` must be used instead of the +> `set_*` versions (deprecated previously). + +[#178]: https://github.com/CLIUtils/CLI11/pull/178 +[#183]: https://github.com/CLIUtils/CLI11/pull/183 +[#185]: https://github.com/CLIUtils/CLI11/pull/185 +[#186]: https://github.com/CLIUtils/CLI11/pull/186 +[#187]: https://github.com/CLIUtils/CLI11/pull/187 +[#190]: https://github.com/CLIUtils/CLI11/pull/190 +[#191]: https://github.com/CLIUtils/CLI11/pull/191 +[#192]: https://github.com/CLIUtils/CLI11/pull/192 +[#197]: https://github.com/CLIUtils/CLI11/pull/197 +[#195]: https://github.com/CLIUtils/CLI11/issues/195 +[#199]: https://github.com/CLIUtils/CLI11/pull/199 +[#200]: https://github.com/CLIUtils/CLI11/pull/200 + +### Version 1.7.1: Quick patch + +This version provides a quick patch for a (correct) warning from GCC 8 for the +windows options code. + +- Fix for Windows style option parsing [#201][] +- Improve `add_subcommand` when throwing an exception [#204][] +- Better metadata for Conan package [#202][] + +[#201]: https://github.com/CLIUtils/CLI11/pull/201 +[#202]: https://github.com/CLIUtils/CLI11/pull/202 +[#204]: https://github.com/CLIUtils/CLI11/pull/204 + +## Version 1.6: Formatting help + +Added a new formatting system [#109][]. You can now set the formatter on Apps. +This has also simplified the internals of Apps and Options a bit by separating +most formatting code. + +- Added `CLI::Formatter` and `formatter` slot for apps, inherited. +- `FormatterBase` is the minimum required. +- `FormatterLambda` provides for the easy addition of an arbitrary function. +- Added `help_all` support (not added by default). + +Changes to the help system (most normal users will not notice this): + +- Renamed `single_name` to `get_name(false, false)` (the default). +- The old `get_name()` is now `get_name(false, true)`. +- The old `get_pname()` is now `get_name(true, false)`. +- Removed `help_*` functions. +- Protected function `_has_help_positional` removed. +- `format_help` can now be chained. +- Added getters for the missing parts of options (help no longer uses any + private parts). +- Help flags now use new `short_circuit` property to simplify parsing. [#121][] + +New for Config file reading and writing [#121][]: + +- Overridable, bidirectional Config. +- ConfigINI provided and used by default. +- Renamed ini to config in many places. +- Has `config_formatter()` and `get_config_formatter()`. +- Dropped prefix argument from `config_to_str`. +- Added `ConfigItem`. +- Added an example of a custom config format using [nlohmann/json][]. [#138][] + +Validators are now much more powerful [#118][], all built in validators upgraded +to the new form: + +- A subclass of `CLI::Validator` is now also accepted. +- They now can set the type name to things like `PATH` and `INT in [1-4]`. +- Validators can be combined with `&` and `|`. +- Old form simple validators are still accepted. + +Other changes: + +- Fixing `parse(args)`'s `args` setting and ordering after parse. [#141][] +- Replaced `set_custom_option` with `type_name` and `type_size` instead of + `set_custom_option`. Methods return `this`. [#136][] +- Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`. + [#136][] +- Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`. + [#136][] +- Fixed support `N<-1` for `type_size`. [#140][] +- Added `->each()` to make adding custom callbacks easier. [#126][] +- Allow empty options `add_option("-n",{})` to be edited later with `each` + [#142][] +- Added filter argument to `get_subcommands`, `get_options`; use empty filter + `{}` to avoid filtering. +- Added `get_groups()` to get groups. +- Better support for manual options with `get_option`, `set_results`, and + `empty`. [#119][] +- `lname` and `sname` have getters, added `const get_parent`. [#120][] +- Using `add_set` will now capture L-values for sets, allowing further + modification. [#113][] +- Dropped duplicate way to run `get_type_name` (`get_typeval`). +- Removed `requires` in favor of `needs` (deprecated in last version). [#112][] +- Const added to argv. [#126][] + +Backend and testing changes: + +- Internally, `type_name` is now a lambda function; for sets, this reads the set + live. [#116][] +- Cleaner tests without `app.reset()` (and `reset` is now `clear`). [#141][] +- Better CMake policy handling. [#110][] +- Includes are properly sorted. [#120][] +- Testing (only) now uses submodules. [#111][] + +[#109]: https://github.com/CLIUtils/CLI11/pull/109 +[#110]: https://github.com/CLIUtils/CLI11/pull/110 +[#111]: https://github.com/CLIUtils/CLI11/pull/111 +[#112]: https://github.com/CLIUtils/CLI11/pull/112 +[#113]: https://github.com/CLIUtils/CLI11/issues/113 +[#116]: https://github.com/CLIUtils/CLI11/pull/116 +[#118]: https://github.com/CLIUtils/CLI11/pull/118 +[#119]: https://github.com/CLIUtils/CLI11/pull/119 +[#120]: https://github.com/CLIUtils/CLI11/pull/120 +[#121]: https://github.com/CLIUtils/CLI11/pull/121 +[#126]: https://github.com/CLIUtils/CLI11/pull/126 +[#136]: https://github.com/CLIUtils/CLI11/pull/136 +[#138]: https://github.com/CLIUtils/CLI11/pull/138 +[#140]: https://github.com/CLIUtils/CLI11/pull/140 +[#141]: https://github.com/CLIUtils/CLI11/pull/141 +[#142]: https://github.com/CLIUtils/CLI11/pull/142 +[nlohmann/json]: https://github.com/nlohmann/json + +### Version 1.6.1: Platform fixes + +This version provides a few fixes for special cases, such as mixing with +`Windows.h` and better defaults for systems like Hunter. The one new feature is +the ability to produce "branded" single file output for providing custom +namespaces or custom macro names. + +- Added fix and test for including Windows.h [#145][] +- No longer build single file by default if main project, supports systems stuck + on Python 2.6 [#149][], [#151][] +- Branding support for single file output [#150][] + +[#145]: https://github.com/CLIUtils/CLI11/pull/145 +[#149]: https://github.com/CLIUtils/CLI11/pull/149 +[#150]: https://github.com/CLIUtils/CLI11/pull/150 +[#151]: https://github.com/CLIUtils/CLI11/pull/151 + +### Version 1.6.2: Help-all + +This version fixes some formatting bugs with help-all. It also adds fixes for +several warnings, including an experimental optional error on Clang 7. Several +smaller fixes. + +- Fixed help-all formatting [#163][] + - Printing help-all on nested command now fixed (App) + - Missing space after help-all restored (Default formatter) + - More detail printed on help all (Default formatter) + - Help-all subcommands get indented with inner blank lines removed (Default + formatter) + - `detail::find_and_replace` added to utilities +- Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156][] +- Fixed warning about local variable hiding class member with MSVC [#157][] +- Fixed compile error with default settings on Clang 7 and libc++ [#158][] +- Fixed special case of `--help` on subcommands (general fix planned for 1.7) + [#168][] +- Removing an option with links [#179][] + +[#156]: https://github.com/CLIUtils/CLI11/issues/156 +[#157]: https://github.com/CLIUtils/CLI11/issues/157 +[#158]: https://github.com/CLIUtils/CLI11/issues/158 +[#163]: https://github.com/CLIUtils/CLI11/pull/163 +[#168]: https://github.com/CLIUtils/CLI11/issues/168 +[#179]: https://github.com/CLIUtils/CLI11/pull/179 + +## Version 1.5: Optionals + +This version introduced support for optionals, along with clarification and +examples of custom conversion overloads. Enums now have been dropped from the +automatic conversion system, allowing explicit protection for out-of-range ints +(or a completely custom conversion). This version has some internal cleanup and +improved support for the newest compilers. Several bugs were fixed, as well. + +Note: This is the final release with `requires`, please switch to `needs`. + +- Fix unlimited short options eating two values before checking for positionals + when no space present [#90][] +- Symmetric exclude text when excluding options, exclude can be called multiple + times [#64][] +- Support for `std::optional`, `std::experimental::optional`, and + `boost::optional` added if `__has_include` is supported [#95][] +- All macros/CMake variables now start with `CLI11_` instead of just `CLI_` + [#95][] +- The internal stream was not being cleared before use in some cases. Fixed. + [#95][] +- Using an enum now requires explicit conversion overload [#97][] +- The separator `--` now is removed when it ends unlimited arguments [#100][] + +Other, non-user facing changes: + +- Added `Macros.hpp` with better C++ mode discovery [#95][] +- Deprecated macros added for all platforms +- C++17 is now tested on supported platforms [#95][] +- Informational printout now added to CTest [#95][] +- Better single file generation [#95][] +- Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next + version of GTest) +- Types now have a specific size, separate from the expected number - cleaner + and more powerful internally [#92][] +- Examples now run as part of testing [#99][] + +[#64]: https://github.com/CLIUtils/CLI11/issues/64 +[#90]: https://github.com/CLIUtils/CLI11/issues/90 +[#92]: https://github.com/CLIUtils/CLI11/issues/92 +[#95]: https://github.com/CLIUtils/CLI11/pull/95 +[#97]: https://github.com/CLIUtils/CLI11/pull/97 +[#99]: https://github.com/CLIUtils/CLI11/pull/99 +[#100]: https://github.com/CLIUtils/CLI11/pull/100 + +### Version 1.5.1: Access + +This patch release adds better access to the App programmatically, to assist +with writing custom converters to other formats. It also improves the help +output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way +unlimited options and positionals interact. + +- Make mixing unlimited positionals and options more intuitive [#102][] +- Add missing getters `get_options` and `get_description` to App [#105][] +- The app name now can be set, and will override the auto name if present + [#105][] +- Add `(REQUIRED)` for required options [#104][] +- Print simple name for Needs/Excludes [#104][] +- Use Needs instead of Requires in help print [#104][] +- Groups now are listed in the original definition order [#106][] + +[#102]: https://github.com/CLIUtils/CLI11/issues/102 +[#104]: https://github.com/CLIUtils/CLI11/pull/104 +[#105]: https://github.com/CLIUtils/CLI11/pull/105 +[#106]: https://github.com/CLIUtils/CLI11/pull/106 + +### Version 1.5.2: LICENSE in single header mode + +This is a quick patch release that makes LICENSE part of the single header file, +making it easier to include. Minor cleanup from codacy. No significant code +changes from 1.5.1. + +### Version 1.5.3: Compiler compatibility + +This version fixes older AppleClang compilers by removing the optimization for +casting. The minimum version of Boost Optional supported has been clarified to +be 1.58. CUDA 7.0 NVCC is now supported. + +### Version 1.5.4: Optionals + +This version fixes the optional search in the single file version; some macros +were not yet defined when it did the search. You can define the +`CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search. + +## Version 1.4: More feedback + +This version adds lots of smaller fixes and additions after the refactor in +version 1.3. More ways to download and use CLI11 in CMake have been added. INI +files have improved support. + +- Lexical cast is now more strict than before [#68][] and fails on overflow + [#84][] +- Added `get_parent()` to access the parent from a subcommand +- Added `ExistingPath` validator [#73][] +- `app.allow_ini_extras()` added to allow extras in INI files [#70][] +- Multiline INI comments now supported +- Descriptions can now be written with `config_to_str` [#66][] +- Double printing of error message fixed [#77][] +- Renamed `requires` to `needs` to avoid C++20 keyword [#75][], [#82][] +- MakeSingleHeader now works if outside of git [#78][] +- Adding install support for CMake [#79][], improved support for `find_package` + [#83][], [#84][] +- Added support for Conan.io [#83][] + +[#70]: https://github.com/CLIUtils/CLI11/issues/70 +[#75]: https://github.com/CLIUtils/CLI11/issues/75 +[#84]: https://github.com/CLIUtils/CLI11/pull/84 +[#83]: https://github.com/CLIUtils/CLI11/pull/83 +[#82]: https://github.com/CLIUtils/CLI11/pull/82 +[#79]: https://github.com/CLIUtils/CLI11/pull/79 +[#78]: https://github.com/CLIUtils/CLI11/pull/78 +[#77]: https://github.com/CLIUtils/CLI11/pull/77 +[#73]: https://github.com/CLIUtils/CLI11/pull/73 +[#68]: https://github.com/CLIUtils/CLI11/pull/68 +[#66]: https://github.com/CLIUtils/CLI11/pull/66 + +## Version 1.3: Refactor + +This version focused on refactoring several key systems to ensure correct +behavior in the interaction of different settings. Most caveats about features +only working on the main App have been addressed, and extra arguments have been +reworked. Inheritance of defaults makes configuring CLI11 much easier without +having to subclass. Policies add new ways to handle multiple arguments to match +your favorite CLI programs. Error messages and help messages are better and more +flexible. Several bugs and odd behaviors in the parser have been fixed. + +- Added a version macro, `CLI11_VERSION`, along with `*_MAJOR`, `*_MINOR`, and + `*_PATCH`, for programmatic access to the version. +- Reworked the way defaults are set and inherited; explicit control given to + user with `->option_defaults()` + [#48](https://github.com/CLIUtils/CLI11/pull/48) +- Hidden options now are based on an empty group name, instead of special + "hidden" keyword [#48](https://github.com/CLIUtils/CLI11/pull/48) +- `parse` no longer returns (so `CLI11_PARSE` is always usable) + [#37](https://github.com/CLIUtils/CLI11/pull/37) +- Added `remaining()` and `remaining_size()` + [#37](https://github.com/CLIUtils/CLI11/pull/37) +- `allow_extras` and `prefix_command` are now valid on subcommands + [#37](https://github.com/CLIUtils/CLI11/pull/37) +- Added `take_last` to only take last value passed + [#40](https://github.com/CLIUtils/CLI11/pull/40) +- Added `multi_option_policy` and shortcuts to provide more control than just a + take last policy [#59](https://github.com/CLIUtils/CLI11/pull/59) +- More detailed error messages in a few cases + [#41](https://github.com/CLIUtils/CLI11/pull/41) +- Footers can be added to help [#42](https://github.com/CLIUtils/CLI11/pull/42) +- Help flags are easier to customize + [#43](https://github.com/CLIUtils/CLI11/pull/43) +- Subcommand now support groups [#46](https://github.com/CLIUtils/CLI11/pull/46) +- `CLI::RuntimeError` added, for easy exit with error codes + [#45](https://github.com/CLIUtils/CLI11/pull/45) +- The clang-format script is now no longer "hidden" + [#48](https://github.com/CLIUtils/CLI11/pull/48) +- The order is now preserved for subcommands (list and callbacks) + [#49](https://github.com/CLIUtils/CLI11/pull/49) +- Tests now run individually, utilizing CMake 3.10 additions if possible + [#50](https://github.com/CLIUtils/CLI11/pull/50) +- Failure messages are now customizable, with a shorter default + [#52](https://github.com/CLIUtils/CLI11/pull/52) +- Some improvements to error codes + [#53](https://github.com/CLIUtils/CLI11/pull/53) +- `require_subcommand` now offers a two-argument form and negative values on the + one-argument form are more useful + [#51](https://github.com/CLIUtils/CLI11/pull/51) +- Subcommands no longer match after the max required number is obtained + [#51](https://github.com/CLIUtils/CLI11/pull/51) +- Unlimited options no longer prioritize over remaining/unlimited positionals + [#51](https://github.com/CLIUtils/CLI11/pull/51) +- Added `->transform` which modifies the string parsed + [#54](https://github.com/CLIUtils/CLI11/pull/54) +- Changed of API in validators to `void(std::string &)` (const for users), + throwing providing nicer errors + [#54](https://github.com/CLIUtils/CLI11/pull/54) +- Added `CLI::ArgumentMismatch` [#56](https://github.com/CLIUtils/CLI11/pull/56) + and fixed missing failure if one arg expected + [#55](https://github.com/CLIUtils/CLI11/issues/55) +- Support for minimum unlimited expected arguments + [#56](https://github.com/CLIUtils/CLI11/pull/56) +- Single internal arg parse function + [#56](https://github.com/CLIUtils/CLI11/pull/56) +- Allow options to be disabled from INI file, rename `add_config` to + `set_config` [#60](https://github.com/CLIUtils/CLI11/pull/60) + +> ### Converting from CLI11 1.2 +> +> - `app.parse` no longer returns a vector. Instead, use `app.remaining(true)`. +> - `"hidden"` is no longer a special group name, instead use `""` +> - Validators API has changed to return an error string; use `.empty()` to get +> the old bool back +> - Use `.set_help_flag` instead of accessing the help pointer directly +> (discouraged, but not removed yet) +> - `add_config` has been renamed to `set_config` +> - Errors thrown in some cases are slightly more specific + +## Version 1.2: Stability + +This release focuses on making CLI11 behave properly in corner cases, and with +config files on the command line. This includes fixes for a variety of reported +issues. A few features were added to make life easier, as well; such as a new +flag callback and a macro for the parse command. + +- Added functional form of flag + [#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14 +- Fixed Config file search if passed on command line + [#30](https://github.com/CLIUtils/CLI11/issues/30) +- Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not + support returning arg) +- The name string can now contain spaces around commas + [#29](https://github.com/CLIUtils/CLI11/pull/29) +- `set_default_str` now only sets string, and `set_default_val` will evaluate + the default string given [#26](https://github.com/CLIUtils/CLI11/issues/26) +- Required positionals now take priority over subcommands + [#23](https://github.com/CLIUtils/CLI11/issues/23) +- Extra requirements enforced by Travis + +## Version 1.1: Feedback + +This release incorporates feedback from the release announcement. The examples +are slowly being expanded, some corner cases improved, and some new +functionality for tricky parsing situations. + +- Added simple support for enumerations, allow non-printable objects + [#12](https://github.com/CLIUtils/CLI11/issues/12) +- Added `app.parse_order()` with original parse order + ([#13](https://github.com/CLIUtils/CLI11/issues/13), + [#16](https://github.com/CLIUtils/CLI11/pull/16)) +- Added `prefix_command()`, which is like `allow_extras` but instantly stops and + returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8), + [#17](https://github.com/CLIUtils/CLI11/pull/17)) +- Removed Windows warning ([#10](https://github.com/CLIUtils/CLI11/issues/10), + [#20](https://github.com/CLIUtils/CLI11/pull/20)) +- Some improvements to CMake, detect Python and no dependencies on Python 2 + (like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18), + [#21](https://github.com/CLIUtils/CLI11/pull/21)) + +## Version 1.0: Official release + +This is the first stable release for CLI11. Future releases will try to remain +backward compatible and will follow semantic versioning if possible. There were +a few small changes since version 0.9: + +- Cleanup using `clang-tidy` and `clang-format` +- Small improvements to Timers, easier to subclass Error +- Move to 3-Clause BSD license + +## Version 0.9: Polish + +This release focused on cleaning up the most exotic compiler warnings, fixing a +few oddities of the config parser, and added a more natural method to check +subcommands. + +- Better CMake named target (CLI11) +- More warnings added, fixed +- Ini output now includes `=false` when `default_also` is true +- Ini no longer lists the help pointer +- Added test for inclusion in multiple files and linking, fixed issues (rarely + needed for CLI, but nice for tools) +- Support for complex numbers +- Subcommands now test true/false directly or with `->parsed()`, cleaner parse + +## Version 0.8: CLIUtils + +This release moved the repository to the CLIUtils main organization. + +- Moved to CLIUtils on GitHub +- Fixed docs build and a few links + +## Version 0.7: Code coverage 100% + +Lots of small bugs fixed when adding code coverage, better in edge cases. Much +more powerful ini support. + +- Allow comments in ini files (lines starting with `;`) +- Ini files support flags, vectors, subcommands +- Added CodeCov code coverage reports +- Lots of small bugfixes related to adding tests to increase coverage to 100% +- Error handling now uses scoped enum in errors +- Reparsing rules changed a little to accommodate Ini files. Callbacks are now + called when parsing INI, and reset any time results are added. +- Adding extra utilities in full version only, `Timer` (not needed for parsing, + but useful for general CLI applications). +- Better support for custom `add_options` like functions. + +## Version 0.6: Cleanup + +Lots of cleanup and docs additions made it into this release. Parsing is simpler +and more robust; fall through option added and works as expected; much more +consistent variable names internally. + +- Simplified parsing to use `vector` only +- Fixed fallthrough, made it optional as well (default: off): `.fallthrough()`. +- Added string versions of `->requires()` and `->excludes()` for consistency. +- Renamed protected members for internal consistency, grouped docs. +- Added the ability to add a number to `.require_subcommand()`. + +## Version 0.5: Windows support + +- Allow `Hidden` options. +- Throw `OptionAlreadyAdded` errors for matching subcommands or options, with + ignore-case included, tests +- `->ignore_case()` added to subcommands, options, and `add_set_ignore_case`. + Subcommands inherit setting from parent App on creation. +- Subcommands now can be "chained", that is, left over arguments can now include + subcommands that then get parsed. Subcommands are now a list + (`get_subcommands`). Added `got_subcommand(App_or_name)` to check for + subcommands. +- Added `.allow_extras()` to disable error on failure. Parse returns a vector of + leftover options. Renamed error to `ExtrasError`, and now triggers on extra + options too. +- Added `require_subcommand` to `App`, to simplify forcing subcommands. Do + **not** do `add_subcommand()->require_subcommand`, since that is the + subcommand, not the main `App`. +- Added printout of ini file text given parsed options, skips flags. +- Support for quotes and spaces in ini files +- Fixes to allow support for Windows (added Appveyor) (Uses `-`, not `/` syntax) + +## Version 0.4: Ini support + +- Updates to help print +- Removed `run`, please use `parse` unless you subclass and add it +- Supports ini files mixed with command line, tested +- Added Range for further Plumbum compatibility +- Added function to print out ini file + +## Version 0.3: Plumbum compatibility + +- Added `->requires`, `->excludes`, and `->envname` from + [Plumbum](http://plumbum.readthedocs.io/en/latest/) +- Supports `->mandatory` from Plumbum +- More tests for help strings, improvements in formatting +- Support type and set syntax in positionals help strings +- Added help groups, with `->group("name")` syntax +- Added initial support for ini file reading with `add_config` option. +- Supports GCC 4.7 again +- Clang 3.5 now required for tests due to googlemock usage, 3.4 should still + work otherwise +- Changes `setup` for an explicit help bool in constructor/`add_subcommand` + +## Version 0.2: Leaner and meaner + +- Moved to simpler syntax, where `Option` pointers are returned and operated on +- Removed `make_` style options +- Simplified Validators, now only requires `->check(function)` +- Removed Combiners +- Fixed pointers to Options, stored in `unique_ptr` now +- Added `Option_p` and `App_p`, mostly for internal use +- Startup sequence, including help flag, can be modified by subclasses + +## Version 0.1: First release + +First release before major cleanup. Still has make syntax and combiners; very +clever syntax but not the best or most commonly expected way to work. diff --git a/libs/CLI11/CLI11.CPack.Description.txt b/libs/CLI11/CLI11.CPack.Description.txt new file mode 100644 index 0000000..9a01891 --- /dev/null +++ b/libs/CLI11/CLI11.CPack.Description.txt @@ -0,0 +1 @@ +CLI11 provides all the features you expect in a powerful command line parser, with a beautiful, minimal syntax and no dependencies beyond C++11. It is header only, and comes in a single file form for easy inclusion in projects. It is easy to use for small projects, but powerful enough for complex command line projects, and can be customized for frameworks. diff --git a/libs/CLI11/CLI11.hpp.in b/libs/CLI11/CLI11.hpp.in new file mode 100644 index 0000000..83f228e --- /dev/null +++ b/libs/CLI11/CLI11.hpp.in @@ -0,0 +1,83 @@ +// CLI11: Version {version} +// Originally designed by Henry Schreiner +// https://github.com/CLIUtils/CLI11 +// +// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts +// from: {git} +// +// CLI11 {version} Copyright (c) 2017-2022 University of Cincinnati, developed by Henry +// Schreiner under NSF AWARD 1414736. All rights reserved. +// +// Redistribution and use in source and binary forms of CLI11, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +// Standard combined includes: +{public_includes} + +{version_hpp} + +{macros_hpp} + +{validators_hpp_filesystem} + +namespace {namespace} {{ + +{string_tools_hpp} + +{string_tools_inl_hpp} + +{error_hpp} + +{type_tools_hpp} + +{split_hpp} + +{split_inl_hpp} + +{config_fwd_hpp} + +{validators_hpp} + +{validators_inl_hpp} + +{formatter_fwd_hpp} + +{option_hpp} + +{option_inl_hpp} + +{app_hpp} + +{app_inl_hpp} + +{config_hpp} + +{config_inl_hpp} + +{formatter_hpp} + +{formatter_inl_hpp} + +}} // namespace {namespace} diff --git a/libs/CLI11/CMakeLists.txt b/libs/CLI11/CMakeLists.txt new file mode 100644 index 0000000..31bbbbb --- /dev/null +++ b/libs/CLI11/CMakeLists.txt @@ -0,0 +1,233 @@ +cmake_minimum_required(VERSION 3.4) +# Note: this is a header only library. If you have an older CMake than 3.4, +# just add the CLI11/include directory and that's all you need to do. + +# Make sure users don't get warnings on a tested (3.4 to 3.22) version +# of CMake. For most of the policies, the new version is better (hence the change). +# We don't use the 3.4...3.21 syntax because of a bug in an older MSVC's +# built-in and modified CMake 3.11 +if(${CMAKE_VERSION} VERSION_LESS 3.22) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +else() + cmake_policy(VERSION 3.22) +endif() + +set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"") + +# Read in the line containing the version +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/Version.hpp" VERSION_STRING + REGEX ${VERSION_REGEX}) + +# Pick out just the version +string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}") + +# Add the project +project( + CLI11 + LANGUAGES CXX + VERSION ${VERSION_STRING}) + +list(APPEND CMAKE_MODULE_PATH "${CLI11_SOURCE_DIR}/cmake") + +# Print the version number of CMake if this is the main project +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + message(STATUS "CMake ${CMAKE_VERSION}") + + find_package(Doxygen) + + if(CMAKE_VERSION VERSION_LESS 3.10) + message(STATUS "CMake 3.10+ adds Doxygen support. Update CMake to build documentation") + elseif(NOT Doxygen_FOUND) + message(STATUS "Doxygen not found, building docs has been disabled") + endif() + + include(CTest) +else() + if(NOT DEFINED BUILD_TESTING) + set(BUILD_TESTING OFF) + endif() +endif() + +include(CMakeDependentOption) +include(GNUInstallDirs) + +if(NOT CMAKE_VERSION VERSION_LESS 3.11) + include(FetchContent) +endif() + +list(APPEND force-libcxx "CMAKE_CXX_COMPILER_ID STREQUAL \"Clang\"") +list(APPEND force-libcxx "CMAKE_SYSTEM_NAME STREQUAL \"Linux\"") +list(APPEND force-libcxx "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME") + +list(APPEND build-docs "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME") +list(APPEND build-docs "NOT CMAKE_VERSION VERSION_LESS 3.11") +list(APPEND build-docs "Doxygen_FOUND") + +# Necessary to support paths with spaces, see #457 +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/docs") + set(docs_EXIST TRUE) +else() + set(docs_EXIST FALSE) +endif() +list(APPEND build-docs "docs_EXIST") + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples") + set(examples_EXIST TRUE) +else() + set(examples_EXIST FALSE) +endif() + +option(CLI11_WARNINGS_AS_ERRORS "Turn all warnings into errors (for CI)") +option(CLI11_SINGLE_FILE "Generate a single header file") +option(CLI11_PRECOMPILED "Generate a precompiled static library instead of a header-only" OFF) +cmake_dependent_option(CLI11_SANITIZERS "Download the sanitizers CMake config" OFF + "NOT CMAKE_VERSION VERSION_LESS 3.11" OFF) + +cmake_dependent_option(CLI11_BUILD_DOCS "Build CLI11 documentation" ON "${build-docs}" OFF) + +cmake_dependent_option(CLI11_BUILD_TESTS "Build CLI11 tests" ON + "BUILD_TESTING;CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF) + +cmake_dependent_option(CLI11_BUILD_EXAMPLES "Build CLI11 examples" ON + "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;${examples_EXIST}" OFF) + +cmake_dependent_option(CLI11_BUILD_EXAMPLES_JSON "Build CLI11 json example" OFF + "CLI11_BUILD_EXAMPLES;NOT CMAKE_VERSION VERSION_LESS 3.11" OFF) + +cmake_dependent_option(CLI11_SINGLE_FILE_TESTS "Duplicate all the tests for a single file build" + OFF "BUILD_TESTING;CLI11_SINGLE_FILE" OFF) + +cmake_dependent_option(CLI11_INSTALL "Install the CLI11 folder to include during install process" + ON "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF) + +cmake_dependent_option( + CLI11_FORCE_LIBCXX "Force clang to use libc++ instead of libstdc++ (Linux only)" OFF + "${force-libcxx}" OFF) + +cmake_dependent_option( + CLI11_CUDA_TESTS "Build the tests with NVCC to check for warnings there - requires CMake 3.9+" + OFF "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF) + +if(CLI11_PRECOMPILED AND CLI11_SINGLE_FILE) + # Sanity check + message(FATAL_ERROR "CLI11_PRECOMPILE and CLI11_SINGLE_FILE are mutually exclusive") +endif() + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif() + +if(NOT DEFINED CMAKE_CXX_EXTENSIONS) + set(CMAKE_CXX_EXTENSIONS OFF) +endif() + +if(NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +# Allow IDE's to group targets into folders +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) +endif() + +include(CLI11Warnings) + +add_subdirectory(src) + +# Allow tests to be run on CUDA +if(CLI11_CUDA_TESTS) + enable_language(CUDA) + + # Print out warning and error numbers + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number") +endif() + +# This folder should be installed +if(CLI11_INSTALL) + + # Use find_package on the installed package + # Since we have no custom code, we can directly write this + # to Config.cmake (otherwise we'd have a custom config and would + # import Targets.cmake + + # Add the version in a CMake readable way + configure_file("cmake/CLI11ConfigVersion.cmake.in" "CLI11ConfigVersion.cmake" @ONLY) + + # Make version available in the install + install(FILES "${PROJECT_BINARY_DIR}/CLI11ConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/CLI11") + + # Install the export target as a file + install( + EXPORT CLI11Targets + FILE CLI11Config.cmake + NAMESPACE CLI11:: + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/CLI11") + + # Use find_package on the installed package + export( + TARGETS CLI11 + NAMESPACE CLI11:: + FILE CLI11Targets.cmake) + + include(cmake/CLI11GeneratePkgConfig.cmake) + + # Register in the user cmake package registry + export(PACKAGE CLI11) +endif() + +if(CLI11_BUILD_TESTS) + include(CTest) + add_subdirectory(tests) +endif() + +if(CLI11_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +if(CLI11_BUILD_DOCS) + add_subdirectory(docs) +endif() + +# From a build system, this might not be included. +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/book") + add_subdirectory(book) +endif() + +# Packaging support +set(CPACK_PACKAGE_VENDOR "github.com/CLIUtils/CLI11") +set(CPACK_PACKAGE_CONTACT "https://${CPACK_PACKAGE_VENDOR}") +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) # Automatic in CMake 3.12+ +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) # Automatic in CMake 3.12+ +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) # Automatic in CMake 3.12+ +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Command line parser with simple and intuitive interface") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CLI11.CPack.Description.txt") +set(CPACK_SOURCE_GENERATOR "TGZ;ZIP") + +# CPack collects *everything* except what's listed here. +set(CPACK_SOURCE_IGNORE_FILES + /.git + /dist + /.*build.* + /\\\\.DS_Store + /.*\\\\.egg-info + /var + /azure-pipelines.yml + /.ci + /docs + /examples + /test_package + /book + /.travis.yml + .swp + /.all-contributorsrc + /.appveyor.yml + /.pre-commit.*yaml) + +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all") +set(CPACK_DEBIAN_COMPRESSION_TYPE "xz") +set(CPACK_DEBIAN_PACKAGE_NAME "libcli11-dev") + +include(CPack) diff --git a/libs/CLI11/CPPLINT.cfg b/libs/CLI11/CPPLINT.cfg new file mode 100644 index 0000000..24dd865 --- /dev/null +++ b/libs/CLI11/CPPLINT.cfg @@ -0,0 +1,13 @@ +set noparent +linelength=120 # As in .clang-format + +# Unused filters +filter=-build/c++11 # Reports e.g. chrono and thread, which overlap with Chromium's API. Not applicable to general C++ projects. +filter=-build/include_order # Requires unusual include order that encourages creating not self-contained headers +filter=-readability/nolint # Conflicts with clang-tidy +filter=-readability/check # Catch uses CHECK(a == b) (Tests only) +filter=-build/namespaces # Currently using it for one test (Tests only) +filter=-runtime/references # Requires fundamental change of API, don't see need for this +filter=-whitespace/blank_line # Unnecessarily strict with blank lines that otherwise help with readability +filter=-whitespace/indent # Requires strange 3-space indent of private/protected/public markers +filter=-whitespace/parens,-whitespace/braces # Conflict with clang-format diff --git a/libs/CLI11/LICENSE b/libs/CLI11/LICENSE new file mode 100644 index 0000000..71c4770 --- /dev/null +++ b/libs/CLI11/LICENSE @@ -0,0 +1,25 @@ +CLI11 2.2 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry +Schreiner under NSF AWARD 1414736. All rights reserved. + +Redistribution and use in source and binary forms of CLI11, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/CLI11/README.md b/libs/CLI11/README.md new file mode 100644 index 0000000..05a3808 --- /dev/null +++ b/libs/CLI11/README.md @@ -0,0 +1,1767 @@ +# CLI11: Command line parser for C++11 + +![CLI11 Logo](./docs/CLI11_300.png) + +[![Build Status Azure][azure-badge]][azure] +[![Actions Status][actions-badge]][actions-link] +[![Build Status AppVeyor][appveyor-badge]][appveyor] +[![Code Coverage][codecov-badge]][codecov] +[![Codacy Badge][codacy-badge]][codacy-link] +[![License: BSD][license-badge]](./LICENSE) [![DOI][doi-badge]][doi-link] + +[![Gitter chat][gitter-badge]][gitter] +[![Latest GHA release][releases-badge]][github releases] +[![Latest release][repology-badge]][repology] +[![Conan.io][conan-badge]][conan-link] +[![Conda Version][conda-badge]][conda-link] +[![Try CLI11 2.1 online][wandbox-badge]][wandbox-link] + +[What's new](./CHANGELOG.md) • [Documentation][gitbook] • [API +Reference][api-docs] + +CLI11 is a command line parser for C++11 and beyond that provides a rich feature +set with a simple and intuitive interface. + +## Table of Contents + +- [Background](#background) + - [Introduction](#introduction) + - [Why write another CLI parser?](#why-write-another-cli-parser) + - [Other parsers](#other-parsers) + - [Features not supported by this library](#features-not-supported-by-this-library) +- [Install](#install) +- [Usage](#usage) + - [Adding options](#adding-options) + - [Option types](#option-types) + - [Example](#example) + - [Option options](#option-options) + - [Validators](#validators) + - [Transforming Validators](#transforming-validators) + - [Validator operations](#validator-operations) + - [Custom Validators](#custom-validators) + - [Querying Validators](#querying-validators) + - [Getting Results](#getting-results) + - [Subcommands](#subcommands) + - [Subcommand options](#subcommand-options) + - [Option groups](#option-groups) + - [Callbacks](#callbacks) + - [Configuration file](#configuration-file) + - [Inheriting defaults](#inheriting-defaults) + - [Formatting](#formatting) + - [Subclassing](#subclassing) + - [How it works](#how-it-works) + - [Utilities](#utilities) + - [Other libraries](#other-libraries) +- [API](#api) +- [Examples](#Examples) +- [Contribute](#contribute) +- [License](#license) + +Features that were added in the last released minor version are marked with +"🆕". Features only available in main are marked with "🚧". + +## Background + +### Introduction + +CLI11 provides all the features you expect in a powerful command line parser, +with a beautiful, minimal syntax and no dependencies beyond C++11. It is header +only, and comes in a single file form for easy inclusion in projects. It is easy +to use for small projects, but powerful enough for complex command line +projects, and can be customized for frameworks. It is tested on [Azure][] and +[GitHub Actions][actions-link], and was originally used by the [GooFit GPU +fitting framework][goofit]. It was inspired by [`plumbum.cli`][plumbum] for +Python. CLI11 has a user friendly introduction in this README, a more in-depth +tutorial [GitBook][], as well as [API documentation][api-docs] generated by +Travis. See the [changelog](./CHANGELOG.md) or [GitHub Releases][] for details +for current and past releases. Also see the [Version 1.0 post][], [Version 1.3 +post][], [Version 1.6 post][], or [Version 2.0 post][] for more information. + +You can be notified when new releases are made by subscribing to + on an RSS reader, like Feedly, +or use the releases mode of the GitHub watching tool. + +### Why write another CLI parser? + +An acceptable CLI parser library should be all of the following: + +- Easy to include (i.e., header only, one file if possible, **no external + requirements**). +- Short, simple syntax: This is one of the main reasons to use a CLI parser, it + should make variables from the command line nearly as easy to define as any + other variables. If most of your program is hidden in CLI parsing, this is a + problem for readability. +- C++11 or better: Should work with GCC 4.8+ (default on CentOS/RHEL 7), Clang + 3.4+, AppleClang 7+, NVCC 7.0+, or MSVC 2015+. +- Work on Linux, macOS, and Windows. +- Well tested on all common platforms and compilers. "Well" is defined as having + good coverage measured by [CodeCov][]. +- Clear help printing. +- Nice error messages. +- Standard shell idioms supported naturally, like grouping flags, a positional + separator, etc. +- Easy to execute, with help, parse errors, etc. providing correct exit and + details. +- Easy to extend as part of a framework that provides "applications" to users. +- Usable subcommand syntax, with support for multiple subcommands, nested + subcommands, option groups, and optional fallthrough (explained later). +- Ability to add a configuration file (`TOML`, `INI`, or custom format), and + produce it as well. +- Produce real values that can be used directly in code, not something you have + pay compute time to look up, for HPC applications. +- Work with common types, simple custom types, and extensible to exotic types. +- Permissively licensed. + +### Other parsers + +
The major CLI parsers for C++ include, with my biased opinions: (click to expand)

+ +| Library | My biased opinion | +| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Boost Program Options][] | A great library if you already depend on Boost, but its pre-C++11 syntax is really odd and setting up the correct call in the main function is poorly documented (and is nearly a page of code). A simple wrapper for the Boost library was originally developed, but was discarded as CLI11 became more powerful. The idea of capturing a value and setting it originated with Boost PO. [See this comparison.][cli11-po-compare] | +| [The Lean Mean C++ Option Parser][] | One header file is great, but the syntax is atrocious, in my opinion. It was quite impractical to wrap the syntax or to use in a complex project. It seems to handle standard parsing quite well. | +| [TCLAP][] | The not-quite-standard command line parsing causes common shortcuts to fail. It also seems to be poorly supported, with only minimal bugfixes accepted. Header only, but in quite a few files. Has not managed to get enough support to move to GitHub yet. No subcommands. Produces wrapped values. | +| [Cxxopts][] | C++11, single file, and nice CMake support, but requires regex, therefore GCC 4.8 (CentOS 7 default) does not work. Syntax closely based on Boost PO, so not ideal but familiar. | +| [DocOpt][] | Completely different approach to program options in C++11, you write the docs and the interface is generated. Too fragile and specialized. | + +After I wrote this, I also found the following libraries: + +| Library | My biased opinion | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [GFlags][] | The Google Commandline Flags library. Uses macros heavily, and is limited in scope, missing things like subcommands. It provides a simple syntax and supports config files/env vars. | +| [GetOpt][] | Very limited C solution with long, convoluted syntax. Does not support much of anything, like help generation. Always available on UNIX, though (but in different flavors). | +| [ProgramOptions.hxx][] | Interesting library, less powerful and no subcommands. Nice callback system. | +| [Args][] | Also interesting, and supports subcommands. I like the optional-like design, but CLI11 is cleaner and provides direct value access, and is less verbose. | +| [Argument Aggregator][] | I'm a big fan of the [fmt][] library, and the try-catch statement looks familiar. :thumbsup: Doesn't seem to support subcommands. | +| [Clara][] | Simple library built for the excellent [Catch][] testing framework. Unique syntax, limited scope. | +| [Argh!][] | Very minimalistic C++11 parser, single header. Don't have many features. No help generation?!?! At least it's exception-free. | +| [CLI][] | Custom language and parser. Huge build-system overkill for very little benefit. Last release in 2009, but still occasionally active. | +| [argparse][] | C++17 single file argument parser. Design seems similar to CLI11 in some ways. The author has several other interesting projects. | +| [lyra][] | a simple header only parser with composable options. Might work well for simple standardized parsing | + +See [Awesome C++][] for a less-biased list of parsers. You can also find other +single file libraries at [Single file libs][]. + +

+
+ +None of these libraries fulfill all the above requirements, or really even come +close. As you probably have already guessed, CLI11 does. So, this library was +designed to provide a great syntax, good compiler compatibility, and minimal +installation fuss. + +### Features not supported by this library + +There are some other possible "features" that are intentionally not supported by +this library: + +- Non-standard variations on syntax, like `-long` options. This is non-standard + and should be avoided, so that is enforced by this library. +- Completion of partial options, such as Python's `argparse` supplies for + incomplete arguments. It's better not to guess. Most third party command line + parsers for python actually reimplement command line parsing rather than using + argparse because of this perceived design flaw (recent versions do have an + option to disable it). +- Autocomplete: This might eventually be added to both Plumbum and CLI11, but it + is not supported yet. +- Wide strings / unicode: Since this uses the standard library only, it might be + hard to properly implement, but I would be open to suggestions in how to do + this. + +## Install + +To use, there are several methods: + +- All-in-one local header: Copy `CLI11.hpp` from the [most recent + release][github releases] into your include directory, and you are set. This + is combined from the source files for every release. This includes the entire + command parser library, but does not include separate utilities (like `Timer`, + `AutoTimer`). The utilities are completely self contained and can be copied + separately. +- All-in-one global header: Like above, but copying the file to a shared folder + location like `/opt/CLI11`. Then, the C++ include path has to be extended to + point at this folder. With CMake, use `include_directories(/opt/CLI11)` +- Local headers and target: Use `CLI/*.hpp` files. You could check out the + repository as a git submodule, for example. With CMake, you can use + `add_subdirectory` and the `CLI11::CLI11` interface target when linking. If + not using a submodule, you must ensure that the copied files are located + inside the same tree directory than your current project, to prevent an error + with CMake and `add_subdirectory`. +- Global headers: Use `CLI/*.hpp` files stored in a shared folder. You could + check out the git repository to a system-wide folder, for example `/opt/`. + With CMake, you could add to the include path via: + +```bash +if(NOT DEFINED CLI11_DIR) +set (CLI11_DIR "/opt/CLI11" CACHE STRING "CLI11 git repository") +endif() +include_directories(${CLI11_DIR}/include) +``` + +And then in the source code (adding several headers might be needed to prevent +linker errors): + +```cpp +#include "CLI/App.hpp" +#include "CLI/Formatter.hpp" +#include "CLI/Config.hpp" +``` + +- Global headers and target: configuring and installing the project is required + for linking CLI11 to your project in the same way as you would do with any + other external library. With CMake, this step allows using + `find_package(CLI11 CONFIG REQUIRED)` and then using the `CLI11::CLI11` target + when linking. If `CMAKE_INSTALL_PREFIX` was changed during install to a + specific folder like `/opt/CLI11`, then you have to pass + `-DCLI11_DIR=/opt/CLI11` when building your current project. You can also use + [Conan.io][conan-link] or [Hunter][]. (These are just conveniences to allow + you to use your favorite method of managing packages; it's just header only so + including the correct path and using C++11 is all you really need.) +- Via FetchContent in CMake 3.14+ (or 3.11+ with more work): you can add this + with fetch-content, then use the `CLI11::CLI11` target as above, and CMake + will download the project in the configure stage: + +```cmake +include(FetchContent) +FetchContent_Declare( + cli11 + GIT_REPOSITORY https://github.com/CLIUtils/CLI11 + GIT_TAG v2.2.0 +) + +FetchContent_MakeAvailable(cli11) +``` + +It is highly recommended that you use the git hash for `GIT_TAG` instead of a +tag or branch, as that will both be more secure, as well as faster to +reconfigure - CMake will not have to reach out to the internet to see if the tag +moved. You can also download just the single header file from the releases using +`file(DOWNLOAD`. + +To build the tests, checkout the repository and use CMake: + +```bash +cmake -S . -B build +cmake --build build +CTEST_OUTPUT_ON_FAILURE=1 cmake --build build -t test +``` + +
Note: Special instructions for GCC 8

+ +If you are using GCC 8 and using it in C++17 mode with CLI11. CLI11 makes use of +the `` header if available, but specifically for this compiler, the +`filesystem` library is separate from the standard library and needs to be +linked separately. So it is available but CLI11 doesn't use it by default. + +Specifically `libstdc++fs` needs to be added to the linking list and +`CLI11_HAS_FILESYSTEM=1` has to be defined. Then the filesystem variant of the +Validators could be used on GCC 8. GCC 9+ does not have this issue so the +`` is used by default. + +There may also be other cases where a specific library needs to be linked. + +Defining `CLI11_HAS_FILESYSTEM=0` which will remove the usage and hence any +linking issue. + +In some cases certain clang compilations may require linking against `libc++fs`. +These situations have not been encountered so the specific situations requiring +them are unknown yet. + +

+
+ +## Usage + +### Adding options + +To set up, add options, and run, your main function will look something like +this: + +```cpp +int main(int argc, char** argv) { + CLI::App app{"App description"}; + + std::string filename = "default"; + app.add_option("-f,--file", filename, "A help string"); + + CLI11_PARSE(app, argc, argv); + return 0; +} +``` + +
Note: If you don't like macros, this is what that macro expands to: (click to expand)

+ +```cpp +try { + app.parse(argc, argv); +} catch (const CLI::ParseError &e) { + return app.exit(e); +} +``` + +The try/catch block ensures that `-h,--help` or a parse error will exit with the +correct return code (selected from `CLI::ExitCodes`). (The return here should be +inside `main`). You should not assume that the option values have been set +inside the catch block; for example, help flags intentionally short-circuit all +other processing for speed and to ensure required options and the like do not +interfere. + +

+
+ +The initialization is just one line, adding options is just two each. The parse +macro is just one line (or 5 for the contents of the macro). After the app runs, +the filename will be set to the correct value if it was passed, otherwise it +will be set to the default. You can check to see if this was passed on the +command line with `app.count("--file")`. + +#### Option types + +While all options internally are the same type, there are several ways to add an +option depending on what you need. The supported values are: + +```cpp +// Add options +app.add_option(option_name, help_str="") + +app.add_option(option_name, + variable_to_bind_to, // bool, char(see note), int, float, vector, enum, std::atomic, or string-like, or anything with a defined conversion from a string or that takes an int, double, or string in a constructor. Also allowed are tuples, std::array or std::pair. Also supported are complex numbers, wrapper types, and containers besides vectors of any other supported type. + help_string="") + +app.add_option_function(option_name, + function , // type can be any type supported by add_option + help_string="") + +// char as an option type is supported before 2.0 but in 2.0 it defaulted to allowing single non numerical characters in addition to the numeric values. + +// There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version. If XC is a std::pair and T is some non pair type. Then a two argument constructor for T is called to assign the value. For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type +app.add_option(option_name, + T &output, // output must be assignable or constructible from a value of type XC + help_string="") + +// Add flags +app.add_flag(option_name, + help_string="") + +app.add_flag(option_name, + variable_to_bind_to, // bool, int, float, complex, containers, enum, std::atomic, or string-like, or any singular object with a defined conversion from a string like add_option + help_string="") + +app.add_flag_function(option_name, + function , + help_string="") + +app.add_flag_callback(option_name,function,help_string="") + +// Add subcommands +App* subcom = app.add_subcommand(name, description); + +Option_group *app.add_option_group(name,description); +``` + +An option name may start with any character except ('-', ' ', '\n', and '!'). +For long options, after the first character all characters are allowed except +('=',':','{',' ', '\n'). For the `add_flag*` functions '{' and '!' have special +meaning which is why they are not allowed. Names are given as a comma separated +string, with the dash or dashes. An option or flag can have as many names as you +want, and afterward, using `count`, you can use any of the names, with dashes as +needed, to count the options. One of the names is allowed to be given without +proceeding dash(es); if present the option is a positional option, and that name +will be used on the help line for its positional form. + +The `add_option_function(...` function will typically require the template +parameter be given unless a `std::function` object with an exact match is +passed. The type can be any type supported by the `add_option` function. The +function should throw an error (`CLI::ConversionError` or `CLI::ValidationError` +possibly) if the value is not valid. + +The two parameter template overload can be used in cases where you want to +restrict the input such as + +```cpp +double val +app.add_option("-v",val); +``` + +which would first verify the input is convertible to an `unsigned int` before +assigning it. Or using some variant type + +```cpp +using vtype=std::variant; + vtype v1; +app.add_option("--vs",v1); +app.add_option("--vi",v1); +app.add_option("--vf",v1); +``` + +otherwise the output would default to a string. The `add_option` can be used +with any integral or floating point types, enumerations, or strings. Or any type +that takes an int, double, or std\::string in an assignment operator or +constructor. If an object can take multiple varieties of those, std::string +takes precedence, then double then int. To better control which one is used or +to use another type for the underlying conversions use the two parameter +template to directly specify the conversion type. + +Types such as (std or boost) `optional`, `optional`, and +`optional` and any other wrapper types are supported directly. For +purposes of CLI11 wrapper types are those which `value_type` definition. See +[CLI11 Advanced Topics/Custom Converters][] for information on how you can add +your own converters for additional types. + +Vector types can also be used in the two parameter template overload + +```cpp +std::vector v1; +app.add_option,int>("--vs",v1); +``` + +would load a vector of doubles but ensure all values can be represented as +integers. + +Automatic direct capture of the default string is disabled when using the two +parameter template. Use `set_default_str(...)` or +`->default_function(std::string())` to set the default string or capture +function directly for these cases. + +Flag options specified through the `add_flag*` functions allow a syntax for the +option names to default particular options to a false value or any other value +if some flags are passed. For example: + +```cpp +app.add_flag("--flag,!--no-flag",result,"help for flag"); +``` + +specifies that if `--flag` is passed on the command line result will be true or +contain a value of 1. If `--no-flag` is passed `result` will contain false or -1 +if `result` is a signed integer type, or 0 if it is an unsigned type. An +alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`; +this is equivalent to the previous example. This also works for short form +options `"-f,!-n"` or `"-f,-n{false}"`. If `variable_to_bind_to` is anything but +an integer value the default behavior is to take the last value given, while if +`variable_to_bind_to` is an integer type the behavior will be to sum all the +given arguments and return the result. This can be modified if needed by +changing the `multi_option_policy` on each flag (this is not inherited). The +default value can be any value. For example if you wished to define a numerical +flag: + +```cpp +app.add_flag("-1{1},-2{2},-3{3}",result,"numerical flag") +``` + +Using any of those flags on the command line will result in the specified number +in the output. Similar things can be done for string values, and enumerations, +as long as the default value can be converted to the given type. + +On a `C++14` compiler, you can pass a callback function directly to `.add_flag`, +while in C++11 mode you'll need to use `.add_flag_function` if you want a +callback function. The function will be given the number of times the flag was +passed. You can throw a relevant `CLI::ParseError` to signal a failure. + +#### Example + +- `"one,-o,--one"`: Valid as long as not a flag, would create an option that can + be specified positionally, or with `-o` or `--one` +- `"this"` Can only be passed positionally +- `"-a,-b,-c"` No limit to the number of non-positional option names + +The add commands return a pointer to an internally stored `Option`. This option +can be used directly to check for the count (`->count()`) after parsing to avoid +a string based lookup. + +#### Option options + +Before parsing, you can set the following options: + +- `->required()`: The program will quit if this option is not present. This is + `mandatory` in Plumbum, but required options seems to be a more standard term. + For compatibility, `->mandatory()` also works. +- `->expected(N)`: Take `N` values instead of as many as possible, only for + vector args. If negative, require at least `-N`; end with `--` or another + recognized option or subcommand. +- `->expected(MIN,MAX)`: Set a range of expected values to accompany an option. + `expected(0,1)` is the equivalent of making a flag. +- `->type_name(typename)`: Set the name of an Option's type (`type_name_fn` + allows a function instead) +- `->type_size(N)`: Set the intrinsic size of an option value. The parser will + require multiples of this number if negative. Most of the time this is + detected automatically though can be modified for specific use cases. +- `->type_size(MIN,MAX)`: Set the intrinsic size of an option to a range. +- `->needs(opt)`: This option requires another option to also be present, opt is + an `Option` pointer. Options can be removed from the `needs` with + `remove_needs(opt)`. The option can also be specified with a string containing + the name of the option +- `->excludes(opt)`: This option cannot be given with `opt` present, opt is an + `Option` pointer. Can also be given as a string containing the name of the + option. Options can be removed from the excludes list with + `->remove_excludes(opt)` +- `->envname(name)`: Gets the value from the environment if present and not + passed on the command line. +- `->group(name)`: The help group to put the option in. No effect for positional + options. Defaults to `"Options"`. `""` will not show up in the help print + (hidden). +- `->ignore_case()`: Ignore the case on the command line (also works on + subcommands, does not affect arguments). +- `->ignore_underscore()`: Ignore any underscores in the options names (also + works on subcommands, does not affect arguments). For example "option_one" + will match with "optionone". This does not apply to short form options since + they only have one character +- `->disable_flag_override()`: From the command line long form flag options can + be assigned a value on the command line using the `=` notation `--flag=value`. + If this behavior is not desired, the `disable_flag_override()` disables it and + will generate an exception if it is done on the command line. The `=` does not + work with short form flag options. +- `->allow_extra_args(true/false)`: If set to true the option will take an + unlimited number of arguments like a vector, if false it will limit the number + of arguments to the size of the type used in the option. Default value depends + on the nature of the type use, containers default to true, others default to + false. +- `->delimiter(char)`: Allows specification of a custom delimiter for separating + single arguments into vector arguments, for example specifying + `->delimiter(',')` on an option would result in `--opt=1,2,3` producing 3 + elements of a vector and the equivalent of --opt 1 2 3 assuming opt is a + vector value. +- `->description(str)`: Set/change the description. +- `->multi_option_policy(CLI::MultiOptionPolicy::Throw)`: Set the multi-option + policy. Shortcuts available: `->take_last()`, `->take_first()`,`->take_all()`, + and `->join()`. This will only affect options expecting 1 argument or bool + flags (which do not inherit their default but always start with a specific + policy). `->join(delim)` can also be used to join with a specific delimiter. + This equivalent to calling `->delimiter(delim)` and `->join()`. Valid values + are `CLI::MultiOptionPolicy::Throw`, `CLI::MultiOptionPolicy::Throw`, + `CLI::MultiOptionPolicy::TakeLast`, `CLI::MultiOptionPolicy::TakeFirst`, + `CLI::MultiOptionPolicy::Join`, `CLI::MultiOptionPolicy::TakeAll`, and + `CLI::MultiOptionPolicy::Sum` 🆕. +- `->check(std::string(const std::string &), validator_name="",validator_description="")`: + Define a check function. The function should return a non empty string with + the error message if the check fails +- `->check(Validator)`: Use a Validator object to do the check see + [Validators](#validators) for a description of available Validators and how to + create new ones. +- `->transform(std::string(std::string &), validator_name="",validator_description=")`: + Converts the input string into the output string, in-place in the parsed + options. +- `->transform(Validator)`: Uses a Validator object to do the transformation see + [Validators](#validators) for a description of available Validators and how to + create new ones. +- `->each(void(const std::string &)>`: Run this function on each value received, + as it is received. It should throw a `ValidationError` if an error is + encountered. +- `->configurable(false)`: Disable this option from being in a configuration + file. +- `->capture_default_str()`: Store the current value attached and display it in + the help string. +- `->default_function(std::string())`: Advanced: Change the function that + `capture_default_str()` uses. +- `->always_capture_default()`: Always run `capture_default_str()` when creating + new options. Only useful on an App's `option_defaults`. +- `->default_str(string)`: Set the default string directly (NO VALIDATION OR + CALLBACKS). This string will also be used as a default value if no arguments + are passed and the value is requested. +- `->default_val(value)`: Generate the default string from a value and validate + that the value is also valid. For options that assign directly to a value type + the value in that type is also updated. Value must be convertible to a + string(one of known types or have a stream operator). The callback may be + triggered if the `run_callback_for_default` is set. +- `->run_callback_for_default()`: This will force the option callback to be + executed or the variable set when the `default_val` is set. +- `->option_text(string)`: Sets the text between the option name and + description. +- `->force_callback()`: Causes the option callback or value set to be triggered + even if the option was not present in parsing. +- `->trigger_on_parse()`: If set, causes the callback and all associated + validation checks for the option to be executed when the option value is + parsed vs. at the end of all parsing. This could cause the callback to be + executed multiple times. Also works with positional options. + +These options return the `Option` pointer, so you can chain them together, and +even skip storing the pointer entirely. The `each` function takes any function +that has the signature `void(const std::string&)`; it should throw a +`ValidationError` when validation fails. The help message will have the name of +the parent option prepended. Since `each`, `check` and `transform` use the same +underlying mechanism, you can chain as many as you want, and they will be +executed in order. Operations added through `transform` are executed first in +reverse order of addition, and `check` and `each` are run following the +transform functions in order of addition. If you just want to see the +unconverted values, use `.results()` to get the `std::vector` of +results. + +On the command line, options can be given as: + +- `-a` (flag) +- `-abc` (flags can be combined) +- `-f filename` (option) +- `-ffilename` (no space required) +- `-abcf filename` (flags and option can be combined) +- `--long` (long flag) +- `--long_flag=true` (long flag with equals to override default value) +- `--file filename` (space) +- `--file=filename` (equals) + +If `allow_windows_style_options()` is specified in the application or subcommand +options can also be given as: + +- `/a` (flag) +- `/f filename` (option) +- `/long` (long flag) +- `/file filename` (space) +- `/file:filename` (colon) +- `/long_flag:false` (long flag with : to override the default value) + - Windows style options do not allow combining short options or values not + separated from the short option like with `-` options + +Long flag options may be given with an `=` to allow specifying a false +value, or some other value to the flag. See [config files](#configuration-file) +for details on the values supported. NOTE: only the `=` or `:` for windows-style +options may be used for this, using a space will result in the argument being +interpreted as a positional argument. This syntax can override the default +values, and can be disabled by using `disable_flag_override()`. + +Extra positional arguments will cause the program to exit, so at least one +positional option with a vector is recommended if you want to allow extraneous +arguments. If you set `.allow_extras()` on the main `App`, you will not get an +error. You can access the missing options using `remaining` (if you have +subcommands, `app.remaining(true)` will get all remaining options, subcommands +included). If the remaining arguments are to processed by another `App` then the +function `remaining_for_passthrough()` can be used to get the remaining +arguments in reverse order such that `app.parse(vector)` works directly and +could even be used inside a subcommand callback. + +You can access a vector of pointers to the parsed options in the original order +using `parse_order()`. If `--` is present in the command line that does not end +an unlimited option, then everything after that is positional only. + +#### Validators + +Validators are structures to check or modify inputs, they can be used to verify +that an input meets certain criteria or transform it into another value. They +are added through the `check` or `transform` functions. The differences between +the two function are that checks do not modify the input whereas transforms can +and are executed before any Validators added through `check`. + +CLI11 has several Validators built-in that perform some common checks + +- `CLI::IsMember(...)`: Require an option be a member of a given set. See + [Transforming Validators](#transforming-validators) for more details. +- `CLI::Transformer(...)`: Modify the input using a map. See + [Transforming Validators](#transforming-validators) for more details. +- `CLI::CheckedTransformer(...)`: Modify the input using a map, and require that + the input is either in the set or already one of the outputs of the set. See + [Transforming Validators](#transforming-validators) for more details. +- `CLI::AsNumberWithUnit(...)`: Modify the ` ` pair by matching + the unit and multiplying the number by the corresponding factor. It can be + used as a base for transformers, that accept things like size values (`1 KB`) + or durations (`0.33 ms`). +- `CLI::AsSizeValue(...)`: Convert inputs like `100b`, `42 KB`, `101 Mb`, + `11 Mib` to absolute values. `KB` can be configured to be interpreted as 10^3 + or 2^10. +- `CLI::ExistingFile`: Requires that the file exists if given. +- `CLI::ExistingDirectory`: Requires that the directory exists. +- `CLI::ExistingPath`: Requires that the path (file or directory) exists. +- `CLI::NonexistentPath`: Requires that the path does not exist. +- `CLI::FileOnDefaultPath`: Best used as a transform, Will check that a file + exists either directly or in a default path and update the path appropriately. + See [Transforming Validators](#transforming-validators) for more details +- `CLI::Range(min,max)`: Requires that the option be between min and max (make + sure to use floating point if needed). Min defaults to 0. +- `CLI::Bounded(min,max)`: Modify the input such that it is always between min + and max (make sure to use floating point if needed). Min defaults to 0. Will + produce an error if conversion is not possible. +- `CLI::PositiveNumber`: Requires the number be greater than 0 +- `CLI::NonNegativeNumber`: Requires the number be greater or equal to 0 +- `CLI::Number`: Requires the input be a number. +- `CLI::ValidIPV4`: Requires that the option be a valid IPv4 string e.g. + `'255.255.255.255'`, `'10.1.1.7'`. +- `CLI::TypeValidator`:Requires that the option be convertible to the + specified type e.g. `CLI::TypeValidator()` would require that + the input be convertible to an `unsigned int` regardless of the end + conversion. + +These Validators can be used by simply passing the name into the `check` or +`transform` methods on an option + +```cpp +->check(CLI::ExistingFile); +->check(CLI::Range(0,10)); +``` + +Validators can be merged using `&` and `|` and inverted using `!`. For example: + +```cpp +->check(CLI::Range(0,10)|CLI::Range(20,30)); +``` + +will produce a check to ensure a value is between 0 and 10 or 20 and 30. + +```cpp +->check(!CLI::PositiveNumber); +``` + +will produce a check for a number less than or equal to 0. + +##### Transforming Validators + +There are a few built in Validators that let you transform values if used with +the `transform` function. If they also do some checks then they can be used +`check` but some may do nothing in that case. + +- `CLI::Bounded(min,max)` will bound values between min and max and values + outside of that range are limited to min or max, it will fail if the value + cannot be converted and produce a `ValidationError` +- The `IsMember` Validator lets you specify a set of predefined options. You can + pass any container or copyable pointer (including `std::shared_ptr`) to a + container to this Validator; the container just needs to be iterable and have + a `::value_type`. The key type should be convertible from a string, You can + use an initializer list directly if you like. If you need to modify the set + later, the pointer form lets you do that; the type message and check will + correctly refer to the current version of the set. The container passed in can + be a set, vector, or a map like structure. If used in the `transform` method + the output value will be the matching key as it could be modified by filters. + +After specifying a set of options, you can also specify "filter" functions of +the form `T(T)`, where `T` is the type of the values. The most common choices +probably will be `CLI::ignore_case` an `CLI::ignore_underscore`, and +`CLI::ignore_space`. These all work on strings but it is possible to define +functions that work on other types. Here are some examples of `IsMember`: + +- `CLI::IsMember({"choice1", "choice2"})`: Select from exact match to choices. +- `CLI::IsMember({"choice1", "choice2"}, CLI::ignore_case, CLI::ignore_underscore)`: + Match things like `Choice_1`, too. +- `CLI::IsMember(std::set({2,3,4}))`: Most containers and types work; you + just need `std::begin`, `std::end`, and `::value_type`. +- `CLI::IsMember(std::map({{"one", 1}, {"two", 2}}))`: You + can use maps; in `->transform()` these replace the matched value with the + matched key. The value member of the map is not used in `IsMember`, so it can + be any type. +- `auto p = std::make_shared>(std::initializer_list("one", "two")); CLI::IsMember(p)`: + You can modify `p` later. +- The `Transformer` and `CheckedTransformer` Validators transform one value into + another. Any container or copyable pointer (including `std::shared_ptr`) to a + container that generates pairs of values can be passed to these `Validator's`; + the container just needs to be iterable and have a `::value_type` that + consists of pairs. The key type should be convertible from a string, and the + value type should be convertible to a string You can use an initializer list + directly if you like. If you need to modify the map later, the pointer form + lets you do that; the description message will correctly refer to the current + version of the map. `Transformer` does not do any checking so values not in + the map are ignored. `CheckedTransformer` takes an extra step of verifying + that the value is either one of the map key values, in which case it is + transformed, or one of the expected output values, and if not will generate a + `ValidationError`. A Transformer placed using `check` will not do anything. + +After specifying a map of options, you can also specify "filter" just like in +`CLI::IsMember`. Here are some examples (`Transformer` and `CheckedTransformer` +are interchangeable in the examples) of `Transformer`: + +- `CLI::Transformer({{"key1", "map1"},{"key2","map2"}})`: Select from key values + and produce map values. +- `CLI::Transformer(std::map({"two",2},{"three",3},{"four",4}}))`: + most maplike containers work, the `::value_type` needs to produce a pair of + some kind. +- `CLI::CheckedTransformer(std::map({{"one", 1}, {"two", 2}}))`: + You can use maps; in `->transform()` these replace the matched key with the + value. `CheckedTransformer` also requires that the value either match one of + the keys or match one of known outputs. +- `auto p = std::make_shared>(std::initializer_list>({"key1", "map1"},{"key2","map2"})); CLI::Transformer(p)`: + You can modify `p` later. `TransformPairs` is an alias for + `std::vector>` + +NOTES: If the container used in `IsMember`, `Transformer`, or +`CheckedTransformer` has a `find` function like `std::unordered_map` or +`std::map` then that function is used to do the searching. If it does not have a +`find` function a linear search is performed. If there are filters present, the +fast search is performed first, and if that fails a linear search with the +filters on the key values is performed. + +- `CLI::FileOnDefaultPath(default_path)`: 🆕 can be used to check for files in a + default path. If used as a transform it will first check that a file exists, + if it does nothing further is done, if it does not it tries to add a default + Path to the file and search there again. If the file does not exist an error + is returned normally but this can be disabled using + `CLI::FileOnDefaultPath(default_path, false)`. This allows multiple paths to + be chained using multiple transform calls. + +##### Validator operations + +Validators are copyable and have a few operations that can be performed on them +to alter settings. Most of the built in Validators have a default description +that is displayed in the help. This can be altered via +`.description(validator_description)`. The name of a Validator, which is useful +for later reference from the `get_validator(name)` method of an `Option` can be +set via `.name(validator_name)` The operation function of a Validator can be set +via `.operation(std::function)`. The `.active()` +function can activate or deactivate a Validator from the operation. A validator +can be set to apply only to a specific element of the output. For example in a +pair option `std::pair` the first element may need to be a +positive integer while the second may need to be a valid file. The +`.application_index(int)` function can specify this. It is zero based and +negative indices apply to all values. + +```cpp +opt->check(CLI::Validator(CLI::PositiveNumber).application_index(0)); +opt->check(CLI::Validator(CLI::ExistingFile).application_index(1)); +``` + +All the validator operation functions return a Validator reference allowing them +to be chained. For example + +```cpp +opt->check(CLI::Range(10,20).description("range is limited to sensible values").active(false).name("range")); +``` + +will specify a check on an option with a name "range", but deactivate it for the +time being. The check can later be activated through + +```cpp +opt->get_validator("range")->active(); +``` + +##### Custom Validators + +A validator object with a custom function can be created via + +```cpp +CLI::Validator(std::function,validator_description,validator_name=""); +``` + +or if the operation function is set later they can be created with + +```cpp +CLI::Validator(validator_description); +``` + +It is also possible to create a subclass of `CLI::Validator`, in which case it +can also set a custom description function, and operation function. + +##### Querying Validators + +Once loaded into an Option, a pointer to a named Validator can be retrieved via + +```cpp +opt->get_validator(name); +``` + +This will retrieve a Validator with the given name or throw a +`CLI::OptionNotFound` error. If no name is given or name is empty the first +unnamed Validator will be returned or the first Validator if there is only one. + +or + +```cpp +opt->get_validator(index); +``` + +Which will return a validator in the index it is applied which isn't necessarily +the order in which was defined. The pointer can be `nullptr` if an invalid index +is given. Validators have a few functions to query the current values: + +- `get_description()`: Will return a description string +- `get_name()`: Will return the Validator name +- `get_active()`: Will return the current active state, true if the Validator is + active. +- `get_application_index()`: Will return the current application index. +- `get_modifying()`: Will return true if the Validator is allowed to modify the + input, this can be controlled via the `non_modifying()` method, though it is + recommended to let `check` and `transform` option methods manipulate it if + needed. + +#### Getting results + +In most cases, the fastest and easiest way is to return the results through a +callback or variable specified in one of the `add_*` functions. But there are +situations where this is not possible or desired. For these cases the results +may be obtained through one of the following functions. Please note that these +functions will do any type conversions and processing during the call so should +not used in performance critical code: + +- `->results()`: Retrieves a vector of strings with all the results in the order + they were given. +- `->results(variable_to_bind_to)`: Gets the results according to the + MultiOptionPolicy and converts them just like the `add_option_function` with a + variable. +- `Value=opt->as()`: Returns the result or default value directly as the + specified type if possible, can be vector to return all results, and a + non-vector to get the result according to the MultiOptionPolicy in place. + +### Subcommands + +Subcommands are supported, and can be nested infinitely. To add a subcommand, +call the `add_subcommand` method with a name and an optional description. This +gives a pointer to an `App` that behaves just like the main app, and can take +options or further subcommands. Add `->ignore_case()` to a subcommand to allow +any variation of caps to also be accepted. `->ignore_underscore()` is similar, +but for underscores. Children inherit the current setting from the parent. You +cannot add multiple matching subcommand names at the same level (including +`ignore_case` and `ignore_underscore`). + +If you want to require that at least one subcommand is given, use +`.require_subcommand()` on the parent app. You can optionally give an exact +number of subcommands to require, as well. If you give two arguments, that sets +the min and max number allowed. 0 for the max number allowed will allow an +unlimited number of subcommands. As a handy shortcut, a single negative value N +will set "up to N" values. Limiting the maximum number allows you to keep +arguments that match a previous subcommand name from matching. + +If an `App` (main or subcommand) has been parsed on the command line, `->parsed` +will be true (or convert directly to bool). All `App`s have a +`get_subcommands()` method, which returns a list of pointers to the subcommands +passed on the command line. A `got_subcommand(App_or_name)` method is also +provided that will check to see if an `App` pointer or a string name was +collected on the command line. + +For many cases, however, using an app's callback capabilities may be easier. +Every app has a set of callbacks that can be executed at various stages of +parsing; a `C++` lambda function (with capture to get parsed values) can be used +as input to the callback definition function. If you throw `CLI::Success` or +`CLI::RuntimeError(return_value)`, you can even exit the program through the +callback. + +Multiple subcommands are allowed, to allow [`Click`][click] like series of +commands (order is preserved). The same subcommand can be triggered multiple +times but all positional arguments will take precedence over the second and +future calls of the subcommand. `->count()` on the subcommand will return the +number of times the subcommand was called. The subcommand callback will only be +triggered once unless the `.immediate_callback()` flag is set or the callback is +specified through the `parse_complete_callback()` function. The +`final_callback()` is triggered only once. In which case the callback executes +on completion of the subcommand arguments but after the arguments for that +subcommand have been parsed, and can be triggered multiple times. + +Subcommands may also have an empty name either by calling `add_subcommand` with +an empty string for the name or with no arguments. Nameless subcommands function +a similarly to groups in the main `App`. See [Option groups](#option-groups) to +see how this might work. If an option is not defined in the main App, all +nameless subcommands are checked as well. This allows for the options to be +defined in a composable group. The `add_subcommand` function has an overload for +adding a `shared_ptr` so the subcommand(s) could be defined in different +components and merged into a main `App`, or possibly multiple `Apps`. Multiple +nameless subcommands are allowed. Callbacks for nameless subcommands are only +triggered if any options from the subcommand were parsed. Subcommand names given +through the `add_subcommand` method have the same restrictions as option names. + +#### Subcommand options + +There are several options that are supported on the main app and subcommands and +option_groups. These are: + +- `.ignore_case()`: Ignore the case of this subcommand. Inherited by added + subcommands, so is usually used on the main `App`. +- `.ignore_underscore()`: Ignore any underscores in the subcommand name. + Inherited by added subcommands, so is usually used on the main `App`. +- `.allow_windows_style_options()`: Allow command line options to be parsed in + the form of `/s /long /file:file_name.ext` This option does not change how + options are specified in the `add_option` calls or the ability to process + options in the form of `-s --long --file=file_name.ext`. +- `.fallthrough()`: Allow extra unmatched options and positionals to "fall + through" and be matched on a parent option. Subcommands always are allowed to + "fall through" as in they will first attempt to match on the current + subcommand and if they fail will progressively check parents for matching + subcommands. +- `.configurable()`: Allow the subcommand to be triggered from a configuration + file. By default subcommand options in a configuration file do not trigger a + subcommand but will just update default values. +- `.disable()`: Specify that the subcommand is disabled, if given with a bool + value it will enable or disable the subcommand or option group. +- `.disabled_by_default()`: Specify that at the start of parsing the + subcommand/option_group should be disabled. This is useful for allowing some + Subcommands to trigger others. +- `.enabled_by_default()`: Specify that at the start of each parse the + subcommand/option_group should be enabled. This is useful for allowing some + Subcommands to disable others. +- `.silent()`: Specify that the subcommand is silent meaning that if used it + won't show up in the subcommand list. This allows the use of subcommands as + modifiers +- `.validate_positionals()`: Specify that positionals should pass validation + before matching. Validation is specified through `transform`, `check`, and + `each` for an option. If an argument fails validation it is not an error and + matching proceeds to the next available positional or extra arguments. +- `.validate_optional_arguments()`:🆕 Specify that optional arguments should + pass validation before being assigned to an option. Validation is specified + through `transform`, `check`, and `each` for an option. If an argument fails + validation it is not an error and matching proceeds to the next available + positional subcommand or extra arguments. +- `.excludes(option_or_subcommand)`: If given an option pointer or pointer to + another subcommand, these subcommands cannot be given together. In the case of + options, if the option is passed the subcommand cannot be used and will + generate an error. +- `.needs(option_or_subcommand)`: If given an option pointer or pointer to + another subcommand, the subcommands will require the given option to have been + given before this subcommand is validated which occurs prior to execution of + any callback or after parsing is completed. +- `.require_option()`: Require 1 or more options or option groups be used. +- `.require_option(N)`: Require `N` options or option groups, if `N>0`, or up to + `N` if `N<0`. `N=0` resets to the default to 0 or more. +- `.require_option(min, max)`: Explicitly set min and max allowed options or + option groups. Setting `max` to 0 implies unlimited options. +- `.require_subcommand()`: Require 1 or more subcommands. +- `.require_subcommand(N)`: Require `N` subcommands if `N>0`, or up to `N` if + `N<0`. `N=0` resets to the default to 0 or more. +- `.require_subcommand(min, max)`: Explicitly set min and max allowed + subcommands. Setting `max` to 0 is unlimited. +- `.add_subcommand(name="", description="")`: Add a subcommand, returns a + pointer to the internally stored subcommand. +- `.add_subcommand(shared_ptr)`: Add a subcommand by shared_ptr, returns a + pointer to the internally stored subcommand. +- `.remove_subcommand(App)`: Remove a subcommand from the app or subcommand. +- `.got_subcommand(App_or_name)`: Check to see if a subcommand was received on + the command line. +- `.get_subcommands(filter)`: The list of subcommands that match a particular + filter function. +- `.add_option_group(name="", description="")`: Add an + [option group](#option-groups) to an App, an option group is specialized + subcommand intended for containing groups of options or other groups for + controlling how options interact. +- `.get_parent()`: Get the parent App or `nullptr` if called on main App. +- `.get_option(name)`: Get an option pointer by option name will throw if the + specified option is not available, nameless subcommands are also searched +- `.get_option_no_throw(name)`: Get an option pointer by option name. This + function will return a `nullptr` instead of throwing if the option is not + available. +- `.get_options(filter)`: Get the list of all defined option pointers (useful + for processing the app for custom output formats). +- `.parse_order()`: Get the list of option pointers in the order they were + parsed (including duplicates). +- `.formatter(fmt)`: Set a formatter, with signature + `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more + details. +- `.description(str)`: Set/change the description. +- `.get_description()`: Access the description. +- `.alias(str)`: set an alias for the subcommand, this allows subcommands to be + called by more than one name. +- `.parsed()`: True if this subcommand was given on the command line. +- `.count()`: Returns the number of times the subcommand was called. +- `.count(option_name)`: Returns the number of times a particular option was + called. +- `.count_all()`: Returns the total number of arguments a particular subcommand + processed, on the main App it returns the total number of processed commands. +- `.name(name)`: Add or change the name. +- `.callback(void() function)`: Set the callback for an app. Either sets the + `pre_parse_callback` or the `final_callback` depending on the value of + `immediate_callback`. See [Subcommand callbacks](#callbacks) for some + additional details. +- `.parse_complete_callback(void() function)`: Set the callback that runs at the + completion of parsing. For subcommands this is executed at the completion of + the single subcommand and can be executed multiple times. See + [Subcommand callbacks](#callbacks) for some additional details. +- `.final_callback(void() function)`: Set the callback that runs at the end of + all processing. This is the last thing that is executed before returning. See + [Subcommand callbacks](#callbacks) for some additional details. +- `.immediate_callback()`: Specifies whether the callback for a subcommand + should be run as a `parse_complete_callback`(true) or `final_callback`(false). + When used on the main app it will execute the main app callback prior to the + callbacks for a subcommand if they do not also have the `immediate_callback` + flag set. It is preferable to use the `parse_complete_callback` or + `final_callback` directly instead of the `callback` and `immediate_callback` + if one wishes to control the ordering and timing of callback. Though + `immediate_callback` can be used to swap them if that is needed. +- `.pre_parse_callback(void(std::size_t) function)`: Set a callback that + executes after the first argument of an application is processed. See + [Subcommand callbacks](#callbacks) for some additional details. +- `.allow_extras()`: Do not throw an error if extra arguments are left over. +- `.positionals_at_end()`: Specify that positional arguments occur as the last + arguments and throw an error if an unexpected positional is encountered. +- `.prefix_command()`: Like `allow_extras`, but stop immediately on the first + unrecognized item. It is ideal for allowing your app or subcommand to be a + "prefix" to calling another app. +- `.footer(message)`: Set text to appear at the bottom of the help string. +- `.footer(std::string())`: Set a callback to generate a string that will appear + at the end of the help string. +- `.set_help_flag(name, message)`: Set the help flag name and message, returns a + pointer to the created option. +- `.set_version_flag(name, versionString or callback, help_message)`: Set the + version flag name and version string or callback and optional help message, + returns a pointer to the created option. +- `.set_help_all_flag(name, message)`: Set the help all flag name and message, + returns a pointer to the created option. Expands subcommands. +- `.failure_message(func)`: Set the failure message function. Two provided: + `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default). +- `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""` + will be hide the subcommand. +- `[option_name]`: retrieve a const pointer to an option given by `option_name` + for Example `app["--flag1"]` will get a pointer to the option for the + "--flag1" value, `app["--flag1"]->as()` will get the results of the + command line for a flag. The operation will throw an exception if the option + name is not valid. + +> Note: if you have a fixed number of required positional options, that will +> match before subcommand names. `{}` is an empty filter function, and any +> positional argument will match before repeated subcommand names. + +#### Callbacks + +A subcommand has three optional callbacks that are executed at different stages +of processing. The `preparse_callback` is executed once after the first argument +of a subcommand or application is processed and gives an argument for the number +of remaining arguments to process. For the main app the first argument is +considered the program name, for subcommands the first argument is the +subcommand name. For Option groups and nameless subcommands the first argument +is after the first argument or subcommand is processed from that group. The +second callback is executed after parsing. This is known as the +`parse_complete_callback`. For subcommands this is executed immediately after +parsing and can be executed multiple times if a subcommand is called multiple +times. On the main app this callback is executed after all the +`parse_complete_callback`s for the subcommands are executed but prior to any +`final_callback` calls in the subcommand or option groups. If the main app or +subcommand has a config file, no data from the config file will be reflected in +`parse_complete_callback` on named subcommands. For `option_group`s the +`parse_complete_callback` is executed prior to the `parse_complete_callback` on +the main app but after the `config_file` is loaded (if specified). The +`final_callback` is executed after all processing is complete. After the +`parse_complete_callback` is executed on the main app, the used subcommand +`final_callback` are executed followed by the "final callback" for option +groups. The last thing to execute is the `final_callback` for the `main_app`. +For example say an application was set up like + +```cpp +app.parse_complete_callback(ac1); +app.final_callback(ac2); +auto sub1=app.add_subcommand("sub1")->parse_complete_callback(c1)->preparse_callback(pc1); +auto sub2=app.add_subcommand("sub2")->final_callback(c2)->preparse_callback(pc2); +app.preparse_callback( pa); + +... A bunch of other options +``` + +Then the command line is given as + +```bash +program --opt1 opt1_val sub1 --sub1opt --sub1optb val sub2 --sub2opt sub1 --sub1opt2 sub2 --sub2opt2 val +``` + +- `pa` will be called prior to parsing any values with an argument of 13. +- `pc1` will be called immediately after processing the `sub1` command with a + value of 10. +- `c1` will be called when the `sub2` command is encountered. +- `pc2` will be called with value of 6 after the `sub2` command is encountered. +- `c1` will be called again after the second `sub2` command is encountered. +- `ac1` will be called after processing of all arguments +- `c2` will be called once after processing all arguments. +- `ac2` will be called last after completing all lower level callbacks have been + executed. + +A subcommand is considered terminated when one of the following conditions are +met. + +1. There are no more arguments to process +2. Another subcommand is encountered that would not fit in an optional slot of + the subcommand +3. The `positional_mark` (`--`) is encountered and there are no available + positional slots in the subcommand. +4. The `subcommand_terminator` mark (`++`) is encountered + +Prior to executed a `parse_complete_callback` all contained options are +processed before the callback is triggered. If a subcommand with a +`parse_complete_callback` is called again, then the contained options are reset, +and can be triggered again. + +#### Option groups + +The subcommand method + +```cpp +.add_option_group(name,description) +``` + +Will create an option group, and return a pointer to it. The argument for +`description` is optional and can be omitted. An option group allows creation of +a collection of options, similar to the groups function on options, but with +additional controls and requirements. They allow specific sets of options to be +composed and controlled as a collective. For an example see +[range example](https://github.com/CLIUtils/CLI11/blob/main/examples/ranges.cpp). +Option groups are a specialization of an App so all +[functions](#subcommand-options) that work with an App or subcommand also work +on option groups. Options can be created as part of an option group using the +add functions just like a subcommand, or previously created options can be added +through. The name given in an option group must not contain newlines or null +characters. + +```cpp +ogroup->add_option(option_pointer); +ogroup->add_options(option_pointer); +ogroup->add_options(option1,option2,option3,...); +``` + +The option pointers used in this function must be options defined in the parent +application of the option group otherwise an error will be generated. +Subcommands can also be added via + +```cpp +ogroup->add_subcommand(subcom_pointer); +``` + +This results in the subcommand being moved from its parent into the option +group. + +Options in an option group are searched for a command line match after any +options in the main app, so any positionals in the main app would be matched +first. So care must be taken to make sure of the order when using positional +arguments and option groups. Option groups work well with `excludes` and +`require_options` methods, as an application will treat an option group as a +single option for the purpose of counting and requirements, and an option group +will be considered used if any of the options or subcommands contained in it are +used. Option groups allow specifying requirements such as requiring 1 of 3 +options in one group and 1 of 3 options in a different group. Option groups can +contain other groups as well. Disabling an option group will turn off all +options within the group. + +The `CLI::TriggerOn` and `CLI::TriggerOff` methods are helper functions to allow +the use of options/subcommands from one group to trigger another group on or +off. + +```cpp +CLI::TriggerOn(group1_pointer, triggered_group); +CLI::TriggerOff(group2_pointer, disabled_group); +``` + +These functions make use of `preparse_callback`, `enabled_by_default()` and +`disabled_by_default`. The triggered group may be a vector of group pointers. +These methods should only be used once per group and will override any previous +use of the underlying functions. More complex arrangements can be accomplished +using similar methodology with a custom `preparse_callback` function that does +more. + +Additional helper functions `deprecate_option` and `retire_option` are available +to deprecate or retire options + +```cpp +CLI::deprecate_option(option *, replacement_name=""); +CLI::deprecate_option(App,option_name,replacement_name=""); +``` + +will specify that the option is deprecated which will display a message in the +help and a warning on first usage. Deprecated options function normally but will +add a message in the help and display a warning on first use. + +```cpp +CLI::retire_option(App,option *); +CLI::retire_option(App,option_name); +``` + +will create an option that does nothing by default and will display a warning on +first usage that the option is retired and has no effect. If the option exists +it is replaces with a dummy option that takes the same arguments. + +If an empty string is passed the option group name the entire group will be +hidden in the help results. For example. + +```cpp +auto hidden_group=app.add_option_group(""); +``` + +will create a group such that no options in that group are displayed in the help +string. + +### Configuration file + +```cpp +app.set_config(option_name="", + default_file_name="", + help_string="Read an ini file", + required=false) +``` + +If this is called with no arguments, it will remove the configuration file +option (like `set_help_flag`). Setting a configuration option is special. If it +is present, it will be read along with the normal command line arguments. The +file will be read if it exists, and does not throw an error unless `required` is +`true`. Configuration files are in [TOML][] format by default, though the +default reader can also accept files in INI format as well. It should be noted +that CLI11 does not contain a full TOML parser but can read strings from most +TOML file and run them through the CLI11 parser. Other formats can be added by +an adept user, some variations are available through customization points in the +default formatter. An example of a TOML file: + +```toml +# Comments are supported, using a # +# The default section is [default], case insensitive + +value = 1 +str = "A string" +vector = [1,2,3] +str_vector = ["one","two","and three"] + +# Sections map to subcommands +[subcommand] +in_subcommand = Wow +sub.subcommand = true +``` + +or equivalently in INI format + +```ini +; Comments are supported, using a ; +; The default section is [default], case insensitive + +value = 1 +str = "A string" +vector = 1 2 3 +str_vector = "one" "two" "and three" + +; Sections map to subcommands +[subcommand] +in_subcommand = Wow +sub.subcommand = true +``` + +Spaces before and after the name and argument are ignored. Multiple arguments +are separated by spaces. One set of quotes will be removed, preserving spaces +(the same way the command line works). Boolean options can be `true`, `on`, `1`, +`yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). +Sections (and `.` separated names) are treated as subcommands (note: this does +not necessarily mean that subcommand was passed, it just sets the "defaults"). +You cannot set positional-only arguments. Subcommands can be triggered from +configuration files if the `configurable` flag was set on the subcommand. Then +the use of `[subcommand]` notation will trigger a subcommand and cause it to act +as if it were on the command line. + +To print a configuration file from the passed arguments, use +`.config_to_str(default_also=false, write_description=false)`, where +`default_also` will also show any defaulted arguments, and `write_description` +will include the app and option descriptions. See +[Config files](https://cliutils.github.io/CLI11/book/chapters/config.html) for +some additional details and customization points. + +If it is desired that multiple configuration be allowed. Use + +```cpp +app.set_config("--config")->expected(1, X); +``` + +Where X is some positive number and will allow up to `X` configuration files to +be specified by separate `--config` arguments. Value strings with quote +characters in it will be printed with a single quote. All other arguments will +use double quote. Empty strings will use a double quoted argument. Numerical or +boolean values are not quoted. + +For options or flags which allow 0 arguments to be passed using an empty string +in the config file, `{}`, or `[]` will convert the result to the default value +specified via `default_str` or `default_val` on the option 🆕. If no user +specified default is given the result is an empty string or the converted value +of an empty string. + +NOTE: Transforms and checks can be used with the option pointer returned from +set_config like any other option to validate the input if needed. It can also be +used with the built in transform `CLI::FileOnDefaultPath` to look in a default +path as well as the current one. For example + +```cpp +app.set_config("--config")->transform(CLI::FileOnDefaultPath("/to/default/path/")); +``` + +See [Transforming Validators](#transforming-validators) for additional details +on this validator. Multiple transforms or validators can be used either by +multiple calls or using `|` operations with the transform. + +### Inheriting defaults + +Many of the defaults for subcommands and even options are inherited from their +creators. The inherited default values for subcommands are `allow_extras`, +`prefix_command`, `ignore_case`, `ignore_underscore`, `fallthrough`, `group`, +`footer`,`immediate_callback` and maximum number of required subcommands. The +help flag existence, name, and description are inherited, as well. + +Options have defaults for `group`, `required`, `multi_option_policy`, +`ignore_case`, `ignore_underscore`, `delimiter`, and `disable_flag_override`. To +set these defaults, you should set the `option_defaults()` object, for example: + +```cpp +app.option_defaults()->required(); +// All future options will be required +``` + +The default settings for options are inherited to subcommands, as well. + +### Formatting + +The job of formatting help printouts is delegated to a formatter callable object +on Apps and Options. You are free to replace either formatter by calling +`formatter(fmt)` on an `App`, where fmt is any copyable callable with the +correct signature. CLI11 comes with a default App formatter functional, +`Formatter`. It is customizable; you can set `label(key, value)` to replace the +default labels like `REQUIRED`, and `column_width(n)` to set the width of the +columns before you add the functional to the app or option. You can also +override almost any stage of the formatting process in a subclass of either +formatter. If you want to make a new formatter from scratch, you can do that +too; you just need to implement the correct signature. The first argument is a +const pointer to the in question. The formatter will get a `std::string` usage +name as the second option, and a `AppFormatMode` mode for the final option. It +should return a `std::string`. + +The `AppFormatMode` can be `Normal`, `All`, or `Sub`, and it indicates the +situation the help was called in. `Sub` is optional, but the default formatter +uses it to make sure expanded subcommands are called with their own formatter +since you can't access anything but the call operator once a formatter has been +set. + +### Subclassing + +The App class was designed allow toolkits to subclass it, to provide preset +default options (see above) and setup/teardown code. Subcommands remain an +unsubclassed `App`, since those are not expected to need setup and teardown. The +default `App` only adds a help flag, `-h,--help`, than can removed/replaced +using `.set_help_flag(name, help_string)`. You can also set a help-all flag with +`.set_help_all_flag(name, help_string)`; this will expand the subcommands (one +level only). You can remove options if you have pointers to them using +`.remove_option(opt)`. You can add a `pre_callback` override to customize the +after parse but before run behavior, while still giving the user freedom to +`callback` on the main app. + +The most important parse function is `parse(std::vector)`, which +takes a reversed list of arguments (so that `pop_back` processes the args in the +correct order). `get_help_ptr` and `get_config_ptr` give you access to the +help/config option pointers. The standard `parse` manually sets the name from +the first argument, so it should not be in this vector. You can also use +`parse(string, bool)` to split up and parse a single string; the optional +boolean should be set to true if you are including the program name in the +string, and false otherwise. The program name can contain spaces if it is an +existing file, otherwise can be enclosed in quotes(single quote, double quote or +backtick). Embedded quote characters can be escaped with `\`. + +Also, in a related note, the `App` you get a pointer to is stored in the parent +`App` in a `shared_ptr`s (similar to `Option`s) and are deleted when the main +`App` goes out of scope unless the object has another owner. + +### How it works + +Every `add_` option you have seen so far depends on one method that takes a +lambda function. Each of these methods is just making a different lambda +function with capture to populate the option. The function has full access to +the vector of strings, so it knows how many times an option was passed or how +many arguments it received. The lambda returns `true` if it could validate the +option strings, and `false` if it failed. + +Other values can be added as long as they support `operator>>` (and defaults can +be printed if they support `operator<<`). To add a new type, for example, +provide a custom `operator>>` with an `istream` (inside the CLI namespace is +fine if you don't want to interfere with an existing `operator>>`). + +If you wanted to extend this to support a completely new type, use a lambda or +add a specialization of the `lexical_cast` function template in the namespace of +the type you need to convert to. Some examples of some new parsers for +`complex` that support all of the features of a standard `add_options` +call are in [one of the tests](./tests/NewParseTest.cpp). A simpler example is +shown below: + +#### Example + +```cpp +app.add_option("--fancy-count", [](std::vector val){ + std::cout << "This option was given " << val.size() << " times." << std::endl; + return true; + }); +``` + +### Utilities + +There are a few other utilities that are often useful in CLI programming. These +are in separate headers, and do not appear in `CLI11.hpp`, but are completely +independent and can be used as needed. The `Timer`/`AutoTimer` class allows you +to easily time a block of code, with custom print output. + +```cpp +{ +CLI::AutoTimer timer {"My Long Process", CLI::Timer::Big}; +some_long_running_process(); +} +``` + +This will create a timer with a title (default: `Timer`), and will customize the +output using the predefined `Big` output (default: `Simple`). Because it is an +`AutoTimer`, it will print out the time elapsed when the timer is destroyed at +the end of the block. If you use `Timer` instead, you can use `to_string` or +`std::cout << timer << std::endl;` to print the time. The print function can be +any function that takes two strings, the title and the time, and returns a +formatted string for printing. + +### Other libraries + +If you use the excellent [Rang][] library to add color to your terminal in a +safe, multi-platform way, you can combine it with CLI11 nicely: + +```cpp +std::atexit([](){std::cout << rang::style::reset;}); +try { + app.parse(argc, argv); +} catch (const CLI::ParseError &e) { + std::cout << (e.get_exit_code()==0 ? rang::fg::blue : rang::fg::red); + return app.exit(e); +} +``` + +This will print help in blue, errors in red, and will reset before returning the +terminal to the user. + +If you are on a Unix-like system, and you'd like to handle control-c and color, +you can add: + +```cpp + #include + void signal_handler(int s) { + std::cout << std::endl << rang::style::reset << rang::fg::red << rang::fg::bold; + std::cout << "Control-C detected, exiting..." << rang::style::reset << std::endl; + std::exit(1); // will call the correct exit func, no unwinding of the stack though + } +``` + +And, in your main function: + +```cpp + // Nice Control-C + struct sigaction sigIntHandler; + sigIntHandler.sa_handler = signal_handler; + sigemptyset(&sigIntHandler.sa_mask); + sigIntHandler.sa_flags = 0; + sigaction(SIGINT, &sigIntHandler, nullptr); +``` + +## API + +The API is [documented here][api-docs]. Also see the [CLI11 tutorial +GitBook][gitbook]. + +## Examples + +Several short examples of different features are included in the repository. A +brief description of each is included here + +- [callback_passthrough](https://github.com/CLIUtils/CLI11/blob/main/examples/callback_passthrough.cpp): + Example of directly passing remaining arguments through to a callback function + which generates a CLI11 application based on existing arguments. +- [custom_parse](https://github.com/CLIUtils/CLI11/blob/main/examples/custom_parse.cpp): + Based on [Issue #566](https://github.com/CLIUtils/CLI11/issues/566), example + of custom parser +- [digit_args](https://github.com/CLIUtils/CLI11/blob/main/examples/digit_args.cpp): + Based on [Issue #123](https://github.com/CLIUtils/CLI11/issues/123), uses + digit flags to pass a value +- [enum](https://github.com/CLIUtils/CLI11/blob/main/examples/enum.cpp): Using + enumerations in an option, and the use of + [CheckedTransformer](#transforming-validators) +- [enum_ostream](https://github.com/CLIUtils/CLI11/blob/main/examples/enum_ostream.cpp): + In addition to the contents of example enum.cpp, this example shows how a + custom ostream operator overrides CLI11's enum streaming. +- [formatter](https://github.com/CLIUtils/CLI11/blob/main/examples/formatter.cpp): + Illustrating usage of a custom formatter +- [groups](https://github.com/CLIUtils/CLI11/blob/main/examples/groups.cpp): + Example using groups of options for help grouping and a the timer helper class +- [inter_argument_order](https://github.com/CLIUtils/CLI11/blob/main/examples/inter_argument_order.cpp): + An app to practice mixing unlimited arguments, but still recover the original + order. +- [json](https://github.com/CLIUtils/CLI11/blob/main/examples/json.cpp): Using + JSON as a config file parser +- [modhelp](https://github.com/CLIUtils/CLI11/blob/main/examples/modhelp.cpp): + How to modify the help flag to do something other than default +- [nested](https://github.com/CLIUtils/CLI11/blob/main/examples/nested.cpp): + Nested subcommands +- [option_groups](https://github.com/CLIUtils/CLI11/blob/main/examples/option_groups.cpp): + Illustrating the use of option groups and a required number of options. Based + on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88) to set interacting + groups of options +- [positional_arity](https://github.com/CLIUtils/CLI11/blob/main/examples/positional_arity.cpp): + Illustrating use of `preparse_callback` to handle situations where the number + of arguments can determine which should get parsed, Based on + [Issue #166](https://github.com/CLIUtils/CLI11/issues/166) +- [positional_validation](https://github.com/CLIUtils/CLI11/blob/main/examples/positional_validation.cpp): + Example of how positional arguments are validated using the + `validate_positional` flag, also based on + [Issue #166](https://github.com/CLIUtils/CLI11/issues/166) +- [prefix_command](https://github.com/CLIUtils/CLI11/blob/main/examples/prefix_command.cpp): + Illustrating use of the `prefix_command` flag. +- [ranges](https://github.com/CLIUtils/CLI11/blob/main/examples/ranges.cpp): App + to demonstrate exclusionary option groups based on + [Issue #88](https://github.com/CLIUtils/CLI11/issues/88) +- [shapes](https://github.com/CLIUtils/CLI11/blob/main/examples/shapes.cpp): + Illustrating how to set up repeated subcommands Based on + [gitter discussion](https://gitter.im/CLI11gitter/Lobby?at=5c7af6b965ffa019ea788cd5) +- [simple](https://github.com/CLIUtils/CLI11/blob/main/examples/simple.cpp): A + simple example of how to set up a CLI11 Application with different flags and + options +- [subcom_help](https://github.com/CLIUtils/CLI11/blob/main/examples/subcom_help.cpp): + Configuring help for subcommands +- [subcom_partitioned](https://github.com/CLIUtils/CLI11/blob/main/examples/subcom_partitioned.cpp): + Example with a timer and subcommands generated separately and added to the + main app later. +- [subcommands](https://github.com/CLIUtils/CLI11/blob/main/examples/subcommands.cpp): + Short example of subcommands +- [validators](https://github.com/CLIUtils/CLI11/blob/main/examples/validators.cpp): + Example illustrating use of validators + +## Contribute + +To contribute, open an [issue][github issues] or [pull +request][github pull requests] on GitHub, or ask a question on [gitter][]. There +is also a short note to contributors [here](./.github/CONTRIBUTING.md). This +readme roughly follows the [Standard Readme Style][] and includes a mention of +almost every feature of the library. More complex features are documented in +more detail in the [CLI11 tutorial GitBook][gitbook]. + +This project was created by [Henry Schreiner](https://github.com/henryiii) and +major features were added by [Philip Top](https://github.com/phlptp). Special +thanks to all the contributors +([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Henry Schreiner

🐛 📖 💻

Philip Top

🐛 📖 💻

Christoph Bachhuber

💡 💻

Marcus Brinkmann

🐛 💻

Jonas Nilsson

🐛 💻

Doug Johnston

🐛 💻

Lucas Czech

🐛 💻

Rafi Wiener

🐛 💻

Daniel Mensinger

📦

Jesus Briales

💻 🐛

Sean Fisk

🐛 💻

fpeng1985

💻

almikhayl

💻 📦

Andrew Hardin

💻

Anton

💻

Fred Helmesjö

🐛 💻

Kannan

🐛 💻

Khem Raj

💻

Mak Kolybabi

📖

Mathias Soeken

📖

Nathan Hourt

🐛 💻

Paul le Roux

💻 📦

Paweł Bylica

📦

Peter Azmanov

💻

Stéphane Del Pino

💻

Viacheslav Kroilov

💻

christos

💻

deining

📖

elszon

💻

ncihnegn

💻

nurelin

💻

ryan4729

⚠️

Isabella Muerte

📦

KOLANICH

📦

James Gerity

📖

Josh Soref

🔧

geir-t

📦

Ondřej Čertík

🐛

Sam Hocevar

💻

Ryan Curtin

📖

Michael Hall

📖

ferdymercury

📖

Jakob Lover

💻

Dominik Steinberger

💻

D. Fleury

💻

Dan Barowy

📖

Olaf Meeuwissen

💻

dryleev

💻

Max

💻

Alex Dewar

💻
+ + + + + + +This project follows the +[all-contributors](https://github.com/all-contributors/all-contributors) +specification. Contributions of any kind welcome! + +## License + +As of version 1.0, this library is available under a 3-Clause BSD license. See +the [LICENSE](./LICENSE) file for details. + +CLI11 was developed at the [University of Cincinnati][] to support of the +[GooFit][] library under [NSF Award 1414736][]. Version 0.9 was featured in a +[DIANA/HEP][] meeting at CERN ([see the slides][diana slides]). Please give it a +try! Feedback is always welcome. + +[doi-badge]: https://zenodo.org/badge/80064252.svg +[doi-link]: https://zenodo.org/badge/latestdoi/80064252 +[azure-badge]: + https://dev.azure.com/CLIUtils/CLI11/_apis/build/status/CLIUtils.CLI11?branchName=main +[azure]: https://dev.azure.com/CLIUtils/CLI11 +[actions-link]: https://github.com/CLIUtils/CLI11/actions +[actions-badge]: + https://github.com/CLIUtils/CLI11/actions/workflows/tests.yml/badge.svg +[appveyor-badge]: + https://ci.appveyor.com/api/projects/status/82niaxpaa28dwbms/branch/main?svg=true +[appveyor]: https://ci.appveyor.com/project/HenrySchreiner/cli11 +[repology-badge]: https://repology.org/badge/latest-versions/cli11.svg +[repology]: https://repology.org/project/cli11/versions +[codecov-badge]: + https://codecov.io/gh/CLIUtils/CLI11/branch/main/graph/badge.svg?token=2O4wfs8NJO +[codecov]: https://codecov.io/gh/CLIUtils/CLI11 +[gitter-badge]: https://badges.gitter.im/CLI11gitter/Lobby.svg +[gitter]: https://gitter.im/CLI11gitter/Lobby +[license-badge]: https://img.shields.io/badge/License-BSD-blue.svg +[conan-badge]: https://img.shields.io/badge/conan-io-blue +[conan-link]: https://conan.io/center/cli11 +[conda-badge]: https://img.shields.io/conda/vn/conda-forge/cli11.svg +[conda-link]: https://github.com/conda-forge/cli11-feedstock +[github releases]: https://github.com/CLIUtils/CLI11/releases +[github issues]: https://github.com/CLIUtils/CLI11/issues +[github pull requests]: https://github.com/CLIUtils/CLI11/pulls +[goofit]: https://GooFit.github.io +[plumbum]: https://plumbum.readthedocs.io/en/latest/ +[click]: http://click.pocoo.org +[api-docs]: https://CLIUtils.github.io/CLI11/index.html +[rang]: https://github.com/agauniyal/rang +[boost program options]: + http://www.boost.org/doc/libs/1_63_0/doc/html/program_options.html +[the lean mean c++ option parser]: http://optionparser.sourceforge.net +[tclap]: http://tclap.sourceforge.net +[cxxopts]: https://github.com/jarro2783/cxxopts +[docopt]: https://github.com/docopt/docopt.cpp +[gflags]: https://gflags.github.io/gflags +[getopt]: https://www.gnu.org/software/libc/manual/html_node/Getopt.html +[diana/hep]: http://diana-hep.org +[nsf award 1414736]: https://nsf.gov/awardsearch/showAward?AWD_ID=1414736 +[university of cincinnati]: http://www.uc.edu +[gitbook]: https://cliutils.github.io/CLI11/book/ +[cli11 advanced topics/custom converters]: + https://cliutils.gitlab.io/CLI11Tutorial/chapters/advanced-topics.html#custom-converters +[programoptions.hxx]: https://github.com/Fytch/ProgramOptions.hxx +[argument aggregator]: https://github.com/vietjtnguyen/argagg +[args]: https://github.com/Taywee/args +[argh!]: https://github.com/adishavit/argh +[fmt]: https://github.com/fmtlib/fmt +[catch]: https://github.com/philsquared/Catch +[clara]: https://github.com/philsquared/Clara +[version 1.0 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-10/ +[version 1.3 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-13/ +[version 1.6 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-16/ +[version 2.0 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-20/ +[wandbox-badge]: https://img.shields.io/badge/try_2.1-online-blue.svg +[wandbox-link]: https://wandbox.org/permlink/CA5bymNHh0AczdeN +[releases-badge]: https://img.shields.io/github/release/CLIUtils/CLI11.svg +[cli11-po-compare]: + https://iscinumpy.gitlab.io/post/comparing-cli11-and-boostpo/ +[diana slides]: + https://indico.cern.ch/event/619465/contributions/2507949/attachments/1448567/2232649/20170424-diana-2.pdf +[awesome c++]: https://github.com/fffaraz/awesome-cpp/blob/master/README.md#cli +[cli]: https://codesynthesis.com/projects/cli/ +[single file libs]: + https://github.com/nothings/single_file_libs/blob/master/README.md +[codacy-badge]: + https://app.codacy.com/project/badge/Grade/2796b969c1b54321a02ad08affec0800 +[codacy-link]: + https://www.codacy.com/gh/CLIUtils/CLI11/dashboard?utm_source=github.com&utm_medium=referral&utm_content=CLIUtils/CLI11&utm_campaign=Badge_Grade +[hunter]: https://docs.hunter.sh/en/latest/packages/pkg/CLI11.html +[standard readme style]: https://github.com/RichardLitt/standard-readme +[argparse]: https://github.com/p-ranav/argparse +[toml]: https://toml.io +[lyra]: https://github.com/bfgroup/Lyra diff --git a/libs/CLI11/azure-pipelines.yml b/libs/CLI11/azure-pipelines.yml new file mode 100644 index 0000000..d9e4487 --- /dev/null +++ b/libs/CLI11/azure-pipelines.yml @@ -0,0 +1,139 @@ +# C/C++ with GCC +# Build your C/C++ project with GCC using make. +# Add steps that publish test results, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/c-cpp/gcc + +trigger: + - main + - "v*" + +pr: + - main + - "v*" + +variables: + cli11.single: ON + cli11.std: 14 + cli11.build_type: Debug + cli11.options: -DCLI11_EXAMPLES_JSON=ON + cli11.precompile: OFF + CMAKE_BUILD_PARALLEL_LEVEL: 4 + +jobs: + - job: CppLint + pool: + vmImage: "ubuntu-latest" + container: sharaku/cpplint:latest + steps: + - bash: cpplint --counting=detailed --recursive examples include/CLI tests + displayName: Checking against google style guide + + # TODO: Fix macOS error and windows warning in c++17 mode + - job: Native + strategy: + matrix: + Linux14: + vmImage: "ubuntu-latest" + Linux14PC: + vmImage: "ubuntu-latest" + cli11.precompile: ON + macOS17: + vmImage: "macOS-latest" + cli11.std: 17 + macOS11: + vmImage: "macOS-latest" + cli11.std: 11 + macOS11PC: + vmImage: "macOS-latest" + cli11.std: 11 + cli11.precompile: ON + Windows17: + vmImage: "windows-2019" + cli11.std: 17 + Windows17PC: + vmImage: "windows-2019" + cli11.std: 17 + cli11.precompile: ON + Windows11: + vmImage: "windows-2019" + cli11.std: 11 + Windows20: + vmImage: "windows-2022" + cli11.std: 20 + cli11.options: -DCMAKE_CXX_FLAGS="/EHsc" + WindowsLatest: + vmImage: "windows-2022" + cli11.std: 23 + cli11.options: -DCMAKE_CXX_FLAGS="/EHsc" + Linux17nortti: + vmImage: "ubuntu-latest" + cli11.std: 17 + cli11.options: -DCMAKE_CXX_FLAGS="-fno-rtti" + pool: + vmImage: $(vmImage) + steps: + - template: .ci/azure-build.yml + - template: .ci/azure-test.yml + + - job: Meson + pool: + vmImage: "ubuntu-latest" + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: "3.7" + - script: python3 -m pip install meson ninja + displayName: install meson + - script: mkdir tests/mesonTest/subprojects + displayName: generate test directories + - script: ln -s "$(pwd)" tests/mesonTest/subprojects/CLI11 + displayName: generate CLI11 symlink + - script: meson build + displayName: Run meson to generate build + workingDirectory: tests/mesonTest + - script: ninja -C tests/mesonTest/build + displayName: Build with Ninja + - script: ./tests/mesonTest/build/main --help + displayName: Run help + + - job: Docker + variables: + cli11.single: OFF + pool: + vmImage: "ubuntu-latest" + strategy: + matrix: + gcc9: + containerImage: gcc:9 + cli11.std: 17 + cli11.options: -DCMAKE_CXX_FLAGS="-Wstrict-overflow=5" + gcc11: + containerImage: gcc:11 + cli11.std: 20 + gcc8: + containerImage: gcc:8 + cli11.std: 17 + gcc4.8: + containerImage: helics/buildenv:gcc4-8-builder + cli11.std: 11 + cli11.options: + clang3.4: + containerImage: silkeh/clang:3.4 + cli11.std: 11 + clang8: + containerImage: silkeh/clang:8 + cli11.std: 14 + cli11.options: -DCLI11_FORCE_LIBCXX=ON + clang8_17: + containerImage: silkeh/clang:8 + cli11.std: 17 + cli11.options: -DCLI11_FORCE_LIBCXX=ON + clang10_20: + containerImage: silkeh/clang:10 + cli11.std: 20 + cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 + container: $[ variables['containerImage'] ] + steps: + - template: .ci/azure-cmake.yml + - template: .ci/azure-build.yml + - template: .ci/azure-test.yml diff --git a/libs/CLI11/book/.gitignore b/libs/CLI11/book/.gitignore new file mode 100644 index 0000000..bb77454 --- /dev/null +++ b/libs/CLI11/book/.gitignore @@ -0,0 +1,20 @@ +# Node rules: +## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +## Dependency directory +## Commenting this out is preferred by some people, see +## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git +node_modules + +# Book build output +_book + +# eBook build output +*.epub +*.mobi +*.pdf + +a.out + +*build* diff --git a/libs/CLI11/book/CMakeLists.txt b/libs/CLI11/book/CMakeLists.txt new file mode 100644 index 0000000..8934873 --- /dev/null +++ b/libs/CLI11/book/CMakeLists.txt @@ -0,0 +1,7 @@ +set(book_sources README.md SUMMARY.md) + +file( + GLOB book_chapters + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + chapters/*.md) +add_custom_target(cli_book SOURCES ${book_sources} ${book_chapters}) diff --git a/libs/CLI11/book/README.md b/libs/CLI11/book/README.md new file mode 100644 index 0000000..002b8da --- /dev/null +++ b/libs/CLI11/book/README.md @@ -0,0 +1,94 @@ +# CLI11: An introduction + +This gitbook is designed to provide an introduction to using the CLI11 library +to write your own command line programs. The library is designed to be clean, +intuitive, but powerful. There are no requirements beyond C++11 support (and +even `` support not required). It works on Mac, Linux, and Windows, and +has 100% test coverage on all three systems. You can simply drop in a single +header file (`CLI11.hpp` available in [releases][]) to use CLI11 in your own +application. Other ways to integrate it into a build system are listed in the +[README][]. + +The library was inspired the Python libraries [Plumbum][] and [Click][], and +incorporates many of their user friendly features. The library is extensively +documented, with a [friendly introduction][readme], this tutorial book, and more +technical [API docs][]. + +> Feel free to contribute to [this documentation here][cli11tutorial] if +> something can be improved! + +The syntax is simple and scales from a basic application to a massive physics +analysis with multiple models and many parameters and switches. For example, +this is a simple program that has an optional parameter that defaults to 0: + +```term +gitbook $ ./a.out +Parameter value: 0 + +gitbook $ ./a.out -p 4 +Parameter value: 4 + +gitbook $ ./a.out --help +App description +Usage: ./a.out [OPTIONS] + +Options: + -h,--help Print this help message and exit + -p INT Parameter +``` + +Like any good command line application, help is provided. This program can be +implemented in 10 lines: + +[include](code/intro.cpp) + +[Source code](https://github.com/CLIUtils/CLI11/blob/main/book/code/intro.cpp) + +Unlike some other libraries, this is enough to exit correctly and cleanly if +help is requested or if incorrect arguments are passed. You can try this example +out for yourself. To compile with GCC: + +```term +gitbook:examples $ c++ -std=c++11 intro.cpp +``` + +Much more complicated options are handled elegantly: + +```cpp +std::string file; +app.add_option("-f,--file", file, "Require an existing file") + ->required() + ->check(CLI::ExistingFile); +``` + +You can use any valid type; the above example could have used a +`boost::file_system` file instead of a `std::string`. The value is a real value +and does not require any special lookups to access. You do not have to risk +typos by repeating the values after parsing like some libraries require. The +library also handles positional arguments, flags, fixed or unlimited repeating +options, interdependent options, flags, custom validators, help groups, and +more. + +You can use subcommands, as well. Subcommands support callback lambda functions +when parsed, or they can be checked later. You can infinitely nest subcommands, +and each is a full `App` instance, supporting everything listed above. + +Reading/producing `.ini` files for configuration is also supported, as is using +environment variables as input. The base `App` can be subclassed and customized +for use in a toolkit (like [GooFit][]). All the standard shell idioms, like +`--`, work as well. + +CLI11 was developed at the [University of Cincinnati][] in support of the +[GooFit][] library under [NSF Award 1414736][nsf 1414736]. It was featured in a +[DIANA/HEP][] meeting at CERN. Please give it a try! Feedback is always welcome. + +[goofit]: https://github.com/GooFit/GooFit +[diana/hep]: https://diana-hep.org +[cli11tutorial]: https://cliutils.github.io/CLI11/book +[releases]: https://github.com/CLIUtils/CLI11/releases +[api docs]: https://cliutils.github.io/CLI11 +[readme]: https://github.com/CLIUtils/CLI11/blob/main/README.md +[nsf 1414736]: https://nsf.gov/awardsearch/showAward?AWD_ID=1414736 +[university of cincinnati]: https://www.uc.edu +[plumbum]: https://plumbum.readthedocs.io/en/latest/ +[click]: https://click.palletsprojects.com diff --git a/libs/CLI11/book/SUMMARY.md b/libs/CLI11/book/SUMMARY.md new file mode 100644 index 0000000..40f8479 --- /dev/null +++ b/libs/CLI11/book/SUMMARY.md @@ -0,0 +1,15 @@ +# Summary + +- [Introduction](/README.md) +- [Installation](/chapters/installation.md) +- [Basics](/chapters/basics.md) +- [Flags](/chapters/flags.md) +- [Options](/chapters/options.md) +- [Validators](/chapters/validators.md) +- [Subcommands and the App](/chapters/subcommands.md) +- [An advanced example](/chapters/an-advanced-example.md) +- [Configuration files](/chapters/config.md) +- [Formatting help output](/chapters/formatting.md) +- [Toolkits](/chapters/toolkits.md) +- [Advanced topics](/chapters/advanced-topics.md) +- [Internals](/chapters/internals.md) diff --git a/libs/CLI11/book/book.json b/libs/CLI11/book/book.json new file mode 100644 index 0000000..a0a5d2d --- /dev/null +++ b/libs/CLI11/book/book.json @@ -0,0 +1,12 @@ +{ + "title": "CLI11 Tutorial", + "description": "A set of examples and detailed information about CLI11", + "author": "Henry Schreiner", + "plugins": ["include-codeblock", "term", "hints"], + "pluginsConfig": { + "include-codeblock": { + "unindent": true, + "fixlang": true + } + } +} diff --git a/libs/CLI11/book/chapters/advanced-topics.md b/libs/CLI11/book/chapters/advanced-topics.md new file mode 100644 index 0000000..b450eb7 --- /dev/null +++ b/libs/CLI11/book/chapters/advanced-topics.md @@ -0,0 +1,152 @@ +# Advanced topics + +## Environment variables + +Environment variables can be used to fill in the value of an option: + +```cpp +std::string opt; +app.add_option("--my_option", opt)->envname("MY_OPTION"); +``` + +If not given on the command line, the environment variable will be checked and +read from if it exists. All the standard tools, like default and required, work +as expected. If passed on the command line, this will ignore the environment +variable. + +## Needs/excludes + +You can set a network of requirements. For example, if flag a needs flag b but +cannot be given with flag c, that would be: + +```cpp +auto a = app.add_flag("-a"); +auto b = app.add_flag("-b"); +auto c = app.add_flag("-c"); + +a->needs(b); +a->excludes(c); +``` + +CLI11 will make sure your network of requirements makes sense, and will throw an +error immediately if it does not. + +## Custom option callbacks + +You can make a completely generic option with a custom callback. For example, if +you wanted to add a complex number (already exists, so please don't actually do +this): + +```cpp +CLI::Option * +add_option(CLI::App &app, std::string name, cx &variable, std::string description = "", bool defaulted = false) { + CLI::callback_t fun = [&variable](CLI::results_t res) { + double x, y; + bool worked = CLI::detail::lexical_cast(res[0], x) && CLI::detail::lexical_cast(res[1], y); + if(worked) + variable = cx(x, y); + return worked; + }; + + CLI::Option *opt = app.add_option(name, fun, description, defaulted); + opt->set_custom_option("COMPLEX", 2); + if(defaulted) { + std::stringstream out; + out << variable; + opt->set_default_str(out.str()); + } + return opt; +} +``` + +Then you could use it like this: + +```cpp +std::complex comp{0, 0}; +add_option(app, "-c,--complex", comp); +``` + +## Custom converters + +You can add your own converters to allow CLI11 to accept more option types in +the standard calls. These can only be used for "single" size options (so +complex, vector, etc. are a separate topic). If you set up a custom +`istringstream& operator <<` overload before include CLI11, you can support +different conversions. If you place this in the CLI namespace, you can even keep +this from affecting the rest of your code. Here's how you could add +`boost::optional` for a compiler that does not have `__has_include`: + +```cpp +// CLI11 already does this if __has_include is defined +#ifndef __has_include + +#include + +// Use CLI namespace to avoid the conversion leaking into your other code +namespace CLI { + +template std::istringstream &operator>>(std::istringstream &in, boost::optional &val) { + T v; + in >> v; + val = v; + return in; +} + +} + +#endif + +#include +``` + +This is an example of how to use the system only; if you are just looking for a +way to activate `boost::optional` support on older compilers, you should define +`CLI11_BOOST_OPTIONAL` before including a CLI11 file, you'll get the +`boost::optional` support. + +## Custom converters and type names: std::chrono example + +An example of adding a custom converter and typename for `std::chrono` follows: + +```cpp +namespace CLI +{ + template + std::istringstream &operator>>(std::istringstream &in, std::chrono::duration &val) + { + T v; + in >> v; + val = std::chrono::duration(v); + return in; + } + + template + std::stringstream &operator<<(std::stringstream &in, std::chrono::duration &val) + { + in << val.count(); + return in; + } + } + +#include + +namespace CLI +{ + namespace detail + { + template <> + constexpr const char *type_name() + { + return "TIME [H]"; + } + + template <> + constexpr const char *type_name() + { + return "TIME [MIN]"; + } + } +} +``` + +Thanks to Olivier Hartmann for the example. diff --git a/libs/CLI11/book/chapters/an-advanced-example.md b/libs/CLI11/book/chapters/an-advanced-example.md new file mode 100644 index 0000000..0b1a069 --- /dev/null +++ b/libs/CLI11/book/chapters/an-advanced-example.md @@ -0,0 +1,39 @@ +# Making a git clone + +Let's try our hand at a little `git` clone, called `geet`. It will just print +it's intent, rather than running actual code, since it's just a demonstration. +Let's start by adding an app and requiring 1 subcommand to run: + +[include:"Intro"](../code/geet.cpp) + +Now, let's define the first subcommand, `add`, along with a few options: + +[include:"Add"](../code/geet.cpp) + +Now, let's add `commit`: + +[include:"Commit"](../code/geet.cpp) + +All that's need now is the parse call. We'll print a little message after the +code runs, and then return: + +[include:"Parse"](../code/geet.cpp) + +[Source code](https://github.com/CLIUtils/CLI11/tree/main/book/code/geet.cpp) + +If you compile and run: + +```term +gitbook:examples $ c++ -std=c++11 geet.cpp -o geet +``` + +You'll see it behaves pretty much like `git`. + +## Multi-file App parse code + +This example could be made much nicer if it was split into files, one per +subcommand. If you simply use shared pointers instead of raw values in the +lambda capture, you can tie the lifetime to the lambda function lifetime. CLI11 +has a +[multifile example](https://github.com/CLIUtils/CLI11/tree/main/examples/subcom_in_files) +in its example folder. diff --git a/libs/CLI11/book/chapters/basics.md b/libs/CLI11/book/chapters/basics.md new file mode 100644 index 0000000..29daf73 --- /dev/null +++ b/libs/CLI11/book/chapters/basics.md @@ -0,0 +1,39 @@ +# The Basics + +The simplest CLI11 program looks like this: + +[include](../code/simplest.cpp) + +The first line includes the library; this explicitly uses the single file +edition (see [Selecting an edition](/chapters/installation)). + +After entering the main function, you'll see that a `CLI::App` object is +created. This is the basis for all interactions with the library. You could +optionally provide a description for your app here. + +A normal CLI11 application would define some flags and options next. This is a +simplest possible example, so we'll go on. + +The macro `CLI11_PARSE` just runs five simple lines. This internally runs +`app.parse(argc, argv)`, which takes the command line info from C++ and parses +it. If there is an error, it throws a `ParseError`; if you catch it, you can use +`app.exit` with the error as an argument to print a nice message and produce the +correct return code for your application. + +If you just use `app.parse` directly, your application will still work, but the +stack will not be correctly unwound since you have an uncaught exception, and +the command line output will be cluttered, especially for help. + +For this (and most of the examples in this book) we will assume that we have the +`CLI11.hpp` file in the current directory and that we are creating an output +executable `a.out` on a macOS or Linux system. The commands to compile and test +this example would be: + +```term +gitbook:examples $ g++ -std=c++11 simplest.cpp +gitbook:examples $ ./a.out -h +Usage: ./a.out [OPTIONS] + +Options: + -h,--help Print this help message and exit +``` diff --git a/libs/CLI11/book/chapters/config.md b/libs/CLI11/book/chapters/config.md new file mode 100644 index 0000000..d062c65 --- /dev/null +++ b/libs/CLI11/book/chapters/config.md @@ -0,0 +1,340 @@ +# Accepting configure files + +## Reading a configure file + +You can tell your app to allow configure files with `set_config("--config")`. +There are arguments: the first is the option name. If empty, it will clear the +config flag. The second item is the default file name. If that is specified, the +config will try to read that file. The third item is the help string, with a +reasonable default, and the final argument is a boolean (default: false) that +indicates that the configuration file is required and an error will be thrown if +the file is not found and this is set to true. + +### Adding a default path + +if it is desired that config files be searched for a in a default path the +`CLI::FileOnDefaultPath` transform can be used. + +```cpp +app.set_config("--config")->transform(CLI::FileOnDefaultPath("/default_path/")); +``` + +This will allow specified files to either exist as given or on a specified +default path. + +```cpp +app.set_config("--config") + ->transform(CLI::FileOnDefaultPath("/default_path/")) + ->transform(CLI::FileOnDefaultPath("/default_path2/",false)); +``` + +Multiple default paths can be specified through this mechanism. The last +transform given is executed first so the error return must be disabled so it can +be chained to the first. The same effect can be achieved though the or(`|`) +operation with validators + +```cpp +app.set_config("--config") + ->transform(CLI::FileOnDefaultPath("/default_path2/") | CLI::FileOnDefaultPath("/default_path/")); +``` + +### Extra fields + +Sometimes configuration files are used for multiple purposes so CLI11 allows +options on how to deal with extra fields + +```cpp +app.allow_config_extras(true); +``` + +will allow capture the extras in the extras field of the app. (NOTE: This also +sets the `allow_extras` in the app to true) + +```cpp +app.allow_config_extras(false); +``` + +will generate an error if there are any extra fields for slightly finer control +there is a scoped enumeration of the modes or + +```cpp +app.allow_config_extras(CLI::config_extras_mode::ignore); +``` + +will completely ignore extra parameters in the config file. This mode is the +default. + +```cpp +app.allow_config_extras(CLI::config_extras_mode::capture); +``` + +will store the unrecognized options in the app extras fields. This option is the +closest equivalent to `app.allow_config_extras(true);` with the exception that +it does not also set the `allow_extras` flag so using this option without also +setting `allow_extras(true)` will generate an error which may or may not be the +desired behavior. + +```cpp +app.allow_config_extras(CLI::config_extras_mode::error); +``` + +is equivalent to `app.allow_config_extras(false);` + +```cpp +app.allow_config_extras(CLI::config_extras_mode::ignore_all); +``` + +will completely ignore any mismatches, extras, or other issues with the config +file + +### Getting the used configuration file name + +If it is needed to get the configuration file name used this can be obtained via +`app.get_config_ptr()->as()` or +`app["--config"]->as()` assuming `--config` was the configuration +option name. + +## Configure file format + +Here is an example configuration file, in +[TOML](https://github.com/toml-lang/toml) format: + +```ini +# Comments are supported, using a # +# The default section is [default], case insensitive + +value = 1 +str = "A string" +vector = [1,2,3] + +# Section map to subcommands +[subcommand] +in_subcommand = Wow +[subcommand.sub] +subcommand = true # could also be give as sub.subcommand=true +``` + +Spaces before and after the name and argument are ignored. Multiple arguments +are separated by spaces. One set of quotes will be removed, preserving spaces +(the same way the command line works). Boolean options can be `true`, `on`, `1`, +`y`, `t`, `+`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `n`, `f`, `-`, +`disable`, (case insensitive). Sections (and `.` separated names) are treated as +subcommands (note: this does not necessarily mean that subcommand was passed, it +just sets the "defaults". If a subcommand is set to `configurable` then passing +the subcommand using `[sub]` in a configuration file will trigger the +subcommand.) + +CLI11 also supports configuration file in INI format. + +```ini +; Comments are supported, using a ; +; The default section is [default], case insensitive + +value = 1 +str = "A string" +vector = 1 2 3 + +; Section map to subcommands +[subcommand] +in_subcommand = Wow +sub.subcommand = true +``` + +The main differences are in vector notation and comment character. Note: CLI11 +is not a full TOML parser as it just reads values as strings. It is possible +(but not recommended) to mix notation. + +## Multiple configuration files + +If it is desired that multiple configuration be allowed. Use + +```cpp +app.set_config("--config")->expected(1, X); +``` + +Where X is some positive integer and will allow up to `X` configuration files to +be specified by separate `--config` arguments. + +## Writing out a configure file + +To print a configuration file from the passed arguments, use +`.config_to_str(default_also=false, write_description=false)`, where +`default_also` will also show any defaulted arguments, and `write_description` +will include option descriptions and the App description + +```cpp + CLI::App app; + app.add_option(...); + // several other options + CLI11_PARSE(app, argc, argv); + //the config printout should be after the parse to capture the given arguments + std::cout<to_config(&app,true,true,"sub."); + //prefix can be used to set a prefix before each argument, like "sub." +``` + +### Customization of configure file output + +The default config parser/generator has some customization points that allow +variations on the TOML format. The default formatter has a base configuration +that matches the TOML format. It defines 5 characters that define how different +aspects of the configuration are handled. You must use +`get_config_formatter_base()` to have access to these fields + +```cpp +/// the character used for comments +char commentChar = '#'; +/// the character used to start an array '\0' is a default to not use +char arrayStart = '['; +/// the character used to end an array '\0' is a default to not use +char arrayEnd = ']'; +/// the character used to separate elements in an array +char arraySeparator = ','; +/// the character used separate the name from the value +char valueDelimiter = '='; +/// the character to use around strings +char stringQuote = '"'; +/// the character to use around single characters +char characterQuote = '\''; +/// the maximum number of layers to allow +uint8_t maximumLayers{255}; +/// the separator used to separator parent layers +char parentSeparatorChar{'.'}; +/// Specify the configuration index to use for arrayed sections +uint16_t configIndex{0}; +/// Specify the configuration section that should be used +std::string configSection; +``` + +These can be modified via setter functions + +- `ConfigBase *comment(char cchar)`: Specify the character to start a comment + block +- `ConfigBase *arrayBounds(char aStart, char aEnd)`: Specify the start and end + characters for an array +- `ConfigBase *arrayDelimiter(char aSep)`: Specify the delimiter character for + an array +- `ConfigBase *valueSeparator(char vSep)`: Specify the delimiter between a name + and value +- `ConfigBase *quoteCharacter(char qString, char qChar)` :specify the characters + to use around strings and single characters +- `ConfigBase *maxLayers(uint8_t layers)` : specify the maximum number of parent + layers to process. This is useful to limit processing for larger config files +- `ConfigBase *parentSeparator(char sep)` : specify the character to separate + parent layers from options +- `ConfigBase *section(const std::string §ionName)` : specify the section + name to use to get the option values, only this section will be processed +- `ConfigBase *index(uint16_t sectionIndex)` : specify an index section to use + for processing if multiple TOML sections of the same name are present + `[[section]]` + +For example, to specify reading a configure file that used `:` to separate name +and values: + +```cpp +auto config_base=app.get_config_formatter_base(); +config_base->valueSeparator(':'); +``` + +The default configuration file will read INI files, but will write out files in +the TOML format. To specify outputting INI formatted files use + +```cpp +app.config_formatter(std::make_shared()); +``` + +which makes use of a predefined modification of the ConfigBase class which TOML +also uses. If a custom formatter is used that is not inheriting from the from +ConfigBase class `get_config_formatter_base() will return a nullptr if RTTI is +on (usually the default), or garbage if RTTI is off, so some care must be +exercised in its use with custom configurations. + +## Custom formats + +You can invent a custom format and set that instead of the default INI +formatter. You need to inherit from `CLI::Config` and implement the following +two functions: + +```cpp +std::string to_config(const CLI::App *app, bool default_also, bool, std::string) const; +std::vector from_config(std::istream &input) const; +``` + +The `CLI::ConfigItem`s that you return are simple structures with a name, a +vector of parents, and a vector of results. A optionally customizable `to_flag` +method on the formatter lets you change what happens when a ConfigItem turns +into a flag. + +Finally, set your new class as new config formatter: + +```cpp +app.config_formatter(std::make_shared()); +``` + +See +[`examples/json.cpp`](https://github.com/CLIUtils/CLI11/blob/main/examples/json.cpp) +for a complete JSON config example. + +### Trivial JSON configuration example + +```JSON +{ + "test": 56, + "testb": "test", + "flag": true +} +``` + +The parser can handle these structures with only a minor tweak + +```cpp +app.get_config_formatter_base()->valueSeparator(':'); +``` + +The open and close brackets must be on a separate line and the comma gets +interpreted as an array separator but since no values are after the comma they +get ignored as well. This will not support multiple layers or sections or any +other moderately complex JSON, but can work if the input file is simple. + +## Triggering Subcommands + +Configuration files can be used to trigger subcommands if a subcommand is set to +configure. By default configuration file just set the default values of a +subcommand. But if the `configure()` option is set on a subcommand then the if +the subcommand is utilized via a `[subname]` block in the configuration file it +will act as if it were called from the command line. Subsubcommands can be +triggered via `[subname.subsubname]`. Using the `[[subname]]` will be as if the +subcommand were triggered multiple times from the command line. This +functionality can allow the configuration file to act as a scripting file. + +For custom configuration files this behavior can be triggered by specifying the +parent subcommands in the structure and `++` as the name to open a new +subcommand scope and `--` to close it. These names trigger the different +callbacks of configurable subcommands. + +## Stream parsing + +In addition to the regular parse functions a +`parse_from_stream(std::istream &input)` is available to directly parse a stream +operator. For example to process some arguments in an already open file stream. +The stream is fed directly in the config parser so bypasses the normal command +line parsing. + +## Implementation Notes + +The config file input works with any form of the option given: Long, short, +positional, or the environment variable name. When generating a config file it +will create an option name in following priority. + +1. First long name +2. Positional name +3. First short name +4. Environment name diff --git a/libs/CLI11/book/chapters/flags.md b/libs/CLI11/book/chapters/flags.md new file mode 100644 index 0000000..16134b2 --- /dev/null +++ b/libs/CLI11/book/chapters/flags.md @@ -0,0 +1,167 @@ +# Adding Flags + +The most basic addition to a command line program is a flag. This is simply +something that does not take any arguments. Adding a flag in CLI11 is done in +one of three ways. + +## Boolean flags + +The simplest way to add a flag is probably a boolean flag: + +```cpp +bool my_flag{false}; +app.add_flag("-f", my_flag, "Optional description"); +``` + +This will bind the flag `-f` to the boolean `my_flag`. After the parsing step, +`my_flag` will be `false` if the flag was not found on the command line, or +`true` if it was. By default, it will be allowed any number of times, but if you +explicitly\[^1\] request `->take_last(false)`, it will only be allowed once; +passing something like `./my_app -f -f` or `./my_app -ff` will throw a +`ParseError` with a nice help description. A flag name may start with any +character except ('-', ' ', '\n', and '!'). For long flags, after the first +character all characters are allowed except ('=',':','{',' ', '\n'). Names are +given as a comma separated string, with the dash or dashes. An flag can have as +many names as you want, and afterward, using `count`, you can use any of the +names, with dashes as needed. + +## Integer flags + +If you want to allow multiple flags and count their value, simply use any +integral variables instead of a bool: + +```cpp +int my_flag{0}; +app.add_flag("-f", my_flag, "Optional description"); +``` + +After the parsing step, `my_flag` will contain the number of times this flag was +found on the command line, including 0 if not found. + +This behavior can also be controlled manually via +`->multi_option_policy(CLI::MultiOptionPolicy::Sum)` as of version 2.2. + +## Arbitrary type flags + +CLI11 allows the type of the variable to assign to in the `add_flag` function to +be any supported type. This is particularly useful in combination with +specifying default values for flags. The allowed types include bool, int, float, +vector, enum, or string-like. + +### Default Flag Values + +Flag options specified through the `add_flag*` functions allow a syntax for the +option names to default particular options to a false value or any other value +if some flags are passed. For example: + +```cpp +app.add_flag("--flag,!--no-flag",result,"help for flag"); +``` + +specifies that if `--flag` is passed on the command line result will be true or +contain a value of 1. If `--no-flag` is passed `result` will contain false or -1 +if `result` is a signed integer type, or 0 if it is an unsigned type. An +alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`; +this is equivalent to the previous example. This also works for short form +options `"-f,!-n"` or `"-f,-n{false}"`. If `variable_to_bind_to` is anything but +an integer value the default behavior is to take the last value given, while if +`variable_to_bind_to` is an integer type the behavior will be to sum all the +given arguments and return the result. This can be modified if needed by +changing the `multi_option_policy` on each flag (this is not inherited). The +default value can be any value. For example if you wished to define a numerical +flag: + +```cpp +app.add_flag("-1{1},-2{2},-3{3}",result,"numerical flag") +``` + +using any of those flags on the command line will result in the specified number +in the output. Similar things can be done for string values, and enumerations, +as long as the default value can be converted to the given type. + +## Pure flags + +Every command that starts with `add_`, such as the flag commands, return a +pointer to the internally stored `CLI::Option` that describes your addition. If +you prefer, you can capture this pointer and use it, and that allows you to skip +adding a variable to bind to entirely: + +```cpp +CLI::Option* my_flag = app.add_flag("-f", "Optional description"); +``` + +After parsing, you can use `my_flag->count()` to count the number of times this +was found. You can also directly use the value (`*my_flag`) as a bool. +`CLI::Option` will be discussed in more detail later. + +## Callback flags + +If you want to define a callback that runs when you make a flag, you can use +`add_flag_function` (C++11 or newer) or `add_flag` (C++14 or newer only) to add +a callback function. The function should have the signature `void(std::size_t)`. +This could be useful for a version printout, etc. + +```cpp +auto callback = [](int count){std::cout << "This was called " << count << " times";}; +app.add_flag_function("-c", callback, "Optional description"); +``` + +## Aliases + +The name string, the first item of every `add_` method, can contain as many +short and long names as you want, separated by commas. For example, +`"-a,--alpha,-b,--beta"` would allow any of those to be recognized on the +command line. If you use the same name twice, or if you use the same name in +multiple flags, CLI11 will immediately throw a `CLI::ConstructionError` +describing your problem (it will not wait until the parsing step). + +If you want to make an option case insensitive, you can use the +`->ignore_case()` method on the `CLI::Option` to do that. For example, + +```cpp +bool flag{false}; +app.add_flag("--flag", flag) + ->ignore_case(); +``` + +would allow the following to count as passing the flag: + +```term +gitbook $ ./my_app --fLaG +``` + +## Example + +The following program will take several flags: + +[include:"define"](../code/flags.cpp) + +The values would be used like this: + +[include:"usage"](../code/flags.cpp) + +[Source code](https://github.com/CLIUtils/CLI11/tree/main/book/code/flags.cpp) + +If you compile and run: + +```term +gitbook:examples $ g++ -std=c++11 flags.cpp +gitbook:examples $ ./a.out -h +Flag example program +Usage: ./a.out [OPTIONS] + +Options: + -h,--help Print this help message and exit + -b,--bool This is a bool flag + -i,--int This is an int flag + -p,--plain This is a plain flag + +gitbook:examples $ ./a.out -bii --plain -i +The flags program +Bool flag passed +Flag int: 3 +Flag plain: 1 +``` + +\[^1\]: It will not inherit this from the parent defaults, since this is often +useful even if you don't want all options to allow multiple passed options. diff --git a/libs/CLI11/book/chapters/formatting.md b/libs/CLI11/book/chapters/formatting.md new file mode 100644 index 0000000..66f0765 --- /dev/null +++ b/libs/CLI11/book/chapters/formatting.md @@ -0,0 +1,86 @@ +# Formatting help output + +{% hint style='info' %} New in CLI11 1.6 {% endhint %} + +## Customizing an existing formatter + +In CLI11, you can control the output of the help printout in full or in part. +The default formatter was written in such a way as to be customizable. You can +use `app.get_formatter()` to get the current formatter. The formatter you set +will be inherited by subcommands that are created after you set the formatter. + +There are several configuration options that you can set: + +| Set method | Description | Availability | +| --------------------- | -------------------------------- | ------------ | +| `column_width(width)` | The width of the columns | Both | +| `label(key, value)` | Set a label to a different value | Both | + +Labels will map the built in names and type names from key to value if present. +For example, if you wanted to change the width of the columns to 40 and the +`REQUIRED` label from `(REQUIRED)` to `(MUST HAVE)`: + +```cpp +app.get_formatter()->column_width(40); +app.get_formatter()->label("REQUIRED", "(MUST HAVE)"); +``` + +## Subclassing + +You can further configure pieces of the code while still keeping most of the +formatting intact by subclassing either formatter and replacing any of the +methods with your own. The formatters use virtual functions most places, so you +are free to add or change anything about them. For example, if you wanted to +remove the info that shows up between the option name and the description: + +```cpp +class MyFormatter : public CLI::Formatter { + public: + std::string make_option_opts(const CLI::Option *) const override {return "";} +}; +app.formatter(std::make_shared()); +``` + +Look at the class definitions in `FormatterFwd.hpp` or the method definitions in +`Formatter.hpp` to see what methods you have access to and how they are put +together. + +## Anatomy of a help message + +This is a normal printout, with `<>` indicating the methods used to produce each +line. + +```text + + + + + + + + ... + + + + +``` + +`make_usage` calls `make_option_usage(opt)` on all the positionals to build that +part of the line. `make_subcommand` passes the subcommand as the app pointer. + +The `make_groups` print the group name then call `make_option(o)` on the options +listed in that group. The normal printout for an option looks like this: + +```text + make_option_opts(o) + ┌───┴────┐ + -n,--name (REQUIRED) This is a description +└────┬────┘ └──────────┬──────────┘ +make_option_name(o,p) make_option_desc(o) +``` + +Notes: + +- `*1`: This signature depends on whether the call is from a positional or + optional. +- `o` is opt pointer, `p` is true if positional. diff --git a/libs/CLI11/book/chapters/installation.md b/libs/CLI11/book/chapters/installation.md new file mode 100644 index 0000000..c8af7df --- /dev/null +++ b/libs/CLI11/book/chapters/installation.md @@ -0,0 +1,114 @@ +# Installation + +## Single file edition + +```cpp +#include +``` + +This example uses the single file edition of CLI11. You can download `CLI11.hpp` +from the latest release and put it into the same folder as your source code, +then compile this with C++ enabled. For a larger project, you can just put this +in an include folder and you are set. + +## Full edition + +```cpp +#include +``` + +If you want to use CLI11 in its full form, you can also use the original +multiple file edition. This has an extra utility (`Timer`), and is does not +require that you use a release. The only change to your code would be the +include shown above. + +### CMake support for the full edition + +If you use CMake 3.4+ for your project (highly recommended), CLI11 comes with a +powerful CMakeLists.txt file that was designed to also be used with +`add_subproject`. You can add the repository to your code (preferably as a git +submodule), then add the following line to your project (assuming your folder is +called CLI11): + +```cmake +add_subdirectory(CLI11) +``` + +Then, you will have a target `CLI11::CLI11` that you can link to with +`target_link_libraries`. It will provide the include paths you need for the +library. This is the way [GooFit](https://github.com/GooFit/GooFit) uses CLI11, +for example. + +You can also configure and optionally install CLI11, and CMake will create the +necessary `lib/cmake/CLI11/CLI11Config.cmake` files, so +`find_package(CLI11 CONFIG REQUIRED)` also works. + +If you use conan.io, CLI11 supports that too. + +### Running tests on the full edition + +CLI11 has examples and tests that can be accessed using a CMake build on any +platform. Simply build and run ctest to run the 200+ tests to ensure CLI11 works +on your system. + +As an example of the build system, the following code will download and test +CLI11 in a simple Alpine Linux docker container [^1]: + +```term +gitbook:~ $ docker run -it alpine +root:/ # apk add --no-cache g++ cmake make git +fetch ... +root:/ # git clone https://github.com/CLIUtils/CLI11.git +Cloning into 'CLI11' ... +root:/ # cd CLI11 +root:CLI11 # mkdir build +root:CLI11 # cd build +root:build # cmake .. +-- The CXX compiler identification is GNU 6.3.0 ... +root:build # make +Scanning dependencies ... +root:build # make test +[warning]Running tests... +Test project /CLI11/build + Start 1: HelpersTest + 1/10 Test #1: HelpersTest ...................... Passed 0.01 sec + Start 2: IniTest + 2/10 Test #2: IniTest .......................... Passed 0.01 sec + Start 3: SimpleTest + 3/10 Test #3: SimpleTest ....................... Passed 0.01 sec + Start 4: AppTest + 4/10 Test #4: AppTest .......................... Passed 0.02 sec + Start 5: CreationTest + 5/10 Test #5: CreationTest ..................... Passed 0.01 sec + Start 6: SubcommandTest + 6/10 Test #6: SubcommandTest ................... Passed 0.01 sec + Start 7: HelpTest + 7/10 Test #7: HelpTest ......................... Passed 0.01 sec + Start 8: NewParseTest + 8/10 Test #8: NewParseTest ..................... Passed 0.01 sec + Start 9: TimerTest + 9/10 Test #9: TimerTest ........................ Passed 0.24 sec + Start 10: link_test_2 +10/10 Test #10: link_test_2 ...................... Passed 0.00 sec + +100% tests passed, 0 tests failed out of 10 + +Total Test time (real) = 0.34 sec +``` + +For the curious, the CMake options and defaults are listed below. Most options +default to off if CLI11 is used as a subdirectory in another project. + +| Option | Description | +| ----------------------------- | ----------------------------------------------------------------------------------------------- | +| `CLI11_SINGLE_FILE=ON` | Build the `CLI11.hpp` file from the sources. Requires Python (version 3 or 2.7). | +| `CLI11_SINGLE_FILE_TESTS=OFF` | Run the tests on the generated single file version as well | +| `CLI11_EXAMPLES=ON` | Build the example programs. | +| `CLI11_TESTING=ON` | Build the tests. | +| `CLI11_CLANG_TIDY=OFF` | Run `clang-tidy` on the examples and headers. Requires CMake 3.6+. | +| `CLI11_CLANG_TIDY_OPTIONS=""` | Options to pass to `clang-tidy`, such as `-fix` (single threaded build only if applying fixes!) | + +[^1]: + Docker is being used to create a pristine disposable environment; there is + nothing special about this container. Alpine is being used because it is + small, modern, and fast. Commands are similar on any other platform. diff --git a/libs/CLI11/book/chapters/internals.md b/libs/CLI11/book/chapters/internals.md new file mode 100644 index 0000000..f8479c5 --- /dev/null +++ b/libs/CLI11/book/chapters/internals.md @@ -0,0 +1,54 @@ +# CLI11 Internals + +## Callbacks + +The library was designed to bind to existing variables without requiring typed +classes or inheritance. This is accomplished through lambda functions. + +This looks like: + +```cpp +Option* add_option(string name, T item) { + this->function = [&item](string value){ + item = detail::lexical_cast(value); + } +} +``` + +Obviously, you can't access `T` after the `add_` method is over, so it stores +the string representation of the default value if it receives the special `true` +value as the final argument (not shown above). + +## Parsing + +Parsing follows the following procedure: + +1. `_validate`: Make sure the defined options and subcommands are self + consistent. +2. `_parse`: Main parsing routine. See below. +3. `_run_callback`: Run an App callback if present. + +The parsing phase is the most interesting: + +1. `_parse_single`: Run on each entry on the command line and fill the + options/subcommands. +2. `_process`: Run the procedure listed below. +3. `_process_extra`: This throws an error if needed on extra arguments that + didn't fit in the parse. + +The `_process` procedure runs the following steps; each step is recursive and +completes all subcommands before moving to the next step (new in 1.7). This +ensures that interactions between options and subcommand options is consistent. + +1. `_process_ini`: This reads an INI file and fills/changes options as needed. +2. `_process_env`: Look for environment variables. +3. `_process_callbacks`: Run the callback functions - this fills out the + variables. +4. `_process_help_flags`: Run help flags if present (and quit). +5. `_process_requirements`: Make sure needs/excludes, required number of options + present. + +## Exceptions + +The library immediately returns a C++ exception when it detects a problem, such +as an incorrect construction or a malformed command line. diff --git a/libs/CLI11/book/chapters/options.md b/libs/CLI11/book/chapters/options.md new file mode 100644 index 0000000..3944711 --- /dev/null +++ b/libs/CLI11/book/chapters/options.md @@ -0,0 +1,459 @@ +# Options + +## Simple options + +The most versatile addition to a command line program is an option. This is like +a flag, but it takes an argument. CLI11 handles all the details for many types +of options for you, based on their type. To add an option: + +```cpp +int int_option{0}; +app.add_option("-i", int_option, "Optional description"); +``` + +This will bind the option `-i` to the integer `int_option`. On the command line, +a single value that can be converted to an integer will be expected. Non-integer +results will fail. If that option is not given, CLI11 will not touch the initial +value. This allows you to set up defaults by simply setting your value +beforehand. If you want CLI11 to display your default value, you can add +`->capture_default_str()` after the option. + +```cpp +int int_option{0}; +app.add_option("-i", int_option, "Optional description")->capture_default_str(); +``` + +You can use any C++ int-like type, not just `int`. CLI11 understands the +following categories of types: + +| Type | CLI11 | +| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| number like | Integers, floats, bools, or any type that can be constructed from an integer or floating point number. Accepts common numerical strings like `0xFF` as well as octal, and decimal | +| string-like | std::string, or anything that can be constructed from or assigned a std::string | +| char | For a single char, single string values are accepted, otherwise longer strings are treated as integral values and a conversion is attempted | +| complex-number | std::complex or any type which has a real(), and imag() operations available, will allow 1 or 2 string definitions like "1+2j" or two arguments "1","2" | +| enumeration | any enum or enum class type is supported through conversion from the underlying type(typically int, though it can be specified otherwise) | +| container-like | a container(like vector) of any available types including other containers | +| wrapper | any other object with a `value_type` static definition where the type specified by `value_type` is one of the type in this list, including `std::atomic<>` | +| tuple | a tuple, pair, or array, or other type with a tuple size and tuple_type operations defined and the members being a type contained in this list | +| function | A function that takes an array of strings and returns a string that describes the conversion failure or empty for success. May be the empty function. (`{}`) | +| streamable | any other type with a `<<` operator will also work | + +By default, CLI11 will assume that an option is optional, and one value is +expected if you do not use a vector. You can change this on a specific option +using option modifiers. An option name may start with any character except ('-', +' ', '\n', and '!'). For long options, after the first character all characters +are allowed except ('=',':','{',' ', '\n'). Names are given as a comma separated +string, with the dash or dashes. An option can have as many names as you want, +and afterward, using `count`, you can use any of the names, with dashes as +needed, to count the options. One of the names is allowed to be given without +proceeding dash(es); if present the option is a positional option, and that name +will be used on the help line for its positional form. + +## Positional options and aliases + +When you give an option on the command line without a name, that is a positional +option. Positional options are accepted in the same order they are defined. So, +for example: + +```term +gitbook:examples $ ./a.out one --two three four +``` + +The string `one` would have to be the first positional option. If `--two` is a +flag, then the remaining two strings are positional. If `--two` is a +one-argument option, then `four` is the second positional. If `--two` accepts +two or more arguments, then there are no more positionals. + +To make a positional option, you simply give CLI11 one name that does not start +with a dash. You can have as many (non-overlapping) names as you want for an +option, but only one positional name. So the following name string is valid: + +```cpp +"-a,-b,--alpha,--beta,mypos" +``` + +This would make two short option aliases, two long option alias, and the option +would be also be accepted as a positional. + +## Containers of options + +If you use a vector or other container instead of a plain option, you can accept +more than one value on the command line. By default, a container accepts as many +options as possible, until the next value that could be a valid option name. You +can specify a set number using an option modifier `->expected(N)`. (The default +unlimited behavior on vectors is restored with `N=-1`) CLI11 does not +differentiate between these two methods for unlimited acceptance options. + +| Separate names | Combined names | +| ----------------- | -------------- | +| `--vec 1 --vec 2` | `--vec 1 2` | + +It is also possible to specify a minimum and maximum number through +`->expected(Min,Max)`. It is also possible to specify a min and max type size +for the elements of the container. It most cases these values will be +automatically determined but a user can manually restrict them. + +An example of setting up a vector option: + +```cpp +std::vector int_vec; +app.add_option("--vec", int_vec, "My vector option"); +``` + +Vectors will be replaced by the parsed content if the option is given on the +command line. + +A definition of a container for purposes of CLI11 is a type with a `end()`, +`insert(...)`, `clear()` and `value_type` definitions. This includes `vector`, +`set`, `deque`, `list`, `forward_iist`, `map`, `unordered_map` and a few others +from the standard library, and many other containers from the boost library. + +### Empty containers + +By default a container will never return an empty container. If it is desired to +allow an empty container to be returned, then the option must be modified with a +0 as the minimum expected value + +```cpp +std::vector int_vec; +app.add_option("--vec", int_vec, "Empty vector allowed")->expected(0,-1); +``` + +An empty vector can than be specified on the command line as `--vec {}` + +To allow an empty vector from config file, the default must be set in addition +to the above modification. + +```cpp +std::vector int_vec; +app.add_option("--vec", int_vec, "Empty vector allowed")->expected(0,-1)->default_str("{}"); +``` + +Then in the file + +```toml +vec={} +``` + +or + +```toml +vec=[] +``` + +will generate an empty vector in `int_vec`. + +### Containers of containers + +Containers of containers are also supported. + +```cpp +std::vector> int_vec; +app.add_option("--vec", int_vec, "My vector of vectors option"); +``` + +CLI11 inserts a separator sequence at the start of each argument call to +separate the vectors. So unless the separators are injected as part of the +command line each call of the option on the command line will result in a +separate element of the outer vector. This can be manually controlled via +`inject_separator(true|false)` but in nearly all cases this should be left to +the defaults. To insert of a separator from the command line add a `%%` where +the separation should occur. + +```bash +cmd --vec_of_vec 1 2 3 4 %% 1 2 +``` + +would then result in a container of size 2 with the first element containing 4 +values and the second 2. + +This separator is also the only way to get values into something like + +```cpp +std::pair,std::vector> two_vecs; +app.add_option("--vec", two_vecs, "pair of vectors"); +``` + +without calling the argument twice. + +Further levels of nesting containers should compile but intermediate layers will +only have a single element in the container, so is probably not that useful. + +### Nested types + +Types can be nested. For example: + +```cpp +std::map> map; +app.add_option("--dict", map, "map of pairs"); +``` + +will require 3 arguments for each invocation, and multiple sets of 3 arguments +can be entered for a single invocation on the command line. + +```cpp +std::map>> map; +app.add_option("--dict", map, "map of pairs"); +``` + +will result in a requirement for 2 integers on each invocation and absorb an +unlimited number of strings including 0. + +## Option modifiers + +When you call `add_option`, you get a pointer to the added option. You can use +that to add option modifiers. A full listing of the option modifiers: + +| Modifier | Description | +| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `->required()` | The program will quit if this option is not present. This is `mandatory` in Plumbum, but required options seems to be a more standard term. For compatibility, `->mandatory()` also works. | +| `->expected(N)` | Take `N` values instead of as many as possible, mainly for vector args. | +| `->expected(Nmin,Nmax)` | Take between `Nmin` and `Nmax` values. | +| `->type_size(N)` | specify that each block of values would consist of N elements | +| `->type_size(Nmin,Nmax)` | specify that each block of values would consist of between Nmin and Nmax elements | +| `->needs(opt)` | This option requires another option to also be present, opt is an `Option` pointer or a string with the name of the option. Can be removed with `->remove_needs(opt)` | +| `->excludes(opt)` | This option cannot be given with `opt` present, opt is an `Option` pointer or a string with the name of the option. Can be removed with `->remove_excludes(opt)` | +| `->envname(name)` | Gets the value from the environment if present and not passed on the command line. | +| `->group(name)` | The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `"Hidden"` will not show up in the help print. | +| `->description(string)` | Set/change the description | +| `->ignore_case()` | Ignore the case on the command line (also works on subcommands, does not affect arguments). | +| `->ignore_underscore()` | Ignore any underscores on the command line (also works on subcommands, does not affect arguments). | +| `->allow_extra_args()` | Allow extra argument values to be included when an option is passed. Enabled by default for vector options. | +| `->disable_flag_override()` | specify that flag options cannot be overridden on the command line use `=` | +| `->delimiter('')` | specify a character that can be used to separate elements in a command line argument, default is , common values are ',', and ';' | +| `->multi_option_policy( CLI::MultiOptionPolicy::Throw)` | Sets the policy for handling multiple arguments if the option was received on the command line several times. `Throw`ing an error is the default, but `TakeLast`, `TakeFirst`, `TakeAll`, `Join`, and `Sum` are also available. See the next four lines for shortcuts to set this more easily. | +| `->take_last()` | Only use the last option if passed several times. This is always true by default for bool options, regardless of the app default, but can be set to false explicitly with `->multi_option_policy()`. | +| `->take_first()` | sets `->multi_option_policy(CLI::MultiOptionPolicy::TakeFirst)` | +| `->take_all()` | sets `->multi_option_policy(CLI::MultiOptionPolicy::TakeAll)` | +| `->join()` | sets `->multi_option_policy(CLI::MultiOptionPolicy::Join)`, which uses newlines or the specified delimiter to join all arguments into a single string output. | +| `->join(delim)` | sets `->multi_option_policy(CLI::MultiOptionPolicy::Join)`, which uses `delim` to join all arguments into a single string output. this also sets the delimiter | +| `->check(Validator)` | perform a check on the returned results to verify they meet some criteria. See [Validators](./validators.md) for more info | +| `->transform(Validator)` | Run a transforming validator on each value passed. See [Validators](./validators.md) for more info | +| `->each(void(std::string))` | Run a function on each parsed value, _in order_. | +| `->default_str(string)` | set a default string for use in the help and as a default value if no arguments are passed and a value is requested | +| `->default_function(std::string())` | Advanced: Change the function that `capture_default_str()` uses. | +| `->default_val(value)` | Generate the default string from a value and validate that the value is also valid. For options that assign directly to a value type the value in that type is also updated. Value must be convertible to a string(one of known types or have a stream operator). | +| `->capture_default_str()` | Store the current value attached and display it in the help string. | +| `->always_capture_default()` | Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`. | +| `->run_callback_for_default()` | Force the option callback to be executed or the variable set when the `default_val` is used. | +| `->force_callback()` | Force the option callback to be executed regardless of whether the option was used or not. Will use the default_str if available, if no default is given the callback will be executed with an empty string as an argument, which will translate to a default initialized value, which can be compiler dependent | +| `->trigger_on_parse()` | Have the option callback be triggered when the value is parsed vs. at the end of all parsing, the option callback can potentially be executed multiple times. Generally only useful if you have a user defined callback or validation check. Or potentially if a vector input is given multiple times as it will clear the results when a repeat option is given via command line. It will trigger the callbacks once per option call on the command line | +| `->option_text(string)` | Sets the text between the option name and description. | + +The `->check(...)` and `->transform(...)` modifiers can also take a callback +function of the form `bool function(std::string)` that runs on every value that +the option receives, and returns a value that tells CLI11 whether the check +passed or failed. + +## Using the `CLI::Option` pointer + +Each of the option creation mechanisms returns a pointer to the internally +stored option. If you save that pointer, you can continue to access the option, +and change setting on it later. The Option object can also be converted to a +bool to see if it was passed, or `->count()` can be used to see how many times +the option was passed. Since flags are also options, the same methods work on +them. + +```cpp +CLI::Option* opt = app.add_flag("--opt"); + +CLI11_PARSE(app, argv, argc); + +if(* opt) + std::cout << "Flag received " << opt->count() << " times." << std::endl; +``` + +## Inheritance of defaults + +One of CLI11's systems to allow customizability without high levels of verbosity +is the inheritance system. You can set default values on the parent `App`, and +all options and subcommands created from it remember the default values at the +point of creation. The default value for Options, specifically, are accessible +through the `option_defaults()` method. There are a number of settings that can +be set and inherited: + +- `group`: The group name starts as "Options" +- `required`: If the option must be given. Defaults to `false`. Is ignored for + flags. +- `multi_option_policy`: What to do if several copies of an option are passed + and one value is expected. Defaults to `CLI::MultiOptionPolicy::Throw`. This + is also used for bool flags, but they always are created with the value + `CLI::MultiOptionPolicy::TakeLast` or `CLI::MultiOptionPolicy::Sum` regardless + of the default, so that multiple bool flags does not cause an error. But you + can override that setting by calling the `multi_option_policy` directly. +- `ignore_case`: Allow any mixture of cases for the option or flag name +- `ignore_underscore`: Allow any number of underscores in the option or flag + name +- `configurable`: Specify whether an option can be configured through a config + file +- `disable_flag_override`: do not allow flag values to be overridden on the + command line +- `always_capture_default`: specify that the default values should be + automatically captured. +- `delimiter`: A delimiter to use for capturing multiple values in a single + command line string (e.g. --flag="flag,-flag2,flag3") + +An example of usage: + +```cpp +app.option_defaults()->ignore_case()->group("Required"); + +app.add_flag("--CaSeLeSs"); +app.get_group() // is "Required" +``` + +Groups are mostly for visual organization, but an empty string for a group name +will hide the option. + +### Windows style options + +You can also set the app setting `app->allow_windows_style_options()` to allow +windows style options to also be recognized on the command line: + +- `/a` (flag) +- `/f filename` (option) +- `/long` (long flag) +- `/file filename` (space) +- `/file:filename` (colon) +- `/long_flag:false` (long flag with : to override the default value) + +Windows style options do not allow combining short options or values not +separated from the short option like with `-` options. You still specify option +names in the same manner as on Linux with single and double dashes when you use +the `add_*` functions, and the Linux style on the command line will still work. +If a long and a short option share the same name, the option will match on the +first one defined. + +## Parse configuration + +How an option and its arguments are parsed depends on a set of controls that are +part of the option structure. In most circumstances these controls are set +automatically based on the type or function used to create the option and the +type the arguments are parsed into. The variables define the size of the +underlying type (essentially how many strings make up the type), the expected +size (how many groups are expected) and a flag indicating if multiple groups are +allowed with a single option. And these interact with the `multi_option_policy` +when it comes time to parse. + +### Examples + +How options manage this is best illustrated through some examples. + +```cpp +std::string val; +app.add_option("--opt",val,"description"); +``` + +creates an option that assigns a value to a `std::string` When this option is +constructed it sets a type_size min and max of 1. Meaning that the assignment +uses a single string. The Expected size is also set to 1 by default, and +`allow_extra_args` is set to false. meaning that each time this option is called +1 argument is expected. This would also be the case if val were a `double`, +`int` or any other single argument types. + +now for example + +```cpp +std::pair val; +app.add_option("--opt",val,"description"); +``` + +In this case the typesize is automatically detected to be 2 instead of 1, so the +parsing would expect 2 arguments associated with the option. + +```cpp +std::vector val; +app.add_option("--opt",val,"description"); +``` + +detects a type size of 1, since the underlying element type is a single string, +so the minimum number of strings is 1. But since it is a vector the expected +number can be very big. The default for a vector is (1<<30), and the +allow_extra_args is set to true. This means that at least 1 argument is expected +to follow the option, but arbitrary numbers of arguments may follow. These are +checked if they have the form of an option but if not they are added to the +argument. + +```cpp +std::vector> val; +app.add_option("--opt",val,"description"); +``` + +gets into the complicated cases where the type size is now 3. and the expected +max is set to a large number and `allow_extra_args` is set to true. In this case +at least 3 arguments are required to follow the option, and subsequent groups +must come in groups of three, otherwise an error will result. + +```cpp +bool val{false}; +app.add_flag("--opt",val,"description"); +``` + +Using the add_flag methods for creating options creates an option with an +expected size of 0, implying no arguments can be passed. + +```cpp +std::complex val; +app.add_option("--opt",val,"description"); +``` + +triggers the complex number type which has a min of 1 and max of 2, so 1 or 2 +strings can be passed. Complex number conversion supports arguments of the form +"1+2j" or "1","2", or "1" "2i". The imaginary number symbols `i` and `j` are +interchangeable in this context. + +```cpp +std::vector> val; +app.add_option("--opt",val,"description"); +``` + +has a type size of 1 to (1<<30). + +### Customization + +The `type_size(N)`, `type_size(Nmin, Nmax)`, `expected(N)`, +`expected(Nmin,Nmax)`, and `allow_extra_args()` can be used to customize an +option. For example + +```cpp +std::string val; +auto opt=app.add_flag("--opt{vvv}",val,"description"); +opt->expected(0,1); +``` + +will create a hybrid option, that can exist on its own in which case the value +"vvv" is used or if a value is given that value will be used. + +There are some additional options that can be specified to modify an option for +specific cases: + +- `->run_callback_for_default()` will specify that the callback should be + executed when a default_val is set. This is set automatically when appropriate + though it can be turned on or off and any user specified callback for an + option will be executed when the default value for an option is set. + +- `->force_callback()` will for the callback/value assignment to run at the + conclusion of parsing regardless of whether the option was supplied or not. + This can be used to force the default or execute some code. + +- `->trigger_on_parse()` will trigger the callback or value assignment each time + the argument is passed. The value is reset if the option is supplied multiple + times. + +## Unusual circumstances + +There are a few cases where some things break down in the type system managing +options and definitions. Using the `add_option` method defines a lambda function +to extract a default value if required. In most cases this is either +straightforward or a failure is detected automatically and handled. But in a few +cases a streaming template is available that several layers down may not +actually be defined. This results in CLI11 not being able to detect this +circumstance automatically and will result in compile error. One specific known +case is `boost::optional` if the boost optional_io header is included. This +header defines a template for all boost optional values even if they do not +actually have a streaming operator. For example `boost::optional` +does not have a streaming operator but one is detected since it is part of a +template. For these cases a secondary method `app->add_option_no_stream(...)` is +provided that bypasses this operation completely and should compile in these +cases. diff --git a/libs/CLI11/book/chapters/subcommands.md b/libs/CLI11/book/chapters/subcommands.md new file mode 100644 index 0000000..a2124e8 --- /dev/null +++ b/libs/CLI11/book/chapters/subcommands.md @@ -0,0 +1,194 @@ +# Subcommands and the App + +Subcommands are keyword that invoke a new set of options and features. For +example, the `git` command has a long series of subcommands, like `add` and +`commit`. Each can have its own options and implementations. This chapter will +focus on implementations that are contained in the same C++ application, though +the system git uses to extend the main command by calling other commands in +separate executables is supported too; that's called "Prefix commands" and is +included at the end of this chapter. + +## The parent App + +We'll start by discussing the parent `App`. You've already used it quite a bit, +to create options and set option defaults. There are several other things you +can do with an `App`, however. + +You are given a lot of control the help output. You can set a footer with +`app.footer("My Footer")`. You can replace the default help print when a +`ParseError` is thrown with +`app.set_failure_message(CLI::FailureMessage::help)`. The default is +`CLI:::FailureMessage::simple`, and you can easily define a new one. Just make a +(lambda) function that takes an App pointer and a reference to an error code +(even if you don't use them), and returns a string. + +## Adding a subcommand + +Subcommands can be added just like an option: + +```cpp +CLI::App* sub = app.add_subcommand("sub", "This is a subcommand"); +``` + +The subcommand should have a name as the first argument, and a little +description for the second argument. A pointer to the internally stored +subcommand is provided; you usually will be capturing that pointer and using it +later (though you can use callbacks if you prefer). As always, feel free to use +`auto sub = ...` instead of naming the type. + +You can check to see if the subcommand was received on the command line several +ways: + +```cpp +if(*sub) ... +if(sub->parsed()) ... +if(app.got_subcommand(sub)) ... +if(app.got_subcommand("sub")) ... +``` + +You can also get a list of subcommands with `get_subcommands()`, and they will +be in parsing order. + +There are a lot of options that you can set on a subcommand; in fact, +subcommands have exactly the same options as your main app, since they are +actually the same class of object (as you may have guessed from the type above). +This has the pleasant side affect of making subcommands infinitely nestable. + +## Required subcommands + +Each App has controls to set the number of subcommands you expect. This is +controlled by: + +```cpp +app.require_subcommand(/* min */ 0, /* max */ 1); +``` + +If you set the max to 0, CLI11 will allow an unlimited number of subcommands. +After the (non-unlimited) maximum is reached, CLI11 will stop trying to match +subcommands. So the if you pass "`one two`" to a command, and both `one` and +`two` are subcommands, it will depend on the maximum number as to whether the +"`two`" is a subcommand or an argument to the "`one`" subcommand. + +As a shortcut, you can also call the `require_subcommand` method with one +argument; that will be the fixed number of subcommands if positive, it will be +the maximum number if negative. Calling it without an argument will set the +required subcommands to 1 or more. + +The maximum number of subcommands is inherited by subcommands. This allows you +to set the maximum to 1 once at the beginning on the parent app if you only want +single subcommands throughout your app. You should keep this in mind, if you are +dealing with lots of nested subcommands. + +## Using callbacks + +You've already seen how to check to see what subcommands were given. It's often +much easier, however, to just define the code you want to run when you are +making your parser, and not run a bunch of code after `CLI11_PARSE` to analyse +the state (Procedural! Yuck!). You can do that with lambda functions. A +`std::function` callback `.callback()` is provided, and CLI11 ensures +that all options are prepared and usable by reference capture before entering +the callback. An example is shown below in the `geet` program. + +## Inheritance of defaults + +The following values are inherited when you add a new subcommand. This happens +at the point the subcommand is created: + +- The name and description for the help flag +- The footer +- The failure message printer function +- Option defaults +- Allow extras +- Prefix command +- Ignore case +- Ignore underscore +- Allow Windows style options +- Fallthrough +- Group name +- Max required subcommands +- validate positional arguments +- validate optional arguments + +## Special modes + +There are several special modes for Apps and Subcommands. + +### Allow extras + +Normally CLI11 throws an error if you don't match all items given on the command +line. However, you can enable `allow_extras()` to instead store the extra values +in `.remaining()`. You can get all remaining options including those in +contained subcommands recursively in the original order with `.remaining(true)`. +`.remaining_size()` is also provided; this counts the size but ignores the `--` +special separator if present. + +### Fallthrough + +Fallthrough allows an option that does not match in a subcommand to "fall +through" to the parent command; if that parent allows that option, it matches +there instead. This was added to allow CLI11 to represent models: + +```term +gitbook:code $ ./my_program my_model_1 --model_flag --shared_flag +``` + +Here, `--shared_flag` was set on the main app, and on the command line it "falls +through" `my_model_1` to match on the main app. + +### Prefix command + +This is a special mode that allows "prefix" commands, where the parsing +completely stops when it gets to an unknown option. Further unknown options are +ignored, even if they could match. Git is the traditional example for prefix +commands; if you run git with an unknown subcommand, like "`git thing`", it then +calls another command called "`git-thing`" with the remaining options intact. + +### Silent subcommands + +Subcommands can be modified by using the `silent` option. This will prevent the +subcommand from showing up in the get_subcommands list. This can be used to make +subcommands into modifiers. For example, a help subcommand might look like + +```c++ + auto sub1 = app.add_subcommand("help")->silent(); + sub1->parse_complete_callback([]() { throw CLI::CallForHelp(); }); +``` + +This would allow calling help such as: + +```bash +./app help +./app help sub1 +``` + +### Positional Validation + +Some arguments supplied on the command line may be legitamately applied to more +than 1 positional argument. In this context enabling `positional_validation` on +the application or subcommand will check any validators before applying the +command line argument to the positional option. It is not an error to fail +validation in this context, positional arguments not matching any validators +will go into the `extra_args` field which may generate an error depending on +settings. + +### Optional Argument Validation + +Similar to positional validation, there are occasional contexts in which case it +might be ambiguous whether an argument should be applied to an option or a +positional option. + +```c++ + std::vector vec; + std::vector ivec; + app.add_option("pos", vec); + app.add_option("--args", ivec)->check(CLI::Number); + app.validate_optional_arguments(); +``` + +In this case a sequence of integers is expected for the argument and remaining +strings go to the positional string vector. Without the +`validate_optional_arguments()` active it would be impossible get any later +arguments into the positional if the `--args` option is used. The validator in +this context is used to make sure the optional arguments match with what the +argument is expecting and if not the `-args` option is closed, and remaining +arguments fall into the positional. diff --git a/libs/CLI11/book/chapters/toolkits.md b/libs/CLI11/book/chapters/toolkits.md new file mode 100644 index 0000000..a636e7b --- /dev/null +++ b/libs/CLI11/book/chapters/toolkits.md @@ -0,0 +1,40 @@ +# Using CLI11 in a Toolkit + +CLI11 was designed to be integrate into a toolkit, providing a native experience +for users. This was used in GooFit to provide `GooFit::Application`, an class +designed to make ROOT users feel at home. + +## Custom namespace + +If you want to provide CLI11 in a custom namespace, you'll want to at least put +`using CLI::App` in your namespace. You can also include Option, some errors, +and validators. You can also put `using namespace CLI` inside your namespace to +import everything. + +You may also want to make your own copy of the `CLI11_PARSE` macro. Something +like: + +```cpp + #define MYPACKAGE_PARSE(app, argv, argc) \ + try { \ + app.parse(argv, argc); \ + } catch(const CLI::ParseError &e) { \ + return app.exit(e); \ + } +``` + +## Subclassing App + +If you subclass `App`, you'll just need to do a few things. You'll need a +constructor; calling the base `App` constructor is a good idea, but not +necessary (it just sets a description and adds a help flag. + +You can call anything you would like to configure in the constructor, like +`option_defaults()->take_last()` or `fallthrough()`, and it will be set on all +user instances. You can add flags and options, as well. + +## Virtual functions provided + +You are given a few virtual functions that you can change (only on the main +App). `pre_callback` runs right before the callbacks run, letting you print out +custom messages at the top of your app. diff --git a/libs/CLI11/book/chapters/validators.md b/libs/CLI11/book/chapters/validators.md new file mode 100644 index 0000000..fffa38c --- /dev/null +++ b/libs/CLI11/book/chapters/validators.md @@ -0,0 +1,66 @@ +# Validators + +There are two forms of validators: + +- `transform` validators: mutating +- `check` validators: non-mutating (recommended unless the parsed string must be + mutated) + +A transform validator comes in one form, a function with the signature +`std::string(std::string)`. The function will take a string and return the +modified version of the string. If there is an error, the function should throw +a `CLI::ValidationError` with the appropriate reason as a message. + +However, `check` validators come in two forms; either a simple function with the +const version of the above signature, `std::string(const std::string &)`, or a +subclass of `struct CLI::Validator`. This structure has two members that a user +should set; one (`func_`) is the function to add to the Option (exactly matching +the above function signature, since it will become that function), and the other +is `name_`, and is the type name to set on the Option (unless empty, in which +case the typename will be left unchanged). + +Validators can be combined with `&` and `|`, and they have an `operator()` so +that you can call them as if they were a function. In CLI11, const static +versions of the validators are provided so that the user does not have to call a +constructor also. + +An example of a custom validator: + +```cpp +struct LowerCaseValidator : public Validator { + LowerCaseValidator() { + name_ = "LOWER"; + func_ = [](const std::string &str) { + if(CLI::detail::to_lower(str) != str) + return std::string("String is not lower case"); + else + return std::string(); + }; + } +}; +const static LowerCaseValidator Lowercase; +``` + +If you were not interested in the extra features of Validator, you could simply +pass the lambda function above to the `->check()` method of `Option`. + +The built-in validators for CLI11 are: + +| Validator | Description | +| ------------------- | ---------------------------------------------------------------------- | +| `ExistingFile` | Check for existing file (returns error message if check fails) | +| `ExistingDirectory` | Check for an existing directory (returns error message if check fails) | +| `ExistingPath` | Check for an existing path | +| `NonexistentPath` | Check for an non-existing path | +| `Range(min=0, max)` | Produce a range (factory). Min and max are inclusive. | + +And, the protected members that you can set when you make your own are: + +| Type | Member | Description | +| ------------------------------------------- | -------------------- | ---------------------------------------------------------------------- | +| `std::function` | `func_` | Core validation function - modifies input and returns "" if successful | +| `std::function` | `desc_function` | Optional description function (uses `description_` instead if not set) | +| `std::string` | `name_` | The name for search purposes | +| `int` (`-1`) | `application_index_` | The element this validator applies to (-1 for all) | +| `bool` (`true`) | `active_` | This can be disabled | +| `bool` (`false`) | `non_modifying_` | Specify that this is a Validator instead of a Transformer | diff --git a/libs/CLI11/book/code/CMakeLists.txt b/libs/CLI11/book/code/CMakeLists.txt new file mode 100644 index 0000000..987d53c --- /dev/null +++ b/libs/CLI11/book/code/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.11) + +project(CLI11_Examples LANGUAGES CXX) + +# Using CMake 3.11's ability to set imported interface targets +add_library(CLI11::CLI11 IMPORTED INTERFACE) +target_include_directories(CLI11::CLI11 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/../../include") +target_compile_features(CLI11::CLI11 INTERFACE cxx_std_11) + +# Add CTest +enable_testing() + +# Quick function to add the base executable +function(add_cli_exe NAME) + add_executable(${NAME} ${NAME}.cpp) + target_link_libraries(${NAME} CLI11::CLI11) +endfunction() + +add_cli_exe(simplest) +add_test(NAME simplest COMMAND simplest) + +add_cli_exe(intro) +add_test(NAME intro COMMAND intro) +add_test(NAME intro_p COMMAND intro -p 5) + +add_cli_exe(flags) +add_test(NAME flags COMMAND flags) +add_test(NAME flags_bip COMMAND flags -b -i -p) + +add_cli_exe(geet) +add_test(NAME geet_add COMMAND geet add) +add_test(NAME geet_commit COMMAND geet commit -m "Test") diff --git a/libs/CLI11/book/code/flags.cpp b/libs/CLI11/book/code/flags.cpp new file mode 100644 index 0000000..54ac71a --- /dev/null +++ b/libs/CLI11/book/code/flags.cpp @@ -0,0 +1,36 @@ +#include "CLI/CLI.hpp" +#include + +int main(int argc, char **argv) { + using std::cout; + using std::endl; + CLI::App app{"Flag example program"}; + + /// [define] + bool flag_bool; + app.add_flag("--bool,-b", flag_bool, "This is a bool flag"); + + int flag_int; + app.add_flag("-i,--int", flag_int, "This is an int flag"); + + CLI::Option *flag_plain = app.add_flag("--plain,-p", "This is a plain flag"); + /// [define] + + /// [parser] + try { + app.parse(argc, argv); + } catch(const CLI::ParseError &e) { + return app.exit(e); + } + /// [parser] + + /// [usage] + cout << "The flags program" << endl; + if(flag_bool) + cout << "Bool flag passed" << endl; + if(flag_int > 0) + cout << "Flag int: " << flag_int << endl; + if(*flag_plain) + cout << "Flag plain: " << flag_plain->count() << endl; + /// [usage] +} diff --git a/libs/CLI11/book/code/geet.cpp b/libs/CLI11/book/code/geet.cpp new file mode 100644 index 0000000..a4caf26 --- /dev/null +++ b/libs/CLI11/book/code/geet.cpp @@ -0,0 +1,50 @@ +#include "CLI/CLI.hpp" + +#include + +int main(int argc, char **argv) { + + /// [Intro] + CLI::App app{"Geet, a command line git lookalike that does nothing"}; + app.require_subcommand(1); + /// [Intro] + + /// [Add] + auto add = app.add_subcommand("add", "Add file(s)"); + + bool add_update; + add->add_flag("-u,--update", add_update, "Add updated files only"); + + std::vector add_files; + add->add_option("files", add_files, "Files to add"); + + add->callback([&]() { + std::cout << "Adding:"; + if(add_files.empty()) { + if(add_update) + std::cout << " all updated files"; + else + std::cout << " all files"; + } else { + for(auto file : add_files) + std::cout << " " << file; + } + }); + /// [Add] + + /// [Commit] + auto commit = app.add_subcommand("commit", "Commit files"); + + std::string commit_message; + commit->add_option("-m,--message", commit_message, "A message")->required(); + + commit->callback([&]() { std::cout << "Commit message: " << commit_message; }); + /// [Commit] + + /// [Parse] + CLI11_PARSE(app, argc, argv); + + std::cout << "\nThanks for using geet!\n" << std::endl; + return 0; + /// [Parse] +} diff --git a/libs/CLI11/book/code/intro.cpp b/libs/CLI11/book/code/intro.cpp new file mode 100644 index 0000000..2db50f1 --- /dev/null +++ b/libs/CLI11/book/code/intro.cpp @@ -0,0 +1,15 @@ +#include "CLI/CLI.hpp" +#include + +int main(int argc, char **argv) { + CLI::App app{"App description"}; + + // Define options + int p = 0; + app.add_option("-p", p, "Parameter"); + + CLI11_PARSE(app, argc, argv); + + std::cout << "Parameter value: " << p << std::endl; + return 0; +} diff --git a/libs/CLI11/book/code/simplest.cpp b/libs/CLI11/book/code/simplest.cpp new file mode 100644 index 0000000..a848ff3 --- /dev/null +++ b/libs/CLI11/book/code/simplest.cpp @@ -0,0 +1,11 @@ +#include "CLI/CLI.hpp" + +int main(int argc, char **argv) { + CLI::App app; + + // Add new options/flags here + + CLI11_PARSE(app, argc, argv); + + return 0; +} diff --git a/libs/CLI11/cmake/CLI11.pc.in b/libs/CLI11/cmake/CLI11.pc.in new file mode 100644 index 0000000..8d41873 --- /dev/null +++ b/libs/CLI11/cmake/CLI11.pc.in @@ -0,0 +1,9 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${prefix}/include + +Name: CLI11 +Description: C++ command line parser +Version: @PROJECT_VERSION@ + +Cflags: -I${includedir} diff --git a/libs/CLI11/cmake/CLI11ConfigVersion.cmake.in b/libs/CLI11/cmake/CLI11ConfigVersion.cmake.in new file mode 100644 index 0000000..49faee5 --- /dev/null +++ b/libs/CLI11/cmake/CLI11ConfigVersion.cmake.in @@ -0,0 +1,13 @@ +# Adapted from write_basic_package_version_file(... COMPATIBILITY AnyNewerVersion) output +# ARCH_INDEPENDENT is only present in cmake 3.14 and onwards + +set(PACKAGE_VERSION "@VERSION_STRING@") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/libs/CLI11/cmake/CLI11GeneratePkgConfig.cmake b/libs/CLI11/cmake/CLI11GeneratePkgConfig.cmake new file mode 100644 index 0000000..5abb03d --- /dev/null +++ b/libs/CLI11/cmake/CLI11GeneratePkgConfig.cmake @@ -0,0 +1,3 @@ +configure_file("cmake/CLI11.pc.in" "CLI11.pc" @ONLY) + +install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc" DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig") diff --git a/libs/CLI11/cmake/CLI11Warnings.cmake b/libs/CLI11/cmake/CLI11Warnings.cmake new file mode 100644 index 0000000..8b4b499 --- /dev/null +++ b/libs/CLI11/cmake/CLI11Warnings.cmake @@ -0,0 +1,37 @@ +# Special target that adds warnings. Is not exported. +add_library(CLI11_warnings INTERFACE) + +set(unix-warnings -Wall -Wextra -pedantic -Wshadow -Wsign-conversion -Wswitch-enum) + +# Clang warnings +# -Wfloat-equal could be added with Catch::literals and _a usage +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list( + APPEND + unix-warnings + -Wcast-align + -Wimplicit-atomic-properties + -Wmissing-declarations + -Woverlength-strings + -Wshadow + -Wstrict-selector-match + -Wundeclared-selector) + # -Wunreachable-code Doesn't work on Clang 3.4 +endif() + +# Buggy in GCC 4.8 +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) + list(APPEND unix-warnings -Weffc++) +endif() + +target_compile_options( + CLI11_warnings + INTERFACE $<$:-stdlib=libc++> + $<$:/W4 + $<$:/WX>> + $<$>:${unix-warnings} + $<$:-Werror>>) + +if(NOT CMAKE_VERSION VERSION_LESS 3.13) + target_link_options(CLI11_warnings INTERFACE $<$:-stdlib=libc++>) +endif() diff --git a/libs/CLI11/cmake/CodeCoverage.cmake b/libs/CLI11/cmake/CodeCoverage.cmake new file mode 100644 index 0000000..e011ef1 --- /dev/null +++ b/libs/CLI11/cmake/CodeCoverage.cmake @@ -0,0 +1,243 @@ +# Copyright (c) 2012 - 2017, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# CHANGES: +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# 2016-02-03, Lars Bilke +# - Refactored functions to use named parameters +# +# 2017-06-02, Lars Bilke +# - Merged with modified version from github.com/ufz/ogs +# +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# include(CodeCoverage) +# +# 3. Append necessary compiler flags: +# APPEND_COVERAGE_COMPILER_FLAGS() +# +# 4. If you need to exclude additional directories from the report, specify them +# using the COVERAGE_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE. +# Example: +# set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*') +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +# Check prereqs +find_program(GCOV_PATH gcov) +find_program(LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl) +find_program(GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat) +find_program(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) +find_program(SIMPLE_PYTHON_EXECUTABLE python) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() +elseif(NOT CMAKE_COMPILER_IS_GNUCXX) + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") +endif() + +set(COVERAGE_COMPILER_FLAGS + "-g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline" + CACHE INTERNAL "") + +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." FORCE) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." FORCE) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE) +mark_as_advanced(CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE) + +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +else() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Setup target + add_custom_target( + ${Coverage_NAME} + # Cleanup lcov + COMMAND ${LCOV_PATH} --directory . --zerocounters + # Create baseline to make sure untouched files show up in the report + COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base + # Run tests + COMMAND ${Coverage_EXECUTABLE} + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info + # add baseline counters + COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file + ${Coverage_NAME}.total + COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file + ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total + ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT + "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show where to find the lcov info report + add_custom_command( + TARGET ${Coverage_NAME} + POST_BUILD + COMMAND ; + COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info.") + + # Show info where to find the report + add_custom_command( + TARGET ${Coverage_NAME} + POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report.") + +endfunction() # SETUP_TARGET_FOR_COVERAGE + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE_COBERTURA( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE_COBERTURA) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT SIMPLE_PYTHON_EXECUTABLE) + message(FATAL_ERROR "python not found! Aborting...") + endif() # NOT SIMPLE_PYTHON_EXECUTABLE + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Combine excludes to several -e arguments + set(COBERTURA_EXCLUDES "") + foreach(EXCLUDE ${COVERAGE_EXCLUDES}) + set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}") + endforeach() + + add_custom_target( + ${Coverage_NAME} + # Run tests + ${Coverage_EXECUTABLE} + # Running gcovr + COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES} -o ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Running gcovr to produce Cobertura code coverage report.") + + # Show info where to find the report + add_custom_command( + TARGET ${Coverage_NAME} + POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml.") + +endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA + +function(APPEND_COVERAGE_COMPILER_FLAGS) + set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" + PARENT_SCOPE) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" + PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # APPEND_COVERAGE_COMPILER_FLAGS diff --git a/libs/CLI11/conanfile.py b/libs/CLI11/conanfile.py new file mode 100644 index 0000000..b5b9e49 --- /dev/null +++ b/libs/CLI11/conanfile.py @@ -0,0 +1,49 @@ +from conans import ConanFile, CMake +from conans.tools import load, cross_building +import re + + +def get_version(): + try: + content = load("include/CLI/Version.hpp") + version = re.search(r'#define CLI11_VERSION "(.*)"', content).group(1) + return version + except Exception: + return None + + +class CLI11Conan(ConanFile): + name = "CLI11" + version = get_version() + description = "Command Line Interface toolkit for C++11" + topics = ("cli", "c++11", "parser", "cli11") + url = "https://github.com/CLIUtils/CLI11" + homepage = "https://github.com/CLIUtils/CLI11" + author = "Henry Schreiner " + license = "BSD-3-Clause" + + settings = "os", "compiler", "arch", "build_type" + exports_sources = ( + "LICENSE", + "README.md", + "include/*", + "src/*", + "extern/*", + "cmake/*", + "CMakeLists.txt", + "CLI11.CPack.Description.txt", + "tests/*", + ) + + def build(self): # this is not building a library, just tests + cmake = CMake(self) + cmake.definitions["CLI11_BUILD_EXAMPLES"] = "OFF" + cmake.definitions["CLI11_SINGLE_FILE"] = "OFF" + cmake.configure() + cmake.build() + if not cross_building(self.settings): + cmake.test() + cmake.install() + + def package_id(self): + self.info.header_only() diff --git a/libs/CLI11/docs/.gitignore b/libs/CLI11/docs/.gitignore new file mode 100644 index 0000000..a243610 --- /dev/null +++ b/libs/CLI11/docs/.gitignore @@ -0,0 +1,2 @@ +/html/* +/latex/* diff --git a/libs/CLI11/docs/CLI11.svg b/libs/CLI11/docs/CLI11.svg new file mode 100644 index 0000000..e12b99b --- /dev/null +++ b/libs/CLI11/docs/CLI11.svg @@ -0,0 +1,114 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/libs/CLI11/docs/CLI11_100.png b/libs/CLI11/docs/CLI11_100.png new file mode 100644 index 0000000000000000000000000000000000000000..d318c48a0df1a7e23025a38cf592d4ce97dbdc97 GIT binary patch literal 3355 zcmV+$4dn8PP)Zz)h(B1s~?*pi6 z(>Owm08$3_?(Gm85Wt{5eY(|MceCa6Y1SP*3J?jrh7fh#;ivn8BE(o=&$D)R{dUco z#hSy1+4I8>-R7>lQOe~+`}uL9tc*n|Db&^1@1{?m5Z-+AZdd#2o}dU32*h|gI+}gt z?ahKcd(d3I+%2viCMHrTo2O65!P1hToja+hu0D=J;myjGrCsT#>w^*zu@t@jgI8Q# zrGFVa7N7WdekdvFayP#e5+Gcq!gu&^rtjE6p;mhin1&Eny2^*Fs|=x5%lPeYH_9ZE z)$dK7Eb$#aoT=NllYi@0m$~REXf9u-s;-W$K0X}C%j;iKSvd<2kAq}n+~^AXT@#e| z-#6#lwVmd2d1yjV5SFH<_{GO_tGc>N%=bjTxqhAOk`mNGL7XWn>YZO+{s&a5V`wz_ zoweQhpsZbMLseDE01J!B`{&N(`{H6=-n*CD`ua|r?&;*+yvf15JYoX_DXFY9`>wb+ z1eGcWjV7xzb~_i8HESHHtIKeWB-r5y;-bOwL}8gor99KGA5U9Z(O0SDZfz}B zD=IisR7AB-*CE$E8HG&7Co^YaXKqfQT8*}*CYk{QUgoveYTIL{{XvO{SSr!$KL}T; zq*EOo@rjS8_|6@JBEPq{XVI83OdB?gzGh}kOjPT1Xf9volhdc!m7Pt!zWJBw_R5u* z%jNg4{Sp$`-O41?)6tRrp`rJ$>-BnM@4VC2ZwSCsmX^Hh;lc9sbgtjNZM4h`Cnr1| z9a)^3djFmg$()W-8NiAa+P3;OX-7RJ2(ixG#ANx7fBK`?7J` zG`xllYtfLYOvY44N2WSD^7XZAge4^zZE3#*)=DMI$Bko|n;WJw87tD$o0J(na3KHi z^kkxg1N$#tH26#p2#tpP@^Uif&&MY&Zc27Z$w7qhMu_6J)S+!b*|5Qsva;v_78b#u z&z{X!SFiG?{re5xaCZj>b_NI2zgMp|nQUOxz=526^;Lq@YEmy;XxFn{i9#mh^--e` zDiu~nS~vXMdP1F@kw{wZWTL+LhJuO;QbR+Tmy|U6P=5X~)~tDvRjYDatBbVN+6rM! zS=oV+wzk1X7A|D#nKLX+OEU<_y4+}FIkZPTdFRxxDF*}#W_N304!%{alqXCgir7RjVhW(+TOdC41)qpgRo|ngr*jTpu_z>dkJOrKY zFhaPt_FT&?MTj9l%9J5Pe)I8+8AcV>Fl%enK|#o+hVeaLTFTlZN7$8}&Fz|+`}buM z34tR<;O*puIxCBm++1`mj42O;;{^pwijKxyF6Z{jl}$dct*>WOW+t05GkIh5Xf}Cy zwb}M}#l^TsMUfm5f|HHS6GEdogb+apk=EQZ&9@XG#sJ4&c6I&DCND3%cI+@Jc{h4_ zH5tr5K6MJ`&6|lnd)6Qz06M*%gsd#)CMB^qC+8Or$itvet7T$T6mItRY?(2`!bB?F zgAgIjl{X#~A$%ngNrq6VY+rirIVMC!86Aix4Ia!?M@NHu9~?WzYsty~FJ|=ZL0eP9 z%(ytrOiV})2~qSmHQkO7!dTg+K@nn!xkB;TuHfKaBW-Q**tV^S&G8i zao|AbzrkZljZQ~cQWD1t3OF!#uEfsVJRBj`BZNU59=wnsgcx99u|8woJlU07w+P<3 z(?Ie*h| z^4@!WDJ%P8%8(&{NS!l>#VIL#`1RMV8g;O;GPo|ed$-wc?pKVHo|nhWxHuwxe3(6Q z}nPBu0ZlS4vyb?@FbPv9&~O%1NAn(5|#rDeXoaf8JvDSYbdi<6Db zNMMT;Sddd%dU|$ZBL6deI{!9cK%0y;o&?&OnM~%Y1og3~H zG8wDf-3{_dIi;msDlc!Boks;znT+lJ{yb}E$GFHyU4d4+1R<6p#QnKMWVe{G)`8 zQb~GP7$udJ1gO|x?N8lMb4Y;I?(Qsm{&|D@g<9=n8I+;c)*M;55Or1-OViTI>h=052%$Ds zw)uo)czB{tulHJFI3B%*;b3 z8;cM}n=9XP>OMR?10lw*KXD?hprYc*jQR5kQmZ*tRCK?{rSfuS?c7PqoH+*n6e}|` z)=rwlyB;1~xpj*|triP~f??Ly^m<@<_d(wN*T4Au{P`BE6z%8N>}RtR6N&%+`xc*n z*vxlvA>7>^|AYk2T)%z-n8~VDEv`VeWs&Q9V0>bB_W9-{^TA7(@QjI}q_VQ91BryE zt*jU~Xb{iZ*%=LpPOoQKS{m;iZT97P%iP==6xMFQqb*Cqtp^1_h|9p(;{^p@ zPKk-({V7v;ebgv}B8T$x8M9?etD71c^IdT<06{5TXq5yiit_JU%j#(BJ*8iDbT1UXEWv0u!R5*mm}8lUaWQ zw`*$HbN)O5YBeq&e#nW!!Zuf`x!(d)MF0NyCnQi_Rn=j0k2>Q94Pv{$KZ{dSNzTbB z1N;!;a7S!)TtjL!U+Pt=t0}p;)2+0oyV`4a8T6z+> zd=jfycj`Dq=Vx0Q&3RO+gV`k|zL|xEz0^TLTqr9ex2&wwrh77`G8v!x`7zAe8m}EY z__4BbKT4%HZ@ty&FWxm%V2!2#m1Ma7JLxw)2~`ud{N>-qZHwJtH=)38x0Ne&6& z(#@O9+r67Aoo*`-!r%VZC4*|$o_V}?W62;XKRmCoAa<;75IYr>L}xLezFCZb(Dbgh^-3Zd%ozflu$MyTx z`dEuvYwq*hd+xb=@3YU1P<=0lhfRqM0)g;g@=$dU2#Fo|I}{Tg_!+LU=nnisb%DS% zFo7>0%#Y!~|5%Rlx-K9PSp45NlHTVNU=-*jLPiJi;gbcz-Ne}(R z+}T!4KO;a73}s){d)0A~_dHWZ<${g}*`j~mWBf_7doUC(U_a}3Os(zW94&c<8k(zR zB$qe$H}_(Z_%`2saOG(_JU6$lout=9r66H6H}C6YaU#8dAbX6ikouPLP z{+4V7m#Q~Fs|@tVrcP<4ktAoV;S~(#niE?u$SM~twN&~N!~|!rDAVgJeYBt}-A3UA zL#xht5GtFZv6-8j%T{$%fv+|kE3@eIWaA1gCkjD}>~BmierWn!O{kRjtEpCh6Y3S?n@c#%qsrZb4?@f@V zBvaBoQJk>(-WOK8+GgU6yW)Ht8`q`W25sfH)92*)WTnctrtu>QWqytDdh)?HYTk}y zW16D=eS5Cop+2anZN7{ zDM2jVv*1bfp4rK@(cEo4*wL{A|*%IElft2B8PrNf1IZc`WLM z%bKBLx8|2Yt3qW(7q0}4?KL)dme0DP!?B=Lw9~9~jC4OxYf#s>~3&hoA81m{DF(ORo_UGTb-55@9!GqGJW<)^k< zje-y|uJq;B(d;p5SGA`1J8N&@kYJRBK(38S4NRuvULc#2X~Y$v@|eGokySlCxN`0F z%6GP_p9je{q{RbtCii{#(v~(;+A%IUF;a-R9DU zFU`glQuZXnD(s1U!o-{$`i6*T*!Nhti?*|DXJpKO3_S5@L>!@K9LNNw_Q0;Y6Xi>5 z2Ii8ZVRWf#X`LDfD^e>aRQSO|t^*N|lv1PebvLmcTnVlN!mi zzE)pMVf?weQlJCbSUyBV{~I<&zaH#gZQ4?UkYeiYTI(rU-BLqaIHWc||D$Nr?*jBD zRE!$mVG8(k84eH`^~*+0)%FAixwmE!C+|vP!_ZHz%=k_V#9ikVSz-rCA@*8wjb#M9MdxjB zf=v)wGA0ujVck4Nj73z`cpZ*ro7Em0p39iMH3(rK`%FXDGilhW`o-QWGbLHJvwkH( z`$DxIoS^aHA~_tX44>$&`y>bID+C0REA$Z|M4B-8DJXAE|;e>~XLuT2?Vc^^DLI z2tAqqGwQMj!^$3PUVe%V4)H+230Uhjalu||nAG?ckDaqg--)c)E%6GS-a$xIPVc*y zjH0ErJX#Y~STia{A|;(l7rbdZPw?!FqT23dGlwBUCYd-wv8tWe33)e;P;)y7a8 z+5cHBGO8YlCZ?;(#3aAB4|qTLO&78v6y+6dofj+RZ_O74wnUmmR#;>|BKi@VkdmnxJ6u?)z{~}Nscht@X<+yTF`Pr@e*Al=(yi(vXodBpx+A{FT3d5Dtpw!gt5Qw{V4g&IwrTA2K@;T&cVt zXZrR@x6ML1G$f2<jSVX;+l_GJD--S_uN$Ytvjifnz(nX`cA6Na(D{W%HT?|;l|ET)UXPJ zjglaY+p`oS;GiP<9~npFidDJz*rHYLt_rM==F?j}C+M$>H;#UbihFS}fssF{s8}2> zSf26&d?6d>d5)VLE?Z|)Wp=3Jk{rG>&~Ft?ScU1d;NTw|Bebn&!w#thT^Xxa0!ddX z#xbH=`7>Qy5g2CoRwszoJ6fExrTzGH<0U2ecI9Vth5PJRPZdUzBTAXWU&1kMJT&mw zq0atbz1r3G?uh*Ep0QfDqezuXWX^(whzt>@{kj>CB5(I7!{XmgK$vRyZ|ln z{g@0!HQZmEyZB=nKu4HcwTDsO=^L3$Xb{l4E9;LU5^^FrHug~B@87jL*=TJI+0OhO$j&5$nR_FbnHE?94f|nSA$dOd->Hd5m##GxXuJ( z*)o0DSu9QH>}EJ-a!=1!iQoJfS6`ItoZpliO%R*%oV=0EV55xD4i;Zn~^&Nr{ zE@j21KRB{|&Z7v`_Yk`D@u5gdFn!SaKrjn+KEq5%_~q_ldfkzv0>=&}Y{!kp)=F75 zzEVlIV$lIK-tO&`w$_VMwWEde^C-?H*N$-#c$CZq9!nFhL5Hv*B}D%NNjo~;USn&ah2g70oUMBEov>*)a;u#JAZvK*x zyqqh~DESbdt@rWSe4NpuubV<(V}U9u3qeI{b<8B}5EG=8xi+mUsjan+ zPI_tTCPT0%*FV*LpUQ1V%OB|$7)X|7jE4P+Lo7WJ$gZ}#>!P1y95~v!_0aT&oCBS_ zdgyMEPErmifpA?h*m0jH(Ism7{;wd08;bZPJs^yq@hOb8=xe7pZ{mLW;^EwA#^|A; z`8chD0Hm=v+Oy#f%T^fcUdfu{=05z!)lsQEN+bqE?|#UR_%{kNwHuu+z%!@FmFX&y zmrhy^BPIV$6iLEh1C;HR4M5gbv2nzHPi9BDKcpwM;jeH%va$VXF~G^Ot)xW`U=En! zHHQ71TS~8=pBTKJBW}9bY*)Yp3tmS4I|OG~*fBu!wMyF0z9b=}4-XrGCCoEha&ytI-{czgqF=(M9rdvRxvzoSh{V6jSnS z1CgZ813=Tv%*4RCG|mza-Vk+TEY{}yHo?DLG?b$2dd4Wqsc-z8#7Zh*%!^Rwj>hb^%FH6pvrUDLwnTfh@P3x0l?emA-!B8YxMfB<=9$R zdX=%Ltf3mw!Ni1aR_2J_H$h%DvGn?8cg}id_1vjyZt)CG|J#tdA{D(Y;l$Z2`<)T- z6PL$fCB1(3x29VWBm`pHqXx~NsmR#5K1EP0<)F|%JryR0I~sFN6v^@0&(q6oZS?0B zNQE;hk#^>onE2QOQv!Ijn@!i$A;q)c6ky0N4MIM4KBaA`88LsXbeuQCe;=7+M@H!) zZnzXd8x)HzNRGi7A!c_#3+J``CNvc{+3fnP)jBa8b^fxEB*X^{HZ>` zf4mFdAv7&wICE4Q8+Wx%#bBfiD}q8#0E`Poy9T(MhmEOcyBwKLPIi1g)Trq5y6MwX z7r}$sDDBx%OQyz;sp{1~^yJjevjlO_b-s&aOy3mDR;JE;MJT8ei(Zxi8rkYn+2(b# z7UtSNI3KRo;T#P4zBAAp^L4g3acU>4!70eWW#{Z^B*TqUhZyFXpO73**-o60`26wj z{X#vUjiQ^~-BCiP9D(CMg@x6k&zv;h6!wP#I7-4n=r6Hz3Vhtp7&9zJx3fvS^F}4cRqk1j0J$_}tP&Oy@DpIJ_F<9WCWiv6Al5Fg)zjPTc01ZN-nvTv zw{IqI-kj|zfUAgsJcsodfSDP(eJnz6>n9LU8owl6H){Evkhlm4OYc_iJ)ugaT)I3iyxsTPW=25$=5++_uvx5u_ufzVn&qS!o5=V4X|KoP;Dki|~=u8OxoWu%;K-J+*I9zOu!qW77 zeKm0sHmAbpueA~}L&syeRa|1#gZzkU;Zo#*#EjXWz+Ph&GciIF%${Er^^$^F_v zdN`UX7ae}2o{(sSegX}zvZ^yuEhO}MljK87(&dp?#*_7TWz_ayrg>4#;kQ*0@!n{H z{30d$$w)H0e*egJ&36`3Y_vR4#H-nrtXcD+hB6ms55NR_K~MQMaGS!_`sDO1w>W-7 zzhugJ^UgKp1zP}^wTbt}W3J$DDzJ=KnF>rt$S6a~!EKHQ zD2uLA62XYNp^h}Ohezgn#(Q^*!oKB#*wk(mids~XQq7W~!=VikVwgRVsR#bo?< z?;eCqkZGs{P*<-Xd@>*JY=hEtdbzV%CkhMpP_}&G6NN`zU3sq^-_fP{pS)6wB7gaF z4}pVa@)w8m&mcaDJ9`i1=+uV!^Q);4peWnMrS8A1Uj{RA#P*Z3gZc+Y-JL9mVOuYW zDF-uO7{1CsRNkE_Woz=iWs=lyvGSP}XlZR`fHtnS#@-ZvP+8rY!V~&VU@z_-OMAZk zl9{2tR4=8KgjwiuW+^Rqs?o`;tM~Ya!Vx7u5MC1NMCQ|tU@Rq%bu61=jjhw*JqA>k|^KV z=qgmpqnK@~Ykf+_ZuGq_?~&jJRH67c0asPoSZSp1-}uec?AWwdd=dd^Mc`wjlwzOH z$?idV0#p z*h%^?KViWb1yo@nj-r1uu9s_eF9*&V!(cEywYT1&l*=4;bMf^I^9cE>>XaFvB>vOc zIZ`wN1|;W$k{xc6$S$V!@7dh!7|H?{r85b+{~Ml&{jXa%!f)5hg9I3QExh zy(RpA%MyvLNO=L+&Y>yeO_B?02s|tk_1kUBBnt;Pyaxlu_%y;=5u-{ z1YM+qINodjizd!lw)cwPQsgCrcOD2hwN{r;{VG?7IU1~eZu0t30Pie9>Gi!XzMq;j zwi_oTSj>4zF03Rjd$FdRoa_V$-~9&!y#UTmcerSMdHcM(kTTPRs8ZyZ=4o~RM7&T} zv%d(~C);#lI;Vle5h&c6m~oaC68~39AlyY< zb@GS)%HWs&X`qGbThig^$o0qN)(q1~epw_R>X!rF;@)uI825UIq)_z;MeZU(w=BU? zM4Y3@3ExB^P34U5Q6soa1{0}8N>}=wV<{5^N6D~lxllX*+Ux40y(##zlp@Up?}^{0 z5;4oQe7wB0Zwt80#_x0!Wh1)hbg~JL(VFO?P2zt)`M*>S_hcdM0!dep0tQINM(-Ga zJ>NcEPizhO{PJ&8o(Z>^OEB}lOPs2(Nh(k|-=U+1ru8-y^pkZG6^i9JJ-|9Rpb~^X&bwUPxf<%XriDm{e)+a*!fx<6XpfkB z7y!w`MnnWq5+o$Ycf=pe3^ceDE#_4sFD05qiMWPiV&!-zGGF*!jCoUD&UN-2+O2Ds zI^JmH115}(s?U+kg#Y6Zd!aC_)C`z>l&KjW&hfuClx}r5qC@;e2ski5pFeh_?^HB= z#a9r8ep2e~ACjj^sD7hMSiWH^D1!+MNC7ogZTMq%?M*+?=f}reA)fK~0|(nuS2pus z44Gq4YtGK`dd6mkhCC|smj(t$U)!9T0_MNSA*~nX)DQD(+a|Bb#BMLZ@%n!S4&cgj z0|gGE9!ce6JhaAhXou8)$y_-!d`x$akz%aWtD_qJ4ea8B z4QZNBpY}bxMQe?h-gxtfJ8Yz70Hj6E5^Q;LvKvbH{*BIRX)YR<=b1sUJm|@q+AWxA z{SuE#ez~fv5U~^pl>8TZ4XRf|2|{FTgRH@lx$3TF`;$f)U$bi5@okCLe^-Zo4h=~J zqJ36N11Peh20=ml>ifIsnugR2<%-+$x%-7rfC+O(XfkhJo855ZhrOoo@OXbR(|nE*oVTC<(e&xi!9?sUk_VP{Ao zHvKLeo>Oc!kSPaVwTw*csJYxWEFN1UG+y&_#HU9QB#2c0q5UI?k$jC3^X*^07lxGq zw(oTiDe@P%Sa{|D+wrlHm;xu^Y%^WB&>K@xm4#V!eq5EP+@6i8n|$@;Py&!qZVC zb&Qj*pcwtt#@ZN}P#M8X_lQ4cwkhF2C0FRM@;*$rX4dOC{kQc()M2yx?NBni*wgJ! zVVezcg!HM#+uOL8AzWUkrY^~$mPFtlGS9U2yIi!U(9dtDKI{tUAjj4~)9)VL!EH}z zeo^FKV^`hY3WtRF)Y`saw-{dCSZY?*d>PT5b5pDV*!brPJ=klyt8ap5w<5)UuhGij ztXB9x(ip8+2D1z#2>UdTW;3@0ZW*Q=SVG zF~$S{2!M0i_4z)gMJ$v}&%(iaUDTKnvMDUu7wI@dLyjFRkDL%46!Z9SBf&lPYG9k3 zEWXkd&G!Amby&Mf0R-r-`lbmM`Kl7yBcouQU6xHYqV@EoH+m*!aTr<5^h6!DA|et6 z9UAggL#8TJjG4~e{&_nMe^=;;sO`o|`vB6y|M+qCH8+kGIiayySnNYC*iFv_+ppTm z%*NYW`|d_@ZVuRiYXurAD)L^yczZi9jVYqobx^K>Nf+Eq&Q1eq!5(hk<)2n5_@_&s z*!7TAbEkOBAHAN=&qwi<3o_#flx=1T0rdsgoZmM#r2W*0fJu@jB|AGcp_zd|=vx2o z0*DKyxCnkqh)>-3BgRN<%e5rkuyv@rp3Es|;5dUkF_h-n#C~j03ra`~%bwyu$1Rf) zPg0Oh!4&7cKB_5J42G)H0QvNFtgX$Yg9d@Urf55p#?i2X)(h?y92pr?r>>uvF|^`) zy*FV=1wS&*X5LjwwN=SN4?%X-?fM0@falTCtG6fL%%RJG-(72+9i6O&#9_>{iYPrtZd<36C`Lcrm{fhO# z*0{lGRyP?lqMHWbdVEC~_srHu{1a@5#z4nc%^EAD{Cp3`ha06;vW?0THX`DP60Rb` z5oN`VEpM{Uw5`)%hjzf_fS54IJC7jr3+u7ZKnuQ~^=;GhB~UmPDLQg3^u_Yqu{Wh9O0R_A%pta; z_i}auBru)YfhR`(Xf8C5-J8hDuSKvET2Ut_W5QfJkwZ=_TUyZ1j+>``d~&~h3kLz+ z839mPbk{gBeK9_uYaF`!UdOsGH*Q=o(kNX50rtPwBb1R@LCN^vXMT9RP5P&{wnj4W zs_t2WK`wzQKYkSCfPeI*CBIqtxs|KMiIfR~?{~RlSpLc0 zwzG9wLt| z&4_IzBs(hJ(4w^6pNkSw^lYfTuY!j#RD{y@_5OuToiC05`xMB=_Xcn<1b}A7)rGZn z#D5KFL>(P=FL^_O;q547o!?lJxEYzsT!G65*Ri<@I-c zqxi#g&jsLxUg%Z^YzR7}(t6Pn#95{a*tbn2B8Uj&#*kaFE?G{fWm``P3|j}6SNzNX zgP31T+48m*H3fdm~KBlOYcA;8sB9;!&Ll8llx_%21CO`hS17dDZ0JB(|q4Lzw z|L>2Vv~%Q5Ej7i{%o0tAXPF3q%l*)Wicf(O#-4KO?#Y+R_W)9RnbzNFgz@kU2`f2 z&_*MmAZme`A4a2LuaT|l2G1THQZFTixhoG*4-EXxp7IMHXj6PnW`{*Yb*U5}uXe{! ziM2Tw>}3zxgoQy&cBAR5=r|>B895PrcH_oZfha9a4jGNFZx}qh@K;-}+2}M4V&Y|n zNa=f#jX;LIYq5A#)dJk{K+k~#rl|hNGG*iGeQxp8=w8tnR}Ye=lU0CZKf-P{bc zs#{SNpw=2?sI#qc*p#3DQY=OsQMXA(cKR@wR4U>*zSwteJ!!SxWdlHiZtZax&^WA< zYQ!d6J^Ed1*m`n##^ayaZQswyQJ6g|-ds~E(wR1w`Ho7t+kuisd=mXH)<_vdQ93_ih-K-zB* sA%i8Y;j7NMPdvZsHj!igka6?;7cuvWys+mta3u`{lX(v