[24.03,RFC] argparse: add argparse library

Message ID 20231121122651.7078-1-fengchengwen@huawei.com (mailing list archive)
State Superseded
Delegated to: Thomas Monjalon
Headers
Series [24.03,RFC] argparse: add argparse library |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS

Commit Message

fengchengwen Nov. 21, 2023, 12:26 p.m. UTC
  Introduce argparse library (which was inspired by the thread [1]),
compared with getopt, the argparse has following advantages:
1) Set the help information when defining parameters.
2) Support positional parameters.

The parameters parsing according following:
1) positional: use callback to parse (passed the long-name as the key
   for callback).
2) optional:
   In addition to callback to parse, but also support:
2.1) no-val: support set default value to saver.
2.2) has-val: support set value to saver, the value must be conform
              RTE_ARGPARSE_ARG_VAL_xxx.
2.3) opt-val: if current without value then treat as no-val, else could
              treat as has-val.

Examples: (take dmafwd as example):
1) If parse with callback:
	static int
	func(const char *key, const char *value, const char *opaque)
	{
		if (!strcmp("--mac-updating", key)) {
			mac_updating = 1;
		} else if (!strcmp("--no-mac-updating", key)) {
			mac_updating = 0;
		} else if (!strcmp("--portmask", key)) {
			dma_enabled_port_mask = dma_parse_portmask(optarg);
			if (dma_enabled_port_mask & ~default_port_mask ||
						dma_enabled_port_mask <= 0) {
				...
			}
		} else {
			...
		}
	}

	static int
	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
	{
		static struct rte_argparse opts[] = {
			.prog = "dma",
			.usage = NULL,
			.descriptor = "dma and nic fwd example",
			.epilog = NULL,
			.exit_on_error = true,
			.opt = {
				{ "--mac-updating", NULL, "Enable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--no-mac-updating", NULL, "disable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
			}
		};
		return rte_argparse_parse(opts, argc, argv);
	}

2) If parse with value:
	static int
	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
	{
		static struct rte_argparse opts[] = {
			.prog = "dma",
			.usage = NULL,
			.descriptor = "dma and nic fwd example",
			.epilog = NULL,
			.exit_on_error = true,
			.opt = {
				{ "--mac-updating", NULL, "Enable MAC addresses updating", NULL, 0, &mac_updating, (void *)1, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--no-mac-updating", NULL, "disable MAC addresses updating", NULL, 0, &mac_updating, (void *)0, RTE_ARGPARSE_ARG_NO_VAL },
				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", NULL, 0, &dma_enabled_port_mask, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
			}
		};
		int ret;
		ret = rte_argparse_parse(opts, argc, argv);
		if (ret != 0)
			return ret;
		if (dma_enabled_port_mask & ~default_port_mask ||
					dma_enabled_port_mask <= 0) {
			...
		}
	}

3) Also could mix parse with func and with value.

[1] https://patchwork.dpdk.org/project/dpdk/patch/20231105054539.22303-2-fengchengwen@huawei.com/

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
 lib/argparse/meson.build    |   6 ++
 lib/argparse/rte_argparse.h | 139 ++++++++++++++++++++++++++++++++++++
 lib/argparse/version.map    |   7 ++
 lib/meson.build             |   1 +
 4 files changed, 153 insertions(+)
 create mode 100644 lib/argparse/meson.build
 create mode 100644 lib/argparse/rte_argparse.h
 create mode 100644 lib/argparse/version.map
  

Comments

Stephen Hemminger Nov. 21, 2023, 4:36 p.m. UTC | #1
On Tue, 21 Nov 2023 12:26:51 +0000
Chengwen Feng <fengchengwen@huawei.com> wrote:

