From 507117c964fd49d5b89753a8a6adc7b3a83cf380 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 10:01:27 -0700 Subject: [PATCH 01/11] meson: Add EncodingTest to the Meson definitions --- tests/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/meson.build b/tests/meson.build index 7fd05a4ba..510bfced4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -58,6 +58,7 @@ testnames = [ ['ComplexTypeTest', {}], ['TrueFalseTest', {}], ['OptionGroupTest', {}], + ['EncodingTest', {}], # multi-only ['TimerTest', {}], # link_test From c7673699696d436e91950dde1fc2ec6c1eee40ba Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 10:08:33 -0700 Subject: [PATCH 02/11] azure-pipelines: use `meson setup $builddir` instead of `meson $builddir` The latter has been deprecated due to it's ambiguity. --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 647c7982b..1c5fbc1d8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -100,7 +100,7 @@ jobs: displayName: generate test directories - script: ln -s "$(pwd)" tests/mesonTest/subprojects/CLI11 displayName: generate CLI11 symlink - - script: meson build + - script: meson setup build displayName: Run meson to generate build workingDirectory: tests/mesonTest - script: ninja -C tests/mesonTest/build From 400cb8d440df04957079bcb1394ed17e4f9c287d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 10:18:59 -0700 Subject: [PATCH 03/11] tests: Remove 'c' language from Meson test It's not used. --- tests/mesonTest/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mesonTest/meson.build b/tests/mesonTest/meson.build index 56ebadb65..409829c9e 100644 --- a/tests/mesonTest/meson.build +++ b/tests/mesonTest/meson.build @@ -1,4 +1,4 @@ -project('mesonTest', ['c', 'cpp'], default_options: ['cpp_std=c++11']) +project('mesonTest', ['cpp'], default_options: ['cpp_std=c++11']) cli11_dep = subproject('CLI11').get_variable('CLI11_dep') From 0914fec115db3d99f72059def0bf25b8ec80f13f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 10:14:39 -0700 Subject: [PATCH 04/11] CI: use the modern Meson `dependency()` method for subprojects This models the upstream recommendation that consumers avoid the `subproject('CLI11').get_variable('dep_cli11')` pattern, and instead simply use `dependency('CLI11')`. This allows build scripts to switch between system provided dependencies found with pkg-config or cmake, and subprojects configured and built with the main project without modification to the build scripts. Users can use the Meson options `--wrap-mode` and `--force-fallback-for` to get the behavior that they want. I have added the `--force-fallback-for=CLI11` switch to the CI to ensure that the test continues to exercise what it's intended to. --- azure-pipelines.yml | 3 ++- tests/mesonTest/meson.build | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1c5fbc1d8..c2cbb7a55 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -100,7 +100,8 @@ jobs: displayName: generate test directories - script: ln -s "$(pwd)" tests/mesonTest/subprojects/CLI11 displayName: generate CLI11 symlink - - script: meson setup build + # Ensure that Meson doesn't use cmake or pkgconfig to find CLI11 + - script: meson setup build --force-fallback-for=CLI11 displayName: Run meson to generate build workingDirectory: tests/mesonTest - script: ninja -C tests/mesonTest/build diff --git a/tests/mesonTest/meson.build b/tests/mesonTest/meson.build index 409829c9e..9fa9d385a 100644 --- a/tests/mesonTest/meson.build +++ b/tests/mesonTest/meson.build @@ -1,5 +1,5 @@ project('mesonTest', ['cpp'], default_options: ['cpp_std=c++11']) -cli11_dep = subproject('CLI11').get_variable('CLI11_dep') +cli11_dep = dependency('CLI11') mainExe = executable('main', ['main.cpp'], dependencies: [cli11_dep]) From 3b7c8dd7c37ff932b933f9e12266ce1cd180c50a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 12:00:00 -0700 Subject: [PATCH 05/11] meson: Add support for single header file mode This should be a replica of what the CMake does --- include/CLI/meson.build | 46 +++++++++++++++++++++++++++++++++++++++++ meson.build | 11 ++++++++++ meson_options.txt | 1 + 3 files changed, 58 insertions(+) create mode 100644 include/CLI/meson.build diff --git a/include/CLI/meson.build b/include/CLI/meson.build new file mode 100644 index 000000000..f6fa01dd0 --- /dev/null +++ b/include/CLI/meson.build @@ -0,0 +1,46 @@ +# Because Meson does not allow outputs to be placed in subfolders, we must have +# meson.build here when generating the single file header so that it is placced +# in the correct location. + +prog_python = find_program('python') + +cli11_headers = files( + 'App.hpp', + 'Argv.hpp', + 'CLI.hpp', + 'Config.hpp', + 'ConfigFwd.hpp', + 'Encoding.hpp', + 'Error.hpp', + 'Formatter.hpp', + 'FormatterFwd.hpp', + 'Macros.hpp', + 'Option.hpp', + 'Split.hpp', + 'StringTools.hpp', + 'TypeTools.hpp', + 'Validators.hpp', + 'Version.hpp', +) + +cli11_impl_headers = files( + 'impl/App_inl.hpp', + 'impl/Argv_inl.hpp', + 'impl/Config_inl.hpp', + 'impl/Encoding_inl.hpp', + 'impl/Formatter_inl.hpp', + 'impl/Option_inl.hpp', + 'impl/Split_inl.hpp', + 'impl/StringTools_inl.hpp', + 'impl/Validators_inl.hpp', +) + +single_main_file = files('../../CLI11.hpp.in') + +single_header = custom_target( + 'CLI11.hpp', + input: [files('../../scripts/MakeSingleHeader.py'), cli11_headers, cli11_impl_headers], + output: 'CLI11.hpp', + command : [prog_python, '@INPUT@', '--main', single_main_file, '--output', '@OUTPUT@'], + depend_files: [single_main_file], +) diff --git a/meson.build b/meson.build index 1b6d98e9b..6c64e63a8 100644 --- a/meson.build +++ b/meson.build @@ -7,9 +7,20 @@ project('CLI11', ['cpp'], cxx = meson.get_compiler('cpp') +if get_option('single-file-header') + subdir('include/CLI') +else + # the `declare_dependency` needs to have the single_header source as a source + # dependency, to ensure that the generator runs before any attempts to include + # the header happen. Adding an empty list is an idiomatic way to ensure the + # variable exists but does nothing + single_header = [] +endif + CLI11_inc = include_directories(['include']) CLI11_dep = declare_dependency( + sources : single_header, include_directories : CLI11_inc, version : meson.project_version(), ) diff --git a/meson_options.txt b/meson_options.txt index dd4654d48..6545ec51a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1 +1,2 @@ option('tests', type: 'boolean', value: false, description: 'Build CLI11 tests') +option('single-file-header', type: 'boolean', value: false, description : 'Generate a single header file.') From 47778f855740e29aaaf3c7192f084af6c4ffb6b3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 12:21:02 -0700 Subject: [PATCH 06/11] meson: Add option to build pre-compiled Tries to match the CMake behavior. It does fail in the Helper tests, but I was unable to get CMake to build the pre-compiled configuration at all. --- include/CLI/meson.build | 22 +++++++++++++++------- meson.build | 41 ++++++++++++++++++++++++++--------------- meson_options.txt | 1 + 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/include/CLI/meson.build b/include/CLI/meson.build index f6fa01dd0..1084872df 100644 --- a/include/CLI/meson.build +++ b/include/CLI/meson.build @@ -37,10 +37,18 @@ cli11_impl_headers = files( single_main_file = files('../../CLI11.hpp.in') -single_header = custom_target( - 'CLI11.hpp', - input: [files('../../scripts/MakeSingleHeader.py'), cli11_headers, cli11_impl_headers], - output: 'CLI11.hpp', - command : [prog_python, '@INPUT@', '--main', single_main_file, '--output', '@OUTPUT@'], - depend_files: [single_main_file], -) +if use_single_header + single_header = custom_target( + 'CLI11.hpp', + input: [files('../../scripts/MakeSingleHeader.py'), cli11_headers, cli11_impl_headers], + output: 'CLI11.hpp', + command : [prog_python, '@INPUT@', '--main', single_main_file, '--output', '@OUTPUT@'], + depend_files: [single_main_file], + ) +else + # the `declare_dependency` needs to have the single_header source as a source + # dependency, to ensure that the generator runs before any attempts to include + # the header happen. Adding an empty list is an idiomatic way to ensure the + # variable exists but does nothing + single_header = [] +endif diff --git a/meson.build b/meson.build index 6c64e63a8..9adf7c37a 100644 --- a/meson.build +++ b/meson.build @@ -7,20 +7,37 @@ project('CLI11', ['cpp'], cxx = meson.get_compiler('cpp') -if get_option('single-file-header') - subdir('include/CLI') -else - # the `declare_dependency` needs to have the single_header source as a source - # dependency, to ensure that the generator runs before any attempts to include - # the header happen. Adding an empty list is an idiomatic way to ensure the - # variable exists but does nothing - single_header = [] +use_single_header = get_option('single-file-header') +use_precompiled = get_option('precompiled') + +if use_precompiled and use_single_header + error('Options "single-file"header" and "precompiled" are mutually exclusive') endif +subdir('include/CLI') + CLI11_inc = include_directories(['include']) +warnings = ['-Wshadow', '-Wsign-conversion', '-Wswitch-enum'] +if cxx.get_id() == 'gcc' and cxx.version().version_compare('>=4.9') + warnings += '-Weffc++' +endif +add_project_arguments(cxx.get_supported_arguments(warnings), language: 'cpp') + +if use_precompiled + libcli11 = static_library( + 'CLI11', + 'src/Precompile.cpp', + include_directories : CLI11_inc, + cpp_args : ['-DCLI11_COMPILE'], + ) +else + libcli11 = [] +endif + CLI11_dep = declare_dependency( sources : single_header, + link_with : libcli11, include_directories : CLI11_inc, version : meson.project_version(), ) @@ -28,11 +45,5 @@ CLI11_dep = declare_dependency( meson.override_dependency('CLI11', CLI11_dep) if get_option('tests') - warnings = ['-Wshadow', '-Wsign-conversion', '-Wswitch-enum'] - if cxx.get_id() == 'gcc' and cxx.version().version_compare('>=4.9') - warnings += '-Weffc++' - endif - add_project_arguments(cxx.get_supported_arguments(warnings), language: 'cpp') - - subdir('tests') + subdir('tests') endif diff --git a/meson_options.txt b/meson_options.txt index 6545ec51a..f32583d87 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,3 @@ option('tests', type: 'boolean', value: false, description: 'Build CLI11 tests') option('single-file-header', type: 'boolean', value: false, description : 'Generate a single header file.') +option('precompiled', type: 'boolean', value: false, description : 'Generate a precompiled static library instead of a header-only') From f70c6f118a7dfa22987b2d3cfa6dba85bea675da Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 12:24:36 -0700 Subject: [PATCH 07/11] Meson: Add clang specific warnings --- meson.build | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/meson.build b/meson.build index 9adf7c37a..bb0480465 100644 --- a/meson.build +++ b/meson.build @@ -22,6 +22,16 @@ warnings = ['-Wshadow', '-Wsign-conversion', '-Wswitch-enum'] if cxx.get_id() == 'gcc' and cxx.version().version_compare('>=4.9') warnings += '-Weffc++' endif +if cxx.get_id() == 'clang' + warnings += [ + '-Wcast-align', + '-Wimplicit-atomic-properties', + '-Wmissing-declarations', + '-Woverlength-strings', + '-Wstrict-selector-match', + '-Wundeclared-selector', + ] +endif add_project_arguments(cxx.get_supported_arguments(warnings), language: 'cpp') if use_precompiled From 71bd9bf1fb981c0d80147eea57e19bf394460995 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 13:04:47 -0700 Subject: [PATCH 08/11] book/installation: move GloalHeaders into CMake support Since this section is still about CMake --- book/chapters/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/chapters/installation.md b/book/chapters/installation.md index e1678a523..22c3dad33 100644 --- a/book/chapters/installation.md +++ b/book/chapters/installation.md @@ -51,7 +51,7 @@ If the CMake option `CLI11_PRECOMPILED` is set then the library is compiled into a static library. This can be used to improve compile times if CLI11 is included in many different parts of a project. -### Global Headers +#### Global Headers Use `CLI/*.hpp` files stored in a shared folder. You could check out the git repository to a system-wide folder, for example `/opt/`. With CMake, you could From 74b47a5d232812a3bef951505d4df6c7b19d5f3b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 20 Mar 2024 13:42:28 -0700 Subject: [PATCH 09/11] book/installation: Add installation instructions with Meson --- book/chapters/installation.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/book/chapters/installation.md b/book/chapters/installation.md index 22c3dad33..c51b1a66d 100644 --- a/book/chapters/installation.md +++ b/book/chapters/installation.md @@ -194,6 +194,32 @@ default to off if CLI11 is used as a subdirectory in another project. nothing special about this container. Alpine is being used because it is small, modern, and fast. Commands are similar on any other platform. +## Meson support + +### Global Headers from pkg-config + +If CLI11 is installed globally, then nothing more than `dependency('CLI11')` is +required. If it installed in a non-default search path, then setting the +`PKG_CONFIG_PATH` environment variable of the `--pkg-config-path` option to +`meson setup` is all that's required. + +### Using Meson's subprojects + +Meson has a system called +[wraps](https://mesonbuild.com/Wrap-dependency-system-manual.html), which +allow Meson to fetch sources, configure, and build dependencies as part of a +main project. This is the mechanism that Meson recommends for projects to use, +as it allows updating the dependency transparently, and allows packagers to have +fine grained control on the use of subprojects vs system provided dependencies. +Simply run `meson wrap install cli11` to install the `cli11.wrap` file, and +commit it, if desired. + +It is also possible to use git submodules. This is generally discouraged by +Meson upstream, but may be appropriate if a project needs to build with multiple +build systems and wishes to share subprojects between them. As long as the +submodule is in the parent project's subproject directory nothing additional is +needed. + ## Installing cli11 using vcpkg You can download and install cli11 using the From 50cf6825bfd91d3c41ae3ea0b6a3e297a1b94197 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 20:50:59 +0000 Subject: [PATCH 10/11] style: pre-commit.ci fixes --- book/chapters/installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/chapters/installation.md b/book/chapters/installation.md index c51b1a66d..467638a03 100644 --- a/book/chapters/installation.md +++ b/book/chapters/installation.md @@ -206,11 +206,11 @@ required. If it installed in a non-default search path, then setting the ### Using Meson's subprojects Meson has a system called -[wraps](https://mesonbuild.com/Wrap-dependency-system-manual.html), which -allow Meson to fetch sources, configure, and build dependencies as part of a -main project. This is the mechanism that Meson recommends for projects to use, -as it allows updating the dependency transparently, and allows packagers to have -fine grained control on the use of subprojects vs system provided dependencies. +[wraps](https://mesonbuild.com/Wrap-dependency-system-manual.html), which allow +Meson to fetch sources, configure, and build dependencies as part of a main +project. This is the mechanism that Meson recommends for projects to use, as it +allows updating the dependency transparently, and allows packagers to have fine +grained control on the use of subprojects vs system provided dependencies. Simply run `meson wrap install cli11` to install the `cli11.wrap` file, and commit it, if desired. From 8267ddefd61769b1b9fc281890a7c1acdc41db9b Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Wed, 1 May 2024 14:32:04 -0400 Subject: [PATCH 11/11] refactor: use single-include dir Signed-off-by: Henry Schreiner --- meson.build | 33 ++++++++++++++++++- {include/CLI => single-include}/meson.build | 35 ++------------------- 2 files changed, 34 insertions(+), 34 deletions(-) rename {include/CLI => single-include}/meson.build (52%) diff --git a/meson.build b/meson.build index bb0480465..004bd615c 100644 --- a/meson.build +++ b/meson.build @@ -14,7 +14,38 @@ if use_precompiled and use_single_header error('Options "single-file"header" and "precompiled" are mutually exclusive') endif -subdir('include/CLI') +cli11_headers = files( + 'include/CLI/App.hpp', + 'include/CLI/Argv.hpp', + 'include/CLI/CLI.hpp', + 'include/CLI/Config.hpp', + 'include/CLI/ConfigFwd.hpp', + 'include/CLI/Encoding.hpp', + 'include/CLI/Error.hpp', + 'include/CLI/Formatter.hpp', + 'include/CLI/FormatterFwd.hpp', + 'include/CLI/Macros.hpp', + 'include/CLI/Option.hpp', + 'include/CLI/Split.hpp', + 'include/CLI/StringTools.hpp', + 'include/CLI/TypeTools.hpp', + 'include/CLI/Validators.hpp', + 'include/CLI/Version.hpp', +) + +cli11_impl_headers = files( + 'include/CLI/impl/App_inl.hpp', + 'include/CLI/impl/Argv_inl.hpp', + 'include/CLI/impl/Config_inl.hpp', + 'include/CLI/impl/Encoding_inl.hpp', + 'include/CLI/impl/Formatter_inl.hpp', + 'include/CLI/impl/Option_inl.hpp', + 'include/CLI/impl/Split_inl.hpp', + 'include/CLI/impl/StringTools_inl.hpp', + 'include/CLI/impl/Validators_inl.hpp', +) + +subdir('single-include') CLI11_inc = include_directories(['include']) diff --git a/include/CLI/meson.build b/single-include/meson.build similarity index 52% rename from include/CLI/meson.build rename to single-include/meson.build index 1084872df..ee58adf6f 100644 --- a/include/CLI/meson.build +++ b/single-include/meson.build @@ -4,43 +4,12 @@ prog_python = find_program('python') -cli11_headers = files( - 'App.hpp', - 'Argv.hpp', - 'CLI.hpp', - 'Config.hpp', - 'ConfigFwd.hpp', - 'Encoding.hpp', - 'Error.hpp', - 'Formatter.hpp', - 'FormatterFwd.hpp', - 'Macros.hpp', - 'Option.hpp', - 'Split.hpp', - 'StringTools.hpp', - 'TypeTools.hpp', - 'Validators.hpp', - 'Version.hpp', -) - -cli11_impl_headers = files( - 'impl/App_inl.hpp', - 'impl/Argv_inl.hpp', - 'impl/Config_inl.hpp', - 'impl/Encoding_inl.hpp', - 'impl/Formatter_inl.hpp', - 'impl/Option_inl.hpp', - 'impl/Split_inl.hpp', - 'impl/StringTools_inl.hpp', - 'impl/Validators_inl.hpp', -) - -single_main_file = files('../../CLI11.hpp.in') +single_main_file = files('CLI11.hpp.in') if use_single_header single_header = custom_target( 'CLI11.hpp', - input: [files('../../scripts/MakeSingleHeader.py'), cli11_headers, cli11_impl_headers], + input: [files('../scripts/MakeSingleHeader.py'), cli11_headers, cli11_impl_headers], output: 'CLI11.hpp', command : [prog_python, '@INPUT@', '--main', single_main_file, '--output', '@OUTPUT@'], depend_files: [single_main_file],