diff --git a/README.md b/README.md index f26964c..08c3a4a 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,65 @@ [![clang-tidy](https://github.com/argtable/argtable3/actions/workflows/clang-tidy.yml/badge.svg)](https://github.com/argtable/argtable3/actions/workflows/clang-tidy.yml) [![coverity](https://github.com/argtable/argtable3/actions/workflows/coverity.yml/badge.svg)](https://github.com/argtable/argtable3/actions/workflows/coverity.yml) -[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) +[![coverity](https://github.com/argtable/argtable3/actions/workflows/asan.yml/badge.svg)](https://github.com/argtable/argtable3/actions/workflows/asan.yml) +[![coverity](https://github.com/argtable/argtable3/actions/workflows/valgrind.yml/badge.svg)](https://github.com/argtable/argtable3/actions/workflows/valgrind.yml) Introduction of Argtable3 ========================= -**Argtable3** is an open source ANSI C library that parses GNU-style -command-line options with the `getopt` library. It simplifies command-line -parsing by defining a declarative-style API that you can use to specify what -your command-line syntax looks like. Argtable3 will automatically generate -consistent error handling logic and textual descriptions of the command line -syntax, which are essential but tedious to implement for a robust CLI program. +**Argtable3** is an open-source ANSI C library that simplifies parsing GNU-style +command-line options. It provides a declarative API to define your command-line +syntax, and because it's built on the standard `getopt` library, it ensures 100% +GNU-compliant behavior. Argtable3 automatically generates the error-handling +logic and usage descriptions that are essential for any robust command-line +program, saving you from tedious boilerplate code. Quick Start ----------- -You can embed the amalgamation source files in your projects, add Argtable3 as a -dependency in the vcpkg manifest, install Argtable3 as a system-wide CMake -package, or build the library from release archives. +There are several ways to use Argtable3 in your C/C++ projects: + +- **Embed Amalgamation Source Files**: Download the amalgamation package and + include `argtable3.c` and `argtable3.h` in your project. This is the simplest + and recommended approach. + +- **Use vcpkg**: Add Argtable3 as a dependency in your project's vcpkg manifest + for single-project use, or install it globally with vcpkg for system-wide + access. + +- **Use Meson WrapDB**: Integrate Argtable3 into Meson-based projects using the + Meson WrapDB. + +- **Use Conan**: Add Argtable3 as a dependency in your Conanfile for projects + using Conan package management. + +- **Build from Source**: Download release archives or clone the repository to + build Argtable3 manually. This is ideal for contributors or those needing + custom features. -### Embed Amalgamation Source Files -> We no longer provide the amalgamation source files (`argtable3.c` and -> `argtable3.h`) in the repository. You can get the amalgamation distribution -> either from the release page (`argtable--amalgamation.(zip|tar.gz)`), -> or generate the distribution yourself by using the generator under the `tools` -> directory: -> -> 1. Navigate to the `tools` directory. -> 2. Run `./build dist`, which will generate the distribution under the `/dist` -> directory. +### Embed Amalgamation Source Files -Add `argtable3.c` and `argtable3.h` from the amalgamation distribution to your -projects. This is the simplest and recommended way to use Argtable3: it not only -removes the hassle of building the library, but also allows compilers to do -better inter-procedure optimization. +Download the amalgamation package from the release page and add `argtable3.c` +and `argtable3.h` to your project. This approach is the simplest and recommended +way to use Argtable3, as it eliminates the need to build the library and enables +better inter-procedural optimization by the compiler. -### Install for a Single Project with vcpkg Manifest +### Use vcpkg for a Single Project [vcpkg](https://vcpkg.io) is an open source C/C++ package manager based on -CMake, and it supports certain stable releases of Argtable3. To add the library -to your CMake project, it's recommended to add vcpkg as a submodule to your -project repo and use it to manage project dependencies. All libraries installed -in this way can only be consumed by the project and won't impact other projects -in the system. +CMake, and it supports the latest releases of Argtable3. To add the library to +your CMake project, it's recommended to add vcpkg as a submodule to your project +repo and use it to manage project dependencies. All libraries installed in this +way can only be consumed by the project and won't impact other projects in the +system. If your project is under `D:/projects/demo` and the vcpkg submodule is under `D:/projects/demo/deps/vcpkg`, first you need to add Argtable3 to the manifest, `D:/projects/demo/vcpkg.json`: + ``` { "name": "demo", @@ -69,6 +78,7 @@ To add Argtable3 to your CMake scripts, you need to integrate the local vcpkg to CMake by setting the `CMAKE_TOOLCHAIN_FILE` variable. You also need to link to the static VC runtime (`/MT` or `/MTd`) if you want to use the static library version of Argtable3: + ``` cmake_minimum_required(VERSION 3.18) @@ -89,6 +99,7 @@ endif() Now you can run `cmake` to install Argtable3, configure and generate build scripts, and build the project: + ``` $ mkdir build $ cd build @@ -96,12 +107,13 @@ $ cmake .. -DVCPKG_TARGET_TRIPLET=x64-windows-static $ cmake --build . ``` -### Install for All Projects with vcpkg +### Use vcpkg for All Projects If you want to make Argtable3 available for all projects in the system, you can clone vcpkg to any directory and install packages there. Assuming vcpkg has been cloned in `D:/dev/vcpkg` and the directory has been added to `PATH`, you can install the static library version of Argtable3 in `D:/dev/vcpkg/installed`: + ``` $ vcpkg install argtable3:x64-windows-static ``` @@ -110,6 +122,7 @@ Since each developer may clone vcpkg in a different place, it may not be appropriate to specify the `CMAKE_TOOLCHAIN_FILE` variable in `CMakeLists.txt`. Therefore, you should remove setting the `CMAKE_TOOLCHAIN_FILE` variable in the `CMakeLists.txt` example above, and set the variable in the command line: + ``` $ mkdir build $ cd build @@ -118,264 +131,161 @@ $ cmake --build . ``` -### Build from Release Archives or Source +### Use Meson WrapDB -If none of the methods above suits your needs, or if you want to help developing -Argtable3, you can always build from archives on the release page or from the -repository. +If you are using [Meson](https://mesonbuild.com) as your build system, you can +use the [Meson WrapDB](https://mesonbuild.com/Wrap-dependency-system-manual.html) +to add Argtable3 as a dependency. This allows Meson to manage downloading and +building Argtable3 automatically. -* If you use GCC (Linux, MacOSX, MinGW, Cygwin), run: +First, add the Argtable3 wrap file to your project's `subprojects` directory by +running the following command in your project root: - ``` - $ mkdir build - $ cd build - $ cmake -DCMAKE_BUILD_TYPE=Debug .. - $ make - $ make test - ``` +```bash +$ meson wrap install argtable3 +``` - Makefile-based generators in CMake only support one configuration at a time, - so you need to specify `CMAKE_BUILD_TYPE` to `Debug`, `Release`, `MinSizeRel`, - or `RelWithDebInfo`. To build multiple configurations, you need to create a - build directory for each configuraiton. +Next, declare the dependency in your `meson.build` file. Meson will automatically find the subproject. - Since v3.2.1, CMake scripts will check `BUILD_SHARED_LIBS` and build either - the static library or the dynamic library at a time. `BUILD_SHARED_LIBS` is - `OFF` by default, so if you want to build the dynamic library, you have to set - `BUILD_SHARED_LIBS` to `ON` explicitly: +```meson +# meson.build +project('demo', 'c', version: '0.0.1') - ``` - $ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON .. - ``` +# Find the argtable3 dependency. Meson will find it in the subprojects +# directory via the .wrap file. +argtable3_dep = dependency('argtable3', version: '>=3.3.1') - To cleanup, run `make clean` or remove the build directory: +executable( + 'main', + 'main.c', + dependencies: [argtable3_dep] +) +``` - ``` - $ rm -rf build - ``` +Now you can configure and build your project, and Meson will handle the Argtable3 dependency: -* If you use Microsoft Visual C++ compiler, run: +```bash +meson setup build +meson compile -C build +``` - ``` - $ mkdir build - $ cd build - $ cmake -G "Visual Studio 15 2017 Win64" .. - $ cmake --build . --config Debug - $ ctest -C Debug - ``` - You can also use Visual Studio 2017 IDE to open the generated solution. To - cleanup, just remove the `build` directory. +### Use Conan +If you are using [Conan](https://conan.io) as your package manager, you can add +Argtable3 as a dependency. Argtable3 is available on the [Conan Center +Index](https://conan.io/center/recipes/argtable3). -To build a tagged version, go to the project root directory, and use the -`Makefile` in the project root folder to check out the specified version: +First, create a `conanfile.txt` in your project root with the following content. +This will use the modern `CMakeDeps` and `CMakeToolchain` generators. - ``` - $ make taglist - Available TAGs: - v3.1.1.432a160 - $ make co TAG=v3.1.1.432a160 - $ cd .tags/v3.1.1.432a160 - $ mkdir build - $ cd build - $ cmake .. - $ make - $ make test - ``` +``` +[requires] +argtable3/3.3.1 -You will find the shared library (or Windows DLL), static library, and the -amalgamation distribution under the build directory. +[generators] +CMakeDeps +CMakeToolchain +``` +Next, install the dependencies from your project root. This command will +download the package and generate the necessary CMake integration files in the +`build` directory. -Documentation -------------- +```bash +conan install . --output-folder=build --build=missing -s build_type=Release +``` -To learn how to use the Argtable3 API, you can read the documentation on the web -site, study examples in the `examples` directory, or even check the unit tests -in the `tests` directory. +Now, you can use `find_package` in your `CMakeLists.txt` to find and link +against Argtable3. -To build a local copy of the documentation, you need to install the following -tools: +```cmake +# CMakeLists.txt +cmake_minimum_required(VERSION 3.15) +project(demo C) -* [Sphinx](https://www.sphinx-doc.org): A documentation generator based on the - reStructuredText markup format. -* [Furo Theme](https://pradyunsg.me/furo/quickstart/): A Sphinx theme designed - to look modern and be mobile-friendly. -* [Breathe](https://breathe.readthedocs.io): A bridge between the Sphinx and - Doxygen documentation systems. -* [Doxygen](http://www.doxygen.nl/): A documentation generator for C/C++ - sources. -* [MyST Parser](https://myst-parser.readthedocs.io): A Sphinx extension to parse - MyST, a rich and extensible flavour of Markdown for authoring technical and - scientific documentation. +# Find the package configuration files generated by Conan +find_package(Argtable3 REQUIRED) -Except Doxygen, all the document generation tools are Python-based, so you can -install the tools in a Python virtual environment: +add_executable(main main.c) +# Link the imported target provided by Conan +target_link_libraries(main PRIVATE argtable3::argtable3) ``` -$ python --version -Python 3.11.5 -$ python -m venv .py311 -$ .py311\Scripts\activate.bat +Finally, configure and build your project, making sure to point CMake to the +toolchain file generated by Conan. -(.py311) $ pip install --upgrade sphinx -(.py311) $ pip install --upgrade furo -(.py311) $ pip install --upgrade breathe -(.py311) $ pip install --upgrade myst-parser +```bash +# From your project root +cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release +cmake --build build ``` -After installing the tools, go to the `docs` directory and run the `doxygen` -command to generate the Doxygen XML output, which should be generated in the -`docs/source/xml` directory. Finally, run `make html` to generate the -documentation in the `docs/build/html` directory. -``` -$ cd docs -$ doxygen -$ make html -``` +### Build from Release Archives or Source +If none of the methods above suits your needs, or if you want to help developing +Argtable3, you can always build from archives on the release page or from the +repository. -Unit Tests ----------- +``` +$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug +$ cmake --build build --config Debug +$ ctest --test-dir build -C Debug +``` -Argtable3 is a BSD-licensed open source library, so you can modify the library -anyway you want. However, before committing your code to your own repository or -the Argtable3 official repository, please make sure your changes won't cause any -compiler warning and can pass the unit tests included in the distribution. +Makefile-based generators in CMake only support one configuration at a time, +so you need to specify `CMAKE_BUILD_TYPE` to `Debug`, `Release`, `MinSizeRel`, +or `RelWithDebInfo`. To build multiple configurations, you need to create a +build directory for each configuration. -To build and test each configuration (`Debug`, `Release`, `MinSizeRel`, -`RelWithDebInfo`), you can run CMake and CTest on all supported platforms: +Since v3.2.1, CMake scripts will check `BUILD_SHARED_LIBS` and build either +the static library or the dynamic library at a time. `BUILD_SHARED_LIBS` is +`OFF` by default, so if you want to build the dynamic library, you have to set +`BUILD_SHARED_LIBS` to `ON` explicitly: ``` -$ mkdir build_debug && cd build_debug -$ cmake -DCMAKE_BUILD_TYPE=Debug .. -$ cmake --build . --config Debug -$ ctest -C Debug - -$ cd .. && mkdir build_release && cd build_release -$ cmake -DCMAKE_BUILD_TYPE=Release .. -$ cmake --build . --config Release -$ ctest -C Release - -$ cd .. && mkdir build_minsizerel && cd build_minsizerel -$ cmake -DCMAKE_BUILD_TYPE=MinSizeRel .. -$ cmake --build . --config MinSizeRel -$ ctest -C MinSizeRel - -$ cd .. && mkdir build_relwithdebinfo && cd build_relwithdebinfo -$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .. -$ cmake --build . --config RelWithDebInfo -$ ctest -C RelWithDebInfo +$ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON .. ``` -If you see the following screenshot, you know that some unit tests are broken: +To cleanup, run `make clean` or remove the build directory: ``` -$ make test -Running tests... -Test project ~/Projects/argtable3/build-gcc-release - Start 1: test_shared -1/4 Test #1: test_shared ......................***Failed 0.07 sec - Start 2: test_static -2/4 Test #2: test_static ......................***Failed 0.13 sec - Start 3: test_src -3/4 Test #3: test_src .........................***Failed 0.13 sec - Start 4: test_amalgamation -4/4 Test #4: test_amalgamation ................***Failed 0.14 sec - -0% tests passed, 4 tests failed out of 4 - -Total Test time (real) = 0.48 sec - -The following tests FAILED: - 1 - test_shared (Failed) - 2 - test_static (Failed) - 3 - test_src (Failed) - 4 - test_amalgamation (Failed) -Errors while running CTest -make: *** [Makefile:97: test] Error 8 +$ rm -rf build ``` -To understand which unit tests are broken, you need to run the failed test -programs (based on CuTest) directly: +To build a tagged version, go to the project root directory, and use the +`Makefile` in the project root to check out the specified tag: ``` -$ ./tests/test_shared -....................................................................................... -...................................................................F............. - -There was 1 failure: -1) test_argdstr_basic_001: ~/Projects/argtable3/tests/testargdstr.c:51: assert failed - -!!!FAILURES!!! -Runs: 168 Passes: 167 Fails: 1 +$ make taglist +Available TAGs: +... +v3.3.1 +... +$ make co TAG=v3.3.1 +$ cd .archive/argtable-v3.3.1 +$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug +$ cmake --build build --config Debug +$ ctest --test-dir build -C Debug ``` -Memory Issue Detection with ASan and Valgrind ---------------------------------------------- - -In order to prevent common memory issues in C, such as memory leak and buffer -overflow, we should use [ASan -(AddressSanitizer)](https://en.wikipedia.org/wiki/AddressSanitizer) and -[Valgrind](https://en.wikipedia.org/wiki/Valgrind) to detect as many -memory-related problems as possible before committing our code. - -To use ASan, we need to add `-fsanitize=address` to the `CFLAGS` variable when -we run `cmake` to build the **Debug** version. We should use the Debug version -because CMake will add `-g` to `CFLAGS` and prevent optimizing the code, so we -can see accurate file names and line numbers in ASan error messages. After -building the code, set the `CTEST_OUTPUT_ON_FAILURE` variable to `1` to output -error messages when we run unit tests: +Documentation +------------- -``` -$ mkdir build -$ cd build -$ CFLAGS="-fsanitize=address" cmake -DCMAKE_BUILD_TYPE=Debug .. -$ make -$ CTEST_OUTPUT_ON_FAILURE=1 make test -Running tests... -Test project /home/tomghuang/Projects/argtable3/build - Start 1: test_shared -1/4 Test #1: test_shared ...................... Passed 3.45 sec - Start 2: test_static -2/4 Test #2: test_static ...................... Passed 3.31 sec - Start 3: test_src -3/4 Test #3: test_src ......................... Passed 3.06 sec - Start 4: test_amalgamation -4/4 Test #4: test_amalgamation ................ Passed 3.29 sec - -100% tests passed, 0 tests failed out of 4 - -Total Test time (real) = 13.12 sec -``` +To learn how to use the Argtable3 API: +- Visit the [official documentation](https://www.argtable.org/docs/). +- Explore examples in the `examples` directory. +- Review unit tests in the `tests` directory. -To use Valgrind, just use `valgrind` to run the unit test programs: +To build a local copy of the documentation, make sure you have installed Docker +and run the following command in the repository root. The generated HTML files +will be located in the `docs/build/html` directory. ``` -$ valgrind ./tests/test_src -==23290== Memcheck, a memory error detector -==23290== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. -==23290== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info -==23290== Command: ./test_src -==23290== -...................................................................................... -.................................................................................. - -OK (168 tests) - -==23290== -==23290== HEAP SUMMARY: -==23290== in use at exit: 0 bytes in 0 blocks -==23290== total heap usage: 102,085 allocs, 102,085 frees, 5,589,475 bytes allocated -==23290== -==23290== All heap blocks were freed -- no leaks are possible -==23290== -==23290== For counts of detected and suppressed errors, rerun with: -v -==23290== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +$ make docs ``` @@ -389,8 +299,8 @@ Parts are Copyright (C) 1989-1994, 1996-1999, 2001, 2003 Argtable was written by Stewart Heitmann Argtable is now maintained by Tom G. Huang -The project homepage of argtable 3.x is http://www.argtable.org -The project homepage of argtable 2.x is http://argtable.sourceforge.net/ +The project homepage of Argtable3 is https://www.argtable.org +The project homepage of argtable2 is https://argtable.sourceforge.io Here is a list of contributors who have helped to improve argtable: