diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ae22de..f188762 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,19 @@ cmake_minimum_required(VERSION 3.4 FATAL_ERROR) -project(CLI11 LANGUAGES CXX) +set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"") -SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +# Read in the line containing the version +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/Version.hpp" + VERSION_STRING REGEX ${VERSION_REGEX}) +# Pick out just the version +string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}") + +project(CLI11 LANGUAGES CXX VERSION ${VERSION_STRING}) + +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + +# User settable set(CLI_CXX_STD "11" CACHE STRING "The CMake standard to require") if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) @@ -70,6 +80,18 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include) # to Config.cmake (otherwise we'd have a custom config and would # import Targets.cmake +# Add the version in a CMake readable way +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + CLI11ConfigVersion.cmake + VERSION ${CLI11_VERSION} + COMPATIBILITY AnyNewerVersion + ) + +# Make version available in the install +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/CLI11ConfigVersion.cmake" + DESTINATION lib/cmake/CLI11) + # Make an export target install(TARGETS CLI11 EXPORT CLI11Targets) @@ -129,3 +151,24 @@ if(CLI_EXAMPLES) add_subdirectory(examples) endif() +# Packaging support +set(CPACK_PACKAGE_VENDOR "github.com/CLIUtils/CLI11") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Command line interface") +set(CPACK_PACKAGE_VERSION_MAJOR ${CLI11_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${CLI11_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${CLI11_VERSION_PATCH}) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +set(CPACK_SOURCE_GENERATOR "TGZ;ZIP") +# CPack collects *everything* except what's listed here. +set(CPACK_SOURCE_IGNORE_FILES + /.git + /dist + /.*build.* + /\\\\.DS_Store + /.*\\\\.egg-info + /var + /Pipfile.*$ +) +include(CPack) + diff --git a/cmake/AddGoogletest.cmake b/cmake/AddGoogletest.cmake index c85c61e..80eb9ed 100644 --- a/cmake/AddGoogletest.cmake +++ b/cmake/AddGoogletest.cmake @@ -15,7 +15,11 @@ download_project(PROJ googletest ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# CMake warning suppression will not be needed in version 1.9 +set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "") add_subdirectory(${googletest_SOURCE_DIR} ${googletest_SOURCE_DIR} EXCLUDE_FROM_ALL) +unset(CMAKE_SUPPRESS_DEVELOPER_WARNINGS) if (CMAKE_CONFIGURATION_TYPES) add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} diff --git a/conanfile.py b/conanfile.py index 9949f12..77e584f 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,14 +1,24 @@ from conans import ConanFile, CMake +from conans.tools import load +import re + +def get_version(): + try: + content = load("include/CLI/Version.hpp") + version = re.search(r'#define CLI11_VERSION "(.*)"', content).group(1) + return version + except Exception: + return None class HelloConan(ConanFile): name = "CLI11" - version = "1.3.0" + version = get_version() url = "https://github.com/CLIUtils/CLI11" settings = "os", "compiler", "arch", "build_type" license = "BSD 3 clause" description = "Command Line Interface toolkit for C++11" - exports_sources = "LICENCE", "include/*", "cmake/*", "CMakeLists.txt", "tests/*" + exports_sources = "LICENSE", "README.md", "include/*", "cmake/*", "CMakeLists.txt", "tests/*" def build(self): # this is not building a library, just tests cmake = CMake(self) diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index 58476d9..fecdbaf 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -79,8 +79,9 @@ template (std::stoll(input, &n, 0)); - return n == input.size(); + long long output_ll = std::stoll(input, &n, 0); + output = static_cast(output_ll); + return n == input.size() && static_cast(output) == output_ll; } catch(const std::invalid_argument &) { return false; } catch(const std::out_of_range &) { @@ -97,8 +98,9 @@ bool lexical_cast(std::string input, T &output) { try { size_t n = 0; - output = static_cast(std::stoull(input, &n, 0)); - return n == input.size(); + unsigned long long output_ll = std::stoull(input, &n, 0); + output = static_cast(output_ll); + return n == input.size() && static_cast(output) == output_ll; } catch(const std::invalid_argument &) { return false; } catch(const std::out_of_range &) { diff --git a/tests/HelpersTest.cpp b/tests/HelpersTest.cpp index 0660dac..0f6d87a 100644 --- a/tests/HelpersTest.cpp +++ b/tests/HelpersTest.cpp @@ -348,6 +348,16 @@ TEST(Types, TypeName) { EXPECT_EQ("TEXT", text2_name); } +TEST(Types, OverflowSmall) { + char x; + auto strmax = std::to_string(INT8_MAX + 1); + EXPECT_FALSE(CLI::detail::lexical_cast(strmax, x)); + + unsigned char y; + strmax = std::to_string(UINT8_MAX + 1); + EXPECT_FALSE(CLI::detail::lexical_cast(strmax, y)); +} + TEST(Types, LexicalCastInt) { std::string signed_input = "-912"; int x_signed; @@ -357,7 +367,7 @@ TEST(Types, LexicalCastInt) { std::string unsigned_input = "912"; unsigned int x_unsigned; EXPECT_TRUE(CLI::detail::lexical_cast(unsigned_input, x_unsigned)); - EXPECT_EQ(912, x_unsigned); + EXPECT_EQ((unsigned int)912, x_unsigned); EXPECT_FALSE(CLI::detail::lexical_cast(signed_input, x_unsigned));