diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..ffaf098f6f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,635 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +env: + UBSAN_OPTIONS: print_stacktrace=1 + +jobs: + posix: + strategy: + fail-fast: false + matrix: + include: + - toolset: gcc-4.8 + cxxstd: "11" + container: ubuntu:18.04 + os: ubuntu-latest + install: g++-4.8 + - toolset: gcc-5 + cxxstd: "11,14,1z" + container: ubuntu:18.04 + os: ubuntu-latest + install: g++-5 + - toolset: gcc-6 + cxxstd: "11,14,1z" + container: ubuntu:18.04 + os: ubuntu-latest + install: g++-6 + - toolset: gcc-7 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-7 + - toolset: gcc-8 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-8 + - toolset: gcc-9 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + - toolset: gcc-10 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: g++-10 + - toolset: gcc-11 + cxxstd: "11,14,17,2a" + container: ubuntu:22.04 + os: ubuntu-latest + install: g++-11 + - toolset: gcc-12 + cxxstd: "11,14,17,20,2b" + container: ubuntu:22.04 + os: ubuntu-latest + install: g++-12 + - toolset: gcc-13 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: g++-13 + - toolset: clang + compiler: clang++-3.9 + cxxstd: "11,14" + container: ubuntu:18.04 + os: ubuntu-latest + install: clang-3.9 + - toolset: clang + compiler: clang++-4.0 + cxxstd: "11,14" + container: ubuntu:18.04 + os: ubuntu-latest + install: clang-4.0 + - toolset: clang + compiler: clang++-5.0 + cxxstd: "11,14,1z" + container: ubuntu:18.04 + os: ubuntu-latest + install: clang-5.0 + - toolset: clang + compiler: clang++-6.0 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-6.0 + - toolset: clang + compiler: clang++-7 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-7 + - toolset: clang + compiler: clang++-8 + cxxstd: "11,14,17" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-8 + - toolset: clang + compiler: clang++-9 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-9 + - toolset: clang + compiler: clang++-10 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-10 + - toolset: clang + compiler: clang++-11 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-11 + - toolset: clang + compiler: clang++-12 + cxxstd: "11,14,17,2a" + container: ubuntu:20.04 + os: ubuntu-latest + install: clang-12 + - toolset: clang + compiler: clang++-13 + cxxstd: "11,14,17,20,2b" + container: ubuntu:22.04 + os: ubuntu-latest + install: clang-13 + - toolset: clang + compiler: clang++-14 + cxxstd: "11,14,17,20,2b" + container: ubuntu:22.04 + os: ubuntu-latest + install: clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + container: ubuntu:22.04 + os: ubuntu-latest + install: clang-15 + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-16 + - toolset: clang + compiler: clang++-17 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.10 + os: ubuntu-latest + install: clang-17 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-13 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-14 + - toolset: clang + cxxstd: "11,14,17,20,23" + os: macos-15 + + runs-on: ${{matrix.os}} + container: + image: ${{matrix.container}} + volumes: + - /node20217:/node20217:rw,rshared + - ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }} + + defaults: + run: + shell: bash + + steps: + - name: Install nodejs20glibc2.17 + if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }} + run: | + set -x + apt-get update + apt-get install -y curl xz-utils + curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz + tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217 + + - name: Setup container environment + if: matrix.container + run: | + apt-get update + apt-get -y install sudo python3 git g++ + + - name: Install packages + if: matrix.install + run: | + sudo apt-get update + sudo apt-get -y install ${{matrix.install}} + + - uses: actions/checkout@v4 + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + ./bootstrap.sh + ./b2 -d0 headers + + - name: Create user-config.jam + if: matrix.compiler + run: | + echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam + + - name: Run tests + run: | + cd ../boost-root + ./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release + + windows: + strategy: + fail-fast: false + matrix: + include: + - toolset: msvc-14.0 + cxxstd: "14,latest" + addrmd: 32,64 + os: windows-2019 + - toolset: msvc-14.2 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2019 + - toolset: msvc-14.3 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: clang-win + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: gcc + cxxstd: "11,14,17,2a" + addrmd: 64 + os: windows-2019 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + cmd /c bootstrap + b2 -d0 headers + + - name: Run tests + shell: cmd + run: | + cd ../boost-root + b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker + + posix-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-13 + - os: macos-14 + - os: macos-15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Use library with add_subdirectory + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-13 + - os: macos-14 + - os: macos-15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. + + - name: Install + run: | + cd ../boost-root/__build__ + cmake --build . --target install + + - name: Use the installed library + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=~/.local .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-13 + - os: macos-14 + - os: macos-15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error + + windows-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + - os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Use library with add_subdirectory (Debug) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + + - name: Use library with add_subdirectory (Release) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__ + cmake --build . --config Release + ctest --output-on-failure --no-tests=error -C Release + + windows-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + - os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Configure + shell: cmd + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + + - name: Install (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target install --config Debug + + - name: Install (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target install --config Release + + - name: Use the installed library (Debug) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + + - name: Use the installed library (Release) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__ + cmake --build . --config Release + ctest --output-on-failure --no-tests=error -C Release + + windows-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + - os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Configure + shell: cmd + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON .. + + - name: Build tests (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target tests --config Debug + + - name: Run tests (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error -C Debug + + - name: Build tests (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target tests --config Release + + - name: Run tests (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error -C Release diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..024966ee2b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,62 @@ +# Generated by `boostdep --cmake program_options` +# Copyright 2020, 2021 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.8...3.20) + +project(boost_program_options VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_program_options + src/cmdline.cpp + src/config_file.cpp + src/convert.cpp + src/options_description.cpp + src/parsers.cpp + src/positional_options.cpp + src/split.cpp + src/utf8_codecvt_facet.cpp + src/value_semantic.cpp + src/variables_map.cpp + src/winmain.cpp +) + +add_library(Boost::program_options ALIAS boost_program_options) + +target_include_directories(boost_program_options PUBLIC include) + +target_link_libraries(boost_program_options + PUBLIC + Boost::any + Boost::config + Boost::core + Boost::detail + Boost::function + Boost::iterator + Boost::lexical_cast + Boost::smart_ptr + Boost::throw_exception + Boost::type_traits + PRIVATE + Boost::bind + Boost::tokenizer +) + +target_compile_features(boost_program_options PUBLIC cxx_std_11) + +target_compile_definitions(boost_program_options + PUBLIC BOOST_PROGRAM_OPTIONS_NO_LIB + PRIVATE BOOST_PROGRAM_OPTIONS_SOURCE +) + +if(BUILD_SHARED_LIBS) + target_compile_definitions(boost_program_options PUBLIC BOOST_PROGRAM_OPTIONS_DYN_LINK) +else() + target_compile_definitions(boost_program_options PUBLIC BOOST_PROGRAM_OPTIONS_STATIC_LINK) +endif() + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() diff --git a/Jamfile b/Jamfile deleted file mode 100644 index f0de2e0bc8..0000000000 --- a/Jamfile +++ /dev/null @@ -1,11 +0,0 @@ -# Boost.ProgramOptions Library Jamfile -# -# Copyright (c) 2018 James E. King III -# -# Use, modification, and distribution are subject to the -# Boost Software License, Version 1.0. (See accompanying file -# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -# please order by name to ease maintenance -build-project example ; -build-project test ; diff --git a/README.md b/README.md index b2bd595ed8..202056963e 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ Distributed under the [Boost Software License, Version 1.0](http://www.boost.org |Branch | Travis | Appveyor | codecov.io | Deps | Docs | Tests | |:-------------: | ------ | -------- | ---------- | ---- | ---- | ----- | -|[`master`](https://github.com/boostorg/program_options/tree/master) | [![Build Status](https://travis-ci.org/boostorg/program_options.svg?branch=master)](https://travis-ci.org/boostorg/program_options) | [![Build status](https://ci.appveyor.com/api/projects/status/e0quisadwh1v7ok5/branch/master?svg=true)](https://ci.appveyor.com/project/vprus/program-options/branch/master) | [![codecov](https://codecov.io/gh/boostorg/program_options/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/program_options/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/program_options.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/program_options.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/program_options.html) -|[`develop`](https://github.com/boostorg/program_options/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/program_options.svg?branch=develop)](https://travis-ci.org/boostorg/program_options) | [![Build status](https://ci.appveyor.com/api/projects/status/e0quisadwh1v7ok5/branch/develop?svg=true)](https://ci.appveyor.com/project/vprus/program-options/branch/develop) | [![codecov](https://codecov.io/gh/boostorg/program_options/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/program_options/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/program_options.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/doc/html/program_options.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/program_options.html) +|[`master`](https://github.com/boostorg/program_options/tree/master) | [![Build Status](https://travis-ci.org/boostorg/program_options.svg?branch=master)](https://travis-ci.org/boostorg/program_options) | [![Build status](https://ci.appveyor.com/api/projects/status/e0quisadwh1v7ok5/branch/master?svg=true)](https://ci.appveyor.com/project/vprus/program-options/branch/master) | [![codecov](https://codecov.io/gh/boostorg/program_options/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/program_options/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/program_options.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/program_options.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](https://regression.boost.io/master/developer/program_options.html) +|[`develop`](https://github.com/boostorg/program_options/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/program_options.svg?branch=develop)](https://travis-ci.org/boostorg/program_options) | [![Build status](https://ci.appveyor.com/api/projects/status/e0quisadwh1v7ok5/branch/develop?svg=true)](https://ci.appveyor.com/project/vprus/program-options/branch/develop) | [![codecov](https://codecov.io/gh/boostorg/program_options/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/program_options/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/program_options.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/doc/html/program_options.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](https://regression.boost.io/develop/developer/program_options.html) ### Directories diff --git a/appveyor.yml b/appveyor.yml index df2b856203..dddb3c612c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,78 +1,68 @@ -# Copyright 2016, 2017 Peter Dimov -# Copyright (C) 2017, 2018 James E. King III +# Copyright 2016-2019 Peter Dimov # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) -# When copying this to a new library, be sure to update the name of the library -# in two places (once each at the top of install: and test_script:) - version: 1.0.{build}-{branch} shallow_clone: true branches: only: - - develop - master - -matrix: - allow_failures: - - MAYFAIL: true + - develop + - /feature\/.*/ environment: - global: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - # see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties - # to use the default for a given environment, comment it out; recommend you build debug and release however.. - # on Windows it is important to exercise all the possibilities, especially shared vs static - # B2_ADDRESS_MODEL: address-model=64,32 - # B2_LINK: link=shared,static - # B2_THREADING: threading=multi,single - B2_VARIANT: variant=release,debug - CXXSTD: 03 - matrix: - - FLAVOR: Visual Studio 2017 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + TOOLSET: msvc-14.0 + CXXSTD: 14,latest + ADDRMD: 32,64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 TOOLSET: msvc-14.1 - B2_ADDRESS_MODEL: address-model=64,32 - - FLAVOR: Visual Studio 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - TOOLSET: msvc-12.0 - - FLAVOR: mingw32 - ARCH: i686 - B2_ADDRESS_MODEL: address-model=32 - SCRIPT: ci\mingw.bat - - FLAVOR: mingw64 - ARCH: x86_64 - B2_ADDRESS_MODEL: address-model=64 - SCRIPT: ci\mingw.bat - - FLAVOR: cygwin (64-bit) + CXXSTD: 14,17,latest + ADDRMD: 32,64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: clang-win + CXXSTD: 14,17,latest + ADDRMD: 64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + TOOLSET: clang-win + CXXSTD: 14,17,20,latest + ADDRMD: 64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + ADDPATH: C:\cygwin\bin; + TOOLSET: gcc + CXXSTD: 11,14,1z + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 ADDPATH: C:\cygwin64\bin; - B2_ADDRESS_MODEL: address-model=64 TOOLSET: gcc - MAYFAIL: true - - FLAVOR: cygwin (32-bit) - ADDPATH: C:\cygwin\bin; - B2_ADDRESS_MODEL: address-model=32 + CXXSTD: 11,14,1z + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin; + TOOLSET: gcc + CXXSTD: 11,14,17,2a + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin; TOOLSET: gcc - MAYFAIL: true + CXXSTD: 11,14,17,2a install: - - set SELF=program_options + - set BOOST_BRANCH=develop + - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master - cd .. - - git clone -b %APPVEYOR_REPO_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - - git submodule update -q --init tools/boostdep - - git submodule update -q --init tools/build - - git submodule update -q --init tools/inspect - - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\%SELF% - - python tools/boostdep/depinst/depinst.py --include example %SELF% + - git submodule update --init tools/boostdep + - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\program_options\ + - python tools/boostdep/depinst/depinst.py program_options - cmd /c bootstrap - - b2 headers + - b2 -d0 headers build: off test_script: - - set SELF=program_options - PATH=%ADDPATH%%PATH% - - IF DEFINED SCRIPT (call libs\%SELF%\%SCRIPT%) ELSE (b2 libs/%SELF% toolset=%TOOLSET% cxxstd=%CXXSTD% %CXXFLAGS% %DEFINES% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3) + - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% + - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - b2 -j3 libs/program_options/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release diff --git a/build.jam b/build.jam new file mode 100644 index 0000000000..566b2573ef --- /dev/null +++ b/build.jam @@ -0,0 +1,31 @@ +# Copyright René Ferdinand Rivera Morell 2023-2024 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +require-b2 5.2 ; + +constant boost_dependencies : + /boost/any//boost_any + /boost/config//boost_config + /boost/core//boost_core + /boost/detail//boost_detail + /boost/function//boost_function + /boost/iterator//boost_iterator + /boost/lexical_cast//boost_lexical_cast + /boost/smart_ptr//boost_smart_ptr + /boost/throw_exception//boost_throw_exception + /boost/type_traits//boost_type_traits ; + +project /boost/program_options + ; + +explicit + [ alias boost_program_options : build//boost_program_options ] + [ alias all : boost_program_options example test ] + ; + +call-if : boost-library program_options + : install boost_program_options + ; + diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 852054d017..811a7aff2d 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -1,16 +1,25 @@ -project boost/program_options - : source-location ../src +constant boost_dependencies_private : + /boost/bind//boost_bind + /boost/tokenizer//boost_tokenizer + ; + +project + : source-location ../src + : common-requirements ../include $(boost_dependencies) + : requirements $(boost_dependencies_private) ; SOURCES = - cmdline config_file options_description parsers variables_map + cmdline config_file options_description parsers variables_map value_semantic positional_options utf8_codecvt_facet convert winmain split ; -boost-lib program_options +lib boost_program_options : $(SOURCES).cpp : # See https://svn.boost.org/trac/boost/ticket/5049 hpux,gcc:_INCLUDE_STDC__SOURCE_199901 - ; \ No newline at end of file + shared:BOOST_PROGRAM_OPTIONS_DYN_LINK=1 + BOOST_PROGRAM_OPTIONS_NO_LIB=1 + ; diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 22a680ef7c..616e55267b 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -2,15 +2,15 @@ import toolset ; toolset.using doxygen ; -boostbook program_option - : program_options.xml - : autodoc +boostbook program_option + : program_options.xml + : autodoc boost.root=../../../.. pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html ; -doxygen autodoc - : [ glob ../../../boost/program_options/*.hpp ] ; +doxygen autodoc + : [ glob ../include/boost/program_options/*.hpp ] ; ############################################################################### alias boostdoc diff --git a/doc/acknowledgements.xml b/doc/acknowledgements.xml index e72e33c2f7..1fe0badba6 100644 --- a/doc/acknowledgements.xml +++ b/doc/acknowledgements.xml @@ -8,7 +8,7 @@
Acknowledgements - I'm very gratefull to all the people who helped with the development, + I'm very grateful to all the people who helped with the development, by discussion, fixes, and as users. It was pleasant to see all that involvement, which made the library much better than it would be otherwise. @@ -25,7 +25,7 @@ The formal review lead to numerous comments and enhancements. Pavol Droba helped with the option description semantic. Gennadiy Rozental has criticised many aspects of the library which caused various simplifications. - Pavel Vozenilek did carefull review of the implementation. A number of + Pavel Vozenilek did careful review of the implementation. A number of comments were made by: David Abrahams diff --git a/doc/design.xml b/doc/design.xml index 0881500b0c..85e3fe8939 100644 --- a/doc/design.xml +++ b/doc/design.xml @@ -74,7 +74,7 @@ of the library -- ascii and Unicode. - Another important point is that ascii strings are passed though + Another important point is that ascii strings are passed through without modification. In other words, it's not possible to just convert ascii to Unicode and process the Unicode further. The problem is that the default conversion mechanism -- the codecvt facet -- might @@ -85,7 +85,7 @@ don't support Unicode option names. Unicode support is hard and requires a Boost-wide solution. Even comparing two arbitrary Unicode strings is non-trivial. Finally, using Unicode in option names is - related to internationalization, which has it's own + related to internationalization, which has its own complexities. E.g. if option names depend on current locale, then all program parts and other parts which use the name must be internationalized too. @@ -210,4 +210,4 @@ sgml-parent-document: ("program_options.xml" "section") sgml-set-face: t End: ---> \ No newline at end of file +--> diff --git a/doc/howto.xml b/doc/howto.xml index 0841c9f1e2..0e3b6d655f 100644 --- a/doc/howto.xml +++ b/doc/howto.xml @@ -23,7 +23,7 @@ options groups/hidden options Non-conventional Syntax Sometimes, standard command line syntaxes are not enough. For - example, the gcc compiler has "-frtti" and -fno-rtti" options, and this + example, the gcc compiler has "-frtti" and "-fno-rtti" options, and this syntax is not directly supported. @@ -66,7 +66,7 @@ store(command_line_parser(ac, av).options(desc).extra_parser(reg_foo) response files - Some operating system have very low limits of the command line + Some operating systems have very low limits of the command line length. The common way to work around those limitations is using response files. A response file is just a configuration file which uses the same syntax as the command line. If @@ -304,7 +304,7 @@ void validate(boost::any& v, for the value, and in this case is either empty or contains an instance of the magic_number class. The second is the list of strings found in the next occurrence of the option. The remaining two parameters - are needed to workaround the lack of partial template specialization and + are needed to work around the lack of partial template specialization and partial function template ordering on some compilers. @@ -346,7 +346,7 @@ void validate(boost::any& v, some Unicode-aware options. They are different from ordinary options in that they accept wstring input, and process it using wide character streams. Creating an Unicode-aware option - is easy: just use the the wvalue function instead of the + is easy: just use the wvalue function instead of the regular value. @@ -379,7 +379,7 @@ locale::global(locale("")); implementation, though. The quick test involves three steps: - Go the the "test" directory and build the "test_convert" binary. + Go to the "test" directory and build the "test_convert" binary. Set some non-ascii locale in the environment. On Linux, one can diff --git a/doc/overview.xml b/doc/overview.xml index 52fe9b9865..ab1b733b70 100644 --- a/doc/overview.xml +++ b/doc/overview.xml @@ -50,7 +50,7 @@ provides a class which stores all option values and that class can be freely passed around your program to modules which need access to the options. All the other components can be used only in the place where - the actual parsing is the done. However, it might also make sense for the + the actual parsing is done. However, it might also make sense for the individual program modules to describe their options and pass them to the main module, which will merge all options. Of course, this is only important when the number of options is large and declaring them in one @@ -185,9 +185,9 @@ desc.add_options() ("email", value<string>()->multitoken(), "email to send to") ; - For the first parameter, we specify only the name and the + For the first option, we specify only the name and the description. No value can be specified in the parsed source. - For the first option, the user must specify a value, using a single + For the second option, the user must specify a value, using a single token. For the third option, the user may either provide a single token for the value, or no token at all. For the last option, the value can span several tokens. For example, the following command line is OK: @@ -208,7 +208,7 @@ desc.add_options() The description string has one or more paragraphs, separated by the newline character ('\n'). When an option is output, the library will compute the indentation for options's description. Each of the - paragraph is output as a separate line with that intentation. If + paragraph is output as a separate line with that indentation. If a paragraph does not fit on one line it is spanned over multiple lines (which will have the same indentation). @@ -538,7 +538,7 @@ desc.add_options() The environment variables can be parsed with the - &parse_environment; function. The function have several overloaded + &parse_environment; function. The function has several overloaded versions. The first parameter is always an &options_description; instance, and the second specifies what variables must be processed, and what option names must correspond to it. To describe the second @@ -546,13 +546,13 @@ desc.add_options() variables. If you have an option that should be specified via environment - variable, you need make up the variable's name. To avoid name clashes, + variable, you need to make up the variable's name. To avoid name clashes, we suggest that you use a sufficiently unique prefix for environment variables. Also, while option names are most likely in lower case, environment variables conventionally use upper case. So, for an option name proxy the environment variable might be called BOOST_PROXY. During parsing, we need to perform reverse - conversion of the names. This is accomplished by passing the choosen + conversion of the names. This is accomplished by passing the chosen prefix as the second parameter of the &parse_environment; function. Say, if you pass BOOST_ as the prefix, and there are two variables, CVSROOT and BOOST_PROXY, the @@ -588,7 +588,7 @@ desc.add_options() representations that are available in C++ literals are not supported by lexical_cast, and thus will not work with program_options. - Booleans a special in that there are multiple ways to come at them. + Booleans are special in that there are multiple ways to come at them. Similar to another value type, it can be specified as ("my-option", value<bool>()), and then set as: @@ -648,7 +648,7 @@ example --other-switch &parse_command_line; - parses command line (simpified interface) + parses command line (simplified interface) diff --git a/doc/program_options.xml b/doc/program_options.xml index cd879f7d65..c9455683be 100644 --- a/doc/program_options.xml +++ b/doc/program_options.xml @@ -70,7 +70,7 @@ - Now let's see some examples of the library usage in the . diff --git a/include/boost/program_options.hpp b/include/boost/program_options.hpp index dc35011957..46e1b7d3a5 100644 --- a/include/boost/program_options.hpp +++ b/include/boost/program_options.hpp @@ -5,8 +5,8 @@ // See www.boost.org/libs/program_options for documentation. -#ifndef PROGRAM_OPTIONS_VP_2003_05_19 -#define PROGRAM_OPTIONS_VP_2003_05_19 +#ifndef BOOST_PROGRAM_OPTIONS_VP_2003_05_19 +#define BOOST_PROGRAM_OPTIONS_VP_2003_05_19 #if defined(_MSC_VER) #pragma once @@ -22,4 +22,4 @@ #include #include -#endif +#endif // BOOST_PROGRAM_OPTIONS_VP_2003_05_19 diff --git a/include/boost/program_options/cmdline.hpp b/include/boost/program_options/cmdline.hpp index 8705e60f21..8b57819d85 100644 --- a/include/boost/program_options/cmdline.hpp +++ b/include/boost/program_options/cmdline.hpp @@ -9,7 +9,7 @@ namespace boost { namespace program_options { namespace command_line_style { /** Various possible styles of options. - There are "long" options, which start with "--" and "short", + There are "long" options, which start with "--", and "short", which start with either "-" or "/". Both kinds can be allowed or disallowed, see allow_long and allow_short. The allowed character for short options is also configurable. @@ -51,7 +51,7 @@ namespace boost { namespace program_options { namespace command_line_style { /** Allow to merge several short options together, so that "-s -k" become "-sk". All of the options but last should accept no parameter. For example, if - "-s" accept a parameter, then "k" will be taken as + "-s" accepts a parameter, then "k" will be taken as parameter, not another short option. Dos-style short options cannot be sticky. */ diff --git a/include/boost/program_options/config.hpp b/include/boost/program_options/config.hpp index 8b70521741..69141726b9 100644 --- a/include/boost/program_options/config.hpp +++ b/include/boost/program_options/config.hpp @@ -48,5 +48,5 @@ #endif -#endif // PROGRAM_OPTIONS_CONFIG_HK_2004_01_11 +#endif // BOOST_PROGRAM_OPTIONS_CONFIG_HK_2004_01_11 diff --git a/include/boost/program_options/detail/config_file.hpp b/include/boost/program_options/detail/config_file.hpp index be6bba1447..808bec7f1d 100644 --- a/include/boost/program_options/detail/config_file.hpp +++ b/include/boost/program_options/detail/config_file.hpp @@ -76,7 +76,7 @@ namespace boost { namespace program_options { namespace detail { const std::set& allowed_options, bool allow_unregistered = false); - virtual ~common_config_file_iterator() {} + BOOST_DEFAULTED_FUNCTION(virtual ~common_config_file_iterator(), {}) public: // Method required by eof_iterator diff --git a/include/boost/program_options/detail/parsers.hpp b/include/boost/program_options/detail/parsers.hpp index b644aaa176..cdda539cae 100644 --- a/include/boost/program_options/detail/parsers.hpp +++ b/include/boost/program_options/detail/parsers.hpp @@ -24,7 +24,7 @@ namespace boost { namespace program_options { basic_command_line_parser:: basic_command_line_parser(int argc, const charT* const argv[]) : detail::cmdline( - to_internal(std::vector >(argv+1, argv+argc))), + to_internal(std::vector >(argc ? argv+1 : argv, argv+argc))), m_desc() {} diff --git a/include/boost/program_options/detail/value_semantic.hpp b/include/boost/program_options/detail/value_semantic.hpp index 9531339a34..27b7c241b5 100644 --- a/include/boost/program_options/detail/value_semantic.hpp +++ b/include/boost/program_options/detail/value_semantic.hpp @@ -8,18 +8,24 @@ #include +#ifndef BOOST_NO_CXX17_HDR_OPTIONAL +# include +#endif + // forward declaration namespace boost { template class optional; } namespace boost { namespace program_options { - extern BOOST_PROGRAM_OPTIONS_DECL std::string arg; + namespace detail { + extern BOOST_PROGRAM_OPTIONS_DECL std::string arg; + } template std::string typed_value::name() const { - std::string const& var = (m_value_name.empty() ? arg : m_value_name); + std::string const& var = (m_value_name.empty() ? detail::arg : m_value_name); if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) { std::string msg = "[=" + var + "(=" + m_implicit_value_as_text + ")]"; if (!m_default_value.empty() && !m_default_value_as_text.empty()) @@ -146,7 +152,7 @@ namespace boost { namespace program_options { boost::any a; std::vector > cv; cv.push_back(s[i]); - validate(a, cv, (T*)0, 0); + validate(a, cv, static_cast(nullptr), 0); tv->push_back(boost::any_cast(a)); } catch(const bad_lexical_cast& /*e*/) { @@ -165,10 +171,26 @@ namespace boost { namespace program_options { validators::check_first_occurrence(v); validators::get_single_string(s); boost::any a; - validate(a, s, (T*)0, 0); + validate(a, s, static_cast(nullptr), 0); v = boost::any(boost::optional(boost::any_cast(a))); } +#ifndef BOOST_NO_CXX17_HDR_OPTIONAL + /** Validates std::optional arguments. */ + template + void validate(boost::any& v, + const std::vector >& s, + std::optional*, + int) + { + validators::check_first_occurrence(v); + validators::get_single_string(s); + boost::any a; + validate(a, s, static_cast(nullptr), 0); + v = boost::any(std::optional(boost::any_cast(a))); + } +#endif + template void typed_value:: @@ -181,7 +203,7 @@ namespace boost { namespace program_options { if (new_tokens.empty() && !m_implicit_value.empty()) value_store = m_implicit_value; else - validate(value_store, new_tokens, (T*)0, 0); + validate(value_store, new_tokens, static_cast(nullptr), 0); } template diff --git a/include/boost/program_options/eof_iterator.hpp b/include/boost/program_options/eof_iterator.hpp index 5e53df5b81..c95d27f6b6 100644 --- a/include/boost/program_options/eof_iterator.hpp +++ b/include/boost/program_options/eof_iterator.hpp @@ -11,12 +11,12 @@ namespace boost { /** The 'eof_iterator' class is useful for constructing forward iterators - in cases where iterator extract data from some source and it's easy + in cases where the iterator extracts data from some source and it's easy to detect 'eof' \-- i.e. the situation where there's no data. One apparent example is reading lines from a file. Implementing such iterators using 'iterator_facade' directly would - require to create class with three core operation, a couple of + require to create class with three core operations, a couple of constructors. When using 'eof_iterator', the derived class should define only one method to get new value, plus a couple of constructors. diff --git a/include/boost/program_options/errors.hpp b/include/boost/program_options/errors.hpp index 6f3da0db1e..953db13667 100644 --- a/include/boost/program_options/errors.hpp +++ b/include/boost/program_options/errors.hpp @@ -35,7 +35,7 @@ namespace boost { namespace program_options { } /** Base class for all errors in the library. */ - class BOOST_PROGRAM_OPTIONS_DECL error : public std::logic_error { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE error : public std::logic_error { public: error(const std::string& xwhat) : std::logic_error(xwhat) {} }; @@ -44,15 +44,15 @@ namespace boost { namespace program_options { /** Class thrown when there are too many positional options. This is a programming error. */ - class BOOST_PROGRAM_OPTIONS_DECL too_many_positional_options_error : public error { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE too_many_positional_options_error : public error { public: too_many_positional_options_error() : error("too many positional options have been specified on the command line") {} }; - /** Class thrown when there are programming error related to style */ - class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_style : public error { + /** Class thrown when there are programming errors related to style */ + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE invalid_command_line_style : public error { public: invalid_command_line_style(const std::string& msg) : error(msg) @@ -60,7 +60,7 @@ namespace boost { namespace program_options { }; /** Class thrown if config file can not be read */ - class BOOST_PROGRAM_OPTIONS_DECL reading_file : public error { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE reading_file : public error { public: reading_file(const char* filename) : error(std::string("can not read options configuration file '").append(filename).append("'")) @@ -83,7 +83,7 @@ namespace boost { namespace program_options { * Options are displayed in "canonical" form * This is the most unambiguous form of the * *parsed* option name and would correspond to - * option_description::format_name() + * option_description::format_name(), * i.e. what is shown by print_usage() * * The "canonical" form depends on whether the option is @@ -91,7 +91,7 @@ namespace boost { namespace program_options { * or without a prefix (from a configuration file) * * */ - class BOOST_PROGRAM_OPTIONS_DECL error_with_option_name : public error { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE error_with_option_name : public error { protected: /** can be @@ -110,18 +110,18 @@ namespace boost { namespace program_options { std::map m_substitution_defaults; public: - /** template with placeholders */ - std::string m_error_template; + /** template with placeholders */ + std::string m_error_template; - error_with_option_name(const std::string& template_, - const std::string& option_name = "", - const std::string& original_token = "", - int option_style = 0); + error_with_option_name(const std::string& template_, + const std::string& option_name = "", + const std::string& original_token = "", + int option_style = 0); /** gcc says that throw specification on dtor is loosened * without this line * */ - ~error_with_option_name() throw() {} + BOOST_DEFAULTED_FUNCTION(~error_with_option_name() BOOST_NOEXCEPT_OR_NOTHROW, {}) //void dump() const @@ -183,7 +183,7 @@ namespace boost { namespace program_options { /** Creates the error_message on the fly * Currently a thin wrapper for substitute_placeholders() */ - virtual const char* what() const throw(); + virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW override; protected: /** Used to hold the error text returned by what() */ @@ -204,28 +204,28 @@ namespace boost { namespace program_options { /** Class thrown when there are several option values, but user called a method which cannot return them all. */ - class BOOST_PROGRAM_OPTIONS_DECL multiple_values : public error_with_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE multiple_values : public error_with_option_name { public: multiple_values() : error_with_option_name("option '%canonical_option%' only takes a single argument"){} - ~multiple_values() throw() {} + BOOST_DEFAULTED_FUNCTION(~multiple_values() BOOST_NOEXCEPT_OR_NOTHROW, {}) }; /** Class thrown when there are several occurrences of an option, but user called a method which cannot return them all. */ - class BOOST_PROGRAM_OPTIONS_DECL multiple_occurrences : public error_with_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE multiple_occurrences : public error_with_option_name { public: multiple_occurrences() : error_with_option_name("option '%canonical_option%' cannot be specified more than once"){} - ~multiple_occurrences() throw() {} + BOOST_DEFAULTED_FUNCTION(~multiple_occurrences() BOOST_NOEXCEPT_OR_NOTHROW, {}) }; /** Class thrown when a required/mandatory option is missing */ - class BOOST_PROGRAM_OPTIONS_DECL required_option : public error_with_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE required_option : public error_with_option_name { public: // option name is constructed by the option_descriptor and never on the fly required_option(const std::string& option_name) @@ -233,7 +233,7 @@ namespace boost { namespace program_options { { } - ~required_option() throw() {} + BOOST_DEFAULTED_FUNCTION(~required_option() BOOST_NOEXCEPT_OR_NOTHROW, {}) }; /** Base class of unparsable options, @@ -243,11 +243,11 @@ namespace boost { namespace program_options { * It makes no sense to have an option name, when we can't match an option to the * parameter * - * Having this a part of the error_with_option_name hierachy makes error handling + * Having this as part of the error_with_option_name hierarchy makes error handling * a lot easier, even if the name indicates some sort of conceptual dissonance! * * */ - class BOOST_PROGRAM_OPTIONS_DECL error_with_no_option_name : public error_with_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE error_with_no_option_name : public error_with_option_name { public: error_with_no_option_name(const std::string& template_, const std::string& original_token = "") @@ -256,40 +256,40 @@ namespace boost { namespace program_options { } /** Does NOT set option name, because no option name makes sense */ - virtual void set_option_name(const std::string&) {} + virtual void set_option_name(const std::string&) override {} - ~error_with_no_option_name() throw() {} + BOOST_DEFAULTED_FUNCTION(~error_with_no_option_name() BOOST_NOEXCEPT_OR_NOTHROW, {}) }; /** Class thrown when option name is not recognized. */ - class BOOST_PROGRAM_OPTIONS_DECL unknown_option : public error_with_no_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE unknown_option : public error_with_no_option_name { public: unknown_option(const std::string& original_token = "") : error_with_no_option_name("unrecognised option '%canonical_option%'", original_token) { } - ~unknown_option() throw() {} + BOOST_DEFAULTED_FUNCTION(~unknown_option() BOOST_NOEXCEPT_OR_NOTHROW, {}) }; - /** Class thrown when there's ambiguity amoung several possible options. */ - class BOOST_PROGRAM_OPTIONS_DECL ambiguous_option : public error_with_no_option_name { + /** Class thrown when there's ambiguity among several possible options. */ + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE ambiguous_option : public error_with_no_option_name { public: ambiguous_option(const std::vector& xalternatives) : error_with_no_option_name("option '%canonical_option%' is ambiguous"), m_alternatives(xalternatives) {} - ~ambiguous_option() throw() {} + BOOST_DEFAULTED_FUNCTION(~ambiguous_option() BOOST_NOEXCEPT_OR_NOTHROW, {}) - const std::vector& alternatives() const throw() {return m_alternatives;} + const std::vector& alternatives() const BOOST_NOEXCEPT_OR_NOTHROW {return m_alternatives;} protected: /** Makes all substitutions using the template */ - virtual void substitute_placeholders(const std::string& error_template) const; + virtual void substitute_placeholders(const std::string& error_template) const override; private: // TODO: copy ctor might throw std::vector m_alternatives; @@ -299,7 +299,7 @@ namespace boost { namespace program_options { /** Class thrown when there's syntax error either for command * line or config file options. See derived children for * concrete classes. */ - class BOOST_PROGRAM_OPTIONS_DECL invalid_syntax : public error_with_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE invalid_syntax : public error_with_option_name { public: enum kind_t { long_not_allowed = 30, @@ -320,7 +320,7 @@ namespace boost { namespace program_options { { } - ~invalid_syntax() throw() {} + BOOST_DEFAULTED_FUNCTION(~invalid_syntax() BOOST_NOEXCEPT_OR_NOTHROW, {}) kind_t kind() const {return m_kind;} @@ -332,7 +332,7 @@ namespace boost { namespace program_options { kind_t m_kind; }; - class BOOST_PROGRAM_OPTIONS_DECL invalid_config_file_syntax : public invalid_syntax { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE invalid_config_file_syntax : public invalid_syntax { public: invalid_config_file_syntax(const std::string& invalid_line, kind_t kind): invalid_syntax(kind) @@ -340,27 +340,27 @@ namespace boost { namespace program_options { m_substitutions["invalid_line"] = invalid_line; } - ~invalid_config_file_syntax() throw() {} + BOOST_DEFAULTED_FUNCTION(~invalid_config_file_syntax() BOOST_NOEXCEPT_OR_NOTHROW, {}) /** Convenience functions for backwards compatibility */ - virtual std::string tokens() const {return m_substitutions.find("invalid_line")->second; } + virtual std::string tokens() const override {return m_substitutions.find("invalid_line")->second; } }; /** Class thrown when there are syntax errors in given command line */ - class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_syntax : public invalid_syntax { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE invalid_command_line_syntax : public invalid_syntax { public: invalid_command_line_syntax(kind_t kind, const std::string& option_name = "", const std::string& original_token = "", int option_style = 0): invalid_syntax(kind, option_name, original_token, option_style) {} - ~invalid_command_line_syntax() throw() {} + BOOST_DEFAULTED_FUNCTION(~invalid_command_line_syntax() BOOST_NOEXCEPT_OR_NOTHROW, {}) }; /** Class thrown when value of option is incorrect. */ - class BOOST_PROGRAM_OPTIONS_DECL validation_error : public error_with_option_name { + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE validation_error : public error_with_option_name { public: enum kind_t { multiple_values_not_allowed = 30, @@ -380,7 +380,7 @@ namespace boost { namespace program_options { { } - ~validation_error() throw() {} + BOOST_DEFAULTED_FUNCTION(~validation_error() BOOST_NOEXCEPT_OR_NOTHROW, {}) kind_t kind() const { return m_kind; } @@ -391,7 +391,7 @@ namespace boost { namespace program_options { }; /** Class thrown if there is an invalid option value given */ - class BOOST_PROGRAM_OPTIONS_DECL invalid_option_value + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE invalid_option_value : public validation_error { public: @@ -402,7 +402,7 @@ namespace boost { namespace program_options { }; /** Class thrown if there is an invalid bool value given */ - class BOOST_PROGRAM_OPTIONS_DECL invalid_bool_value + class BOOST_PROGRAM_OPTIONS_DECL BOOST_SYMBOL_VISIBLE invalid_bool_value : public validation_error { public: diff --git a/include/boost/program_options/options_description.hpp b/include/boost/program_options/options_description.hpp index 90d913d3e3..da2c4bbfe3 100644 --- a/include/boost/program_options/options_description.hpp +++ b/include/boost/program_options/options_description.hpp @@ -105,7 +105,7 @@ namespace program_options { /** Returns the canonical name for the option description to enable the user to - recognised a matching option. + recognise a matching option. 1) For short options ('-', '/'), returns the short name prefixed. 2) For long options ('--' / '-') returns the first long name prefixed 3) All other cases, returns the first long name (if present) or the short diff --git a/include/boost/program_options/parsers.hpp b/include/boost/program_options/parsers.hpp index 0576469278..c86b537469 100644 --- a/include/boost/program_options/parsers.hpp +++ b/include/boost/program_options/parsers.hpp @@ -30,7 +30,7 @@ namespace boost { namespace program_options { /** Results of parsing an input source. The primary use of this class is passing information from parsers - component to value storage component. This class does not makes + component to value storage component. This class does not make much sense itself. */ template @@ -48,7 +48,7 @@ namespace boost { namespace program_options { const options_description* description; /** Mainly used for the diagnostic messages in exceptions. - * The canonical option prefix for the parser which generated these results, + * The canonical option prefix for the parser which generated these results, * depending on the settings for basic_command_line_parser::style() or * cmdline::style(). In order of precedence of command_line_style enums: * allow_long @@ -77,7 +77,7 @@ namespace boost { namespace program_options { basic_parsed_options utf8_encoded_options; /** Mainly used for the diagnostic messages in exceptions. - * The canonical option prefix for the parser which generated these results, + * The canonical option prefix for the parser which generated these results, * depending on the settings for basic_command_line_parser::style() or * cmdline::style(). In order of precedence of command_line_style enums: * allow_long @@ -120,7 +120,11 @@ namespace boost { namespace program_options { basic_command_line_parser(const std::vector< std::basic_string >& args); /** Creates a command line parser for the specified arguments - list. The parameters should be the same as passed to 'main'. + list. The parameters should be the same as passed to 'main', meaning: + @param argc Must be non-negative i.e. >= 0 + @param argv Argv[argc] must be 0 e.g. nullptr and + if argc is >0 argv[0] up to argv[argc-1] must point to + null terminated strings */ basic_command_line_parser(int argc, const charT* const argv[]); @@ -146,7 +150,7 @@ namespace boost { namespace program_options { instance of basic_option will be added to result, with 'unrecognized' field set to 'true'. It's possible to collect all unrecognized options with the 'collect_unrecognized' - funciton. + function. */ basic_command_line_parser& allow_unregistered(); @@ -210,7 +214,7 @@ namespace boost { namespace program_options { /** Collects the original tokens for all named options with 'unregistered' flag set. If 'mode' is 'include_positional' also collects all positional options. - Returns the vector of origianl tokens for all collected + Returns the vector of original tokens for all collected options. */ template @@ -250,8 +254,8 @@ namespace boost { namespace program_options { /** Splits a given string to a collection of single strings which can be passed to command_line_parser. The second parameter is - used to specify a collection of possible seperator chars used - for splitting. The seperator is defaulted to space " ". + used to specify a collection of possible separator chars used + for splitting. The separator is defaulted to space " ". Splitting is done in a unix style way, with respect to quotes '"' and escape characters '\' */ diff --git a/include/boost/program_options/positional_options.hpp b/include/boost/program_options/positional_options.hpp index ac2a3122d5..c19c9250ea 100644 --- a/include/boost/program_options/positional_options.hpp +++ b/include/boost/program_options/positional_options.hpp @@ -37,7 +37,7 @@ namespace boost { namespace program_options { public: positional_options_description(); - /** Species that up to 'max_count' next positional options + /** Specifies that up to 'max_count' next positional options should be given the 'name'. The value of '-1' means 'unlimited'. No calls to 'add' can be made after call with 'max_value' equal to '-1'. diff --git a/include/boost/program_options/value_semantic.hpp b/include/boost/program_options/value_semantic.hpp index ac9dbc663b..717f2cd99a 100644 --- a/include/boost/program_options/value_semantic.hpp +++ b/include/boost/program_options/value_semantic.hpp @@ -51,7 +51,7 @@ namespace boost { namespace program_options { /** Parses a group of tokens that specify a value of option. Stores the result in 'value_store', using whatever representation - is desired. May be be called several times if value of the same + is desired. May be called several times if value of the same option is specified more than once. */ virtual void parse(boost::any& value_store, @@ -71,7 +71,7 @@ namespace boost { namespace program_options { virtual ~value_semantic() {} }; - /** Helper class which perform necessary character conversions in the + /** Helper class which performs necessary character conversions in the 'parse' method and forwards the data further. */ template @@ -92,7 +92,7 @@ namespace boost { namespace program_options { private: // base overrides void parse(boost::any& value_store, const std::vector& new_tokens, - bool utf8) const; + bool utf8) const override; protected: // interface for derived classes. virtual void xparse(boost::any& value_store, const std::vector& new_tokens) @@ -112,7 +112,7 @@ namespace boost { namespace program_options { private: // base overrides void parse(boost::any& value_store, const std::vector& new_tokens, - bool utf8) const; + bool utf8) const override; protected: // interface for derived classes. #if !defined(BOOST_NO_STD_WSTRING) virtual void xparse(boost::any& value_store, @@ -130,34 +130,34 @@ namespace boost { namespace program_options { : m_zero_tokens(zero_tokens) {} - std::string name() const; + std::string name() const override; - unsigned min_tokens() const; - unsigned max_tokens() const; + unsigned min_tokens() const override; + unsigned max_tokens() const override; - bool is_composing() const { return false; } + bool is_composing() const override { return false; } - bool is_required() const { return false; } + bool is_required() const override { return false; } /** If 'value_store' is already initialized, or new_tokens - has more than one elements, throws. Otherwise, assigns + has more than one element, throws. Otherwise, assigns the first string from 'new_tokens' to 'value_store', without any modifications. */ void xparse(boost::any& value_store, - const std::vector& new_tokens) const; + const std::vector& new_tokens) const override; /** Does nothing. */ - bool apply_default(boost::any&) const { return false; } + bool apply_default(boost::any&) const override { return false; } /** Does nothing. */ - void notify(const boost::any&) const {} + void notify(const boost::any&) const override {} private: bool m_zero_tokens; }; #ifndef BOOST_NO_RTTI - /** Base class for all option that have a fixed type, and are + /** Base class for all options that have a fixed type, and are willing to announce this type to the outside world. Any 'value_semantics' for which you want to find out the type can be dynamic_cast-ed to typed_value_base. If conversion @@ -218,7 +218,7 @@ namespace boost { namespace program_options { /** Specifies an implicit value, which will be used if the option is given, but without an adjacent value. - Using this implies that an explicit value is optional, + Using this implies that an explicit value is optional. */ typed_value* implicit_value(const T &v) { @@ -228,7 +228,7 @@ namespace boost { namespace program_options { return this; } - /** Specifies the name used to to the value in help message. */ + /** Specifies the name used for the value in the help message. */ typed_value* value_name(const std::string& name) { m_value_name = name; @@ -278,7 +278,7 @@ namespace boost { namespace program_options { } /** Specifies that no tokens may be provided as the value of - this option, which means that only presense of the option + this option, which means that only presence of the option is significant. For such option to be useful, either the 'validate' function should be specialized, or the 'implicit_value' method should be also used. In most @@ -299,11 +299,11 @@ namespace boost { namespace program_options { public: // value semantic overrides - std::string name() const; + std::string name() const override; - bool is_composing() const { return m_composing; } + bool is_composing() const override { return m_composing; } - unsigned min_tokens() const + unsigned min_tokens() const override { if (m_zero_tokens || !m_implicit_value.empty()) { return 0; @@ -312,7 +312,7 @@ namespace boost { namespace program_options { } } - unsigned max_tokens() const { + unsigned max_tokens() const override { if (m_multitoken) { return std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION(); } else if (m_zero_tokens) { @@ -322,19 +322,19 @@ namespace boost { namespace program_options { } } - bool is_required() const { return m_required; } + bool is_required() const override { return m_required; } /** Creates an instance of the 'validator' class and calls its operator() to perform the actual conversion. */ void xparse(boost::any& value_store, const std::vector< std::basic_string >& new_tokens) - const; + const override; /** If default value was specified via previous call to 'default_value', stores that value into 'value_store'. Returns true if default value was stored. */ - virtual bool apply_default(boost::any& value_store) const + virtual bool apply_default(boost::any& value_store) const override { if (m_default_value.empty()) { return false; @@ -347,12 +347,12 @@ namespace boost { namespace program_options { /** If an address of variable to store value was specified when creating *this, stores the value there. Otherwise, does nothing. */ - void notify(const boost::any& value_store) const; + void notify(const boost::any& value_store) const override; public: // typed_value_base overrides #ifndef BOOST_NO_RTTI - const std::type_info& value_type() const + const std::type_info& value_type() const override { return typeid(T); } diff --git a/include/boost/program_options/variables_map.hpp b/include/boost/program_options/variables_map.hpp index 362dedf283..3d76629311 100644 --- a/include/boost/program_options/variables_map.hpp +++ b/include/boost/program_options/variables_map.hpp @@ -62,7 +62,7 @@ namespace boost { namespace program_options { : v(xv), m_defaulted(xdefaulted) {} - /** If stored value if of type T, returns that value. Otherwise, + /** If stored value is of type T, returns that value. Otherwise, throws boost::bad_any_cast exception. */ template const T& as() const { @@ -138,7 +138,7 @@ namespace boost { namespace program_options { const abstract_variables_map* m_next; }; - /** Concrete variables map which store variables in real map. + /** Concrete variables map which stores variables in real map. This class is derived from std::map, so you can use all map operators to examine its content. @@ -162,7 +162,7 @@ namespace boost { namespace program_options { private: /** Implementation of abstract_variables_map::get which does 'find' in *this. */ - const variable_value& get(const std::string& name) const; + const variable_value& get(const std::string& name) const override; /** Names of option with 'final' values \-- which should not be changed by subsequence assignments. */ diff --git a/meta/libraries.json b/meta/libraries.json index 5fbf312680..be94bf07fd 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -11,5 +11,6 @@ ], "maintainers": [ "Vladimir Prus " - ] + ], + "cxxstd": "11" } diff --git a/src/cmdline.cpp b/src/cmdline.cpp index c2cf1da11f..8f4ae64e4a 100644 --- a/src/cmdline.cpp +++ b/src/cmdline.cpp @@ -3,7 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include @@ -15,7 +17,7 @@ #include #include -#include +#include #include #include @@ -29,6 +31,8 @@ #include +using namespace boost::placeholders; + namespace boost { namespace program_options { using namespace std; diff --git a/src/config_file.cpp b/src/config_file.cpp index f2a57b4b82..d586523703 100644 --- a/src/config_file.cpp +++ b/src/config_file.cpp @@ -3,8 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include diff --git a/src/convert.cpp b/src/convert.cpp index 9be759e260..fbe2758b12 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -13,15 +13,18 @@ #include -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include #include #include -#include +#include using namespace std; +using namespace boost::placeholders; namespace boost { namespace detail { diff --git a/src/options_description.cpp b/src/options_description.cpp index dc0eae8744..0efdc33882 100644 --- a/src/options_description.cpp +++ b/src/options_description.cpp @@ -4,8 +4,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include // FIXME: this is only to get multiple_occurrences class diff --git a/src/parsers.cpp b/src/parsers.cpp index dd62c66d37..4dac608d3e 100644 --- a/src/parsers.cpp +++ b/src/parsers.cpp @@ -6,7 +6,9 @@ #include -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include #include @@ -16,7 +18,7 @@ #include #include -#include +#include #include #include @@ -61,6 +63,7 @@ extern char** environ; #endif using namespace std; +using namespace boost::placeholders; namespace boost { namespace program_options { @@ -152,7 +155,16 @@ namespace boost { namespace program_options { { boost::throw_exception(reading_file(filename)); } - return parse_config_file(strm, desc, allow_unregistered); + + basic_parsed_options result + = parse_config_file(strm, desc, allow_unregistered); + + if (strm.bad()) + { + boost::throw_exception(reading_file(filename)); + } + + return result; } template diff --git a/src/positional_options.cpp b/src/positional_options.cpp index 72dc0d6b0d..cb6a145240 100644 --- a/src/positional_options.cpp +++ b/src/positional_options.cpp @@ -3,7 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include diff --git a/src/split.cpp b/src/split.cpp index 96da068b82..c674403ff2 100644 --- a/src/split.cpp +++ b/src/split.cpp @@ -3,7 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include diff --git a/src/utf8_codecvt_facet.cpp b/src/utf8_codecvt_facet.cpp index 2e4c532c35..075e4aebb9 100644 --- a/src/utf8_codecvt_facet.cpp +++ b/src/utf8_codecvt_facet.cpp @@ -3,7 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #define BOOST_UTF8_BEGIN_NAMESPACE \ diff --git a/src/value_semantic.cpp b/src/value_semantic.cpp index a7366d4386..c4feb688e3 100644 --- a/src/value_semantic.cpp +++ b/src/value_semantic.cpp @@ -3,7 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include #include @@ -82,12 +84,14 @@ namespace boost { namespace program_options { } #endif - BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg"); + namespace detail { + BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg"); + } std::string untyped_value::name() const { - return arg; + return detail::arg; } unsigned @@ -258,7 +262,7 @@ namespace boost { namespace program_options { } - const char* error_with_option_name::what() const throw() + const char* error_with_option_name::what() const BOOST_NOEXCEPT_OR_NOTHROW { // will substitute tokens each time what is run() substitute_placeholders(m_error_template); diff --git a/src/variables_map.cpp b/src/variables_map.cpp index bc85f7e34b..94ac6148c4 100644 --- a/src/variables_map.cpp +++ b/src/variables_map.cpp @@ -3,8 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include #include diff --git a/src/winmain.cpp b/src/winmain.cpp index 6220043f6c..31c8adcb7f 100644 --- a/src/winmain.cpp +++ b/src/winmain.cpp @@ -3,7 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_PROGRAM_OPTIONS_SOURCE +#ifndef BOOST_PROGRAM_OPTIONS_SOURCE +# define BOOST_PROGRAM_OPTIONS_SOURCE +#endif #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..ea8832ec15 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2018-2020 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +include(BoostTest OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) + +if(NOT HAVE_BOOST_TEST) + return() +endif() + +set(BOOST_TEST_LINK_LIBRARIES Boost::program_options) + +boost_test(TYPE run SOURCES options_description_test.cpp) +boost_test(TYPE run SOURCES parsers_test.cpp ARGUMENTS ${CMAKE_CURRENT_SOURCE_DIR}/config_test.cfg) +boost_test(TYPE run SOURCES variable_map_test.cpp) +boost_test(TYPE run SOURCES cmdline_test.cpp) +boost_test(TYPE run SOURCES positional_options_test.cpp) +boost_test(TYPE run SOURCES unicode_test.cpp) +boost_test(TYPE run SOURCES winmain.cpp) +boost_test(TYPE run SOURCES exception_test.cpp) +boost_test(TYPE run SOURCES split_test.cpp) +boost_test(TYPE run SOURCES unrecognized_test.cpp) +boost_test(TYPE run SOURCES required_test.cpp ARGUMENTS ${CMAKE_CURRENT_SOURCE_DIR}/required_test.cfg) +boost_test(TYPE run SOURCES exception_txt_test.cpp) +boost_test(TYPE run SOURCES optional_test.cpp) + +boost_test(TYPE run SOURCES quick.cpp ARGUMENTS --path=initial LINK_LIBRARIES Boost::core) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a45ed8e67e..968b5a82d1 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -35,10 +35,10 @@ test-suite program_options : [ po-test required_test.cpp : required_test.cfg ] [ po-test exception_txt_test.cpp ] [ po-test optional_test.cpp ] - [ run options_description_test.cpp : : : off BOOST_NO_RTTI BOOST_NO_TYPEID : options_description_no_rtti_test ] + [ run options_description_test.cpp : : : off : options_description_no_rtti_test ] ; -exe test_convert : test_convert.cpp ; +exe test_convert : test_convert.cpp /boost/timer//boost_timer ; # `quick` target (for CI) run quick.cpp : --path=initial ; diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt new file mode 100644 index 0000000000..c741453244 --- /dev/null +++ b/test/cmake_install_test/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.16) + +project(cmake_install_test LANGUAGES CXX) + +find_package(boost_program_options REQUIRED) +find_package(boost_core REQUIRED) + +add_executable(quick ../quick.cpp) +target_link_libraries(quick Boost::program_options Boost::core) + +enable_testing() +add_test(NAME quick COMMAND quick --path=initial) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt new file mode 100644 index 0000000000..457cf6af58 --- /dev/null +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.16) + +project(cmake_subdir_test LANGUAGES CXX) + +set(BOOST_INCLUDE_LIBRARIES program_options) +add_subdirectory(../../../.. boostorg/boost) + +add_executable(quick ../quick.cpp) +target_link_libraries(quick Boost::program_options Boost::core) + +enable_testing() +add_test(NAME quick COMMAND quick --path=initial) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/exception_txt_test.cpp b/test/exception_txt_test.cpp index 59a3c0269a..43e0014bcb 100644 --- a/test/exception_txt_test.cpp +++ b/test/exception_txt_test.cpp @@ -152,7 +152,7 @@ void test_invalid_option_value_exception_msg() { options_description desc; desc.add_options() - ("int-option,d", value< int >(), "An option taking an integer") + ("int-option,d", value< int >(), "An option taking an integer") ; vector > argv; @@ -308,7 +308,7 @@ void test_invalid_bool_value_exception_msg() { options_description desc; desc.add_options() - ("bool_option,b", value< bool>(), "bool_option") + ("bool_option,b", value< bool>(), "bool_option") ; diff --git a/test/optional_test.cpp b/test/optional_test.cpp index b38308e588..cd34ba6e7a 100644 --- a/test/optional_test.cpp +++ b/test/optional_test.cpp @@ -7,6 +7,9 @@ namespace po = boost::program_options; #include +#ifndef BOOST_NO_CXX17_HDR_OPTIONAL +# include +#endif #include #include "minitest.hpp" @@ -19,9 +22,10 @@ std::vector sv(const char* array[], unsigned size) return r; } +template class OptionalType> void test_optional() { - boost::optional foo, bar, baz; + OptionalType foo, bar, baz; po::options_description desc; desc.add_options() @@ -48,6 +52,9 @@ void test_optional() int main(int, char*[]) { - test_optional(); + test_optional(); +#ifndef BOOST_NO_CXX17_HDR_OPTIONAL + test_optional(); +#endif return 0; } diff --git a/test/parsers_test.cpp b/test/parsers_test.cpp index 4cf832ee75..7eaaaebc56 100644 --- a/test/parsers_test.cpp +++ b/test/parsers_test.cpp @@ -300,6 +300,10 @@ void test_config_file(const char* config_file) check_value(a2[6], "m1.v3", "3"); } +#if defined(__CYGWIN__) + extern "C" int putenv (char *__string); +#endif + void test_environment() { options_description desc; @@ -308,7 +312,7 @@ void test_environment() ("bar", new untyped_value, "") ; -#if (defined(_WIN32) && ! defined(__BORLANDC__)) || (defined(__CYGWIN__)) +#if defined(_WIN32) && ! defined(BOOST_BORLANDC) && ! defined(BOOST_EMBTC) _putenv("PO_TEST_FOO=1"); #else putenv(const_cast("PO_TEST_FOO=1")); diff --git a/test/test_convert.cpp b/test/test_convert.cpp index f03a19eb5d..a541e0264b 100644 --- a/test/test_convert.cpp +++ b/test/test_convert.cpp @@ -3,6 +3,9 @@ // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) +// This will eventually stop working when is removed +#define BOOST_TIMER_ENABLE_DEPRECATED + #include #include #include diff --git a/test/winmain.cpp b/test/winmain.cpp index 0c3512f97a..4cbcad5845 100644 --- a/test/winmain.cpp +++ b/test/winmain.cpp @@ -9,13 +9,12 @@ #include #include #include +#include using namespace std; - -#include using namespace boost::program_options; -void check_equal(const std::vector& actual, char **expected, int n) +void check_equal(const std::vector& actual, const char **expected, int n) { if (actual.size() != n) { @@ -39,7 +38,7 @@ void test_winmain() #define C , #define TEST(input, expected) \ - char* BOOST_PP_CAT(e, __LINE__)[] = expected;\ + const char* BOOST_PP_CAT(e, __LINE__)[] = expected;\ vector BOOST_PP_CAT(v, __LINE__) = split_winmain(input);\ check_equal(BOOST_PP_CAT(v, __LINE__), BOOST_PP_CAT(e, __LINE__),\ sizeof(BOOST_PP_CAT(e, __LINE__))/sizeof(char*));