From c5153634db3626a108e6ff74995f2a7658844018 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Fri, 18 Jul 2025 07:18:26 -0700 Subject: [PATCH] Fix warnings and small issues (#1178) try some things with no standard libraries Add arm64 and freebsd build and tests fix a discrepancy in the handling of chars on Arm processors --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/arm_mac_gcc.yml | 25 +++++++++++++++++++++++++ .github/workflows/freebsd.yml | 28 ++++++++++++++++++++++++++++ .github/workflows/tests.yml | 26 +++++++++++++++++++++++++- CMakeLists.txt | 15 +++++++++------ examples/CMakeLists.txt | 7 ++----- include/CLI/StringTools.hpp | 2 +- include/CLI/TypeTools.hpp | 9 ++++++++- tests/CMakeLists.txt | 15 +++++++++------ tests/HelpersTest.cpp | 16 ++++++++-------- tests/app_helper.hpp | 4 ++-- 10 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/arm_mac_gcc.yml create mode 100644 .github/workflows/freebsd.yml diff --git a/.github/workflows/arm_mac_gcc.yml b/.github/workflows/arm_mac_gcc.yml new file mode 100644 index 00000000..9b17b88b --- /dev/null +++ b/.github/workflows/arm_mac_gcc.yml @@ -0,0 +1,25 @@ +name: ARM GCC +on: + pull_request: + branches: + - main + +jobs: + arm64_gcc: + name: ARM64 GCC + runs-on: ubuntu-24.04-arm + steps: + - uses: actions/checkout@v4 + + - name: Configure + run: | + cmake -S . -B build \ + -DCMAKE_CXX_STANDARD=17 + + - name: Build + run: cmake --build build -j4 + + - name: Test + run: | + cd build + ctest --output-on-failure \ No newline at end of file diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml new file mode 100644 index 00000000..c16b5ca5 --- /dev/null +++ b/.github/workflows/freebsd.yml @@ -0,0 +1,28 @@ +name: freebsd + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + name: run test on FreeBSD + steps: + - uses: actions/checkout@v4 + - name: Test in FreeBSD + id: test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + prepare: | + pkg install -y cmake pkgconf + + run: | + cmake -S . -B build \ + -DCMAKE_CXX_STANDARD=20 + cmake --build build -j4 + cd build + ctest --output-on-failure \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f63d4243..6c147764 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - std: ["11", "14", "17", "20"] + std: ["14", "17", "20","23"] precompile: ["ON", "OFF"] steps: - uses: actions/checkout@v4 @@ -150,6 +150,22 @@ jobs: run: ctest --output-on-failure working-directory: build + sanitizer-build: + name: sanitizer build + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + # this build step will fail + - name: Configure + run: cmake -S . -B build -DCLI11_SANITIZERS=ON + - name: Build + run: cmake --build build -j2 + - name: Run tests + run: ctest --output-on-failure + working-directory: build + meson-build: name: Meson build runs-on: ubuntu-latest @@ -378,4 +394,12 @@ jobs: uses: ./.github/actions/quick_cmake with: cmake-version: "3.31" + args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON + if: success() || failure() + + - name: Check CMake 4.0 + uses: ./.github/actions/quick_cmake + with: + cmake-version: "4.0" + args: -DCLI11_BUILD_EXAMPLES_JSON=ON if: success() || failure() diff --git a/CMakeLists.txt b/CMakeLists.txt index 03968f45..2a9da704 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.10...3.31) -# Note: this is a header only library. If you have an older CMake than 3.5, +cmake_minimum_required(VERSION 3.10...4.0) +# Note: this is a header only library. If you have an older CMake than 3.10, # just add the CLI11/include directory and that's all you need to do. set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"") @@ -69,7 +69,7 @@ option(CLI11_WARNINGS_AS_ERRORS "Turn all warnings into errors (for CI)") option(CLI11_SINGLE_FILE "Generate a single header file") option(CLI11_PRECOMPILED "Generate a precompiled static library instead of a header-only" OFF) cmake_dependent_option(CLI11_SANITIZERS "Download the sanitizers CMake config" OFF - "NOT CMAKE_VERSION VERSION_LESS 3.13" OFF) + "NOT CMAKE_VERSION VERSION_LESS 3.15" OFF) cmake_dependent_option(CLI11_BUILD_DOCS "Build CLI11 documentation" ON "${build-docs}" OFF) @@ -80,7 +80,7 @@ cmake_dependent_option(CLI11_BUILD_EXAMPLES "Build CLI11 examples" ON "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;${examples_EXIST}" OFF) cmake_dependent_option(CLI11_BUILD_EXAMPLES_JSON "Build CLI11 json example" OFF - "CLI11_BUILD_EXAMPLES;NOT CMAKE_VERSION VERSION_LESS 3.11" OFF) + "CLI11_BUILD_EXAMPLES;NOT CMAKE_VERSION VERSION_LESS 3.15" OFF) cmake_dependent_option(CLI11_SINGLE_FILE_TESTS "Duplicate all the tests for a single file build" OFF "BUILD_TESTING;CLI11_SINGLE_FILE" OFF) @@ -113,12 +113,15 @@ if(NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() +include(CLI11Warnings) + # Allow IDE's to group targets into folders if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set_property(GLOBAL PROPERTY USE_FOLDERS ON) -endif() -include(CLI11Warnings) + set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "") + set(CMAKE_CXX_STANDARD_LIBRARIES "") +endif() # Sources diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3d8373d3..f3cb5310 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -10,17 +10,14 @@ function(add_cli_exe T) endif() endfunction() -if(CLI11_BUILD_EXAMPLES_JSON) +if(CLI11_BUILD_EXAMPLES_JSON AND CMAKE_VERSION VERSION_GREATER "3.14.7") message(STATUS "Using nlohmann/json") FetchContent_Declare( json URL https://github.com/nlohmann/json/releases/download/v3.7.3/include.zip URL_HASH "SHA256=87b5884741427220d3a33df1363ae0e8b898099fbc59f1c451113f6732891014") - FetchContent_GetProperties(json) - if(NOT json_POPULATED) - FetchContent_Populate(json) - endif() + FetchContent_MakeAvailable(json) add_cli_exe(json json.cpp) target_include_directories(json PUBLIC SYSTEM "${json_SOURCE_DIR}/single_include") diff --git a/include/CLI/StringTools.hpp b/include/CLI/StringTools.hpp index 116a247b..77899fd9 100644 --- a/include/CLI/StringTools.hpp +++ b/include/CLI/StringTools.hpp @@ -165,7 +165,7 @@ CLI11_INLINE bool valid_name_string(const std::string &str); /// Verify an app name inline bool valid_alias_name_string(const std::string &str) { - static const std::string badChars(std::string("\n") + '\0'); + static const std::string badChars{'\n', '\0'}; return (str.find_first_of(badChars) == std::string::npos); } diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index c4941006..20ca59b3 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -1130,7 +1130,14 @@ bool lexical_cast(const std::string &input, T &output) { output = static_cast(input[0]); return true; } - return integral_conversion(input, output); + std::int8_t res{0}; + // we do it this way as some systems have char as signed and not, this ensures consistency in the way things are + // handled + bool result = integral_conversion(input, res); + if(result) { + output = static_cast(res); + } + return result; } /// Boolean values diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 60e2558a..870666c1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -if(CLI11_SANITIZERS AND ${CMAKE_VERSION} VERSION_GREATER "3.13.0") +if(CLI11_SANITIZERS AND ${CMAKE_VERSION} VERSION_GREATER "3.15.0") message(STATUS "Using arsenm/sanitizers-cmake") FetchContent_Declare( sanitizers @@ -6,11 +6,7 @@ if(CLI11_SANITIZERS AND ${CMAKE_VERSION} VERSION_GREATER "3.13.0") GIT_SHALLOW 1 GIT_TAG 0573e2e) - FetchContent_GetProperties(sanitizers) - - if(NOT sanitizers_POPULATED) - FetchContent_Populate(sanitizers) - endif() + FetchContent_MakeAvailable(sanitizers) list(APPEND CMAKE_MODULE_PATH "${sanitizers_SOURCE_DIR}/cmake") @@ -119,6 +115,7 @@ foreach(DATA_FILE IN LISTS DATA_FILES) VERBATIM) endforeach() add_custom_target(cli11_test_data DEPENDS ${DATA_FILES}) +set_target_properties(cli11_test_data PROPERTIES FOLDER "Tests/Apps") # Make a shim if we are building single file tests if(CLI11_SINGLE_FILE AND CLI11_INSTALL_PACKAGE_TESTS) @@ -132,6 +129,7 @@ set(CLI11_DEPENDENT_APPLICATIONS ensure_utf8 ensure_utf8_twice) foreach(APP IN LISTS CLI11_DEPENDENT_APPLICATIONS) add_executable(${APP} applications/${APP}.cpp) target_include_directories(${APP} PRIVATE ${CMAKE_SOURCE_DIR}/include) + set_target_properties(${APP} PROPERTIES FOLDER "Tests/Apps") endforeach() function(add_dependent_application_definitions TARGET) @@ -139,6 +137,10 @@ function(add_dependent_application_definitions TARGET) string(TOUPPER ${APP} APP_UPPERCASE) target_compile_definitions(${TARGET} PRIVATE CLI11_${APP_UPPERCASE}_EXE="$") + + if(WIN32) + target_link_libraries(${APP} PRIVATE Shell32) + endif() endforeach() endfunction() @@ -246,6 +248,7 @@ if(CLI11_FORCE_LIBCXX) PROPERTY LINK_FLAGS -stdlib=libc++) endif() +set_target_properties(informational PROPERTIES FOLDER "Tests/Apps") # Force this to be in a standard location so CTest can find it set_target_properties( informational diff --git a/tests/HelpersTest.cpp b/tests/HelpersTest.cpp index f105f7ac..5412545c 100644 --- a/tests/HelpersTest.cpp +++ b/tests/HelpersTest.cpp @@ -274,7 +274,7 @@ TEST_CASE("StringTools: binaryEscapeConversion", "[helpers]") { testString2.push_back(0); testString2.push_back(static_cast(197)); testString2.push_back(78); - testString2.push_back(-34); + testString2.push_back(static_cast(-34)); rstring = CLI::detail::extract_binary_string(CLI::detail::binary_escape_string(testString2)); CHECK(rstring == testString2); @@ -294,8 +294,8 @@ TEST_CASE("StringTools: binaryEscapeConversion2", "[helpers]") { testString.push_back(0); testString.push_back(0); testString.push_back(56); - testString.push_back(-112); - testString.push_back(-112); + testString.push_back(static_cast(-112)); + testString.push_back(static_cast(-112)); testString.push_back(39); testString.push_back(97); std::string estring = CLI::detail::binary_escape_string(testString); @@ -310,8 +310,8 @@ TEST_CASE("StringTools: binaryEscapeConversion_withX", "[helpers]") { testString.push_back(0); testString.push_back(0); testString.push_back(56); - testString.push_back(-112); - testString.push_back(-112); + testString.push_back(static_cast(-112)); + testString.push_back(static_cast(-112)); testString.push_back(39); testString.push_back(97); std::string estring = CLI::detail::binary_escape_string(testString); @@ -324,12 +324,12 @@ TEST_CASE("StringTools: binaryEscapeConversion_withBrackets", "[helpers]") { std::string vstr = R"raw('B"([\xb0\x0a\xb0/\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0])"')raw"; std::string testString("["); - testString.push_back(-80); + testString.push_back(static_cast(-80)); testString.push_back('\n'); - testString.push_back(-80); + testString.push_back(static_cast(-80)); testString.push_back('/'); for(int ii = 0; ii < 13; ++ii) { - testString.push_back(-80); + testString.push_back(static_cast(-80)); } testString.push_back(']'); diff --git a/tests/app_helper.hpp b/tests/app_helper.hpp index 5f372c3d..876a401c 100644 --- a/tests/app_helper.hpp +++ b/tests/app_helper.hpp @@ -112,8 +112,8 @@ CLI11_INLINE void check_identical_files(const char *path1, const char *path2) { file1.seekg(0); file2.seekg(0); - std::array buffer1; - std::array buffer2; + static std::array buffer1; + static std::array buffer2; for(size_t ibuffer = 0; file1.good(); ++ibuffer) { // Flawfinder: ignore