This looks cool but c++17 is required (as far as I can tell, since it requires std::optional), so it's difficult to use for many things until all my colleagues (and their clusters) upgrade their compilers.
I switched from gflags to absl::flags and I like it, though there are recommendations against using them too much - https://abseil.io/tips/45 and https://abseil.io/tips/103 (one of my first surprises starting at google, was that binaries (e.g. "exe's") would have thousands of options, just adding a new library to your binary, and more flags are there). I actually like that one, as rather than configuring top-down everything, one can directly "inject" values - for example if you were told to switch from one library to the other, and change your borg template for launching jobs, that new borg template that you've used would have flags set (by another team). Then that team can take it further and modify them if needed, thus allowing them to control their part of the software in your own deployed binary. (This way experiments can be rolled out too, or who knows what else).
I get it, I'm using it in one project myself, and happy. I do wish though if namespaces were kept - e.g. if there is ambiguity in the names, one can resolve with full namespace (but maybe that also creates an issue, as previously existing invocations may help, so it's like - you better don't rely on C++ namespaces as you may need to fully qualify a flag later and that could be problematic).. Hmm..
While I can understand that problem, I think it's a reasonable time to target C++17. In fact I would be somewhat weary of new libraries that use something prior of c++17.
Then upgrade their compilers, it's not as big a jump as c++11 was. It's not bleeding edge.
The only legitimate case I've seen for C++ <17 is if you need to compile on MacOS <= 10.13 for shipping 32 bit binaries on Mac, where C++17 features are experimental in XCode (but I haven't had an issue with compatibility in C++17 supported compilers).
CentOS and Debian shipping ancient GCC versions isn't an excuse, it's trivial to update.
For the record, CentOS 7 can have gcc-9 by installing devtoolset-9. To get access, you have to start a shell that can see them with "scl enable devtoolset-9 bash".
But people delivering libraries to customers who have elected not to upgrade to current releases are pretty much stuck. It is extremely common for banks, in particular, to still be running gcc-4, and to have no plans ever to upgrade.
It is common at least in banks to have an unbreakable policy never to upgrade software on a server to a version that was not on it when it was unboxed. They may bend just so far as to install back-patched security fixes from the vendor. But a libstdc++.so compatible with a current language Standard? Haha, they say, you must be joking.
It is not unusual for them to still run RHEL 6, or even 5. Bloomberg infamously still has 32-bit SPARCs in the basement, running code compiled only ever with Sun's old compiler.
I had a celebration the day I could push RHEL5 builds off the compatibility raft. Then I spent a couple weeks learning about "new" C++ features I hadn't been able to use because it was too hard to ship code that a customer could build on RHEL5.
Kinda frustrating that in 2020 people complain about a library targetting a 3 years old standard as being "too recent". I'm sure some guys in your company update their node_modules daily and don't get any flak so why not just do the same and use recent tools ? Recent compilers are available for every platform. If you can compile c++17 for commodore 64 and MS-DOS you can for everything else too.
The problem is that not everyone is in control of their computing environment, especially on university clusters. Yes, it's possible to install your own compiler (and in some cases, this might require recompiling a bunch of things due to C++ ABI issues), but for many users, that's a difficult task!
Looks like everyone and their grandmum makes a command line parser. I can see the draw. It’s a problem with a small scope that you can make a dent in over a weekend.
> Include <structopt/app.hpp> and you're good to go.
I haven't touched C++ for almost a decade but I assume there's (still?) no obvious way that always works to include a dependency package in your build?
For you C++ devs, does this instruction make it obvious how to install this thing into your project?
The instruction makes me suspect that it is a header only library. In this case I would just drop the library source in a dedicated subfolder and expect it to work.
(While it feels better than fighting the system to get a dependency to link properly I would still rather have a proper package manager...)
It requires some digging into the project, because at first glance it doesn't seem to be a simple header-only library. There's a conanfile.py, and a CMakeLists.txt and all sorts of "junk" in the project directory.
But in the end it all seems to come down to this single header file which only depends on C++ stdlib headers and which can be dropped into your own project (which seems to be generated (aka "amalgamated") from multiple smaller header files):
So for typical C++ libraries, this seems quite straightforward to integrate. Usually when looking at a project directory full of random files like this, it's a lot more complicated.
If this is something you do in CMake projects, check out FetchContent_Declare — newer CMake versions have this command which downloads a git repository and caches it.
I much prefer this to manually downloading the files, even for header-only libraries. The command provided a nice declarative way of adding a dependency.
It mostly depends on how tight you want the coupling between your project and the dependency in question. It can vary between just getting the source files and building them yourself, just like you do with your own stuff, to just using the public headers plus the relevant static/shared library.
Most of the time, you'll want the latter. The right thing to do in 2020 in that case is IMHO to integrate with a source-based build system like vcpkg, portage (see the prefix project), conan, macports etc. Once the dev-env setup script boils down to just a list of packages, the question of importing third-party dependencies stops being a pain.
I've used most of these (except conan) and vcpkg seems like it's the most painless one, especially because it's a CMake-based system and FWIW CMake seems to be what the C++ world is converging on these days. From my bubble anyway.
During, I think MS Build, Microsoft said, vcpkg, it's their C++ package manager, will support this this year. I read it on their roadmap file in the repo too. VCPKG seems to be the path of least resistance, works accross platforms too
If you have a single source file with no dependencies you can just include it into whatever compilation units you want. That is very easy and elegant. When there are complex dependencies it becomes more problematic.
My previous employer's binary repository settled on using nuget for everything as it was primarily a .NET shop. For our internal C++ projects I made a 'nuget_package_add' CMake script which allowed us to package a lot of our C++ libraries and use them by adding a single line to our CMake scripts.
The main problem was nuget support for C++ DLLs is pretty horrible. I did not want to resort to parsing the .targets file from CMake script so I ended up making non-standard nuget packages that pretty much only worked with our CMake script.
Is 'structopt' a common name for this type of argument parser library? I thought it started with the Rust library of the same name but no one has mentioned it yet...
In my opinion, it is _the_ way to quickly create a quality CLI.
Half of the argument-parsing libraries contain either “arg” or “opt” due to the initial widespread of getopt or argp. And since both tools parse the arguments into a struct, the choice isn’t that surprising.
If you look at the repo's tags, they also include `clap`, which is the most popular Rust argument parsing library and the one that the original structopt is built upon.
I don't think this coincidence. This looks like it's directly inspired by the Rust library, even though the README gives no indication of that.
It's an interesting concept where you define the command line "help" syntax and it generates an arguments structure and an associated parser. I've used the C version, I believe the C++ version is better maintained.
Docopt is great until you start digging in and discover the author doesn't have the first clue about parsing. I don't mean in the sense of "weird opinions about recursive descent", but in the literal sense of "has no idea what parsing is or means". The internal implementation is a gigantic clusterfuck of the worst sort of poorly constructed, unmaintainable code you could imagine.
I maintain two ports of docopt and I'm telling you not to use it.
58 comments
[ 3.0 ms ] story [ 119 ms ] threadThe only legitimate case I've seen for C++ <17 is if you need to compile on MacOS <= 10.13 for shipping 32 bit binaries on Mac, where C++17 features are experimental in XCode (but I haven't had an issue with compatibility in C++17 supported compilers).
CentOS and Debian shipping ancient GCC versions isn't an excuse, it's trivial to update.
If only life was that simple.
But people delivering libraries to customers who have elected not to upgrade to current releases are pretty much stuck. It is extremely common for banks, in particular, to still be running gcc-4, and to have no plans ever to upgrade.
It is common at least in banks to have an unbreakable policy never to upgrade software on a server to a version that was not on it when it was unboxed. They may bend just so far as to install back-patched security fixes from the vendor. But a libstdc++.so compatible with a current language Standard? Haha, they say, you must be joking.
It is not unusual for them to still run RHEL 6, or even 5. Bloomberg infamously still has 32-bit SPARCs in the basement, running code compiled only ever with Sun's old compiler.
are your friends
It seems to have plenty of features and good documentation, plus it's available as a single header file.
[0] https://github.com/CLIUtils/CLI11
Looks like everyone and their grandmum makes a command line parser. I can see the draw. It’s a problem with a small scope that you can make a dent in over a weekend.
Now does it generate the synopsis part of a man page automatically?
The nice thing with Python is that I implemented a parser from a function signature, and it also works for NamedTuple.
The advantage wrt to other python parser is that it uses the type annotations, instead of guessing
I haven't touched C++ for almost a decade but I assume there's (still?) no obvious way that always works to include a dependency package in your build?
For you C++ devs, does this instruction make it obvious how to install this thing into your project?
(While it feels better than fighting the system to get a dependency to link properly I would still rather have a proper package manager...)
But in the end it all seems to come down to this single header file which only depends on C++ stdlib headers and which can be dropped into your own project (which seems to be generated (aka "amalgamated") from multiple smaller header files):
https://github.com/p-ranav/structopt/tree/master/single_incl...
So for typical C++ libraries, this seems quite straightforward to integrate. Usually when looking at a project directory full of random files like this, it's a lot more complicated.
* add the structopt repository as a git submodule to your project
* add something like `add_subdirectory(structopt)` to your top-level CMake script
* add structopt to your target_link_libraries
and you're good to go.
But given that it's a header-only library, you can also just download the files, put them in your repo somewhere, and #include them.
I much prefer this to manually downloading the files, even for header-only libraries. The command provided a nice declarative way of adding a dependency.
Most of the time, you'll want the latter. The right thing to do in 2020 in that case is IMHO to integrate with a source-based build system like vcpkg, portage (see the prefix project), conan, macports etc. Once the dev-env setup script boils down to just a list of packages, the question of importing third-party dependencies stops being a pain.
I've used most of these (except conan) and vcpkg seems like it's the most painless one, especially because it's a CMake-based system and FWIW CMake seems to be what the C++ world is converging on these days. From my bubble anyway.
The main problem was nuget support for C++ DLLs is pretty horrible. I did not want to resort to parsing the .targets file from CMake script so I ended up making non-standard nuget packages that pretty much only worked with our CMake script.
static VISIT_STRUCT_CONSTEXPR const int max_visitable_members = 69; https://github.com/p-ranav/structopt/blob/master/single_incl...
That looks like something that was proposed for inclusion in boost a long time ago. I think it eventually got accepted after some renaming :)
The amount of preprocessor magic in that file makes my head hurt.
;-)
https://github.com/oriansj/M2-Planet/blob/master/cc.c#L40
In my opinion, it is _the_ way to quickly create a quality CLI.
https://github.com/TeXitoi/structopt
I don't think this coincidence. This looks like it's directly inspired by the Rust library, even though the README gives no indication of that.
Though I'm not sure if the Rust clap has any origins in any specific library for another language.
It's an interesting concept where you define the command line "help" syntax and it generates an arguments structure and an associated parser. I've used the C version, I believe the C++ version is better maintained.
I maintain two ports of docopt and I'm telling you not to use it.