From f55b63e258d535ff69d099e502e832b33aea6499 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Mon, 23 May 2016 15:32:27 -0400 Subject: [PATCH 1/2] Add missing string.h header required for strcmp --- src/cxxopts.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cxxopts.hpp b/src/cxxopts.hpp index 9207f63..c1f9c6e 100644 --- a/src/cxxopts.hpp +++ b/src/cxxopts.hpp @@ -38,6 +38,7 @@ THE SOFTWARE. #include #include #include +#include //when we ask cxxopts to use Unicode, help strings are processed using ICU, //which results in the correct lengths being computed for strings when they From dd069b6893175cd4a10310bec75a13cf8ee4da98 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Mon, 23 May 2016 15:40:10 -0400 Subject: [PATCH 2/2] Add support for MSVC 2013 Update 5 or newer Use the CMake WriteCompilerDetectionHeader module to add generate a header with compatibility macros. - For static constants, use `const` instead of `constexpr` - Drop `noexcept` if not supported by the compiler - Use ASCII string literals if unicode literals are not supported and replace unicode opening/closing single quotes with ASCII backticks. --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 33 +++++++++++++++++++++++++++++---- src/cxxopts.hpp | 46 ++++++++++++++++++++++++++++++---------------- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 219a714..8a30e80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ RETURN() ENDIF() -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.1) project(cxxopts) set(VERSION "0.0.1") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 625abe9..d6f9b3d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,9 +18,34 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -add_executable(example example.cpp) +add_executable(example example.cpp cxxopts.hpp) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") -target_link_libraries(example ${CXXOPTS_LINKER_LIBRARIES}) +# Visual Studio 12 2013 Update 5 or newer is required to fix in-class member +# initialization using std::make_shared. +# https://connect.microsoft.com/VisualStudio/feedbackdetail/view/818825 +if(MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0.21005.1) + message(SEND_ERROR "Visual Studio 12 2013 Update 5 or newer is required.") +endif() -install(FILES cxxopts.hpp DESTINATION include) +target_link_libraries(example + ${CXXOPTS_LINKER_LIBRARIES} + ) +target_compile_features(example PUBLIC + cxx_auto_type + ) +target_include_directories(example PUBLIC + ${CMAKE_CURRENT_BINARY_DIR} + ) + +include(WriteCompilerDetectionHeader) +write_compiler_detection_header( + FILE cxxopts_compiler_detection.h + PREFIX cxxopts + COMPILERS GNU MSVC Clang + FEATURES + cxx_unicode_literals + cxx_constexpr + cxx_noexcept +) + +install(FILES cxxopts.hpp ${CMAKE_CURRENT_BINARY_DIR}/cxxopts_compiler_detection.h DESTINATION include) diff --git a/src/cxxopts.hpp b/src/cxxopts.hpp index c1f9c6e..57386fc 100644 --- a/src/cxxopts.hpp +++ b/src/cxxopts.hpp @@ -40,6 +40,20 @@ THE SOFTWARE. #include #include +#include + +#if cxxopts_COMPILER_CXX_CONSTEXPR +#define cxxopts_CONSTEXPR_OR_CONST constexpr +#else +#define cxxopts_CONSTEXPR_OR_CONST const +#endif + +#if cxxopts_COMPILER_CXX_UNICODE_LITERALS +#define cxxopts_U8(x) u8 ## x +#else +#define cxxopts_U8(x) x +#endif + //when we ask cxxopts to use Unicode, help strings are processed using ICU, //which results in the correct lengths being computed for strings when they //are formatted for the help output @@ -272,7 +286,7 @@ namespace cxxopts } virtual const char* - what() const noexcept + what() const cxxopts_NOEXCEPT { return m_message.c_str(); } @@ -304,7 +318,7 @@ namespace cxxopts { public: option_exists_error(const std::string& option) - : OptionSpecException(u8"Option ‘" + option + u8"’ already exists") + : OptionSpecException(cxxopts_U8("Option `") + option + cxxopts_U8("` already exists")) { } }; @@ -313,7 +327,7 @@ namespace cxxopts { public: invalid_option_format_error(const std::string& format) - : OptionSpecException(u8"Invalid option format ‘" + format + u8"’") + : OptionSpecException(cxxopts_U8("Invalid option format `") + format + cxxopts_U8("`")) { } }; @@ -322,7 +336,7 @@ namespace cxxopts { public: option_not_exists_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ does not exist") + : OptionParseException(cxxopts_U8("Option `") + option + cxxopts_U8("` does not exist")) { } }; @@ -331,7 +345,7 @@ namespace cxxopts { public: missing_argument_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ is missing an argument") + : OptionParseException(cxxopts_U8("Option `") + option + cxxopts_U8("` is missing an argument")) { } }; @@ -340,7 +354,7 @@ namespace cxxopts { public: option_requires_argument_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ requires an argument") + : OptionParseException(cxxopts_U8("Option `") + option + cxxopts_U8("` requires an argument")) { } }; @@ -354,8 +368,8 @@ namespace cxxopts const std::string& arg ) : OptionParseException( - u8"Option ‘" + option + u8"’ does not take an argument, but argument‘" - + arg + "’ given") + cxxopts_U8("Option `") + option + cxxopts_U8("` does not take an argument, but argument`") + + arg + "` given") { } }; @@ -364,7 +378,7 @@ namespace cxxopts { public: option_not_present_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ not present") + : OptionParseException(cxxopts_U8("Option `") + option + cxxopts_U8("` not present")) { } }; @@ -377,7 +391,7 @@ namespace cxxopts const std::string& arg ) : OptionParseException( - u8"Argument ‘" + arg + u8"’ failed to parse" + cxxopts_U8("Argument `") + arg + cxxopts_U8("` failed to parse") ) { } @@ -429,25 +443,25 @@ namespace cxxopts template struct value_has_arg { - static constexpr bool value = true; + static cxxopts_CONSTEXPR_OR_CONST bool value = true; }; template <> struct value_has_arg { - static constexpr bool value = false; + static cxxopts_CONSTEXPR_OR_CONST bool value = false; }; template struct type_is_container { - static constexpr bool value = false; + static cxxopts_CONSTEXPR_OR_CONST bool value = false; }; template struct type_is_container> { - static constexpr bool value = true; + static cxxopts_CONSTEXPR_OR_CONST bool value = true; }; template @@ -822,8 +836,8 @@ namespace cxxopts namespace { - constexpr int OPTION_LONGEST = 30; - constexpr int OPTION_DESC_GAP = 2; + cxxopts_CONSTEXPR_OR_CONST int OPTION_LONGEST = 30; + cxxopts_CONSTEXPR_OR_CONST int OPTION_DESC_GAP = 2; std::basic_regex option_matcher ("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([a-zA-Z]+)");