Commit d046fe0ad6acab5dbe0dcbc9457cad8fada8b288

Authored by Stefan Hillmich
Committed by GitHub
1 parent 82ac0838

Extend CI and small fixes (#370)

* Extend CI to support Windows and MacOS.
* Minor fixes to types.
.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&amp;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&amp; 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&amp;&amp; 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&amp;s, const String&amp; 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 &amp;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 &amp;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 &amp;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(&quot;-Wnull-dereference&quot;)
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&amp; 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&amp; 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))
... ...