1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-01-16 07:08:01 +00:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Henry Schreiner
04054ad1fa Update Azure 2020-06-01 23:00:20 -04:00
Henry Schreiner
b4bb084e38 Update changelog 2020-06-01 23:00:20 -04:00
Henry Schreiner
de117cf1e5 Updates for TrueFalse test 2020-06-01 23:00:20 -04:00
Henry Schreiner
5188ede219 📝 Add @certik as a contributor 2020-06-01 21:47:01 -04:00
Ondřej Čertík
ccb1ccaa0a Use e.get_name instead of dynamic_cast (#467)
* Use e.get_name instead of dynamic_cast

Also use std::static_pointer_cast instead of std::dynamic_pointer_cast

Fixes #466

* feat: Allow RTTI to be turned off

* ci: Fix CXX flags

* doc: Adding update to book

Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
2020-06-01 21:46:42 -04:00
Christoph Bachhuber
a8185bb499 Simplify clang tidy config file (#469)
* Update submodule

* Treat all enabled clang-tidy warnings as errors

* Revert "Update submodule"

This reverts commit b455d1d0f9.
2020-06-01 21:45:00 -04:00
Henry Schreiner
0cee321ef9 ci: Update GTest to master (#470)
* ci: Update googletest to fix windows error

* chore: Minor updates to CI versions
2020-06-01 21:44:23 -04:00
Philip Top
6f589b8443 fix issue with option defaults not propagating to option groups (#450) 2020-06-01 21:43:24 -04:00
Christoph Bachhuber
eb1150d6be Fix clang tidy (#451)
* Add already passing check

* Remove too modern clang-tidy-9 check
2020-06-01 21:42:53 -04:00
Philip Top
543e7f1577 try clang 10 (#459)
* try clang 10

* use helics-builder clang 10 image

* try new image

* try again

* try different flag addition

* try adding cpp20 to visual studio check

* try with the latest flag enabled for visual studio 2019

* try the correct c++ flag

* remove use of std::result_of

* format files
2020-06-01 21:42:44 -04:00
Philip Top
7e6ff84c69 fix for the cmake_config tests (#455) 2020-06-01 21:42:28 -04:00
Philip Top
023bf54282 Add windows latest and gcc 8 builds to azure (#446)
* add windows latest and gcc 8 builds to azure

* try adding pr trigger

* try adding something specific for gcc 8

* use interface instead of public

* try C++17 on clang 8

* update the readme with some additional notes about gcc 8

* fix some incorrect doxygen comment formatting

* try using the glibcxx_release value

* debug some code paths to make sure macros are working

* Update readme and fix formatting.

* update formatting for Validators
2020-06-01 21:42:08 -04:00
16 changed files with 167 additions and 38 deletions

View File

@ -359,6 +359,15 @@
"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"
]
}
],
"contributorsPerLine": 7,

View File

@ -6,26 +6,16 @@ FormatStyle: file
Checks: '
-*,
google-*,
-google-runtime-int,
-google-runtime-references,
llvm-include-order,
llvm-namespace-comment,
misc-throw-by-value-catch-by-reference,
modernize*,
-modernize-use-trailing-return-type,
readability-container-size-empty,
'
WarningsAsErrors: '
-*,
google-*,
-google-runtime-int,
-google-runtime-references,
llvm-include-order,
llvm-namespace-comment,
misc-throw-by-value-catch-by-reference,
modernize*,
readability-container-size-empty,
'
WarningsAsErrors: '*'
HeaderFilterRegex: '.*hpp'

View File

@ -7,7 +7,7 @@ RUN apt-get update \
libidn11=1.33-2.1ubuntu1.2 \
ca-certificates=20180409 \
make=4.1-9.1ubuntu1 \
git=1:2.17.1-1ubuntu0.5 \
git=1:2.17.1-1ubuntu0.7 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@ -13,15 +13,15 @@ jobs:
name: Formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- name: set PY
run: echo "::set-env name=PY::$(python --version --version | sha256sum | cut -d' ' -f1)"
run: echo "::set-env name=PY::$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')"
- uses: actions/cache@v1
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- uses: pre-commit/action@v1.0.0
- uses: pre-commit/action@v1.1.0
cuda-build:
name: CUDA build only
@ -107,9 +107,14 @@ jobs:
with:
version: 3.15.6
if: success() || failure()
- name: CMake 3.16
uses: ./.github/actions/cmake_config
with:
version: 3.16.8
if: success() || failure()
- name: CMake 3.16 (full)
uses: ./.github/actions/cmake_config
with:
version: 3.16.2
version: 3.17.3
options: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
if: success() || failure()

View File

@ -1,3 +1,33 @@
## Version 2.0: In progress
* Built-in config format is TOML compliant now [#435]
* Config updates [#442]
* More powerful containers, `%%` separator [#423]
* Add a version flag easily [#452]
[#435]: https://github.com/CLIUtils/CLI11/pull/435
[#443]: https://github.com/CLIUtils/CLI11/pull/443
[#423]: https://github.com/CLIUtils/CLI11/pull/423
[#452]: https://github.com/CLIUtils/CLI11/pull/452
### Version 1.9.1: Backporting fixes
This is a patch version that backports fixes from the development of 2.0.
* 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
## 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).

View File

@ -151,6 +151,21 @@ make
GTEST_COLOR=1 CTEST_OUTPUT_ON_FAILURE=1 make test
```
<details><summary>Note: Special instructions for GCC 8</summary><p>
If you are using GCC 8 and using it in C++17 mode with CLI11. CLI11 makes use of the `<filesystem>` 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 `<filesystem>` 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.
</p></details>
</br>
## Usage
### Adding options
@ -910,6 +925,7 @@ This project was created by [Henry Schreiner](https://github.com/henryiii) and m
<tr>
<td align="center"><a href="https://github.com/jsoref"><img src="https://avatars0.githubusercontent.com/u/2119212?v=4" width="100px;" alt=""/><br /><sub><b>Josh Soref</b></sub></a><br /><a href="#tool-jsoref" title="Tools">🔧</a></td>
<td align="center"><a href="https://github.com/geir-t"><img src="https://avatars3.githubusercontent.com/u/35292136?v=4" width="100px;" alt=""/><br /><sub><b>geir-t</b></sub></a><br /><a href="#platform-geir-t" title="Packaging/porting to new platform">📦</a></td>
<td align="center"><a href="https://ondrejcertik.com/"><img src="https://avatars3.githubusercontent.com/u/20568?v=4" width="100px;" alt=""/><br /><sub><b>Ondřej Čertík</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Acertik" title="Bug reports">🐛</a></td>
</tr>
</table>
@ -929,7 +945,7 @@ CLI11 was developed at the [University of Cincinnati][] to support of the [GooFi
[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=master
[azure]: https://dev.azure.com/CLIUtils/CLI11/_build/latest?definitionId=1&branchName=master
[azure]: https://dev.azure.com/CLIUtils/CLI11
[travis-badge]: https://img.shields.io/travis/CLIUtils/CLI11/master.svg?label=Linux/macOS
[travis]: https://travis-ci.org/CLIUtils/CLI11
[appveyor-badge]: https://img.shields.io/appveyor/ci/HenrySchreiner/cli11/master.svg?label=AppVeyor

View File

@ -5,6 +5,11 @@
trigger:
- master
- 'v*'
pr:
- master
- 'v*'
variables:
cli11.single: ON
@ -57,6 +62,14 @@ jobs:
Windows11:
vmImage: 'vs2017-win2016'
cli11.std: 11
Windowslatest:
vmImage: 'windows-2019'
cli11.std: 20
cli11.options: -DCMAKE_CXX_FLAGS="/std:c++latest /EHsc"
Linux17nortti:
vmImage: 'ubuntu-latest'
cli11.std: 17
cli11.options: -DCMAKE_CXX_FLAGS="-fno-rtti"
pool:
vmImage: $(vmImage)
steps:
@ -89,6 +102,9 @@ jobs:
gcc9:
containerImage: gcc:9
cli11.std: 17
gcc8:
containerImage: gcc:8
cli11.std: 17
gcc4.8:
containerImage: gcc:4.8
cli11.std: 11
@ -100,6 +116,14 @@ jobs:
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: helics/buildenv:clang10-builder
cli11.std: 20
cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20
container: $[ variables['containerImage'] ]
steps:
- template: .ci/azure-cmake.yml

View File

@ -115,7 +115,8 @@ The default configuration file will read TOML files, but will write out files in
```cpp
app.config_formatter(std::make_shared<CLI::ConfigTOML>());
```
which makes use of a predefined modification of the ConfigBase class which INI also uses.
which makes use of a predefined modification of the ConfigBase class which INI 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

2
extern/googletest vendored

@ -1 +1 @@
Subproject commit 2fe3bd994b3189899d93f1d5a881e725e046fdc2
Subproject commit 859bfe8981d6724c4ea06e73d29accd8588f3230

View File

@ -975,7 +975,7 @@ class App {
/// creates an option group as part of the given app
template <typename T = Option_group>
T *add_option_group(std::string group_name, std::string group_description = "") {
auto option_group = std::make_shared<T>(std::move(group_description), group_name, nullptr);
auto option_group = std::make_shared<T>(std::move(group_description), group_name, this);
auto ptr = option_group.get();
// move to App_p for overload resolution on older gcc versions
App_p app_ptr = std::dynamic_pointer_cast<App>(option_group);
@ -1314,15 +1314,15 @@ class App {
int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const {
/// Avoid printing anything if this is a CLI::RuntimeError
if(dynamic_cast<const CLI::RuntimeError *>(&e) != nullptr)
if(e.get_name() == "RuntimeError")
return e.get_exit_code();
if(dynamic_cast<const CLI::CallForHelp *>(&e) != nullptr) {
if(e.get_name() == "CallForHelp") {
out << help();
return e.get_exit_code();
}
if(dynamic_cast<const CLI::CallForAllHelp *>(&e) != nullptr) {
if(e.get_name() == "CallForAllHelp") {
out << help("", AppFormatMode::All);
return e.get_exit_code();
}
@ -1524,7 +1524,12 @@ class App {
/// Access the config formatter as a configBase pointer
std::shared_ptr<ConfigBase> get_config_formatter_base() const {
// This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase
#if defined(__cpp_rtti) || (defined(__GXX_RTTI) && __GXX_RTTI) || (defined(_HAS_STATIC_RTTI) && (_HAS_STATIC_RTTI == 0))
return std::dynamic_pointer_cast<ConfigBase>(config_formatter_);
#else
return std::static_pointer_cast<ConfigBase>(config_formatter_);
#endif
}
/// Get the app or subcommand description
@ -3055,7 +3060,18 @@ inline std::string help(const App *app, const Error &e) {
namespace detail {
/// This class is simply to allow tests access to App's protected functions
struct AppFriend {
#ifdef CLI11_CPP14
/// Wrap _parse_short, perfectly forward arguments and return
template <typename... Args> static decltype(auto) parse_arg(App *app, Args &&... args) {
return app->_parse_arg(std::forward<Args>(args)...);
}
/// Wrap _parse_subcommand, perfectly forward arguments and return
template <typename... Args> static decltype(auto) parse_subcommand(App *app, Args &&... args) {
return app->_parse_subcommand(std::forward<Args>(args)...);
}
#else
/// Wrap _parse_short, perfectly forward arguments and return
template <typename... Args>
static auto parse_arg(App *app, Args &&... args) ->
@ -3069,6 +3085,7 @@ struct AppFriend {
typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
return app->_parse_subcommand(std::forward<Args>(args)...);
}
#endif
/// Wrap the fallthrough parent function to make sure that is working correctly
static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
};

View File

@ -24,9 +24,9 @@ class App;
/// the second argument.
enum class AppFormatMode {
Normal, //< The normal, detailed help
All, //< A fully expanded help
Sub, //< Used when printed as part of expanded subcommand
Normal, ///< The normal, detailed help
All, ///< A fully expanded help
Sub, ///< Used when printed as part of expanded subcommand
};
/// This is the minimum requirements to run a formatter.

View File

@ -506,7 +506,7 @@ class Option : public OptionBase<Option> {
/// Can find a string if needed
template <typename T = App> Option *needs(std::string opt_name) {
auto opt = dynamic_cast<T *>(parent_)->get_option_no_throw(opt_name);
auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
if(opt == nullptr) {
throw IncorrectConstruction::MissingOption(opt_name);
}
@ -548,7 +548,7 @@ class Option : public OptionBase<Option> {
/// Can find a string if needed
template <typename T = App> Option *excludes(std::string opt_name) {
auto opt = dynamic_cast<T *>(parent_)->get_option_no_throw(opt_name);
auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name);
if(opt == nullptr) {
throw IncorrectConstruction::MissingOption(opt_name);
}
@ -585,7 +585,7 @@ class Option : public OptionBase<Option> {
template <typename T = App> Option *ignore_case(bool value = true) {
if(!ignore_case_ && value) {
ignore_case_ = value;
auto *parent = dynamic_cast<T *>(parent_);
auto *parent = static_cast<T *>(parent_);
for(const Option_p &opt : parent->options_) {
if(opt.get() == this) {
continue;
@ -610,7 +610,7 @@ class Option : public OptionBase<Option> {
if(!ignore_underscore_ && value) {
ignore_underscore_ = value;
auto *parent = dynamic_cast<T *>(parent_);
auto *parent = static_cast<T *>(parent_);
for(const Option_p &opt : parent->options_) {
if(opt.get() == this) {
continue;

View File

@ -33,7 +33,14 @@
#else
#include <filesystem>
#if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703
#if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9
#define CLI11_HAS_FILESYSTEM 1
#elif defined(__GLIBCXX__)
// if we are using gcc and Version <9 default to no filesystem
#define CLI11_HAS_FILESYSTEM 0
#else
#define CLI11_HAS_FILESYSTEM 1
#endif
#else
#define CLI11_HAS_FILESYSTEM 0
#endif

View File

@ -368,6 +368,18 @@ TEST_F(TApp, InvalidOptions) {
EXPECT_THROW(ogroup->add_option(opt), CLI::OptionNotFound);
}
TEST_F(TApp, OptionGroupInheritedOptionDefaults) {
app.option_defaults()->ignore_case();
auto ogroup = app.add_option_group("clusters");
int res{0};
ogroup->add_option("--test1", res);
args = {"--Test1", "5"};
run();
EXPECT_EQ(res, 5);
EXPECT_EQ(app.count_all(), 1u);
}
struct ManyGroups : public TApp {
CLI::Option_group *main{nullptr};

View File

@ -1,7 +1,13 @@
// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#include "app_helper.hpp"
/// This allows a set of strings to be run over by a test
struct TApp_TBO : public TApp, public ::testing::WithParamInterface<const char *> {};
struct TApp_TBO : public TApp_base, testing::TestWithParam<const char *> {};
TEST_P(TApp_TBO, TrueBoolOption) {
bool value{false}; // Not used, but set just in case
@ -13,10 +19,10 @@ TEST_P(TApp_TBO, TrueBoolOption) {
}
// Change to INSTANTIATE_TEST_SUITE_P in GTest master
INSTANTIATE_TEST_CASE_P(TrueBoolOptions, TApp_TBO, ::testing::Values("true", "on", "True", "ON"), );
INSTANTIATE_TEST_SUITE_P(TrueBoolOptions_test, TApp_TBO, testing::Values("true", "on", "True", "ON"));
/// This allows a set of strings to be run over by a test
struct TApp_FBO : public TApp, public ::testing::WithParamInterface<const char *> {};
struct TApp_FBO : public TApp_base, public ::testing::TestWithParam<const char *> {};
TEST_P(TApp_FBO, FalseBoolOptions) {
bool value{true}; // Not used, but set just in case
@ -27,4 +33,4 @@ TEST_P(TApp_FBO, FalseBoolOptions) {
EXPECT_FALSE(value);
}
INSTANTIATE_TEST_CASE_P(FalseBoolOptions, TApp_FBO, ::testing::Values("false", "off", "False", "OFF"), );
INSTANTIATE_TEST_SUITE_P(FalseBoolOptions_test, TApp_FBO, ::testing::Values("false", "off", "False", "OFF"));

View File

@ -1,3 +1,9 @@
// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
// under NSF AWARD 1414736 and by the respective contributors.
// All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#ifdef CLI11_SINGLE_FILE
@ -8,13 +14,17 @@
#include "gtest/gtest.h"
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using input_t = std::vector<std::string>;
struct TApp : public ::testing::Test {
class TApp_base {
public:
CLI::App app{"My Test Program"};
input_t args{};
virtual ~TApp_base() = default;
void run() {
// It is okay to re-parse - clear is called automatically before a parse.
input_t newargs = args;
@ -23,6 +33,8 @@ struct TApp : public ::testing::Test {
}
};
class TApp : public TApp_base, public ::testing::Test {};
class TempFile {
std::string _name{};