Compare commits

...

259 Commits

Author SHA1 Message Date
liyinlong b6135315a5
fix: parse special floating point values (#499) 2026-06-03 17:57:48 +10:00
Dexter.k 654d63dfae
Avoid undefined std::abs(INT_MIN) in integer_parser (#498)
* Avoid undefined std::abs(INT_MIN) in integer_parser

When parsing a negative integer into a signed type whose minimum value
equals INTMAX_MIN (e.g. int64_t on typical platforms), integer_parser
computes the limit as std::abs(static_cast<intmax_t>(min())). Negating
INTMAX_MIN cannot be represented in intmax_t, so the std::abs call is
undefined behaviour. UBSan flags this on every negative int64_t parse,
including a trivial one like "-1":

  runtime error: negation of -9223372036854775808 cannot be represented
  in type 'long'; cast to an unsigned type to negate this value to itself

Build the same unsigned magnitude (|min| == max + 1 for two's-complement)
directly in the unsigned arithmetic type instead. For unsigned T the
expression wraps to 0, which matches the previous std::abs(0) value, so
behaviour for unsigned types is preserved.

* test: cover INT64_MIN parse and run parser tests under UBSan

* test: skip UBSan flags on Windows clang-cl/MinGW builds
2026-06-03 07:28:20 +10:00
Nitin Kumar a3a21b31ef
feat: Fix issues in help output wrapping, and allow wrapping of the help header (#496)
* feat: Add tests for help menu formatting

* feat: New wrapping algorithm, tests, and using wrapping on help text above options list
2026-04-30 07:37:01 +10:00
Nitin Kumar 11f26227ef
fix: Update positional api (#493)
* fix: Overwrite m_positional_set in parse_positional()

* feat: Allow append in positionals and fix discrepancy between m_positional and m_positional_set during replace
2026-03-18 17:33:51 +11:00
Nitin Kumar 25f319275e
feat: Allow implicit values with disabled arguments (#492)
* feat: Allow implicit values with disabled arguments
2026-03-03 18:21:57 +11:00
Nitin Kumar 370de72bfe
feat: allow arbitrary char in opt name (#491)
* feat: Allow arbitrary characters
2026-02-23 18:14:43 +11:00
Nitin Kumar 068f6c582c
docs: Clarify the usage of options with implicit values and help groups (#490)
* docs: Clarify the usage of options with implicit values

* docs: clarify instructions to print help groups
2026-02-06 07:20:17 +11:00
Nitin Kumar a0f13a1528
fix: Fix short options parsing with equal sign (#488)
* feat: Add test for short options parsing

* fix: Update option parsing to allow = with short options

* fix: Fix custom option parsing in case of CXXOPTS_NO_REGEX
2026-02-02 17:37:12 +11:00
Nitin Kumar b39f57f6bc
fix: Add ci test for options_no_regex, and fix inconsistency between regex pattern and customer parser (#487)
* chore(ci): Add test for options_no_regex

* fix: Fix regex parsing for CXXOPTS_NO_REGEX
2026-01-29 18:02:15 +11:00
Nitin Kumar 5467c627df
docs: Add badges (#482)
* docs: Add badges

* docs: Replace travis badge with github's official badge

* docs: Use img shield badge so that we can print 'Build|Passing' instead of 'Cmake|Passing'
2026-01-19 07:10:07 +11:00
Nitin Kumar 89985f820e
feat: Switch to stable_partition to ensure that only first long options is printed in help (#481)
* feat: Add test for Ordering of multiple long options

* fix: Use stable_partition for deterministic ordering
2026-01-14 06:57:04 +11:00
Dylan Baker 0f1c5a0a79
Add Meson buildsystem support (#424)
* meson: Add a Meson based build system

This is primarily intended to be useful for projects using Meson wishing
to consume cxxopts as a subproject. By hosting the files upstream users
get the benefit of automatic parity with the CMake based install
provided by an OS vendor or distribution.

The implementation attempts to mirror the CMake build as much as
possible, with the exception of generating the cmake-config files, which
Meson doesn't currently support. It uses a small python script to parse
the cxxopts.hpp header to extract the version, due to a concious design
decision of Meson to leave such complex logic to external scripting
languages like Python.

* CI: add basic Meson testing

I've tried to be a bit more minimal here than the CMake tests are, since
there's already a good cross section of testing there. For Meson, I just
want to touch test each of the major platforms to ensure that it works
2026-01-12 18:00:29 +11:00
Nitin Kumar c01a048d88
Fix github CI (#478)
* fix: Use non deprecated upload-artifact action version

* fix: Use branch name in build workflow, use latest checkout action, use cd bulid as job steps doesn't preserve current directories between themselves.

* fix: remove non-existent main branch, remove deprecated ubuntu-20, removed deprecated macos-11 and macos-12, setup g++-9 and g++-10 if not exists, use latest checkout action
2026-01-01 16:08:51 +11:00
Colin 929bf2de37
fix "icu-cu" -> "icu-uc" typo in cmake files (#468) 2025-10-09 15:03:39 +11:00
HanaKami 8df9a4d271
Fixes potential segmentation fault in edge cases. (#465)
The options are parsed starting from 1, so check `current < argc`
instead of `!=` in the case that `argc` is zero.
2025-09-19 07:28:21 +10:00
fiesh 80cb4520f7
Fix some warnings (#452)
* Move `result` up and return it

This allows `gcc` to elide the copy in the return and keeps it from
warning with `-Wnvro` enabled.

* Remove harmful dtor definition

The definition of the dtor is not necessary and actually harmful since
the definition of a class's implicit copy constructor is deprecated if
that class has a user-declared constructor as of C++11.  Compilers can
warn about this with `-Wdeprecated`.

---------

Co-authored-by: Christoph Weiss <weiss@wsoptics.de>
2025-08-07 07:59:52 +10:00
Sascha Brawer 781d8ee87c
Include headers in example, so it compiles (#462) 2025-08-07 07:56:58 +10:00
Victor Proon 5e6d1e29f7
fix the issue with default empty vectors behaviour. update unit test (#460) 2025-07-18 07:09:03 +10:00
Blake-Madden 9431d03437
Explain how to include spaces in list of arguments (#461) 2025-07-16 18:09:19 +10:00
Jarryd Beck 44380e5a44 Fix and bump to next version 2025-05-26 18:09:26 +10:00
Jarryd Beck 52e8f524a9 Changelog for 3.3.0 release 2025-05-23 17:46:26 +10:00
Vitaly dbf4c6a668
Added compatibility with CMake 4. (#451) 2025-03-17 17:46:27 +11:00
Yuxuan Sun 573ec27d72
fix(test): make test C++ standard consistent with build config (#450) 2025-02-27 07:26:25 +11:00
Nigel Stewart 7795b6a47b
C++17 std::filesystem::path support added (#447) 2025-01-14 17:56:41 +11:00
Nigel Stewart f029892dab
C++17 std::optional test coverage fixups (#446) 2024-12-23 07:53:42 +11:00
levonwaveye 10a7a64779
Add ParseResult::contains method (#440) 2024-10-24 07:14:32 +11:00
pastalian 63d1b65a69
Add missing header for gcc-15 (#438) 2024-08-28 21:31:42 +10:00
Jarryd Beck 2ad116a9d3 Update catch header
Fixes #435. Updates catch header to fix include error on MacOS.
2024-07-16 09:29:45 +10:00
權少 59656709c0
Fix example and test compiled warnings and error in MSVC. (#428)
* Fix example and test compiled warnings and error in MSVC.
2024-04-27 12:11:52 +10:00
nyako c39022e047
fix conflict with minwindef.h on windows (#426) 2024-04-07 15:14:01 +10:00
Dylan Baker dcf3e1a551
Fix a number of packaging issues (#423)
* cmake: set PROJECT_DESCRIPTION and PROJECT_HOMEPAGE_URL after project()

Otherwise they are set to an empty string.

* cmake: set the pkg-config URL field

Since the information is already there to set it.

* cmake: use CMAKE_INSTALL_DATAROOTDIR if CMAKE_LIBRARY_ARCHITECTURE is unset

This causes files on NixOS to be put in the proper architecture
independent place, which otherwise was selecting the architecture
dependent location.

* cmake: Properly set pkg-config requires when configured with ICU

In this case the pkg-config file needs to set icu-cu in the `Required`
field, and needs to add the flag `-DCXXOPTS_USE_UNICODE` to the `Cflags`
field.

* cmake: cxxopts is not arch independent when built with ICU support

Since it links to an architecture dependent ICU
2024-03-08 15:47:28 +11:00
Nigel Stewart 3d9a4c06d9
cxxopts as_optional fixup (#422)
Co-authored-by: Nigel Stewart <nigel.stewart@emesent.io>
2024-03-08 15:30:06 +11:00
Nigel Stewart 70fb4e4814
Extend cxxopts API to support as_optional in addition to as query of values (#421)
Co-authored-by: Nigel Stewart <nigel.stewart@emesent.io>
2024-02-29 20:27:19 +11:00
Jarryd Beck 4bf61f0869 Add changes for 3.2.1 2024-02-20 19:39:52 +11:00
jarro2783 1e175bc1db
Fix ordering of parse_value functions (#420)
Fixes #419. Put the definitions of parse_value functions before they
are called so that the right ones are chosen.
2024-02-20 19:38:44 +11:00
jarro2783 3bf268481d
Make cxxopts.hpp ready for 3.2
Update version number in header, ready for 3.2
2024-02-15 16:24:38 +11:00
jarro2783 f7194e9c59
Update CHANGELOG.md
Make changelog ready for 3.2
2024-02-15 16:23:58 +11:00
jarro2783 71d5bf7265
Update CHANGELOG.md 2024-02-15 16:23:15 +11:00
jarro2783 d3de64f26e
Update CHANGELOG.md 2024-02-15 16:21:30 +11:00
ololuki e84ab5f67c
Fix overflow error in integer_parser. (#417)
Fixes #290.
Checking for overflow should be done before integer overflows.
There are two checks:
(result > limit / base) is used for limits greater than rounded up to base,
e.g. for 65535 it will activate for 65540 and higher.
(result * base > limit - digit) is used for limit+1 to limit+n below
next base rounded number, e.g. 65536 up to 65539.
2024-02-01 16:51:32 +11:00
Jarryd Beck 7bf29108d5 Update catch2 to latest 2.x 2024-01-15 21:04:41 +11:00
Nigel Stewart cd61c685eb
Ordered vector of group names to preserve order of groups (#416)
Co-authored-by: Nigel Stewart <nigel.stewart@emesent.io>
2024-01-15 20:52:54 +11:00
Blake-Madden 554396be3b
Minor typo in README.md (#411)
Fix grammar in README
2023-11-25 11:49:16 +11:00
Jarryd Beck 78b90d8f0c Remove incorrect sentence in README
Fixes #410. Removes sentence about ParseResult scope that is no longer correct.
2023-11-13 16:49:18 +11:00
Jarryd Beck c8c932f891 Add CHANGELOG for #398 2023-06-15 07:35:14 +10:00
Alexander Galanin ddc695ebac
Don't split by list delimiter in positional lists (#398) 2023-06-15 07:34:26 +10:00
Jarryd Beck bf1b5a96e0 Update changelog 2023-06-15 07:18:53 +10:00
Jarryd Beck 90b318105f Fix unannoted fallthrough
Fixes #402.
2023-06-15 07:18:30 +10:00
Maximilian Knespel a526762eb8
[fix] Avoid std::regex initialization during dlopen (#406) 2023-05-31 07:26:34 +10:00
Jarryd Beck beda973ec6 Remove incorrect todo.
Fixes #404.
2023-05-22 17:31:17 +10:00
Julien Voisin 714a105fe6
Bump rules_fuzzing to the latest available version (#403) 2023-05-01 06:45:55 +10:00
Nigel Stewart 16cc254919
Output same exception messages for both Linux and Windows (#395)
Co-authored-by: Nigel Stewart <nigel.stewart@emesent.io>
2023-04-03 17:15:01 +10:00
Jarryd Beck 120205ac5a Fix cast warning in Unicode function
Fixes #339. Fixes a sign conversion warning in a function compiled by
-DCXXOPTS_USE_UNICODE_HELP=1.
2023-03-15 07:09:09 +11:00
Jarryd Beck 89a9d334f2 Add note about exceptions in Changelog 2023-03-13 07:52:48 +11:00
Nathaniel Brough 44739d3023
feat(fuzz): Adds trigger for fuzzing in the CI (#392) 2023-02-22 07:03:38 +11:00
Demian Hespe 134f60f973
Fix noexcept warning (#391) 2023-02-20 07:25:13 +11:00
Jarryd Beck eb787304d6 Fix version number 2023-02-16 07:02:16 +11:00
Jarryd Beck c12ce65503 Update CHANGELOG for 3.1 release 2023-02-13 07:31:30 +11:00
Jarryd Beck b80bdfddf0 Added missing CHANGELOG entry 2023-02-13 07:31:30 +11:00
Martijn Courteaux 799ee0e3e8
Add <locale> to be spec-compliant for std::isalnum (didn't work on MSVC). (#385) 2023-02-11 15:47:48 +11:00
Nathaniel Brough 58daccc945
feat(fuzzer): Adds fuzz tests (#386) 2023-02-06 07:30:51 +11:00
Jarryd Beck e1f8c16702 Fix diagnostics pop error 2023-02-02 07:25:12 +11:00
Jarryd Beck 4a3d4dbfe0 Fixes #362.
Fix comparing iterators from a different container.
2023-02-01 06:56:03 +11:00
Jarryd Beck 1bd4786c16 Fix broken example 2023-01-19 07:09:39 +11:00
Jarryd Beck 32afbc6526 Fix default bool values
Fixes #382. Keep boolean values when parsing into a reference.
2022-12-15 07:08:03 +11:00
jarro2783 e9d20c2c07
Remove deprecated iterator type (#381)
Fixes #379. `iterator` is deprecated in C++17.
2022-12-05 07:40:46 +11:00
Sourabh Mehta 1dcb44e79a
Fix an additional space in help generated (#377) 2022-11-10 07:24:19 +11:00
chrisps f087dc8fcd
Code size reduction on msvc via selectany (#373) 2022-11-01 18:52:46 +11:00
Ryan Leary 2e3c6991d3
add . as valid char in option names (#358) 2022-09-29 07:11:32 +10:00
jarro2783 2123115f71
Improve positional help description.
Minor change to the positional option description in README.
2022-09-26 06:59:38 +10:00
Stefan Hillmich d046fe0ad6
Extend CI and small fixes (#370)
* Extend CI to support Windows and MacOS.
* Minor fixes to types.
2022-09-26 06:57:05 +10:00
Stefan Hillmich 82ac083886
Added missing #include (#368) 2022-09-12 07:02:26 +10:00
66maer f7cf84bd56
Fix std::isblank assertion error in Visual Studio Chinese Debug (#365) 2022-09-08 07:33:31 +10:00
Jarryd Beck ab1dc0f684 Update copyright notice
Fixes #361
2022-08-22 07:35:58 +10:00
jarro2783 a10bd5233b
Fix values attached to short options (#360)
Fixes #357.
2022-08-13 07:51:41 +10:00
Jarryd Beck 17b2c91049 Fix iostream for no exceptions
Fixes #356.
2022-08-08 07:07:59 +10:00
Jarryd Beck 96e72f7d15 Fix crash with short only option 2022-08-03 07:00:34 +10:00
Yassir Najmaoui 2abdd4af4d
Add option to display usage (#355)
Make the usage displaying optional
2022-07-28 06:50:13 +10:00
Jarryd Beck 01798ee7a0 GCC 4.8 fixes 2022-07-25 07:21:22 +10:00
Jarryd Beck a6bfe2d457 Further ifdef fixes.
Related to #339.
2022-07-20 20:57:27 +10:00
Jarryd Beck 83aecd628e Fix pragmas 2022-07-20 17:37:37 +10:00
Jarryd Beck 6c8a41a229 Remove unused header 2022-07-20 07:51:04 +10:00
Jarryd Beck 292750d27a Replace pragmas with macros
Fixes ##339
2022-07-20 07:49:59 +10:00
Jarryd Beck 8849551398 Fix #353.
Move nodiscard before inline.
2022-07-18 21:16:04 +10:00
Eyal Rozenberg e976f964c3
Fix issue #240: Multiple long option names / aliases (#349)
* Fixes #240: Multiple long option names / aliases

* We now use a vector of long option names instead of a single name
* When specifying an option, you can provide multiple names separated by commas, at most one of which may have a length of 1 (not necessarily the first specified name). The length-1 name is the single-hyphen switch (the "short name").
* Hashing uses the first long name
* Option help currently only uses the first long name.
2022-07-14 16:42:18 +10:00
Jarryd Beck 43ebb49475 Add changelog entry 2022-07-13 07:22:01 +10:00
Eyal Rozenberg 9cd015ac37
Regards #340, #345: Removed unnecessary indentation of exceptions namespace + added end-of-namespace comment (#351) 2022-07-13 06:49:04 +10:00
Eyal Rozenberg 628dc9202b
Fixes #345, fixes #346: Exception code tweaks (#347)
* Fixes #345, fixes #346, regards #340: Put exceptions in a sub-namespace and renamed them accordingly.

* Also fixed some "loose ends" regarding namespace indentation which were missing in PR #350.

* Dropped `required_option_missing` as it is unused.
2022-07-12 19:45:58 +10:00
Jarryd Beck 548d6196f5 Add clang format to changelog 2022-07-11 20:46:01 +10:00
Jarryd Beck 30d97369f2 Fixes #341. Add a clang-format file 2022-07-11 20:40:51 +10:00
Jarryd Beck fbd79df66b Fixes #336
Memory leak was caused by `exit`.
2022-07-11 17:02:22 +10:00
Jarryd Beck 6bb1e82b61 Add Vim modeline 2022-07-11 07:17:53 +10:00
Eyal Rozenberg 513afbc6dc
Fixes #340: namespace indentation unification (#350)
* Namespace no longer induce indentation
* Namespace opening brace now on same line as namespace name
* Namespace closing brace now has an empty line before it unless the namespace contents were short and with no empty lines
* Namespace closing brace now always followed by a comment with the closed namespace' name
2022-07-11 07:00:50 +10:00
Eyal Rozenberg 8d18c3ed0b
Expanded `.gitignore` coverage. (#344) 2022-07-10 19:03:25 +10:00
Matthew Limbinar 7474a66ef6
Clarify positional argument docs (#335) 2022-07-04 09:55:17 +10:00
Alexander Kiselyov a70771ae89
Fixed cmake install path in case of empty architecture (#322) 2022-06-16 07:34:14 +10:00
Jarryd Beck 5f72b525c2 Add changelog note 2022-05-11 17:47:37 +10:00
Long Deng c59e0c132c
Solve arguments() showing empty keys when only short-only option exists (#318)
* Solve `arguments()` showing empty keys when there is only a short option.
2022-05-11 17:44:25 +10:00
Jarryd Beck f0f465b20f Add unmatched arguments to example
Ref #242. Adds an example in the example file showing the unmatched
arguments that are stored.
2022-05-03 06:21:12 +10:00
Jarryd Beck 8185e6bb3a Remove unused variables
Fixes #324
2022-03-26 12:19:36 +11:00
Yannic Staudt 779c429b0e
Added instructions to use cxxopts with tipi to INSTALL (#325) 2022-03-22 22:01:25 +11:00
Jarryd Beck 4e208b95b7 Add a program function
Fixes 323. Adds a function to retrieve the program name.
2022-01-14 16:26:48 +11:00
Long Deng ad2d1a6b5f
Add iterator (#126) and easily print-out (#223) to ParseResult (#313)
* Add iterator (#126) and easily print-out (#223) to ParseResult
2021-11-09 18:49:58 +11:00
Jarryd Beck c74846a891 Fix short options adding into unmatched
Fixes #312.
2021-10-21 08:06:53 +11:00
Jarryd Beck a150450486 Readme change for 3.0 2021-10-21 07:50:58 +11:00
Jarryd Beck e8b5befff8 Add changes for 3.0 release 2021-10-21 07:47:55 +11:00
Jarryd Beck d2f0bbfed1 Add note about count with default
Fixes #311.
2021-10-21 07:37:23 +11:00
Nick Krichevsky 4a02ad94f4
Include <optional> if possible to check if we can use the feature (#309)
Fixes #303
2021-10-10 13:01:47 +11:00
Jarryd Beck c641241a87 Fixes to #204. 2021-10-09 17:02:27 +11:00
Baojun Wang 4b7fccb5f2 Allow empty string to be valid positional arguments
Fixes #204.
2021-10-09 17:02:27 +11:00
jarro2783 1ff0da6401
Add more compilers (#307) 2021-10-09 15:52:52 +11:00
jarro2783 54489e4276
Add the two available OS (#306) 2021-10-09 12:48:44 +11:00
jarro2783 4fcadd83a7
Try workflow template 2021-10-09 12:18:17 +11:00
Jarryd Beck 7d99716319 Add workflow dispatch 2021-10-09 12:13:11 +11:00
Jarryd Beck 946ebb6f83 Initial build action 2021-10-09 12:03:20 +11:00
Jarryd Beck d3aa51d555 Add dummy workflow 2021-10-09 12:00:13 +11:00
KOLANICH 5eca8a3001
Added CPack packaging, pkg-config and CMake version files. (#298) 2021-07-31 10:34:21 +10:00
Jarryd Beck df229cff0d Fix integer parsing to be more general
Fixes #277. Makes integer parsing to be more general and allow whatever
types the user actually uses instead of hard coding a set of integers.
2021-06-02 17:30:08 +10:00
Jarryd Beck a20bda6179 Fix GCC version check for null deref
Fixes #288.
2021-06-01 17:38:41 +10:00
RonxBulld 97a4d5511f
Support options like `-j5`. (#286)
* Support option value being attached after the option without a space in between. e.g. -j5
2021-05-06 08:46:40 +10:00
spmn 056a6281ac
Fix empty option name in `OptionException` (#256)
Fix bug where option name is missing in error.
2021-05-06 08:45:15 +10:00
RonxBulld c04f8a5bb9
Fully compatible with GCC4.8 compilation system. (#285)
* -Wsuggest-override is not supported by gcc before 5.0
* GCC prior to 5.0 should ignore not only -Wnon-virtual-dtor but also -Weffc++, otherwise non-virtual destructor problems will still be reported.
* The `#pragma GCC diagnostic push' should be used before setting up the temporary environment.
* When using GCC4.8, use manual lexical analysis instead of regular expressions.
* Add gcc4.8 stuff to travis file.
2021-05-04 17:35:45 +10:00
RonxBulld 174510285a
-Wsuggest-override is not supported by gcc before 5.0 (#283)
* -Wsuggest-override is not supported by gcc before 5.0

* GCC prior to 5.0 should ignore not only -Wnon-virtual-dtor but also -Weffc++, otherwise non-virtual destructor problems will still be reported.

* The `#pragma GCC diagnostic push' should be used before setting up the temporary environment.
2021-04-21 18:17:30 +10:00
jarro2783 dd45a0801c
Rename BUILD to BUILD.bazel 2021-02-20 15:12:07 +11:00
Jarryd Beck aaa5e790b6 Rename variable, add to example 2021-02-15 08:34:46 +11:00
Wolfgang Gahr 43ce03fdbd
Improve formatting of help descriptions (#215)
* Improve formatting of help descriptions (#213)

* new function: cxxopts::Option::set_width(size_t width)
  Set the size of a helpline.
* new function: cxxopts::Option::set_tab_expansion()
  Expand the tabs in descriptions.
  The tabsize 8 chars, base is start of description.
  The descriptions are not disturbed by adding additional options.
* Allow newlines \n and tabs \t in descriptions.

Other changes (last commit/new commit):
* 1453/1471: size_t for OPTION_LONGEST and OPTION_DESC_GAP.
  This prevents the static cast in 2086/2140.
* 2088/2142: in case of small width the value of
  "width - longest - OPTION_DEC_GAP" becomes negative.
  Because size_t is unsigned the result is a big number, and
  the width of the column of the descriptions is not shortened.
* new 2143: When the given width is too small, it is set to
  longest + OPTION_DESC_GAP + 10
* new 1570: A long description is broken into multiple lines, and
  the iterator lastSpace remembers the begin of the last word.
  But when the iterator current reaches the end of line, the whole
  string from iterator is printed, which in soome cases is too
  long. Thats why one blank is added to the description to trigger
  the handling of lastSpace.
  Accordingly in 1574/1627 the line is shortened by one char.

* repaired signed/unsigned issue

* changes for unicode
2021-02-12 08:17:55 +11:00
Jarryd Beck f34d603863 Fix missing override 2021-02-08 09:44:26 +11:00
Jarryd Beck d10a9b5678 Upgrade GCC versions 2021-02-08 08:41:20 +11:00
Jarryd Beck e862445ef3 Fix null dereference warning error
Fixes #276. Remove the fix for null dereference warning for GCC after
10.1.0 because this was removed in later versions.
2021-01-23 14:08:56 +11:00
Rosen Penev ed85f04a1b
clang-tidy stuff (#266)
Several clang-tidy improvements.
2021-01-19 17:05:09 +11:00
Benjamin Sergeant 834fb9999b
Ignore gcc-10 warning (#273)
Workaround for GCC 10 null dereference warning.
2021-01-19 17:00:45 +11:00
jpr89 dc9a7728c0
Fixing cmake developer warning (#274)
Here is the warning currently being produced:

CMake Warning (dev) at C:/Program Files/CMake/share/cmake-3.19/Modules/GNUInstallDirs.cmake:223 (message):
Unable to determine default CMAKE_INSTALL_LIBDIR directory because no
target architecture is known. Please enable at least one language before
including GNUInstallDirs.
Call Stack (most recent call first):

I noted how I fixed the error. This is caused by GNUInstallDirs automatically executing code just by including it.

I also added -Werror=dev to the CI to ensure this never happens again.

Co-authored-by: Juan Ramos <juanr0911@gmail.com>
2021-01-19 16:55:23 +11:00
jpr89 c55726ee29
Cmake Revamp (#270)
* Cmake Revamp

I needed to do a variety of things to ensure cxxopts worked well in my own project.

I created a new cmake module to abstract a lot of the logic in the main CMakelists.txt, I think it really assists in the readability of the project. Consequently a lot of logic is now written in functions.

I made a lot of the project options off by default unless the project is being built standalone. As a frequent consumer of cmake libraries this is a huge issue. Since examples, tests, installation, etc. aren't things I expect/desired by default when using libraries.

Co-authored-by: Juan Ramos <juanr0911@gmail.com>
2021-01-17 12:11:02 +11:00
Dan Ibanez 2d8e17c4f8
Add CMake option to not add warning flags (#267)
Allow extra compiler warnings to be disabled.
2020-12-15 08:47:52 +11:00
fiesh 66b52e6cc9
Add -Wsuggest-override (#264)
We also add the suggested `override` keyword.
2020-10-21 10:24:41 +11:00
Daniel Lemire 12e496da3d
Making sure that the library can compile without warnings even when crazy pedantic flags are set (#238)
Makes some fixes to satisfy various strict warnings.
2020-10-06 17:06:33 +11:00
jarro2783 3ef9fddc7b
Fix passing a const array to parse (#258)
Fixes #257. The input array is not modified, so we can declare this as
`char const* const*`.
2020-10-03 20:54:06 +10:00
Jarryd Beck 4b63c333a8 Improve README note 2020-10-01 20:09:16 +10:00
Jarryd Beck 748ac35277 small cleanup 2020-10-01 17:26:32 +10:00
Jarryd Beck 703eeef906 Update version for 3 2020-10-01 17:14:39 +10:00
Jarryd Beck 31b77f11af Prepare notes for v3 2020-10-01 17:14:39 +10:00
Jarryd Beck fedf9d7b57 Refactor parser
Major refactor of the parsing code organisation to improve encapsulation
and not modify the input arguments. The returned result no longer has
pointers into the original option specification.
2020-10-01 17:12:03 +10:00
Daniel Gomez Antonio fd5cdfd547
Fix compiler warning C4702 for MSVC-14 (#225)
* Fix compiler warning C4702  for MSVC-14
2020-09-15 10:07:53 +10:00
Vitaly Zaitsev 584e0c3dd3
Fixed installation on other than Ubuntu GNU/Linux distributions. (#226)
Fixes the installation paths by using cmake variables.
2020-08-19 09:16:11 +10:00
silvergasp 05ca8e1cac
Adding bazel build targets (#251)
Adding support for the bazel build system
2020-08-12 08:48:07 +10:00
Kjetil Andresen 15e8a74e95
Support 'const char**' arguments in Options::parse (#250)
`cxxopts` doesn't modify the contents of the argv strings. This changes
the parse function to take a reference to a `const char**`.
2020-08-11 08:01:29 +10:00
Rosen Penev 07f5cb24f1
[clang-tidy] use nodiscard (#234)
Found with modernize-use-nodiscard

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-07-28 15:40:16 +10:00
Eyal Rozenberg 5f43f4cbfe
Fixes #245: Mention the option name when throwing on "no value" (#246)
* Fixes #245:

* Added a new exception type: `option_has_no_value_exception`; throwing it when an option has no value we can cast with `as()`, instead of an `std::domain_error`.
* The `OptionValue` type now holds a pointer to the long option name (in its corresponding key within ParseResults's `m_results` field.
2020-07-23 17:27:04 +10:00
Eyal Rozenberg 1b660d5680
Regards #244: Explain how vectors of values allow repeated use of the same option on the command-line. (#247) 2020-07-23 16:36:54 +10:00
Akos Kiss 9a454c8e4e
Improve help of short-only options (remove dangling comma) (#235) 2020-06-04 13:21:51 +10:00
Daniel Lemire 794c975287
Exit instead of abort (#233)
Uses std::exit instead of abort to terminate when exceptions are disabled.
2020-05-29 08:30:35 +10:00
Rosen Penev 12bc8d78e7
clang-tidy fixes (#231) 2020-05-12 14:59:47 +10:00
Tomas Barton b0f67a06de
Code highlighting, add more examples (#220) 2020-02-14 08:02:27 +11:00
Jarryd Beck 6fa46a7488 Don't return parse result
Fixes #219. The example was wrong as ParseResult can't be returned out
of scope of the options parser.
2020-01-17 08:03:57 +11:00
Felix Esch 943cdcfbba Fix assertion failure (issue #217) (#218) 2020-01-08 17:14:46 +11:00
Jarryd Beck 23f56e2614 Fix conversion warning in test 2019-11-28 08:32:54 +11:00
Florin Iucha 9457b3de3a Fix -Wconversion warnings with GCC9 (#214) 2019-11-28 08:30:23 +11:00
Abhay Raj Singh 073dd3e645 Fixed empty default showing nothing in help (#205) 2019-10-14 18:08:11 +11:00
Jarryd Beck 4a0af0e950 Fix parsing char type
Fixes #201. Parse char type correctly and check for length.
2019-08-23 08:26:16 +10:00
Jarryd Beck f4f4ece809 Improve README about supported compilers
Fixes #202.
2019-08-23 08:16:22 +10:00
Jarryd Beck cb60381e84 Add to changelog 2019-08-08 08:27:14 +10:00
charlydelta 34784b01f7 Fix: Make CXXOPTS_NO_EXCEPTIONS compilable and print messages (#196)
Fix CXXOPTS_NO_EXCEPTIONS so that it doesn't warn about unused parameters, and print out error messages.
2019-08-08 08:25:34 +10:00
Jarryd Beck fce82fb035 Fix duplicate default option
Fixes #197. Don't parse default options twice when there is a short and
long option.
2019-08-08 08:21:52 +10:00
Anders 6e31c227e2 Add CMake option CXXOPTS_ENABLE_INSTALL (#195)
Install targets will not be generated if this option is set to OFF,
which is useful when including it as a bundled dependency of
another project.
2019-08-01 17:51:01 +10:00
Anders 531c00b96f Define alias target cxxopts::cxxopts (#194) 2019-08-01 17:50:05 +10:00
Jarryd Beck 0d4bb2871a Add to Changelog 2019-08-01 08:29:40 +10:00
charlydelta 37e7220fb4 Allow disabling exceptions and use std::abort instead (#190) 2019-08-01 08:19:59 +10:00
avemilia c19e267790 CMake: search only for C++ compiler (#192)
This speeds up the CMake configuration step by not searching for a C
compiler. By default, CMake looks for C and C++ compilers, unless a set
of compilation languages is specified.
2019-07-31 18:15:58 +10:00
Bartek 3c73d91c0b add_options variant with initializer list (#189)
Allow adding options with a single initializer list.
2019-06-28 08:39:37 +10:00
Jarryd Beck e6858d3429 Add to changelog for #170 2019-06-18 18:17:24 +10:00
linus-sherrill 9910095719 Remove check for container when generating help message. (#170)
Some positional parameters would be listed in the help text and others
would not, when what is desired is that no positional parameters are
listed with the other command options. This change suppresses the help
listing for all positional parameters.
2019-06-18 18:16:31 +10:00
Jarryd Beck 9064fdf459 Add to changelog 2019-06-18 18:00:16 +10:00
Jean-Baptiste Bayle 6b6af4f561 Add a method to remove the implicit value of an option (#178) 2019-06-18 17:49:15 +10:00
Jarryd Beck 4f3fda4bf9 Add to changelog for #182 2019-06-18 08:17:26 +10:00
Christian Lang 7b14d5f60b Fix parsing of std::vector and add test, example and documentation (#182)
Improve parsing into std::vector so that a single argument can take a list.
2019-06-18 08:14:18 +10:00
Jarryd Beck 1eca210edc Remove unused variable 2019-06-14 18:28:04 +10:00
Jarryd Beck e17c6b0827 Fix integer parsing again 2019-06-14 18:20:22 +10:00
Jarryd Beck 3e5ecf1d2a Fix a couple of out of range errors
These were detected using -fsanitize=undefined parsing values equal to
INT_MAX and INT_MIN.
2019-06-14 08:12:29 +10:00
Jean-Baptiste Bayle bd20573829 Parse 0 and 1 into booleans (#177)
* Parse 1 as "true" and 0 as "false" for boolean options.
2019-05-28 17:25:54 +10:00
Jarryd Beck d58271c5fd Allow invalid short option syntax
Fixes #171. Allows invalid syntax for short options to be ignored.
2019-05-28 08:21:36 +10:00
Jarryd Beck cef280fad3 Remove some unreachable code.
Fixes #175. This was broken when throwing an exception on missing
positional parameters in #169.
2019-05-28 08:21:36 +10:00
Jack Clarke e34676f73e fix sign conversion warnings (#174) 2019-05-13 08:33:15 +10:00
Jarryd Beck d31492e2cd Catch exception using reference 2019-05-02 17:32:48 +10:00
Jarryd Beck 5da5d67111 Throw exception on invalid positional argument
Fixes #169. It seems reasonable to throw an exception when an attempt is
made to parse into positional parameters that don't exist.
2019-05-01 18:34:29 +10:00
le-migou 48e265dc4b Remove `u8` prefix in string literals. (#172)
String literals with the prefix `u8` now have the type `const char8_t[N]` in
C++20. As a consequence the library does not compile in c++2a mode with GCC
(you can't concatenate `std::basic_string<char>` and `const char8_t[]` as
`char` and `char8_t` are different types).
2019-04-15 18:26:43 +10:00
Jarryd Beck 3876c09072 Use reference instead of value
Fixes #166.
2019-02-19 18:14:36 +11:00
linus-sherrill 9990f73845 Remove empty string initializer. (#159)
The empty string caused the vector to have one element which caused
the test at line 2041 to always fail.
2019-01-14 08:46:41 +11:00
Jarryd Beck 3d405ef163 Improve boolean readme
Fixes #157. Fix the wording in the README about booleans.
2019-01-02 08:47:17 +11:00
Michael Tesch 0edf37b6cc accept single '-' as argument, such as in `cat -` (#153) 2018-12-20 07:58:37 +11:00
舒俊杰 5950d78558 fix min/max defined macros (#152)
Windows is broken and defines `min` and `max` as a macro, adding parentheses stops them from being expanded.
2018-12-20 07:57:22 +11:00
Jarryd Beck 287d1e39e0 Add to changelog for exception fix 2018-11-20 08:25:24 +11:00
Jean Guyomarc'h 51f9a94c91 Fix invalid exception type in catch (#149)
g++ 8.2.0 refuses to compile the test suite because of polymorphic types
that are caught by value. They shall be caught by reference instead.
2018-11-20 08:06:18 +11:00
Jarryd Beck 84feb4bd87 Throw in ParseResult::as when option isn't present
Fixes #124.
2018-11-19 17:45:51 +11:00
Jarryd Beck c713b44d92 Use a shared pointer for the options map
Fixes #132. Since the map of options is shared between Options and
ParseResult, they should use a shared pointer instead of a reference so
that ParseResult can be returned without referencing destroyed memory.
2018-11-08 18:22:42 +11:00
Jarryd Beck b528324107 Fix option matching 2018-11-08 08:18:54 +11:00
Jarryd Beck cd65c459ec Build the tests by default.
Fixes #143. There is no reason to make the tests optional.
2018-11-07 18:52:40 +11:00
Jarryd Beck 963c5d0494 Add instructions for running the tests 2018-10-30 08:02:32 +11:00
Mario Werner 320d7a3d1a fixed version parsing in the CMake code (#128) 2018-10-29 18:51:26 +11:00
Jarryd Beck 299750a35d Make INSTALL a bit more clearer 2018-10-29 18:13:14 +11:00
Jarryd Beck 3f2d705302 Improve build and test instructions 2018-10-29 08:47:49 +11:00
parkertomatoes f75feab968 Handle newlines in description (#138) 2018-10-08 11:57:33 +11:00
Jan Koßmann 1f7ac82495 Fix std::forward return in toLocalString (#134) 2018-09-27 11:28:07 +10:00
Jarryd Beck 7c468aaf68 Allow iterator inputs to parse_positional 2018-08-07 08:00:41 +10:00
Jarryd Beck 95a48de820 Remove unused get_option
Fixes #121. Removes the unused `ParseResult::get_option`.
2018-08-03 08:46:48 +10:00
Jarryd Beck cde83be99b Fix version numbering in CMakeLists.txt
Fixes #115. Read the version number out of `cxxopts.hpp` instead of
having to duplicate it in CMakeLists.txt.
2018-07-05 17:55:51 +10:00
Jarryd Beck e725ea3084 Use unsigned type for integer digit
Fixes #109. Although we always used numbers in the ASCII range, it was
in a `size_t`, leading to a warning about possible loss of data on some
compilers.
2018-05-08 07:59:17 +10:00
Jarryd Beck d47101a101 Allow leading zeroes in integers
Fixes #101. Allows leading zeroes in the integer parser.
2018-05-07 18:46:26 +10:00
Frank Schoenmann ca6e9f70eb Allow unrecognised options. (#105)
Allows unrecognised options to be left alone by the parser without throwing an exception.
2018-04-12 08:15:07 +10:00
Jarryd Beck 00e8ecc482 Add a readme comment about versions 2018-04-12 08:14:07 +10:00
Jarryd Beck a3ccf3e1f7 Add revert to changelog 2018-04-10 08:50:17 +10:00
Jarryd Beck cc4914f065 Revert "Added const to argv type for better interoperability. (#99)"
This reverts commit 0f819a5cab.
2018-04-10 08:48:08 +10:00
Jarryd Beck 0fe1dc892b Prepare changelog for release 2018-04-09 08:17:56 +10:00
Jarryd Beck 16e3968e1a update readme 2018-03-21 18:14:09 +11:00
Jesús González 0f819a5cab Added const to argv type for better interoperability. (#99)
* Added const to argv type for better interoperability.
2018-03-09 08:07:29 +11:00
Jarryd Beck e40645e084 Don't show default when boolean false
Fixes #102. Don't show the default value when it is a boolean and the
value is false. Note that this is a bit of a hack and the
implementation should probably be reevaluated in the future.
2018-03-08 08:53:26 +11:00
Jarryd Beck 76bd60dc17 Add support for std::optional
Fixes #93. This adds C++17 only support for `std::optional` values for
command line parameters.
2018-01-31 18:25:52 +11:00
Jarryd Beck e792760ab9 Changes default values so that they aren't counted
Fixes #96. Default values of options not specified on the command line
had a `count` of 1. It would be better if they had a count of 0 because
they were not actually specified, so that count is only for options
given by the user.
2018-01-30 18:55:49 +11:00
Jesús González 76717cb3dd Add default "default" value to boolean options (#94)
* Add default "default" value of "false" to boolean options, therefore allowing to call result["boolOpt"].as<bool>() without throwing an exception.
2018-01-17 07:55:45 +11:00
Jarryd Beck 24162899c9 fix some types 2017-12-15 17:43:31 +11:00
Addy ec7db35ac6 fixed “possible loss of data” warning on Visual Studio (#89) 2017-12-15 08:02:02 +11:00
Jarryd Beck c69ca9166d version bump 2017-12-06 18:28:32 +11:00
Jarryd Beck 9c2e41a4e2 add clang back to travis 2017-12-04 18:14:40 +11:00
Masashi Fujita ec9e62c2c8 `|` should be inside of `(…)` (#87)
* `|` should be inside of `(…)`

It's possible to use `(t|true|T|True)` as `truthy_pattern` but still failing `true` as a truthy under my environment :-(

```
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
```
2017-12-04 18:15:20 +11:00
Jarryd Beck fab3bae2ff Clarify ParseResult being in scope 2017-12-01 07:58:15 +11:00
Jarryd Beck 346956eff1 Fix overly strict shadows in GCC 4.9
Fixes #86. Rename some variables so that the overly strict shadows warning
on GCC 4.9 is not triggered.
2017-11-30 08:45:00 +11:00
Jarryd Beck 2015a7438a Add GCC 4.9 to travis build 2017-11-30 08:39:58 +11:00
Jarryd Beck 5b774d7a7e Allow help string to be customised
Fixes #82. This allows the help string after the program name to be
completely replaced by the user.
2017-11-28 18:07:23 +11:00
Jarryd Beck 2ca68adeaf Fix positional arguments overload
Fixes #83.

Adds an overload for positional arguments taking a
`std::initializer_list`. When using an `initializer_list` with one
argument, the function call is ambiguous matching both `std::string`
and `std::vector<std::string>`.
2017-11-28 18:01:41 +11:00
Jarryd Beck abe9ebd6b4 Fix handling of implicit values
Fixes #84. Implicit values are not handled very well. For example:

    --foo false true
    --foo --bar

In the first, `false` is an argument to `--foo`, and then `true` is a
positional argument. In the second, because of the hyphen in `--bar`, `--foo`
is parsed with its implicit value. This seems inconsistent and unintuitive.

Better is that implicit values *never* consume the next parameter to be
completely consistent. This means that values with an implicit parameter
*must* be specified using the `--option=value` form.
2017-11-28 08:43:55 +11:00
Jarryd Beck 0a49b82072 add a test for broken boolean options
The parsing for boolean options was broken by 6c9bae4a07 which added implicit
and default values, and the ability to parse boolean strings. Having an option
after the boolean tried to parse that into the boolean instead of as a
positional parameter.

See #84 for the bug report.
2017-11-27 08:36:34 +11:00
Jarryd Beck 92779bef66 Remove clang for now
It appears that the `libc++` available on Ubuntu 14.04 is broken and
doesn't handle the boolean regex correctly. Newer versions appear to be
correct but I have to work out how to get 14.04 to use it.
2017-11-27 08:33:46 +11:00
Jarryd Beck 8893afe13c Merge branch '2_0' 2017-11-15 18:04:20 +11:00
Jarryd Beck 70b9230639 fix changelog and readme
add booleans into the changelog and the readme
2017-11-15 17:56:25 +11:00
Jarryd Beck 6c9bae4a07 Parse strings for booleans
Fixes #54. Allow default and implicit values for booleans with multiple
boolean strings matched as values.
2017-11-15 17:51:38 +11:00
Jarryd Beck 8d6a91ee27 improve documentation for default and implicit 2017-11-14 08:03:46 +11:00
Jarryd Beck 24450d183a Allow positional arguments to show in help
Fixes #72. This adds an option for positional arguments to be
shown in the help output.
2017-11-13 18:47:12 +11:00
Jarryd Beck 4ebfa25915 Improve version and changelog 2017-11-13 17:57:26 +11:00
Jarryd Beck d74a2c65a5 Add ability to iterate through parsed options
Fixes #74.
2017-11-13 08:10:22 +11:00
Jarryd Beck f0406578bd clean up extraneous comment 2017-11-02 08:34:49 +11:00
DevCodeOne d7b930846c Fix some strange issues in integer_parser (#80)
* Prevent malformed numbers from being parsed as correct numbers.

Fixes #78. If you passed a string for example "test" it would get parsed to 1400.
The problem was that the parser did not throw an exception when an incorrect char was encountered.
Also a number without 0x in front with hexadecimal digits in it got parsed.
The number was treated as a hexadecimal number but it was still calculated with base 10.
So now before the current char is used, it is checked if it is valid in the current base.
Furthermore the number 0x0 was not a valid number, it now is a special case in the `integer_pattern`.

* Fixed `integer_pattern` so it works correctly under clang. Added testcase for invalid integers and for 0x0 being a valid number.
2017-11-02 08:14:21 +11:00
Alcaro 8ce9a587fa __GNU__ isn't a thing (#79)
Fixes a typo that never unsilenced the non virtual destructor warning.
2017-11-01 08:07:28 +11:00
Jarryd Beck c2e19fc210 add a version define
Fixes #77.
2017-10-31 18:23:15 +11:00
Jarryd Beck 3c6bcb9046 Some cleanup 2017-10-31 18:21:18 +11:00
Jarryd Beck 3f5bbb3062 update the readme 2017-10-31 18:19:15 +11:00
Jarryd Beck ef1dfdee33 remove some unused code 2017-10-30 08:46:45 +11:00
Jarryd Beck 7c32b9c5fc add option name to OptionDetails 2017-10-30 08:45:36 +11:00
Jarryd Beck b1f0cb806c fix default 2017-10-27 12:31:18 +11:00
Jarryd Beck 65beaeb2e9 test that fails 2017-10-27 08:47:08 +11:00
Jarryd Beck acbce8e363 all tests pass 2017-10-27 08:38:29 +11:00
Jarryd Beck 3fed557cf2 much closer to working 2017-10-27 07:58:57 +11:00
Jarryd Beck e31c9af607 add clone to options
This is broken at the moment; it needs a complete rewrite.

The problem is that multiple options point to the same `OptionDetails`.
I really need to separate parsing results from describing options.
2017-10-20 08:29:55 +11:00
Jarryd Beck 1d6d1c97f0 clean up standard_value class a bit
This removes the `final` on the class, and the `virtual` keyword on the
functions that made `final` necessary. They shouldn't have been
virtual in the first place since nothing derives from it.

This hopefully doesn't reintroduce the non-virtual-destructor warning.
2017-10-19 18:36:42 +11:00
Jarryd Beck 38b4b1bee4 improve changelog 2017-10-18 18:42:49 +11:00
Jarryd Beck 8010e06952 Move parse result to an immutable object
This is far from ideal, but it's the first step in moving the parse
result to an immutable object so that the parser can be reused.
2017-10-18 18:37:58 +11:00
Jarryd Beck d8458a8c1a remove non virtual destructor silence for GCC
This was fixed in 37fab4ee7a.
2017-10-18 08:07:10 +11:00
Jarryd Beck 33c4d509f1 fix Unicode multiple definition 2017-10-18 08:07:10 +11:00
Jarryd Beck 70ceea57e3 Cleanup uses of inline 2017-10-18 08:07:10 +11:00
Benjamin Buch 37fab4ee7a avoid warning about non-virtual destructor (#75)
´Value´ and ´standard_value´ don't have a virtual destructor. When I understand the code right, this is intended, because they are used through ´shared_ptr´ and so its not required. Nevertheless, clang does warn about it, since at the point of the destructor call it can not check if the object has a final type. Adding the C++11 keyword ´final´ to ´standard_value´ avoids this warning.
2017-10-10 11:58:40 +11:00
Jarryd Beck 0b7686949d Fix compiler warnings for MSVC
Fixes #62. This fixes compiler warnings that are raised by MSVC.

In one case the code that was warned about was never executed, but
this compiles it out in that case to silence the warning.
2017-09-04 17:55:52 +10:00
36 changed files with 22282 additions and 10227 deletions

19
.clang-format Normal file
View File

@ -0,0 +1,19 @@
---
Language: Cpp
BasedOnStyle: LLVM
AccessModifierOffset: 0
AlignConsecutiveAssignments: true
AlwaysBreakAfterReturnType: TopLevel
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: true
AfterClass: true
AfterStruct: true
AfterFunction: true
AfterNamespace: true
AfterControlStatement: Always
BeforeElse: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left

24
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Build cxxopts
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: setup
run: mkdir build
- name: cmake
run: cd build; cmake ..
- name: Build
run: cd build; make -j$(nproc)
- name: test
run: cd build; ctest

24
.github/workflows/cifuzz.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'cxxopts'
language: c++
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'cxxopts'
language: c++
fuzz-seconds: 300
- name: Upload Crash
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

75
.github/workflows/cmake.yml vendored Normal file
View File

@ -0,0 +1,75 @@
name: CMake
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
defaults:
run:
shell: bash
jobs:
build-ubuntu:
strategy:
matrix:
os: [ ubuntu-22.04, ubuntu-24.04 ]
compiler: [ g++-9, g++-10, clang++ ]
name: Build and Test on Ubuntu
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Setup g++-9 if not exists
if: matrix.compiler == 'g++-9'
run: which g++-9 || (sudo apt-get update && sudo apt-get -y install g++-9)
- name: Setup g++10 if not exists
if: matrix.compiler == 'g++-10'
run: which g++10 || (sudo apt-get update && sudo apt-get -y install g++-10)
- name: Configure CMake
run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=${{matrix.compiler}}
- name: Build
run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build/test
run: ctest -C $BUILD_TYPE --output-on-failure
build-macos:
name: Build and Test on MacOS
strategy:
matrix:
os: [macos-latest]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Configure CMake
run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- name: Show compile commands
run: cat build/compile_commands.json
- name: Build
run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build/test
shell: bash
run: ctest -C $BUILD_TYPE --output-on-failure
build-windows:
name: Build and Test on Windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- name: Configure CMake
run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -T "ClangCl"
- name: Build
run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE
- name: Test
working-directory: ${{github.workspace}}/build/test
run: cd $BUILD_TYPE && ./link_test && ./options_test

59
.github/workflows/meson.yml vendored Normal file
View File

@ -0,0 +1,59 @@
name: Meson
on:
push:
branches: [ master, main ]
pull_request:
branches: [ master, main ]
workflow_dispatch:
jobs:
build-ubuntu:
strategy:
matrix:
icu: [enabled, disabled]
name: Build and Test on Ubuntu
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
- uses: BSFishy/meson-build@v1.0.3
with:
action: build
setup-options: -Dicu=${{ matrix.icu }}
meson-version: 0.64.1
directory: builddir
- name: Run Tests
run: meson test -C builddir
- name: Run examples
run: builddir/example
build-macos:
name: Build and Test on MacOS
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
- uses: BSFishy/meson-build@v1.0.3
with:
action: build
meson-version: 1.10.0
directory: builddir
- name: Run Tests
run: meson test -C builddir
build-windows:
name: Build and Test on Windows
runs-on: windows-latest
steps:
- uses: ilammy/msvc-dev-cmd@v1
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
- uses: BSFishy/meson-build@v1.0.3
with:
action: test
setup-options: -Dcpp_std=c++14 # MSVC doesn't actually support C++11, hide the warning
meson-version: 0.64.1
directory: builddir
- name: Run Tests
run: meson test -C builddir

77
.gitignore vendored
View File

@ -1,8 +1,77 @@
syntax: glob
# Temporary, cache, swap files
\#\#*
*.swp
build*
*.bkp
# Files which "ask" to be hidden
*~
.*
unused/
# Build artifacts
*.a
*.o
*.so
*.ptx
bin/*
lib/*
build/
build-*/
bazel-*
# Core dumps
core
core.*
core-*
# CMake & CTest-generated files
CMakeCache.txt
Makefile
CMakeFiles/
Testing/
CTestTestfile.cmake
cmake_install.cmake
CMakeScripts/*
CMakeTmp/*
Makefile
CTestTestfile.cmake
Testing/
# Eclise IDE-related files
.project
.cproject
.settings
# CLion IDE-related files
.idea/
cmake-build-*/
# Patching
*.diff
*.rej
*.orig
# Files/folders downloaded from other repositories as part of the build
external/*
third-party/*
# Miscellaneous
tags
log
*.log
*.v3breakpoints
gmon.out
.DS_Store
# Doxygen
doxygen.log
Doxyfile
docs/
# Archives
*.zip
*.gz
*.bz2
*.tgz
*.tar
*.xz

1
.tipi/deps Normal file
View File

@ -0,0 +1 @@
{ }

1
.tipi/opts Normal file
View File

@ -0,0 +1 @@

View File

@ -2,18 +2,47 @@ sudo: required
dist: trusty
language: cpp
os:
- osx
- linux
matrix:
include:
- os: linux
env: COMPILER=g++-6
addons:
apt:
packages:
- g++-6
sources: &sources
- llvm-toolchain-trusty-3.8
- llvm-toolchain-trusty-5.0
- ubuntu-toolchain-r-test
- os: linux
env: COMPILER=g++-6 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
addons:
apt:
packages:
- g++-6
sources: *sources
- os: linux
env: COMPILER=g++-7
addons:
apt:
packages:
- g++-7
sources: *sources
- os: linux
env: COMPILER=g++-7 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
addons:
apt:
packages:
- g++-7
sources: *sources
- os: linux
env: COMPILER=g++-5
addons:
apt:
packages:
- g++-5
sources: &sources
- llvm-toolchain-precise-3.8
- ubuntu-toolchain-r-test
sources: *sources
- os: linux
env: COMPILER=g++-5 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
addons:
@ -21,6 +50,20 @@ matrix:
packages:
- g++-5
sources: *sources
- os: linux
env: COMPILER=g++-4.8
addons:
apt:
packages:
- g++-4.8
sources: *sources
- os: linux
env: COMPILER=g++-4.8 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes
addons:
apt:
packages:
- g++-4.8
sources: *sources
- os: linux
env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++
addons:
@ -37,9 +80,17 @@ matrix:
- clang-3.8
- libc++-dev
sources: *sources
- os: linux
env: COMPILER=clang++-5.0 CMAKE_OPTIONS=-DCXXOPTS_CXX_STANDARD=17
addons:
apt:
packages:
- clang-5.0
- g++-5
sources: *sources
script: >
cmake -DCXXOPTS_BUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER
-DCMAKE_CXX_FLAGS=$CXXFLAGS $UNICODE_OPTIONS .
cmake -Werror=dev -DCXXOPTS_BUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER
-DCMAKE_CXX_FLAGS=$CXXFLAGS $UNICODE_OPTIONS $CMAKE_OPTIONS .
&& make && make ARGS=--output-on-failure test
before_install:

16
BUILD.bazel Normal file
View File

@ -0,0 +1,16 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "cxxopts",
hdrs = ["include/cxxopts.hpp"],
strip_include_prefix = "include",
visibility = ["//visibility:public"],
)
load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
cc_fuzz_test(
name = "cxxopts_fuzz_test",
srcs = ["test/fuzz.cpp"],
deps = [":cxxopts"],
)

183
CHANGELOG.md Normal file
View File

@ -0,0 +1,183 @@
# Changelog
This is the changelog for `cxxopts`, a C++11 library for parsing command line
options. The project adheres to semantic versioning.
## 3.3.1
### Bug fixes
* Added missing version bump
## 3.3.0
### Bug fixes
* Added missing header for GCC 15
* Fix some CMake packaging problems
### Added
* `as_optional`
* `ParseResult::contains`
* `std::filesystem` support
* CMake 4 compatibility
## 3.2.1
### Bug fixes
* Fix compilation with optional on C++20.
## 3.2
### Bug fixes
* Fix unannotated fallthrough.
* Fix sign conversion with Unicode output.
* Don't initialize regex in static initialiser.
* Fix incorrect integer overflow checks.
### Added
* Add fuzzing to CI
### Changed
* Change quote output to '' to match Windows.
* Don't split positional arguments by the list delimiter.
* Order help groups by the order they were added.
## 3.1.1
### Bug Fixes
* Fixed version number in header.
* Fixed cast warning in Unicode function.
## 3.1
### Added
* Support for multiple long names for the same option (= multiple long aliases)
* Add a `program()` function to retrieve the program name.
* Added a .clang-format file.
* Added iterator and printing for a ParseResult.
### Changed
* Cleanup exception code, add cxxopts::exceptions namespace.
* Renamed several exceptions to be more descriptive, and added to a nested namespace.
### Bug Fixes
* Fix `arguments()` having no key for options that only have a short name.
## 3.0
### Changed
* Only search for a C++ compiler in CMakeLists.txt.
* Allow for exceptions to be disabled.
* Fix duplicate default options when there is a short and long option.
* Add `CXXOPTS_NO_EXCEPTIONS` to disable exceptions.
* Fix char parsing for space and check for length.
* Change argument type in `Options::parse` from `char**` to `const char**`.
* Refactor parser to not change its arguments.
* `ParseResult` doesn't depend on a reference to the parser.
* Fixed several warnings and code quality issues.
* Improved formatting for help descriptions.
* Improve integer parsing.
### Added
* A list of unmatched arguments is available in `ParseResult`.
* Support single letter options with argument attached.
* Use <optional> if it is present.
### Bug Fixes
* Fix missing option name in exception.
## 2.2
### Changed
* Allow integers to have leading zeroes.
* Build the tests by default.
* Don't check for container when showing positional help.
### Added
* Iterator inputs to `parse_positional`.
* Throw an exception if the option in `parse_positional` doesn't exist.
* Parse a delimited list in a single argument for vector options.
* Add an option to disable implicit value on booleans.
### Bug Fixes
* Fix a warning about possible loss of data.
* Fix version numbering in CMakeLists.txt
* Remove unused declaration of the undefined `ParseResult::get_option`.
* Throw on invalid option syntax when beginning with a `-`.
* Throw in `as` when option wasn't present.
* Fix catching exceptions by reference.
* Fix out of bounds errors parsing integers.
## 2.1.1
### Bug Fixes
* Revert the change adding `const` type for `argv`, because most users expect
to pass a non-const `argv` from `main`.
## 2.1
### Changed
* Options with implicit arguments now require the `--option=value` form if
they are to be specified with an option. This is to remove the ambiguity
when a positional argument could follow an option with an implicit value.
For example, `--foo value`, where `foo` has an implicit value, will be
parsed as `--foo=implicit` and a positional argument `value`.
* Boolean values are no longer special, but are just an option with a default
and implicit value.
### Added
* Added support for `std::optional` as a storage type.
* Allow the help string to be customised.
* Use `const` for the type in the `argv` parameter, since the contents of the
arguments is never modified.
### Bug Fixes
* Building against GCC 4.9 was broken due to overly strict shadow warnings.
* Fixed an ambiguous overload in the `parse_positional` function when an
`initializer_list` was directly passed.
* Fixed precedence in the Boolean value regex.
## 2.0
### Changed
* `Options::parse` returns a ParseResult rather than storing the parse
result internally.
* Options with default values now get counted as appearing once if they
were not specified by the user.
### Added
* A new `ParseResult` object that is the immutable result of parsing. It
responds to the same `count` and `operator[]` as `Options` of 1.x did.
* The function `ParseResult::arguments` returns a vector of the parsed
arguments to iterate through in the order they were provided.
* The symbol `cxxopts::version` for the version of the library.
* Booleans can be specified with various strings and explicitly set false.
## 1.x
The 1.x series was the first major version of the library, with release numbers
starting to follow semantic versioning, after 0.x being unstable. It never had
a changelog maintained for it. Releases mostly contained bug fixes, with the
occasional feature added.

View File

@ -17,72 +17,67 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
cmake_minimum_required(VERSION 3.1)
project(cxxopts)
cmake_minimum_required(VERSION 3.5...3.19)
enable_testing()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(cxxopts)
set(VERSION "1.2.0")
# Get the version of the library
cxxopts_getversion(VERSION)
option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ON)
option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" OFF)
project(cxxopts
VERSION "${VERSION}"
LANGUAGES CXX
)
# request c++11 without gnu extension for the whole project and enable more warnings
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -Wshadow")
set("PROJECT_DESCRIPTION" "A header-only lightweight C++ command line option parser")
set("PROJECT_HOMEPAGE_URL" "https://github.com/jarro2783/cxxopts")
# Must include after the project call due to GNUInstallDirs requiring a language be enabled (IE. CXX)
include(GNUInstallDirs)
# Determine whether this is a standalone project or included by other projects
set(CXXOPTS_STANDALONE_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CXXOPTS_STANDALONE_PROJECT ON)
endif()
# Establish the project options
option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ${CXXOPTS_STANDALONE_PROJECT})
option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" ${CXXOPTS_STANDALONE_PROJECT})
option(CXXOPTS_ENABLE_INSTALL "Generate the install target" ${CXXOPTS_STANDALONE_PROJECT})
option(CXXOPTS_ENABLE_WARNINGS "Add warnings to CMAKE_CXX_FLAGS" ${CXXOPTS_STANDALONE_PROJECT})
option(CXXOPTS_USE_UNICODE_HELP "Use ICU Unicode library" OFF)
if (CXXOPTS_STANDALONE_PROJECT)
cxxopts_set_cxx_standard()
endif()
if (CXXOPTS_ENABLE_WARNINGS)
cxxopts_enable_warnings()
endif()
add_library(cxxopts INTERFACE)
add_library(cxxopts::cxxopts ALIAS cxxopts)
add_subdirectory(include)
# optionally, enable unicode support using the ICU library
set(CXXOPTS_USE_UNICODE_HELP FALSE CACHE BOOL "Use ICU Unicode library")
# Link against the ICU library when requested
if(CXXOPTS_USE_UNICODE_HELP)
find_package(PkgConfig)
pkg_check_modules(ICU REQUIRED icu-uc)
target_link_libraries(cxxopts INTERFACE ${ICU_LDFLAGS})
target_compile_options(cxxopts INTERFACE ${ICU_CFLAGS})
target_compile_definitions(cxxopts INTERFACE CXXOPTS_USE_UNICODE)
cxxopts_use_unicode()
endif()
target_include_directories(cxxopts INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Install cxxopts when requested by the user
if (CXXOPTS_ENABLE_INSTALL)
cxxopts_install_logic()
endif()
include(CMakePackageConfigHelpers)
set(CXXOPTS_CMAKE_DIR "lib/cmake/cxxopts" CACHE STRING
"Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
set(version_config "${PROJECT_BINARY_DIR}/cxxopts-config-version.cmake")
set(project_config "${PROJECT_BINARY_DIR}/cxxopts-config.cmake")
set(targets_export_name cxxopts-targets)
# Build examples when requested by the user
if (CXXOPTS_BUILD_EXAMPLES)
add_subdirectory(src)
endif()
# Generate the version, config and target files into the build directory.
write_basic_package_version_file(
${version_config}
VERSION ${VERSION}
COMPATIBILITY AnyNewerVersion)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/cxxopts-config.cmake.in
${project_config}
INSTALL_DESTINATION ${CXXOPTS_CMAKE_DIR})
export(TARGETS cxxopts NAMESPACE cxxopts::
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files.
install(
FILES ${project_config} ${version_config}
DESTINATION ${CXXOPTS_CMAKE_DIR})
install(EXPORT ${targets_export_name} DESTINATION ${CXXOPTS_CMAKE_DIR}
NAMESPACE cxxopts::)
# Install the header file and export the target
install(TARGETS cxxopts EXPORT ${targets_export_name} DESTINATION lib)
install(FILES ${PROJECT_SOURCE_DIR}/include/cxxopts.hpp DESTINATION include)
add_subdirectory(src)
add_subdirectory(test)
# Enable testing when requested by the user
if (CXXOPTS_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()

46
INSTALL
View File

@ -1,10 +1,46 @@
It is preferable to build out of source.
== System installation ==
cmake ${CXXOPTS_DIR}
make
This library is header only. So you can either copy `include/cxxopts.hpp` to `/usr/include` or `/usr/local/include`, or add `include` to your search path.
== Building the examples and tests ==
It is preferable to build out of source. Make a build directory somewhere, and then
do the following, where `${CXXOPTS_DIR}` is the path that you checked out `cxxopts`
to:
cmake ${CXXOPTS_DIR}
make
You can use another build tool, such as ninja.
cmake -G Ninja ${CXXOPTS_DIR}
ninja
cmake -G Ninja ${CXXOPTS_DIR}
ninja
To run the tests, you have to configure `cxxopts` with another flag:
cmake -D CXXOPTS_BUILD_TESTS=On ${CXXOPTS_DIR}
make
make test
== Using cxxopts in tipi.build projects ==
`cxxopts` can be easily used in [tipi.build](https://tipi.build) projects simply by adding the following entry to your `.tipi/deps`:
```json
{
"jarro2783/cxxopts": { "@": "v3.0.0" }
}
```
To try this you can run the following command in `/src` (change the target name appropriately to `linux` or `macos` or `windows`):
```bash
tipi . -t <target>
./build/linux-cxx17/bin/test_package -v
```
To develop `cxxopts` using tipi run the following command at the root of the repository:
```bash
tipi . -t <target> --test all -v
```

272
README.md
View File

@ -1,4 +1,41 @@
[![Build Status](https://travis-ci.org/jarro2783/cxxopts.svg?branch=master)](https://travis-ci.org/jarro2783/cxxopts)
<div align="center">
[![Build Status](https://img.shields.io/github/actions/workflow/status/jarro2783/cxxopts/cmake.yml?label=build)](https://github.com/jarro2783/cxxopts/actions/workflows/cmake.yml)
[![Conan](https://img.shields.io/conan/v/cxxopts)](https://conan.io/center/recipes/cxxopts)
[![vcpkg](https://img.shields.io/vcpkg/v/cxxopts)](https://vcpkg.io/en/package/cxxopts)
[![GitHub release](https://img.shields.io/github/v/release/jarro2783/cxxopts?label=github%20release)](https://github.com/jarro2783/cxxopts/releases)
[![Header Only](https://img.shields.io/badge/header--only-yes-green.svg)](https://github.com/jarro2783/cxxopts)
[![Mentioned in Awesome C++](https://awesome.re/mentioned-badge.svg)](https://github.com/fffaraz/awesome-cpp)
[![Homebrew](https://img.shields.io/homebrew/installs/dy/cxxopts?label=brew%20downloads&logo=homebrew)](https://formulae.brew.sh/formula/cxxopts)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
</div>
# Release versions
Note that `master` is generally a work in progress, and you probably want to use a
tagged release version.
## Version 3 breaking changes
If you have used version 2, there are a couple of breaking changes in version 3
that you should be aware of. If you are new to `cxxopts` you can skip this
section.
The parser no longer modifies its arguments, so you can pass a const `argc` and
`argv` and expect them not to be changed.
The `ParseResult` object no longer depends on the parser. So it can be returned
from a scope outside the parser and still work. Now that the inputs are not
modified, `ParseResult` stores a list of the unmatched arguments. These are
retrieved like follows:
```cpp
auto result = options.parse(argc, argv);
result.unmatched(); // get the unmatched arguments
```
# Quick start
@ -20,18 +57,26 @@ Additionally, anything after `--` will be parsed as a positional argument.
## Basics
#include <cxxopts.hpp>
```cpp
#include <cxxopts.hpp>
```
Create a cxxopts::Options instance.
Create a `cxxopts::Options` instance.
cxxopts::Options options("MyProgram", "One line description of MyProgram");
```cpp
cxxopts::Options options("MyProgram", "One line description of MyProgram");
```
Then use `add_options`.
options.add_options()
("d,debug", "Enable debugging")
("f,file", "File name", cxxopts::value<std::string>())
;
```cpp
options.add_options()
("d,debug", "Enable debugging") // a bool parameter
("i,integer", "Int param", cxxopts::value<int>())
("f,file", "File name", cxxopts::value<std::string>())
("v,verbose", "Verbose output", cxxopts::value<bool>()->default_value("false"))
;
```
Options are declared with a long and an optional short option. A description
must be provided. The third argument is the value, if omitted it is boolean.
@ -39,32 +84,91 @@ Any type can be given as long as it can be parsed, with operator>>.
To parse the command line do:
options.parse(argc, argv);
```cpp
auto result = options.parse(argc, argv);
```
To retrieve an option use `options.count("option")` to get the number of times
To retrieve an option use `result.count("option")` to get the number of times
it appeared, and
options["opt"].as<type>()
```cpp
result["opt"].as<type>()
```
to get its value. If "opt" doesn't exist, or isn't of the right type, then an
exception will be thrown.
## Unrecognised arguments
You can allow unrecognised arguments to be skipped. This applies to both
positional arguments that are not parsed into another option, and `--`
arguments that do not match an argument that you specify. This is done by
calling:
```cpp
options.allow_unrecognised_options();
```
and in the result object they are retrieved with:
```cpp
result.unmatched()
```
## Exceptions
Exceptional situations throw C++ exceptions. There are two types of
exceptions: errors defining the options, and errors when parsing a list of
arguments. All exceptions derive from `cxxopts::exceptions::exception`. Errors
defining options derive from `cxxopts::exceptions::specification` and errors
parsing arguments derive from `cxxopts::exceptions::parsing`.
All exceptions define a `what()` function to get a printable string
explaining the error.
## Help groups
Options can be placed into groups for the purposes of displaying help messages.
To place options in a group, pass the group as a string to `add_options`. Then,
when displaying the help, pass the groups that you would like displayed as a
vector to the `help` function.
To place options in a group, pass the group as a string to `add_options`. Then, when displaying the help, `help` by default prints help for all groups. If you want to only print help for a specific group, pass the groups that you would like displayed as a vector to the `help` function.
## Positional Arguments
Positional arguments can be optionally parsed into one or more options.
To set up positional arguments, call
Positional arguments are those given without a preceding flag and can be used
alongside non-positional arguments. There may be multiple positional arguments,
and the final positional argument may be a container type to hold a list of all
remaining positionals.
options.parse_positional({"first", "second", "last"})
To set up positional arguments, first declare the options, then configure a
set of those arguments as positional like:
where "last" should be the name of an option with a container type, and the
others should have a single value.
```cpp
options.add_options()
("script", "The script file to execute", cxxopts::value<std::string>())
("server", "The server to execute on", cxxopts::value<std::string>())
("filenames", "The filename(s) to process", cxxopts::value<std::vector<std::string>>());
options.parse_positional({"script", "server", "filenames"});
// Parse options the usual way
options.parse(argc, argv);
```
Note : `parse_positional` defaults to replacing the positionals with the arguments provided in the function call. To append to the existing list of positionals, please use `cxxopts::PositionalMode::Append`.
```cpp
options.parse_positional("another_option", cxxopts::PositionalMode::Append);
```
For example, parsing the following arguments:
~~~
my_script.py my_server.com file1.txt file2.txt file3.txt
~~~
will result in parsed arguments like the following table:
| Field | Value |
| ------------- | ----------------------------------------- |
| `"script"` | `"my_script.py"` |
| `"server"` | `"my_server.com"` |
| `"filenames"` | `{"file1.txt", "file2.txt", "file3.txt"}` |
## Default and implicit values
@ -73,29 +177,141 @@ An option can be declared with a default or an implicit value, or both.
A default value is the value that an option takes when it is not specified
on the command line. The following specifies a default value for an option:
cxxopts::value<std::string>()->default_value("value")
```cpp
cxxopts::value<std::string>()->default_value("value")
```
An implicit value is the value that an option takes when it is given on the
command line without an argument. The following specifies an implicit value:
cxxopts::value<std::string>()->implicit_value("implicit")
```cpp
cxxopts::value<std::string>()->implicit_value("implicit")
```
If an option had both, then not specifying it would give the value `"value"`,
writing it on the command line as `--option` would give the value `"implicit"`,
and writing `--option=another` would give it the value `"another"`.
Note that if `option` has an implicit value, specifying `--option another` will not work. You must use `=` syntax - `--option=another` or `-o=another`(assumming `o` is a short name for the option). This is because no argument is required. Hence, there is no good way to determine if the next string is an argument to your option or a positional argument.
Note that the default and implicit value is always stored as a string,
regardless of the type that you want to store it in. It will be parsed as
though it was given on the command line.
Default values are not counted by `Options::count`.
### Implicit values with disabled arguments
You can specify an option for which an argument cannot be specified using below syntax.
```cpp
cxxopts::value<bool>()->implicit_value("true", cxxopts::ImplicitArgPolicy::Disabled)
```
In this case specifying option as `--option=<value>` is disallowed and will throw `specified_disabled_args` exception. Note that `--option value` is not supported for implicit values. It is treated as positional/unmatched.
## Boolean values
Boolean options have a default implicit value of `"true"`, which can be
overridden. The effect is that writing `-o` by itself will set option `o` to
`true`. However, they can also be written with various strings using `=value`.
There is no way to disambiguate positional arguments from the value following
a boolean, so we have chosen that they will be positional arguments, and
therefore, `-o false` does not work.
## `std::vector<T>` values
Parsing a list of values into a `std::vector<T>` is also supported, as long as `T`
can be parsed. To separate single values in a list the define symbol `CXXOPTS_VECTOR_DELIMITER`
is used, which is ',' by default. Ensure that you use no whitespaces between values
(unless the entire list is double quoted) because those would be interpreted as the
next command line option. Example for a command line option
that can be parsed as a `std::vector<double>`:
~~~
--my_list=1,-2.1,3,4.5
~~~
If the list of values is quoted, then spaces can be included. For example:
~~~
--my_list="review,memory sanitize,build help,reformat"
~~~
This will be parsed into `review`, `memory sanitize`, `build help`, and `reformat`.
## Options specified multiple times
The same option can be specified several times, with different arguments, which will all
be recorded in order of appearance. An example:
~~~
--use train --use bus --use ferry
~~~
this is supported through the use of a vector of value for the option:
~~~
options.add_options()
("use", "Usable means of transport", cxxopts::value<std::vector<std::string>>())
~~~
## Custom help
The string after the program name on the first line of the help can be
completely replaced by calling `options.custom_help`. Note that you might
also want to override the positional help by calling `options.positional_help`.
## Example
Putting all together:
```cpp
#include <iostream>
#include "cxxopts.hpp"
int main(int argc, char** argv)
{
cxxopts::Options options("test", "A brief description");
options.add_options()
("b,bar", "Param bar", cxxopts::value<std::string>())
("d,debug", "Enable debugging", cxxopts::value<bool>()->default_value("false"))
("f,foo", "Param foo", cxxopts::value<int>()->default_value("10"))
("h,help", "Print usage")
;
auto result = options.parse(argc, argv);
if (result.count("help"))
{
std::cout << options.help() << std::endl;
exit(0);
}
bool debug = result["debug"].as<bool>();
std::string bar;
if (result.count("bar"))
bar = result["bar"].as<std::string>();
int foo = result["foo"].as<int>();
return 0;
}
```
# Linking
This is a header only library.
# Requirements
The only build requirement is a C++ compiler that supports C++11 regular
expressions. For example GCC >= 4.9 or clang with libc++.
The only build requirement is a C++ compiler that supports C++11 features such as:
* regex
* constexpr
* default constructors
# TODO list
GCC >= 4.9 or clang >= 3.1 with libc++ are known to work.
* Allow unrecognised options.
* Various help strings.
* Unicode aware for help strings.
The following compilers are known not to work:
* MSVC 2013

16
WORKSPACE Normal file
View File

@ -0,0 +1,16 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_fuzzing",
sha256 = "d9002dd3cd6437017f08593124fdd1b13b3473c7b929ceb0e60d317cb9346118",
strip_prefix = "rules_fuzzing-0.3.2",
urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/v0.3.2.zip"],
)
load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
rules_fuzzing_dependencies()
load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
rules_fuzzing_init()

169
cmake/cxxopts.cmake Normal file
View File

@ -0,0 +1,169 @@
# Copyright (c) 2014 Jarryd Beck
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
if (CMAKE_VERSION VERSION_GREATER 3.10 OR CMAKE_VERSION VERSION_EQUAL 3.10)
# Use include_guard() added in cmake 3.10
include_guard()
endif()
include(CMakePackageConfigHelpers)
function(cxxopts_getversion version_arg)
# Parse the current version from the cxxopts header
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/cxxopts.hpp" cxxopts_version_defines
REGEX "#define CXXOPTS__VERSION_(MAJOR|MINOR|PATCH)")
foreach(ver ${cxxopts_version_defines})
if(ver MATCHES "#define CXXOPTS__VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
set(CXXOPTS__VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
endif()
endforeach()
set(VERSION ${CXXOPTS__VERSION_MAJOR}.${CXXOPTS__VERSION_MINOR}.${CXXOPTS__VERSION_PATCH})
# Give feedback to the user. Prefer DEBUG when available since large projects tend to have a lot
# going on already
if (CMAKE_VERSION VERSION_GREATER 3.15 OR CMAKE_VERSION VERSION_EQUAL 3.15)
message(DEBUG "cxxopts version ${VERSION}")
else()
message(STATUS "cxxopts version ${VERSION}")
endif()
# Return the information to the caller
set(${version_arg} ${VERSION} PARENT_SCOPE)
endfunction()
# Optionally, enable unicode support using the ICU library
function(cxxopts_use_unicode)
find_package(PkgConfig)
pkg_check_modules(ICU REQUIRED icu-uc)
target_link_libraries(cxxopts INTERFACE ${ICU_LDFLAGS})
target_compile_options(cxxopts INTERFACE ${ICU_CFLAGS})
target_compile_definitions(cxxopts INTERFACE CXXOPTS_USE_UNICODE)
endfunction()
# Request C++11 without gnu extension for the whole project and enable more warnings
macro(cxxopts_set_cxx_standard)
if (CXXOPTS_CXX_STANDARD)
set(CMAKE_CXX_STANDARD ${CXXOPTS_CXX_STANDARD})
else()
set(CMAKE_CXX_STANDARD 11)
endif()
set(CMAKE_CXX_EXTENSIONS OFF)
endmacro()
# Helper function to enable warnings
function(cxxopts_enable_warnings)
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL 5.0)
set(COMPILER_SPECIFIC_FLAGS "-Wsuggest-override")
endif()
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -Wshadow -Weffc++ -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion ${COMPILER_SPECIFIC_FLAGS}")
endif()
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} PARENT_SCOPE)
endfunction()
# Helper function to ecapsulate install logic
function(cxxopts_install_logic)
if(NOT CXXOPTS_USE_UNICODE_HELP)
if(CMAKE_LIBRARY_ARCHITECTURE)
string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
else()
# On some systems (e.g. NixOS), `CMAKE_LIBRARY_ARCHITECTURE` can be empty
set(CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(${CMAKE_VERSION} VERSION_GREATER "3.14")
set(OPTIONAL_ARCH_INDEPENDENT "ARCH_INDEPENDENT")
endif()
else()
set(CMAKE_INSTALL_LIBDIR_ARCHIND "${CMAKE_INSTALL_LIBDIR}")
endif()
set(CXXOPTS_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR_ARCHIND}/cmake/cxxopts" CACHE STRING "Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.")
set(version_config "${PROJECT_BINARY_DIR}/cxxopts-config-version.cmake")
set(project_config "${PROJECT_BINARY_DIR}/cxxopts-config.cmake")
set(targets_export_name cxxopts-targets)
set(PackagingTemplatesDir "${PROJECT_SOURCE_DIR}/packaging")
# Generate the version, config and target files into the build directory.
write_basic_package_version_file(
${version_config}
VERSION ${VERSION}
COMPATIBILITY AnyNewerVersion
${OPTIONAL_ARCH_INDEPENDENT}
)
configure_package_config_file(
${PackagingTemplatesDir}/cxxopts-config.cmake.in
${project_config}
INSTALL_DESTINATION ${CXXOPTS_CMAKE_DIR})
export(TARGETS cxxopts NAMESPACE cxxopts::
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files.
install(
FILES ${project_config} ${version_config}
DESTINATION ${CXXOPTS_CMAKE_DIR})
install(EXPORT ${targets_export_name} DESTINATION ${CXXOPTS_CMAKE_DIR}
NAMESPACE cxxopts::)
# Install the header file and export the target
install(TARGETS cxxopts EXPORT ${targets_export_name} DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES ${PROJECT_SOURCE_DIR}/include/cxxopts.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "cxxopt developers")
set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
set(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
set(CPACK_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_MAINTAINER}")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_DEBIAN_PACKAGE_NAME "lib${PROJECT_NAME}-dev")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev")
set(CPACK_DEBIAN_PACKAGE_SUGGESTS "cmake, pkg-config, pkg-conf")
set(CPACK_RPM_PACKAGE_NAME "lib${PROJECT_NAME}-devel")
set(CPACK_RPM_PACKAGE_SUGGESTS "${CPACK_DEBIAN_PACKAGE_SUGGESTS}")
set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_NSIS_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_COMPRESSION_TYPE "xz")
set(PKG_CONFIG_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc")
if(CXXOPTS_USE_UNICODE_HELP)
set(PKG_CONFIG_REQUIRES "icu-uc")
set(PKG_CONFIG_EXTRA_CFLAGS "-DCXXOPTS_USE_UNICODE")
endif()
configure_file("${PackagingTemplatesDir}/pkgconfig.pc.in" "${PKG_CONFIG_FILE_NAME}" @ONLY)
install(FILES "${PKG_CONFIG_FILE_NAME}"
DESTINATION "${CMAKE_INSTALL_LIBDIR_ARCHIND}/pkgconfig"
)
include(CPack)
endfunction()

23
include/CMakeLists.txt Normal file
View File

@ -0,0 +1,23 @@
# Copyright (c) 2014 Jarryd Beck
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
target_include_directories(cxxopts INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)

File diff suppressed because it is too large Load Diff

97
meson.build Normal file
View File

@ -0,0 +1,97 @@
# Copyright © 2024-2026 Dylan Baker
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
project(
'cxxopts',
'cpp',
version : run_command(
'meson/version.py', files('include/cxxopts.hpp'), capture : true, check : true).stdout().strip(),
meson_version : '>= 0.64',
license : 'MIT',
default_options : ['cpp_std=c++11', 'warning_level=2'],
)
cpp = meson.get_compiler('cpp')
with_warnings = get_option('warnings').disable_auto_if(meson.is_subproject()).allowed()
if with_warnings
add_project_arguments(
cpp.get_supported_arguments(
'-Wsuggest-override',
'-Wshadow',
'-Weffc++',
'-Wsign-compare',
'-Wshadow',
'-Wwrite-strings',
'-Wpointer-arith',
'-Winit-self',
'-Wconversion',
'-Wno-sign-conversion',
),
language : 'cpp',
)
endif
install_headers('include/cxxopts.hpp')
dep_icu = dependency('icu-uc', required : get_option('icu'))
if dep_icu.found()
add_project_arguments('-DCXXOPTS_USE_UNICODE', language : 'cpp')
endif
with_examples = get_option('examples').disable_auto_if(meson.is_subproject()).allowed()
if with_examples
executable(
'example',
'src/example.cpp',
include_directories : 'include',
dependencies : dep_icu,
override_options : ['cpp_std=c++17'],
)
endif
with_tests = get_option('tests').disable_auto_if(meson.is_subproject()).allowed()
if with_tests
subdir('test')
endif
extra_cflags = []
if dep_icu.found()
extra_cflags += ['-DCXXOPTS_USE_UNICODE']
endif
dep_cxxopts = declare_dependency(
include_directories : 'include',
dependencies : dep_icu,
compile_args : extra_cflags,
)
meson.override_dependency('cxxopts', dep_cxxopts)
pkg = import('pkgconfig')
pkg.generate(
name : 'cxxopts',
description : 'A header-only lightweight C++ command line option parser',
url : 'https://github.com/jarro2783/cxxopts',
extra_cflags : extra_cflags,
requires : dep_icu,
dataonly : not dep_icu.found(),
)

47
meson/version.py Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python
# Copyright © 2024-2026 Dylan Baker
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""Parse the cxxopts.hpp header to get the version."""
import sys
def main():
versions = [None, None, None]
with open(sys.argv[1], 'r', encoding='ascii') as f:
for line in f:
if line.startswith('#define CXXOPTS__VERSION_'):
ver = line.rstrip().rsplit(' ', 1)[-1]
if 'MAJOR' in line:
versions[0] = ver
elif 'MINOR' in line:
versions[1] = ver
elif 'PATCH' in line:
versions[2] = ver
if None not in versions:
break
assert None not in versions, \
"Did not find all of the expected version strings in cxxopts.hpp"
print('.'.join(versions))
if __name__ == "__main__":
main()

41
meson_options.txt Normal file
View File

@ -0,0 +1,41 @@
# Copyright © 2024-2026 Dylan Baker
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
option(
'examples',
type : 'feature',
description : 'Whether to build examples. Defaults to enabled when not built as a subproject, otherwise disabled.',
)
option(
'tests',
type : 'feature',
description : 'Whether to build tests. Defaults to enabled when not built as a subproject, otherwise disabled.',
)
option(
'warnings',
type : 'feature',
description : 'Whether to add additional warnings. Defaults to enabled when not built as a subproject, otherwise disabled.',
)
option(
'icu',
type : 'feature',
value : 'disabled',
description : 'use ICU Unicode library.',
)

View File

@ -0,0 +1,9 @@
prefix=@CMAKE_INSTALL_PREFIX@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
URL: @PROJECT_HOMEPAGE_URL@
Version: @PROJECT_VERSION@
Requires: @PKG_CONFIG_REQUIRES@
Cflags: -I${includedir} @PKG_CONFIG_EXTRA_CFLAGS@

3
src/.tipi/deps Normal file
View File

@ -0,0 +1,3 @@
{
"jarro2783/cxxopts": { }
}

View File

@ -18,7 +18,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
if(CXXOPTS_BUILD_EXAMPLES)
add_executable(example example.cpp)
target_link_libraries(example cxxopts)
endif()
add_executable(example example.cpp)
target_link_libraries(example cxxopts)
target_compile_features(example PRIVATE cxx_std_17)
target_compile_options(example PRIVATE
"$<$<CXX_COMPILER_ID:MSVC>:/utf-8;>")

View File

@ -21,36 +21,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <iostream>
#include "cxxopts.hpp"
int main(int argc, char* argv[])
#include <iostream>
#include <memory>
int
parse(int argc, const char* argv[])
{
try
{
cxxopts::Options options(argv[0], " - example command line options");
options.positional_help("[optional args]");
std::unique_ptr<cxxopts::Options> allocated(new cxxopts::Options(argv[0], " - example command line options"));
auto& options = *allocated;
options
.positional_help("[optional args]")
.show_positional_help();
bool apple = false;
options.add_options()
("a,apple", "an apple", cxxopts::value<bool>(apple))
options
.set_width(70)
.set_tab_expansion()
.allow_unrecognised_options()
.add_options()
("a,apple,ringo", "an apple", cxxopts::value<bool>(apple))
("b,bob", "Bob")
("char", "A character", cxxopts::value<char>())
("t,true", "True", cxxopts::value<bool>()->default_value("true"))
("f, file", "File", cxxopts::value<std::vector<std::string>>(), "FILE")
("i,input", "Input", cxxopts::value<std::string>())
("o,output", "Output file", cxxopts::value<std::string>()
->default_value("a.out")->implicit_value("b.def"), "BIN")
("x", "A short-only option", cxxopts::value<std::string>())
("positional",
"Positional arguments: these are the arguments that are entered "
"without an option", cxxopts::value<std::vector<std::string>>())
("long-description",
"thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace")
("help", "Print help")
("tab-expansion", "Tab\texpansion")
("int", "An integer", cxxopts::value<int>(), "N")
("float", "A floating point number", cxxopts::value<float>())
("vector", "A list of doubles", cxxopts::value<std::vector<double>>())
("option_that_is_too_long_for_the_help", "A very long option")
("l,list", "List all parsed arguments (including default values)")
("range", "Use range-for to list arguments")
#ifdef CXXOPTS_USE_UNICODE
("unicode", u8"A help option with non-ascii: à. Here the size of the"
" string should be correct")
@ -63,28 +78,49 @@ int main(int argc, char* argv[])
options.parse_positional({"input", "output", "positional"});
options.parse(argc, argv);
auto result = options.parse(argc, argv);
if (options.count("help"))
if (result.count("help"))
{
std::cout << options.help({"", "Group"}) << std::endl;
exit(0);
return true;
}
if(result.count("list"))
{
if(result.count("range"))
{
for(const auto &kv: result)
{
std::cout << kv.key() << " = " << kv.value() << std::endl;
}
}
else
{
std::cout << result.arguments_string() << std::endl;
}
return true;
}
if (apple)
{
std::cout << "Saw option a " << options.count("a") << " times " <<
std::cout << "Saw option a " << result.count("a") << " times " <<
std::endl;
}
if (options.count("b"))
if (result.count("b"))
{
std::cout << "Saw option b" << std::endl;
}
if (options.count("f"))
if (result.count("char"))
{
auto& ff = options["f"].as<std::vector<std::string>>();
std::cout << "Saw a character " << result["char"].as<char>() << "" << std::endl;
}
if (result.count("f"))
{
auto& ff = result["f"].as<std::vector<std::string>>();
std::cout << "Files" << std::endl;
for (const auto& f : ff)
{
@ -92,44 +128,74 @@ int main(int argc, char* argv[])
}
}
if (options.count("input"))
if (result.count("input"))
{
std::cout << "Input = " << options["input"].as<std::string>()
std::cout << "Input = " << result["input"].as<std::string>()
<< std::endl;
}
if (options.count("output"))
if (result.count("output"))
{
std::cout << "Output = " << options["output"].as<std::string>()
std::cout << "Output = " << result["output"].as<std::string>()
<< std::endl;
}
if (options.count("positional"))
if (result.count("positional"))
{
std::cout << "Positional = {";
auto& v = options["positional"].as<std::vector<std::string>>();
auto& v = result["positional"].as<std::vector<std::string>>();
for (const auto& s : v) {
std::cout << s << ", ";
}
std::cout << "}" << std::endl;
}
if (options.count("int"))
if (result.count("int"))
{
std::cout << "int = " << options["int"].as<int>() << std::endl;
std::cout << "int = " << result["int"].as<int>() << std::endl;
}
if (options.count("float"))
if (result.count("float"))
{
std::cout << "float = " << options["float"].as<float>() << std::endl;
std::cout << "float = " << result["float"].as<float>() << std::endl;
}
if (result.count("vector"))
{
std::cout << "vector = ";
const auto values = result["vector"].as<std::vector<double>>();
for (const auto& v : values) {
std::cout << v << ", ";
}
std::cout << std::endl;
}
std::cout << "Arguments remain = " << argc << std::endl;
} catch (const cxxopts::OptionException& e)
auto arguments = result.arguments();
std::cout << "Saw " << arguments.size() << " arguments" << std::endl;
std::cout << "Unmatched options: ";
for (const auto& option: result.unmatched())
{
std::cout << "'" << option << "' ";
}
std::cout << std::endl;
}
catch (const cxxopts::exceptions::exception& e)
{
std::cout << "error parsing options: " << e.what() << std::endl;
exit(1);
return false;
}
return true;
}
int main(int argc, const char* argv[])
{
if (!parse(argc, argv))
{
return 1;
}
return 0;

2
test/.tipiignore Normal file
View File

@ -0,0 +1,2 @@
link_a.cpp
link_b.cpp

View File

@ -1,32 +1,78 @@
if (CXXOPTS_BUILD_TESTS)
add_executable(options_test main.cpp options.cpp)
target_link_libraries(options_test cxxopts)
add_test(options options_test)
# Copyright (c) 2014 Jarryd Beck
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# test if the targets are findable from the build directory
add_test(find-package-test ${CMAKE_CTEST_COMMAND}
-C ${CMAKE_BUILD_TYPE}
--build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/find-package-test"
"${CMAKE_CURRENT_BINARY_DIR}/find-package-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-Dcxxopts_DIR=${PROJECT_BINARY_DIR}"
)
add_executable(options_test main.cpp options.cpp)
target_link_libraries(options_test cxxopts)
add_test(options options_test)
# test if the targets are findable when add_subdirectory is used
add_test(add-subdirectory-test ${CMAKE_CTEST_COMMAND}
-C ${CMAKE_BUILD_TYPE}
--build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/add-subdirectory-test"
"${CMAKE_CURRENT_BINARY_DIR}/add-subdirectory-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
)
add_executable(options_test_noregex main.cpp options.cpp)
target_link_libraries(options_test_noregex cxxopts)
target_compile_definitions(options_test_noregex PRIVATE CXXOPTS_NO_REGEX)
add_test(options_no_regex options_test_noregex)
# Run the parser tests under UBSan so undefined behaviour in integer parsing
# (e.g. std::abs(INT64_MIN)) fails the build instead of going unnoticed.
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU" AND NOT WIN32)
foreach(test_target options_test options_test_noregex)
target_compile_options(${test_target} PRIVATE -fsanitize=undefined -fno-sanitize-recover=undefined)
set_target_properties(${test_target} PROPERTIES LINK_FLAGS "-fsanitize=undefined -fno-sanitize-recover=undefined")
endforeach()
endif()
# test if the targets are findable from the build directory
add_test(find-package-test ${CMAKE_CTEST_COMMAND}
-C ${CMAKE_BUILD_TYPE}
--build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/find-package-test"
"${CMAKE_CURRENT_BINARY_DIR}/find-package-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
"-DCMAKE_CXX_EXTENSIONS=${CMAKE_CXX_EXTENSIONS}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-Dcxxopts_DIR=${PROJECT_BINARY_DIR}"
)
# test if the targets are findable when add_subdirectory is used
add_test(add-subdirectory-test ${CMAKE_CTEST_COMMAND}
-C ${CMAKE_BUILD_TYPE}
--build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/add-subdirectory-test"
"${CMAKE_CURRENT_BINARY_DIR}/add-subdirectory-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}"
"-DCMAKE_CXX_EXTENSIONS=${CMAKE_CXX_EXTENSIONS}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
)
add_executable(link_test link_a.cpp link_b.cpp)
target_link_libraries(link_test cxxopts)
if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") AND ("${CMAKE_SYSTEM}" MATCHES "Linux"))
add_executable(fuzzer fuzz.cpp)
target_link_libraries(fuzzer PRIVATE cxxopts)
target_compile_options(fuzzer PRIVATE -fsanitize=fuzzer)
target_link_options(fuzzer PRIVATE -fsanitize=fuzzer)
endif()

View File

@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.5...3.19)
project(cxxopts-test)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
add_subdirectory(../.. cxxopts EXCLUDE_FROM_ALL)
add_executable(library-test "../../src/example.cpp")

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,7 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.5...3.19)
project(cxxopts-test)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(cxxopts REQUIRED)
add_executable(library-test "../../src/example.cpp")

107
test/fuzz.cpp Normal file
View File

@ -0,0 +1,107 @@
#include <cassert>
#include <cxxopts.hpp>
#include <fuzzer/FuzzedDataProvider.h>
constexpr int kMaxOptions = 1024;
constexpr int kMaxArgSize = 1024;
enum class ParseableTypes
{
kInt,
kString,
kVectorString,
kFloat,
kDouble,
// Marker for fuzzer.
kMaxValue,
};
template <typename T>
void
add_fuzzed_option(cxxopts::Options* options, FuzzedDataProvider* provider)
{
assert(options);
assert(provider);
options->add_options()(provider->ConsumeRandomLengthString(kMaxArgSize),
provider->ConsumeRandomLengthString(kMaxArgSize),
cxxopts::value<T>());
}
extern "C" int
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
try
{
FuzzedDataProvider provider(data, size);
// Randomly generate a usage string.
cxxopts::Options options(provider.ConsumeRandomLengthString(kMaxArgSize),
provider.ConsumeRandomLengthString(kMaxArgSize));
// Randomly generate a set of flags configurations.
for (int i = 0; i < provider.ConsumeIntegralInRange<int>(0, kMaxOptions);
i++)
{
switch (provider.ConsumeEnum<ParseableTypes>())
{
case ParseableTypes::kInt:
add_fuzzed_option<int>(&options, &provider);
break;
case ParseableTypes::kString:
add_fuzzed_option<std::string>(&options, &provider);
break;
case ParseableTypes::kVectorString:
add_fuzzed_option<std::vector<std::string>>(&options, &provider);
break;
case ParseableTypes::kFloat:
add_fuzzed_option<float>(&options, &provider);
break;
case ParseableTypes::kDouble:
add_fuzzed_option<double>(&options, &provider);
break;
default:
break;
}
}
// Sometimes allow unrecognised options.
if (provider.ConsumeBool())
{
options.allow_unrecognised_options();
}
// Sometimes allow trailing positional arguments.
if (provider.ConsumeBool())
{
std::string positional_option_name =
provider.ConsumeRandomLengthString(kMaxArgSize);
options.add_options()(positional_option_name,
provider.ConsumeRandomLengthString(kMaxArgSize),
cxxopts::value<std::vector<std::string>>());
options.parse_positional({positional_option_name});
}
// Build command line input.
const int argc = provider.ConsumeIntegralInRange<int>(1, kMaxOptions);
std::vector<std::string> command_line_container;
command_line_container.reserve(argc);
std::vector<const char*> argv;
argv.reserve(argc);
for (int i = 0; i < argc; i++)
{
command_line_container.push_back(
provider.ConsumeRandomLengthString(kMaxArgSize));
argv.push_back(command_line_container[i].c_str());
}
// Parse command line;
auto result = options.parse(argc, argv.data());
} catch (...)
{
}
return 0;
}

6
test/link_a.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "cxxopts.hpp"
int main(int, char**)
{
return 0;
}

1
test/link_b.cpp Normal file
View File

@ -0,0 +1 @@
#include <cxxopts.hpp>

55
test/meson.build Normal file
View File

@ -0,0 +1,55 @@
# Copyright © 2024-2026 Dylan Baker
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
inc = include_directories('../include')
test(
'link',
executable(
'link_test',
'link_a.cpp', 'link_b.cpp',
dependencies : dep_icu,
include_directories : inc,
)
)
test(
'options',
executable(
'options_test',
'main.cpp', 'options.cpp',
dependencies : dep_icu,
include_directories : inc,
)
)
if cpp.get_id() == 'clang' and host_machine.system() == 'linux'
executable(
'fuzzer',
'fuzz.cpp',
cpp_args : ['-fsanitize=fuzzer'],
link_args : ['-fsanitize=fuzzer'],
dependencies : dep_icu,
include_directories : inc,
)
endif
# Meson can generate basic cmake-configs files, but not when targets are used,
# so these tests don't make sense

File diff suppressed because it is too large Load Diff