> Introduce argparse library (which was inspired by the thread [1]),
> compared with getopt, the argparse has following advantages:
> 1) Set the help information when defining parameters.
> 2) Support positional parameters.
> 
> The parameters parsing according following:
> 1) positional: use callback to parse (passed the long-name as the key
>    for callback).
> 2) optional:
>    In addition to callback to parse, but also support:
> 2.1) no-val: support set default value to saver.
> 2.2) has-val: support set value to saver, the value must be conform
>               RTE_ARGPARSE_ARG_VAL_xxx.
> 2.3) opt-val: if current without value then treat as no-val, else could
>               treat as has-val.
> 
> Examples: (take dmafwd as example):
> 1) If parse with callback:
> 	static int
> 	func(const char *key, const char *value, const char *opaque)
> 	{
> 		if (!strcmp("--mac-updating", key)) {
> 			mac_updating = 1;
> 		} else if (!strcmp("--no-mac-updating", key)) {
> 			mac_updating = 0;
> 		} else if (!strcmp("--portmask", key)) {
> 			dma_enabled_port_mask = dma_parse_portmask(optarg);
> 			if (dma_enabled_port_mask & ~default_port_mask ||
> 						dma_enabled_port_mask <= 0) {
> 				...
> 			}
> 		} else {
> 			...
> 		}
> 	}
> 
> 	static int
> 	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
> 	{
> 		static struct rte_argparse opts[] = {
> 			.prog = "dma",
> 			.usage = NULL,
> 			.descriptor = "dma and nic fwd example",
> 			.epilog = NULL,
> 			.exit_on_error = true,
> 			.opt = {
> 				{ "--mac-updating", NULL, "Enable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
> 				{ "--no-mac-updating", NULL, "disable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
> 				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
> 				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
> 			}
> 		};
> 		return rte_argparse_parse(opts, argc, argv);
> 	}
> 
> 2) If parse with value:
> 	static int
> 	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
> 	{
> 		static struct rte_argparse opts[] = {
> 			.prog = "dma",
> 			.usage = NULL,
> 			.descriptor = "dma and nic fwd example",
> 			.epilog = NULL,
> 			.exit_on_error = true,
> 			.opt = {
> 				{ "--mac-updating", NULL, "Enable MAC addresses updating", NULL, 0, &mac_updating, (void *)1, RTE_ARGPARSE_ARG_NO_VAL },
> 				{ "--no-mac-updating", NULL, "disable MAC addresses updating", NULL, 0, &mac_updating, (void *)0, RTE_ARGPARSE_ARG_NO_VAL },
> 				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", NULL, 0, &dma_enabled_port_mask, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
> 				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
> 			}
> 		};
> 		int ret;
> 		ret = rte_argparse_parse(opts, argc, argv);
> 		if (ret != 0)
> 			return ret;
> 		if (dma_enabled_port_mask & ~default_port_mask ||
> 					dma_enabled_port_mask <= 0) {
> 			...
> 		}
> 	}
> 
> 3) Also could mix parse with func and with value.
> 
> [1] https://patchwork.dpdk.org/project/dpdk/patch/20231105054539.22303-2-fengchengwen@huawei.com/
> 
> Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
> ---

Need tests and more detailed man page.
Maybe convert one of the existing examples.

Can it be used in nested fashion for kvargs? 
The existing kvargs syntax is awkward, would be nice to fix/change that but would
cause lots of arguments :-)
  
fengchengwen Nov. 22, 2023, 6:28 a.m. UTC | #2
Hi Stephen,

On 2023/11/22 0:36, Stephen Hemminger wrote:
> On Tue, 21 Nov 2023 12:26:51 +0000
> Chengwen Feng <fengchengwen@huawei.com> wrote:
> 
>> Introduce argparse library (which was inspired by the thread [1]),
>> compared with getopt, the argparse has following advantages:
>> 1) Set the help information when defining parameters.
>> 2) Support positional parameters.
>>
>> The parameters parsing according following:
>> 1) positional: use callback to parse (passed the long-name as the key
>>    for callback).
>> 2) optional:
>>    In addition to callback to parse, but also support:
>> 2.1) no-val: support set default value to saver.
>> 2.2) has-val: support set value to saver, the value must be conform
>>               RTE_ARGPARSE_ARG_VAL_xxx.
>> 2.3) opt-val: if current without value then treat as no-val, else could
>>               treat as has-val.
>>
>> Examples: (take dmafwd as example):
>> 1) If parse with callback:
>> 	static int
>> 	func(const char *key, const char *value, const char *opaque)
>> 	{
>> 		if (!strcmp("--mac-updating", key)) {
>> 			mac_updating = 1;
>> 		} else if (!strcmp("--no-mac-updating", key)) {
>> 			mac_updating = 0;
>> 		} else if (!strcmp("--portmask", key)) {
>> 			dma_enabled_port_mask = dma_parse_portmask(optarg);
>> 			if (dma_enabled_port_mask & ~default_port_mask ||
>> 						dma_enabled_port_mask <= 0) {
>> 				...
>> 			}
>> 		} else {
>> 			...
>> 		}
>> 	}
>>
>> 	static int
>> 	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
>> 	{
>> 		static struct rte_argparse opts[] = {
>> 			.prog = "dma",
>> 			.usage = NULL,
>> 			.descriptor = "dma and nic fwd example",
>> 			.epilog = NULL,
>> 			.exit_on_error = true,
>> 			.opt = {
>> 				{ "--mac-updating", NULL, "Enable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
>> 				{ "--no-mac-updating", NULL, "disable MAC addresses updating", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_NO_VAL },
>> 				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", func, 0, NULL, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
>> 				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
>> 			}
>> 		};
>> 		return rte_argparse_parse(opts, argc, argv);
>> 	}
>>
>> 2) If parse with value:
>> 	static int
>> 	dma_parse_args(int argc, char **argv, unsigned int nb_ports)
>> 	{
>> 		static struct rte_argparse opts[] = {
>> 			.prog = "dma",
>> 			.usage = NULL,
>> 			.descriptor = "dma and nic fwd example",
>> 			.epilog = NULL,
>> 			.exit_on_error = true,
>> 			.opt = {
>> 				{ "--mac-updating", NULL, "Enable MAC addresses updating", NULL, 0, &mac_updating, (void *)1, RTE_ARGPARSE_ARG_NO_VAL },
>> 				{ "--no-mac-updating", NULL, "disable MAC addresses updating", NULL, 0, &mac_updating, (void *)0, RTE_ARGPARSE_ARG_NO_VAL },
>> 				{ "--portmask", "-p", "hexadecimal bitmask of ports to configure", NULL, 0, &dma_enabled_port_mask, NULL, RTE_ARGPARSE_ARG_HAS_VAL },
>> 				{ NULL, NULL, NULL, NULL, 0, NULL, NULL, 0}
>> 			}
>> 		};
>> 		int ret;
>> 		ret = rte_argparse_parse(opts, argc, argv);
>> 		if (ret != 0)
>> 			return ret;
>> 		if (dma_enabled_port_mask & ~default_port_mask ||
>> 					dma_enabled_port_mask <= 0) {
>> 			...
>> 		}
>> 	}
>>
>> 3) Also could mix parse with func and with value.
>>
>> [1] https://patchwork.dpdk.org/project/dpdk/patch/20231105054539.22303-2-fengchengwen@huawei.com/
>>
>> Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
>> ---
> 
> Need tests and more detailed man page.
> Maybe convert one of the existing examples.

Should add now ?
I prefer wait TB decide to accept it before starting it.

> 
> Can it be used in nested fashion for kvargs? 

I planed to use kvargs inner to implement the argparse library.

> The existing kvargs syntax is awkward, would be nice to fix/change that but would
> cause lots of arguments :-)

Yes, I try to fix/change by two different ways but no progress:
1) fix the wrong usage, which involve many drivers.
2) add one new API.

