Ookii.CommandLine for C++ is a powerful and flexible command line argument parsing library for C++ applications.
- Easily define strongly-typed arguments, with a simple builder API or using code-generation.
- Create applications with multiple subcommands.
- Generate fully customizable usage help.
- Supports PowerShell-like and POSIX-like parsing rules.
- Header-only library.
Ookii.CommandLine for C++ is a port of Ookii.CommandLine for .Net, providing the same argument parsing semantics, but using an API that is suitable for C++. It has feature parity with Ookii.CommandLine 2.4 for .Net, with the exception of dictionary argument, and some features from Ookii.CommandLine 3.0 for .Net.
Ookii.CommandLine is a library that lets you parse the command line arguments for your application into a set of strongly-typed, named values. You can easily define the accepted arguments, and then parse the command line supplied to your application for those arguments. In addition, you can generate usage help that can be displayed to the user.
Ookii.CommandLine can be used with any kind of C++ application, whether console or GUI. Some functions, such as creating usage help, are primarily designed for console applications, but even those can be easily adapted for use with other styles of applications.
Two styles of command line parsing rules are supported: the default mode uses rules similar to those used by PowerShell, and the alternative long/short mode uses a style influenced by POSIX conventions, where arguments have separate long and short names with different prefixes. Many aspects of the parsing rules are configurable.
To determine which arguments are accepted, first you create variables that will hold their values.
Then, you use the ookii::parser_builder
class to specify things such as the argument names,
whether or not an argument is required, and descriptions used to customize the usage help, among
other options. This creates an an ookii::command_line_parser
, which can parse those arguments.
For example, the following code defines four arguments: a required positional argument, an optional positional argument, a named-only argument, and a switch argument (sometimes also called a flag):
std::string required_argument;
int optional_argument;
float named_argument;
bool switch_argument;
// argv[0] is used for the application executable name.
auto name = ookii::command_line_parser::get_executable_name(argc, argv);
auto parser = ookii::parser_builder{name}
.add_argument(required_argument, "Required").required().positional()
.description("A required positional argument.")
.add_argument(optional_argument, "Optional").positional()
.description("An optional positional argument.")
.add_argument(named_argument, "Named")
.description("An argument that can only supplied by name.")
.add_argument(switch_argument, "Switch")
.description("A switch argument, which doesn't require a value.")
.build();
Each argument has a different type that determines the kinds of values it can accept.
To parse these arguments, all you have to do is call the following on the generated parser.
ookii::parse_result result = parser.parse(argc, argv, {});
This code will parse the arguments in the argv
array, will handle and print errors to the console,
and will print usage help if needed. It returns an ookii::parse_result
that indicates if the
operation was successful (it can be converted to bool
for this purpose).
If the arguments are invalid, or help is requested, this application will print the following usage help:
Usage: sample_app [-Required] <string> [[-Optional] <int>] [-Help] [-Named <float>]
[-Switch] [-Version]
-Required <string>
A required positional argument.
-Optional <int>
An optional positional argument.
-Help [<bool>] (-?, -h)
Displays this help message.
-Named <float>
An argument that can only supplied by name.
-Switch [<bool>]
A switch argument, which doesn't require a value.
The usage help includes the descriptions given for the arguments.
See the documentation for the samples for more examples of usage help generated by Ookii.CommandLine. The usage help format can also be fully customized.
The application also has one argument that wasn't explicitly defined, -Help
, which is
automatically added by default. You can also easily add a default -Version
argument.
An example invocation of this application, specifying all the arguments, would look like this (argument names are case insensitive by default):
./MyApplication foo 42 -switch -named 5.6
Ookii.CommandLine also provides code generation scripts that can generate the above code using a specially annotated struct or class. For example, the below generates the same arguments as above:
// [arguments]
// [name_transform: PascalCase]
struct arguments
{
// [argument, required, positional]
// A required positional argument.
std::string required;
// [argument, positional]
// An optional positional argument.
int optional;
// [argument]
// An argument that can only supplied by name.
float named;
// [argument: Switch]
// A switch argument, which doesn't require a value.
bool switch_argument;
OOKII_GENERATED_METHODS(arguments);
};
In addition, Ookii.CommandLine can be used to create applications that have multiple subcommands, each with their own arguments.
Ookii.CommandLine for C++ requires the following:
- A compiler supporting C++20 (tested with Visual C++ 2022, g++ 11, and Clang 14 and 15).
- A standard C++ library supporting the
<format>
header, or;- libfmt if
<format>
is not available.
- libfmt if
line_wrapping_ostream
, used to generate usage help, relies ondynamic_cast
and will require RTTI to be enabled to function correctly.
Ookii.CommandLine for C++ should support any operating system (tested on Windows and Linux). If you want to make sure your platform is supported, you can run the tests.
To use Ookii.CommandLine in your project, the easiest way is to use CMake. If you use Visual Studio, you can also use the NuGet package.
Alternatively, you can clone this repository to get the header files and add the "include" folder to your include path. Since Ookii.CommandLine is entirely implemented in the headers, there are no linking requirements.
Although Ookii.CommandLine is split out into several header files, you typically want to include just the following:
#include <ookii/command_line.h>
This gets you all the library functionality, including subcommands.
Ookii.CommandLine provides a Config file for CMake. After installing the library, you can use:
find_package(Ookii.CommandLine CONFIG)
This will add a library called Ookii.CommandLine::OOKIICL
, which you can use with
target_link_libraries
.
You can also use FetchContent to easily incorporate Ookii.CommandLine:
cmake_minimum_required(VERSION 3.15)
include(FetchContent)
# C++ 20 or later is required for Ookii.CommandLine
set(CMAKE_CXX_STANDARD 20)
FetchContent_Declare(OOKIICL
GIT_REPOSITORY "https:://github.com/SvenGroot/Ookii.CommandLine.Cpp"
GIT_TAG "v2.0")
FetchContent_MakeAvailable(OOKIICL)
# Add the header only library to a project.
add_executable(foo)
target_link_libraries(foo PRIVATE Ookii.CommandLine::OOKIICL)
On Windows, you probably want to treat your arguments as wide characters (wchar_t
), since that is
the native character type used by Windows. For instance, that is the case if you're using the
int wmain()
entry point, or the CommandLineToArgvW
function if you're using WinMain
.
The entire Ookii.CommandLine library is implemented using templates which allow the selection of
the character type, so they can support both char
and wchar_t
. The ookii::command_line_parser
class is actually a typedef for ookii::basic_command_line_parser<char>
, and there is a similar
typedef ookii::wcommand_line_parser
that translates to ookii::basic_command_line_parser<wchar_t>
.
The same is true of ookii::parser_builder
, ookii::usage_writer
, ookii::command
,
ookii::command_manager
, ookii::localized_string_provider
, and ookii::line_wrapping_ostream
,
which all have wide character versions starting with w
.
If you wish to test out Unicode support on Windows, you can compile the unit tests for Unicode by
passing -DOOKIICL_UNICODE=1
to CMake. This has no effect on platforms other than Windows, and only
applies to the unit tests; no special define is needed for the library itself to use Unicode, except
for the <ookii/command_line_generated.h>
header (used in conjunction with the
code-generation scripts), which requires the _UNICODE
define.
Due to limitations of some of the libraries used (in particular, <format>
), character types
other than char
and wchar_t
are not supported.
Use the following macros to control the behavior of Ookii.CommandLine, either using #define
or
the appropriate compiler switch.
Macro | Description |
---|---|
_UNICODE |
If defined, certain templates will default to wchar_t for the character type. The <ookii/command_line_generated.h> header (used in conjunction with the code-generation scripts), uses wchar_t for its declarations. Use on Windows to support Unicode arguments. |
_WIN32 |
If defined, the Windows-specific parser_builder::add_win32_version_argument() and command_manager::add_win32_version_command() methods will be available. These methods create a version command that reads information from the VERSIONINFO resource. |
OOKII_PLATFORM_DEFINITION |
See OOKII_PLATFORM_NOT_INLINE . |
OOKII_PLATFORM_NOT_INLINE |
Do not provide an inline definition of platform-specific functionality. This avoids the need to include platform headers such as <windows.h> in every file that uses the <ookii/command_line.h> header. You must have exactly one C++ file where both OOKII_PLATFORM_NOT_INLINE and OOKII_PLATFORM_DEFINITION are defined prior to including <ookii/command_line.h> , to provide a definition to the linker. See the unit tests project for an example how to do this. Implies OOKII_NO_PLATFORM_HEADERS unless OOKII_PLATFORM_DEFINITION is defined. |
OOKII_FORCE_LIBFMT |
Use the libfmt library even if the <format> header is available. |
OOKII_NO_PLATFORM_HEADERS |
Do not include platform headers such as <windows.h> . Use this if you have already included them manually with different settings than the <ookii/platform_helper.h> header uses. If you want to avoid including them at all, use OOKII_PLATFORM_NOT_INLINE . |
Building the tests and samples requires the following:
- CMake 3.15 or later.
- (optional) PowerShell 6 or later for the samples and
tests using the code-generation scripts (tested using PowerShell 7.3 on both
Windows and Linux).
- The Pester module is required to run the script tests.
To build the included tests and samples, clone the repository to a local directory, create a folder to hold the build output, and run CMake to configure the project:
mkdir build
cd build
cmake ..
cmake --build .
A script is provided to aid building on Linux: scripts/build.sh
. You can use the --compiler
argument to use a C++ compiler other than the default on your system (specify only the binary name,
e.g "clang++"), the --clean
argument to reconfigure and rebuild, and the --docs
argument to
build documentation instead of the tests and samples (requires doxygen and
dot)
The unit tests require the existence of the nl_NL.UTF-8
locale. If this locale does not exist,
you will see one test failure. In Linux, you can generate this locale using the following command:
sudo locale-gen nl_NL.UTF-8
To run the tests, use the following command:
ctest --output-on-failure
If everything passes, your environment is supported. If you want to see more detailed output, you can run the unittests binary directly.
You can also use scripts/build.sh --test
to build and run the tests.
After building, you will find several samples in the output. These samples are described in detail, with samples of their usage help output, in the samples documentation.
Please check out the following to get started: