Commit d046fe0ad6acab5dbe0dcbc9457cad8fada8b288
Committed by
GitHub
1 parent
82ac0838
Extend CI and small fixes (#370)
* Extend CI to support Windows and MacOS. * Minor fixes to types.
Showing
2 changed files
with
83 additions
and
61 deletions
.github/workflows/cmake.yml
| ... | ... | @@ -2,43 +2,70 @@ name: CMake |
| 2 | 2 | |
| 3 | 3 | on: |
| 4 | 4 | push: |
| 5 | - branches: [ master ] | |
| 5 | + branches: [ master, main ] | |
| 6 | 6 | pull_request: |
| 7 | - branches: [ master ] | |
| 7 | + branches: [ master, main ] | |
| 8 | 8 | workflow_dispatch: |
| 9 | 9 | |
| 10 | 10 | env: |
| 11 | 11 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) |
| 12 | 12 | BUILD_TYPE: Release |
| 13 | 13 | |
| 14 | + | |
| 15 | +defaults: | |
| 16 | + run: | |
| 17 | + shell: bash | |
| 18 | + | |
| 14 | 19 | jobs: |
| 15 | - build: | |
| 16 | - # The CMake configure and build commands are platform agnostic and should work equally | |
| 17 | - # well on Windows or Mac. You can convert this to a matrix build if you need | |
| 18 | - # cross-platform coverage. | |
| 19 | - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix | |
| 20 | + build-ubuntu: | |
| 21 | + strategy: | |
| 22 | + matrix: | |
| 23 | + os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ] | |
| 24 | + compiler: [ g++-9, g++-10, clang++ ] | |
| 25 | + include: | |
| 26 | + - os: ubuntu-18.04 | |
| 27 | + compiler: g++-7 | |
| 28 | + name: Build and Test on Ubuntu | |
| 20 | 29 | runs-on: ${{matrix.os}} |
| 30 | + steps: | |
| 31 | + - uses: actions/checkout@v3 | |
| 32 | + - name: Configure CMake | |
| 33 | + run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=${{matrix.compiler}} | |
| 34 | + - name: Build | |
| 35 | + run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE | |
| 36 | + - name: Test | |
| 37 | + working-directory: ${{github.workspace}}/build/test | |
| 38 | + run: ctest -C $BUILD_TYPE --output-on-failure | |
| 21 | 39 | |
| 40 | + build-macos: | |
| 41 | + name: Build and Test on MacOS | |
| 22 | 42 | strategy: |
| 23 | 43 | matrix: |
| 24 | - os: [ubuntu-18.04] | |
| 25 | - compiler: [g++-7, g++-9, g++-10, clang++] | |
| 26 | - | |
| 44 | + os: [ macos-11, macos-12 ] | |
| 45 | + runs-on: ${{matrix.os}} | |
| 27 | 46 | steps: |
| 28 | - - uses: actions/checkout@v2 | |
| 29 | - | |
| 30 | - - name: Configure CMake | |
| 31 | - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. | |
| 32 | - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type | |
| 33 | - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=${{matrix.compiler}} | |
| 47 | + - uses: actions/checkout@v3 | |
| 48 | + - name: Configure CMake | |
| 49 | + run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON | |
| 50 | + - name: Show compile commands | |
| 51 | + run: cat build/compile_commands.json | |
| 52 | + - name: Build | |
| 53 | + run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE | |
| 54 | + - name: Test | |
| 55 | + working-directory: ${{github.workspace}}/build/test | |
| 56 | + shell: bash | |
| 57 | + run: ctest -C $BUILD_TYPE --output-on-failure | |
| 34 | 58 | |
| 35 | - - name: Build | |
| 36 | - # Build your program with the given configuration | |
| 37 | - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} | |
| 38 | - | |
| 39 | - - name: Test | |
| 40 | - working-directory: ${{github.workspace}}/build | |
| 41 | - # Execute tests defined by the CMake configuration. | |
| 42 | - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail | |
| 43 | - run: ctest -C ${{env.BUILD_TYPE}} | |
| 44 | - | |
| 59 | + build-windows: | |
| 60 | + name: Build and Test on Windows | |
| 61 | + runs-on: windows-latest | |
| 62 | + steps: | |
| 63 | + - uses: actions/checkout@v3 | |
| 64 | + - uses: ilammy/msvc-dev-cmd@v1 | |
| 65 | + - name: Configure CMake | |
| 66 | + run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -T "ClangCl" | |
| 67 | + - name: Build | |
| 68 | + run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE | |
| 69 | + - name: Test | |
| 70 | + working-directory: ${{github.workspace}}/build/test | |
| 71 | + run: cd $BUILD_TYPE && ./link_test && ./options_test | ... | ... |
include/cxxopts.hpp
| ... | ... | @@ -27,13 +27,10 @@ THE SOFTWARE. |
| 27 | 27 | #ifndef CXXOPTS_HPP_INCLUDED |
| 28 | 28 | #define CXXOPTS_HPP_INCLUDED |
| 29 | 29 | |
| 30 | -#include <cassert> | |
| 31 | -#include <cctype> | |
| 32 | 30 | #include <cstring> |
| 33 | 31 | #include <exception> |
| 34 | 32 | #include <limits> |
| 35 | -#include <list> | |
| 36 | -#include <locale> | |
| 33 | +#include <initializer_list> | |
| 37 | 34 | #include <map> |
| 38 | 35 | #include <memory> |
| 39 | 36 | #include <sstream> |
| ... | ... | @@ -196,9 +193,9 @@ stringAppend(String&s, String a) |
| 196 | 193 | |
| 197 | 194 | inline |
| 198 | 195 | String& |
| 199 | -stringAppend(String& s, size_t n, UChar32 c) | |
| 196 | +stringAppend(String& s, std::size_t n, UChar32 c) | |
| 200 | 197 | { |
| 201 | - for (size_t i = 0; i != n; ++i) | |
| 198 | + for (std::size_t i = 0; i != n; ++i) | |
| 202 | 199 | { |
| 203 | 200 | s.append(c); |
| 204 | 201 | } |
| ... | ... | @@ -220,7 +217,7 @@ stringAppend(String& s, Iterator begin, Iterator end) |
| 220 | 217 | } |
| 221 | 218 | |
| 222 | 219 | inline |
| 223 | -size_t | |
| 220 | +std::size_t | |
| 224 | 221 | stringLength(const String& s) |
| 225 | 222 | { |
| 226 | 223 | return s.length(); |
| ... | ... | @@ -278,7 +275,7 @@ toLocalString(T&& t) |
| 278 | 275 | } |
| 279 | 276 | |
| 280 | 277 | inline |
| 281 | -size_t | |
| 278 | +std::size_t | |
| 282 | 279 | stringLength(const String& s) |
| 283 | 280 | { |
| 284 | 281 | return s.length(); |
| ... | ... | @@ -293,7 +290,7 @@ stringAppend(String&s, const String& a) |
| 293 | 290 | |
| 294 | 291 | inline |
| 295 | 292 | String& |
| 296 | -stringAppend(String& s, size_t n, char c) | |
| 293 | +stringAppend(String& s, std::size_t n, char c) | |
| 297 | 294 | { |
| 298 | 295 | return s.append(n, c); |
| 299 | 296 | } |
| ... | ... | @@ -682,7 +679,7 @@ inline OptionNames split_option_names(const std::string &text) |
| 682 | 679 | "abcdefghijklmnopqrstuvwxyz" |
| 683 | 680 | "0123456789" |
| 684 | 681 | "_-"; |
| 685 | - if (!std::isalnum(text[token_start_pos]) || | |
| 682 | + if (!std::isalnum(text[token_start_pos], std::locale::classic()) || | |
| 686 | 683 | text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) { |
| 687 | 684 | throw_or_mimic<exceptions::invalid_option_format>(text); |
| 688 | 685 | } |
| ... | ... | @@ -701,11 +698,11 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched) |
| 701 | 698 | if (strncmp(pdata, "--", 2) == 0) |
| 702 | 699 | { |
| 703 | 700 | pdata += 2; |
| 704 | - if (isalnum(*pdata)) | |
| 701 | + if (isalnum(*pdata, std::locale::classic())) | |
| 705 | 702 | { |
| 706 | 703 | argu_desc.arg_name.push_back(*pdata); |
| 707 | 704 | pdata += 1; |
| 708 | - while (isalnum(*pdata) || *pdata == '-' || *pdata == '_') | |
| 705 | + while (isalnum(*pdata, std::locale::classic()) || *pdata == '-' || *pdata == '_') | |
| 709 | 706 | { |
| 710 | 707 | argu_desc.arg_name.push_back(*pdata); |
| 711 | 708 | pdata += 1; |
| ... | ... | @@ -733,7 +730,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched) |
| 733 | 730 | { |
| 734 | 731 | pdata += 1; |
| 735 | 732 | argu_desc.grouping = true; |
| 736 | - while (isalnum(*pdata)) | |
| 733 | + while (isalnum(*pdata, std::locale::classic())) | |
| 737 | 734 | { |
| 738 | 735 | argu_desc.arg_name.push_back(*pdata); |
| 739 | 736 | pdata += 1; |
| ... | ... | @@ -1356,7 +1353,7 @@ class OptionDetails |
| 1356 | 1353 | return m_long; |
| 1357 | 1354 | } |
| 1358 | 1355 | |
| 1359 | - size_t | |
| 1356 | + std::size_t | |
| 1360 | 1357 | hash() const |
| 1361 | 1358 | { |
| 1362 | 1359 | return m_hash; |
| ... | ... | @@ -1369,7 +1366,7 @@ class OptionDetails |
| 1369 | 1366 | std::shared_ptr<const Value> m_value{}; |
| 1370 | 1367 | int m_count; |
| 1371 | 1368 | |
| 1372 | - size_t m_hash{}; | |
| 1369 | + std::size_t m_hash{}; | |
| 1373 | 1370 | }; |
| 1374 | 1371 | |
| 1375 | 1372 | struct HelpOptionDetails |
| ... | ... | @@ -1430,7 +1427,7 @@ CXXOPTS_IGNORE_WARNING("-Wnull-dereference") |
| 1430 | 1427 | #endif |
| 1431 | 1428 | |
| 1432 | 1429 | CXXOPTS_NODISCARD |
| 1433 | - size_t | |
| 1430 | + std::size_t | |
| 1434 | 1431 | count() const noexcept |
| 1435 | 1432 | { |
| 1436 | 1433 | return m_count; |
| ... | ... | @@ -1475,7 +1472,7 @@ CXXOPTS_DIAGNOSTIC_POP |
| 1475 | 1472 | // Holding this pointer is safe, since OptionValue's only exist in key-value pairs, |
| 1476 | 1473 | // where the key has the string we point to. |
| 1477 | 1474 | std::shared_ptr<Value> m_value{}; |
| 1478 | - size_t m_count = 0; | |
| 1475 | + std::size_t m_count = 0; | |
| 1479 | 1476 | bool m_default = false; |
| 1480 | 1477 | }; |
| 1481 | 1478 | |
| ... | ... | @@ -1516,8 +1513,8 @@ class KeyValue |
| 1516 | 1513 | std::string m_value; |
| 1517 | 1514 | }; |
| 1518 | 1515 | |
| 1519 | -using ParsedHashMap = std::unordered_map<size_t, OptionValue>; | |
| 1520 | -using NameHashMap = std::unordered_map<std::string, size_t>; | |
| 1516 | +using ParsedHashMap = std::unordered_map<std::size_t, OptionValue>; | |
| 1517 | +using NameHashMap = std::unordered_map<std::string, std::size_t>; | |
| 1521 | 1518 | |
| 1522 | 1519 | class ParseResult |
| 1523 | 1520 | { |
| ... | ... | @@ -1611,7 +1608,7 @@ class ParseResult |
| 1611 | 1608 | return Iterator(this, true); |
| 1612 | 1609 | } |
| 1613 | 1610 | |
| 1614 | - size_t | |
| 1611 | + std::size_t | |
| 1615 | 1612 | count(const std::string& o) const |
| 1616 | 1613 | { |
| 1617 | 1614 | auto iter = m_keys.find(o); |
| ... | ... | @@ -1821,7 +1818,7 @@ class Options |
| 1821 | 1818 | } |
| 1822 | 1819 | |
| 1823 | 1820 | Options& |
| 1824 | - set_width(size_t width) | |
| 1821 | + set_width(std::size_t width) | |
| 1825 | 1822 | { |
| 1826 | 1823 | m_width = width; |
| 1827 | 1824 | return *this; |
| ... | ... | @@ -1939,7 +1936,7 @@ class Options |
| 1939 | 1936 | std::string m_positional_help{}; |
| 1940 | 1937 | bool m_show_positional; |
| 1941 | 1938 | bool m_allow_unrecognised; |
| 1942 | - size_t m_width; | |
| 1939 | + std::size_t m_width; | |
| 1943 | 1940 | bool m_tab_expansion; |
| 1944 | 1941 | |
| 1945 | 1942 | std::shared_ptr<OptionMap> m_options; |
| ... | ... | @@ -1975,8 +1972,8 @@ class OptionAdder |
| 1975 | 1972 | }; |
| 1976 | 1973 | |
| 1977 | 1974 | namespace { |
| 1978 | -constexpr size_t OPTION_LONGEST = 30; | |
| 1979 | -constexpr size_t OPTION_DESC_GAP = 2; | |
| 1975 | +constexpr std::size_t OPTION_LONGEST = 30; | |
| 1976 | +constexpr std::size_t OPTION_DESC_GAP = 2; | |
| 1980 | 1977 | |
| 1981 | 1978 | String |
| 1982 | 1979 | format_option |
| ... | ... | @@ -2028,8 +2025,8 @@ String |
| 2028 | 2025 | format_description |
| 2029 | 2026 | ( |
| 2030 | 2027 | const HelpOptionDetails& o, |
| 2031 | - size_t start, | |
| 2032 | - size_t allowed, | |
| 2028 | + std::size_t start, | |
| 2029 | + std::size_t allowed, | |
| 2033 | 2030 | bool tab_expansion |
| 2034 | 2031 | ) |
| 2035 | 2032 | { |
| ... | ... | @@ -2052,7 +2049,7 @@ format_description |
| 2052 | 2049 | if (tab_expansion) |
| 2053 | 2050 | { |
| 2054 | 2051 | String desc2; |
| 2055 | - auto size = size_t{ 0 }; | |
| 2052 | + auto size = std::size_t{ 0 }; | |
| 2056 | 2053 | for (auto c = std::begin(desc); c != std::end(desc); ++c) |
| 2057 | 2054 | { |
| 2058 | 2055 | if (*c == '\n') |
| ... | ... | @@ -2082,7 +2079,7 @@ format_description |
| 2082 | 2079 | auto startLine = current; |
| 2083 | 2080 | auto lastSpace = current; |
| 2084 | 2081 | |
| 2085 | - auto size = size_t{}; | |
| 2082 | + auto size = std::size_t{}; | |
| 2086 | 2083 | |
| 2087 | 2084 | bool appendNewLine; |
| 2088 | 2085 | bool onlyWhiteSpace = true; |
| ... | ... | @@ -2090,13 +2087,11 @@ format_description |
| 2090 | 2087 | while (current != std::end(desc)) |
| 2091 | 2088 | { |
| 2092 | 2089 | appendNewLine = false; |
| 2093 | - | |
| 2094 | - if (std::isblank(*previous, std::locale::classic())) | |
| 2090 | + if (*previous == ' ' || *previous == '\t') | |
| 2095 | 2091 | { |
| 2096 | 2092 | lastSpace = current; |
| 2097 | 2093 | } |
| 2098 | - | |
| 2099 | - if (!std::isblank(*current, std::locale::classic())) | |
| 2094 | + if (*current != ' ' && *current != '\t') | |
| 2100 | 2095 | { |
| 2101 | 2096 | onlyWhiteSpace = false; |
| 2102 | 2097 | } |
| ... | ... | @@ -2622,7 +2617,7 @@ Options::help_one_group(const std::string& g) const |
| 2622 | 2617 | |
| 2623 | 2618 | OptionHelp format; |
| 2624 | 2619 | |
| 2625 | - size_t longest = 0; | |
| 2620 | + std::size_t longest = 0; | |
| 2626 | 2621 | |
| 2627 | 2622 | String result; |
| 2628 | 2623 | |
| ... | ... | @@ -2647,7 +2642,7 @@ Options::help_one_group(const std::string& g) const |
| 2647 | 2642 | longest = (std::min)(longest, OPTION_LONGEST); |
| 2648 | 2643 | |
| 2649 | 2644 | //widest allowed description -- min 10 chars for helptext/line |
| 2650 | - size_t allowed = 10; | |
| 2645 | + std::size_t allowed = 10; | |
| 2651 | 2646 | if (m_width > allowed + longest + OPTION_DESC_GAP) |
| 2652 | 2647 | { |
| 2653 | 2648 | allowed = m_width - longest - OPTION_DESC_GAP; |
| ... | ... | @@ -2694,7 +2689,7 @@ Options::generate_group_help |
| 2694 | 2689 | const std::vector<std::string>& print_groups |
| 2695 | 2690 | ) const |
| 2696 | 2691 | { |
| 2697 | - for (size_t i = 0; i != print_groups.size(); ++i) | |
| 2692 | + for (std::size_t i = 0; i != print_groups.size(); ++i) | |
| 2698 | 2693 | { |
| 2699 | 2694 | const String& group_help_text = help_one_group(print_groups[i]); |
| 2700 | 2695 | if (empty(group_help_text)) | ... | ... |