Maybe we should keep kvargs as it is.

> 
> .
>
  
Stephen Hemminger Jan. 24, 2024, 3:54 p.m. UTC | #3
On Tue, 21 Nov 2023 12:26:51 +0000
Chengwen Feng <fengchengwen@huawei.com> wrote:

> Introduce argparse library (which was inspired by the thread [1]),
> compared with getopt, the argparse has following advantages:
> 1) Set the help information when defining parameters.
> 2) Support positional parameters.
> 
> The parameters parsing according following:
> 1) positional: use callback to parse (passed the long-name as the key
>    for callback).
> 2) optional:
>    In addition to callback to parse, but also support:
> 2.1) no-val: support set default value to saver.
> 2.2) has-val: support set value to saver, the value must be conform
>               RTE_ARGPARSE_ARG_VAL_xxx.
> 2.3) opt-val: if current without value then treat as no-val, else could
>               treat as has-val.

How compatiable is this with Python or other implementations of argparse
in C?
  
fengchengwen Jan. 25, 2024, 6:31 a.m. UTC | #4
Hi Stephen,

On 2024/1/24 23:54, Stephen Hemminger wrote:
> On Tue, 21 Nov 2023 12:26:51 +0000
> Chengwen Feng <fengchengwen@huawei.com> wrote:
> 
>> Introduce argparse library (which was inspired by the thread [1]),
>> compared with getopt, the argparse has following advantages:
>> 1) Set the help information when defining parameters.
>> 2) Support positional parameters.
>>
>> The parameters parsing according following:
>> 1) positional: use callback to parse (passed the long-name as the key
>>    for callback).
>> 2) optional:
>>    In addition to callback to parse, but also support:
>> 2.1) no-val: support set default value to saver.
>> 2.2) has-val: support set value to saver, the value must be conform
>>               RTE_ARGPARSE_ARG_VAL_xxx.
>> 2.3) opt-val: if current without value then treat as no-val, else could
>>               treat as has-val.
> 
> How compatiable is this with Python or other implementations of argparse
> in C?

This library is a subset of Python argparse, and it don't support some advanced
features, such as: subcommand, exclusive group. We could extend it to support
if needed.

As for other implementation of argparse in C, I found a interesting site [1],
this library supports all features except the compact/order/wchar.

[1] https://attractivechaos.wordpress.com/2018/08/31/a-survey-of-argument-parsing-libraries-in-c-c/

Thanks

> 
> .
>
  
Stephen Hemminger Jan. 26, 2024, 4:38 p.m. UTC | #5
On Thu, 25 Jan 2024 14:31:03 +0800
fengchengwen <fengchengwen@huawei.com> wrote:

> Hi Stephen,
> 
> On 2024/1/24 23:54, Stephen Hemminger wrote:
> > On Tue, 21 Nov 2023 12:26:51 +0000
> > Chengwen Feng <fengchengwen@huawei.com> wrote:
> >   
> >> Introduce argparse library (which was inspired by the thread [1]),
> >> compared with getopt, the argparse has following advantages:
> >> 1) Set the help information when defining parameters.
> >> 2) Support positional parameters.
> >>
> >> The parameters parsing according following:
> >> 1) positional: use callback to parse (passed the long-name as the key
> >>    for callback).
> >> 2) optional:
> >>    In addition to callback to parse, but also support:
> >> 2.1) no-val: support set default value to saver.
> >> 2.2) has-val: support set value to saver, the value must be conform
> >>               RTE_ARGPARSE_ARG_VAL_xxx.
> >> 2.3) opt-val: if current without value then treat as no-val, else could
> >>               treat as has-val.  
> > 
> > How compatiable is this with Python or other implementations of argparse
> > in C?  
> 
> This library is a subset of Python argparse, and it don't support some advanced
> features, such as: subcommand, exclusive group. We could extend it to support
> if needed.
> 
> As for other implementation of argparse in C, I found a interesting site [1],
> this library supports all features except the compact/order/wchar.
> 
> [1] https://attractivechaos.wordpress.com/2018/08/31/a-survey-of-argument-parsing-libraries-in-c-c/


I was looking at https://github.com/cofyc/argparse?tab=readme-ov-file

One good thing there is that argparse options can be defined in array.
Like:
    struct argparse_option options[] = {
        OPT_HELP(),
        OPT_GROUP("Basic options"),
        OPT_BOOLEAN('f', "force", &force, "force to do", NULL, 0, 0),
        OPT_BOOLEAN('t', "test", &test, "test only", NULL, 0, 0),
        OPT_STRING('p', "path", &path, "path to read", NULL, 0, 0),
        OPT_INTEGER('i', "int", &int_num, "selected integer", NULL, 0, 0),
        OPT_FLOAT('s', "float", &flt_num, "selected float", NULL, 0, 0),
        OPT_GROUP("Bits options"),
        OPT_BIT(0, "read", &perms, "read perm", NULL, PERM_READ, OPT_NONEG),
        OPT_BIT(0, "write", &perms, "write perm", NULL, PERM_WRITE, 0),
        OPT_BIT(0, "exec", &perms, "exec perm", NULL, PERM_EXEC, 0),
        OPT_END(),
    };
  
Thomas Monjalon Feb. 14, 2024, 4:53 p.m. UTC | #6
26/01/2024 07:10, Chengwen Feng:
> Introduce argparse library (which was inspired by the thread [1]),
> compared with getopt, it makes it easy to write user-friendly
> command-like program.
> 
> Note: the 2nd commit contains usage examples.
> 
> [1] https://patchwork.dpdk.org/project/dpdk/patch/20231105054539.22303-2-fengchengwen@huawei.com/
> 
> Chengwen Feng (8):
>   eal: introduce more macro for bit definition
>   argparse: add argparse library
>   argparse: support verify argument config
>   argparse: support parse parameters
>   argparse: provide parsing known type API
>   argparse: support parse unsigned base type
>   argparse: pretty help info
>   examples/dma: replace getopt with argparse

With a bit of doc improvement and tidying, applied, thanks.
  

Patch

diff --git a/lib/argparse/meson.build b/lib/argparse/meson.build
new file mode 100644
index 0000000000..ac4a883b8d
--- /dev/null
+++ b/lib/argparse/meson.build
@@ -0,0 +1,6 @@ 
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 HiSilicon Limited.
+
+headers = files('rte_argparse.h')
+
+deps += ['kvargs']
diff --git a/lib/argparse/rte_argparse.h b/lib/argparse/rte_argparse.h
new file mode 100644
index 0000000000..21157a9436
--- /dev/null
+++ b/lib/argparse/rte_argparse.h
@@ -0,0 +1,139 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 HiSilicon Limited
+ */
+
+#ifndef RTE_ARGPARSE_H
+#define RTE_ARGPARSE_H
+
+/**
+ * @file rte_argparse.h
+ *
+ * This API provides argparse function.
+ *
+ * Compare with getopt, the argparse has following advantages:
+ * 1) Set the help information when defining parameters.
+ * 2) Support positional parameters.
+ *
+ * The parameters parsing according following:
+ * 1) positional: use callback to parse (passed the long-name as the key for
+ *    callback).
+ * 2) optional:
+ *    In addition to callback to parse, but also support:
+ *    2.1) no-val: support set default value to saver.
+ *    2.2) has-val: support set value to saver, the value must be conform
+ *                  RTE_ARGPARSE_ARG_VAL_xxx.
+ *    2.3) opt-val: if current without value then treat as no-val, else could
+ *                  treat as has-val.
+ *
+ */
+
+#include <stdint.h>
+
+#include <rte_kvargs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum rte_argparse_arg_flags {
+	/**
+	 * Bit0-1 represent whether has value
+	 */
+	RTE_ARGPARSE_ARG_NO_VAL = 1u << 0, /**< The arg has no value. */
+	RTE_ARGPARSE_ARG_HAS_VAL = 2u << 0, /**< The arg has value. */
+	RTE_ARGPARSE_ARG_OPT_VAL = 3u << 0, /**< The arg has optional value. */
+
+	/**
+	 * Bit2-4 represent the value type
+	 */
+	RTE_ARGPARSE_ARG_VAL_INT = 1u << 2, /**< The arg's value is int type. */
+	RTE_ARGPARSE_ARG_VAL_FLOAT = 2u << 2, /**< The arg's value is float type. */
+	RTE_ARGPARSE_ARG_VAL_BOOL = 3u << 2, /**< The arg's value is bool type. */
+	RTE_ARGPARSE_ARG_VAL_STRING = 4u << 2, /**< The arg's value is string type. */
+};
+
+/**
+ * A structure used to hold opt config.
+ */
+struct rte_argparse_arg {
+	/**
+	 * The long name of arg:
+	 *   1) If the arg is optional, it must start with '--',
+	 *   2) If it is a positional arg, it must not start with '-'.
+	 * Note: only one '-' will treat as error.
+	 */
+	const char *long_name;
+	/**
+	 * The short name of arg:
+	 *   1) This field could be set only if long_name is optional, and must
+	 *      start with only one '-' and one letter,
+	 *   2) Other case it should be set NULL.
+	 */
+	const char *short_name;
+	/** The help info of arg. */
+	const char *help;
+
+	/*
+	 * Parse the arg's callback, it will be used to parse the arg if
+	 * it is not NULL.
+	 */
+	arg_handler_t callback;
+	/** The opaque which used to invoke callback */
+	void *opaque;
+
+	/*
+	 * The saver for the arg. If not NULL, set value to default_val or
+	 * parse from input.
+	 * Note: the flags of the arg must be RTE_ARGPARSE_VAL_* if this value
+	 * is not NULL.
+	 */
+	void *saver;
+	/*
+	 * Default value for the arg, cover following case:
+	 *   1) The arg don't require value, the saver will set to default_val
+	 *      when option found.
+	 *   2) The arg has option value but don't take value this time, the
+	 *      saver will set to default_val when option found.
+	 */
+	void *default_val;
+
+	/** @see rte_argparse_arg_flags. */
+	uint32_t flags;
+};
+
+/**
+ * A structure used to hold argparse basic info.
+ */
+struct rte_argparse {
+	const char *prog;       /**< Program name */
+	const char *usage;      /**< How to use the program */
+	const char *descriptor; /**< Explain what the program does */
+	const char *epilog;     /**< Text at the bottom of help */
+	bool exit_on_error;     /**< Whether exit when error */
+	struct rte_argparse_arg opt[]; /**< */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Parse parameters
+ *
+ * @param self
+ *   Parser handler.
+ * @param argc
+ *   Parameters count
+ * @param argv
+ *   Array of parameters points.
+ *
+ * @return
+ *   0 on success. Otherwise negative value is returned.
+ */
+__rte_experimental
+int rte_argparse_parse(struct rte_argparse *self, int argc, char **argv);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_ARGPARSE_H */
diff --git a/lib/argparse/version.map b/lib/argparse/version.map
new file mode 100644
index 0000000000..36b0902167
--- /dev/null
+++ b/lib/argparse/version.map
@@ -0,0 +1,7 @@ 
+EXPERIMENTAL  {
+	global:
+
+	rte_argparse_parse;
+
+	local: *;
+};
diff --git a/lib/meson.build b/lib/meson.build
index 6c143ce5a6..cdd2d3c536 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -11,6 +11,7 @@ 
 libraries = [
         'log',
         'kvargs', # eal depends on kvargs
+        'argparse',
         'telemetry', # basic info querying
         'eal', # everything depends on eal
         'ring',