├── .clang-format ├── .clang-tidy ├── .editorconfig ├── .github ├── CODEOWNERS ├── FUNDING.yml └── workflows │ └── cmake.yml ├── .gitignore ├── .markdownlint.yaml ├── .options.cmake ├── .version.cmake ├── .vscode ├── launch.json └── settings.json ├── CHANGELOG ├── CMakeLists.txt ├── LICENSE ├── README.md ├── addons └── loaders │ ├── yaml_loader.cmake │ └── yaml_loader.hh ├── build.sh ├── ci └── vcpkg │ └── ports │ └── cmdr-cxx │ ├── portfile.cmake │ └── vcpkg.json ├── cmake ├── Modules │ └── FindXXX.cmake ├── add-policies.cmake ├── config-base.h.in ├── cxx-detect-compilers.cmake ├── cxx-macros.cmake ├── debug-cmd.cmake ├── detect-systems.cmake ├── dummy-project.cmake ├── lexer-tools.cmake ├── load-catch2.cmake ├── load-cmdr-cxx.cmake ├── load-flex.cmake ├── load-googletest.cmake ├── load-llvm.cmake ├── modules-dir.md ├── old │ ├── a-c-p-v.cmake.in │ ├── cxx-standard-def.cmake │ ├── deps_inc_catch2.cmake │ ├── deps_inc_fmt.cmake │ ├── deps_inc_spdlog.cmake │ └── install-pack-helpers.cmake ├── options-def.cmake ├── package-deb.cmake ├── package-dmg.cmake ├── package-rpm.cmake ├── pkg-mgmt.cmake ├── prerequisites.cmake ├── setup-build-env.cmake ├── target-dirs.cmake ├── utils.cmake ├── vcpkg-integration.cmake ├── version-def.cmake ├── version.h.in ├── versions-extract.py └── versions-gen.cmake ├── cmdr-cxx.pc.in ├── docs ├── .gitignore ├── CMakeLists.txt ├── Doxyfile.in ├── README.md ├── customdoxygen.css ├── footer.html ├── header.html ├── logo-square.svg ├── logo-wide.svg ├── release-v0.6.0.txt └── release-v0.6.1.txt ├── examples ├── CMakeLists.txt ├── app1.cc ├── app2.cc ├── more │ ├── CMakeLists.txt │ ├── app1 │ │ ├── CMakeLists.txt │ │ ├── custom_iterator.hh │ │ ├── main.cc │ │ ├── null_stream.cc │ │ └── small_cases.cc │ └── app2 │ │ ├── CMakeLists.txt │ │ └── main.cc ├── second_src.cc ├── second_src.hh └── simple-app.cc ├── libs ├── CMakeLists.txt └── cmdr11 │ ├── CMakeLists.txt │ ├── cmake │ └── cmdr11Config.cmake │ ├── cmdr11-private.hh │ ├── include │ ├── cmdr-cxx.hh │ └── cmdr11 │ │ ├── cmdr11.hh │ │ ├── cmdr_app.hh │ │ ├── cmdr_app_inl.h │ │ ├── cmdr_arg.hh │ │ ├── cmdr_chrono.hh │ │ ├── cmdr_cmd.hh │ │ ├── cmdr_cmd_inl.h │ │ ├── cmdr_cmn.hh │ │ ├── cmdr_common.hh │ │ ├── cmdr_dbg.hh │ │ ├── cmdr_defs.hh │ │ ├── cmdr_if.hh │ │ ├── cmdr_imp1.hh │ │ ├── cmdr_impl.hh │ │ ├── cmdr_internals.hh │ │ ├── cmdr_ios.hh │ │ ├── cmdr_log.hh │ │ ├── cmdr_mmap.hh │ │ ├── cmdr_opts.hh │ │ ├── cmdr_os_io_redirect.hh │ │ ├── cmdr_path.hh │ │ ├── cmdr_pipeable.hh │ │ ├── cmdr_pool.hh │ │ ├── cmdr_priority_queue.hh │ │ ├── cmdr_process.hh │ │ ├── cmdr_public.hh │ │ ├── cmdr_small_string.hh │ │ ├── cmdr_string.hh │ │ ├── cmdr_terminal.hh │ │ ├── cmdr_types.hh │ │ ├── cmdr_types_check.hh │ │ ├── cmdr_utils.hh │ │ ├── cmdr_var_t.hh │ │ ├── cmdr_var_t_inl.h │ │ ├── cmdr_x_class.hh │ │ ├── cmdr_x_test.hh │ │ └── cmdr_z_test.hh │ ├── src │ ├── main.cc │ └── private.cc │ └── tests │ ├── CMakeLists.txt │ ├── main.cxx │ └── test_store.cc └── tests ├── .gitignore ├── CMakeLists.txt ├── any_1.cc ├── app1.cc ├── app2.cc ├── basic.cc ├── chrono_literals_test.cc ├── chrono_test.cc ├── compiler.cc ├── complex_test.cc ├── etc ├── app1 │ └── app1.yml └── ex-app1.yml ├── factory.cc ├── flags_c2.cc ├── inplace_constructions.cc ├── jaro_c2.cc ├── mem_test_for_singleton.cc ├── observer.cc ├── pool.cc ├── priority_queue.cc ├── process.cc ├── second_src.cc ├── second_src.hh ├── sso_test_1.cc ├── sso_test_2.cc ├── store_c2.cc ├── traits.cc ├── valarray_test.cc ├── visit_any.cc └── visit_any.hh /.clang-format: -------------------------------------------------------------------------------- 1 | # Generated from CLion C/C++ Code Style settings 2 | --- 3 | Language: Cpp 4 | BasedOnStyle: LLVM 5 | AccessModifierOffset: -2 6 | AlignAfterOpenBracket: Align 7 | AlignConsecutiveAssignments: AcrossEmptyLinesAndComments 8 | AlignOperands: Align 9 | AlignTrailingComments: true 10 | AllowAllArgumentsOnNextLine: false 11 | AllowAllConstructorInitializersOnNextLine: false 12 | AllowAllParametersOfDeclarationOnNextLine: false 13 | AllowShortBlocksOnASingleLine: Always 14 | AllowShortCaseLabelsOnASingleLine: false 15 | AllowShortFunctionsOnASingleLine: All 16 | AllowShortIfStatementsOnASingleLine: Always 17 | AllowShortLambdasOnASingleLine: All 18 | AllowShortLoopsOnASingleLine: true 19 | AlwaysBreakAfterReturnType: None 20 | AlwaysBreakTemplateDeclarations: Yes 21 | BreakBeforeBraces: Custom 22 | BraceWrapping: 23 | AfterCaseLabel: false 24 | AfterClass: false 25 | AfterControlStatement: Never 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterUnion: false 30 | BeforeCatch: false 31 | BeforeElse: false 32 | IndentBraces: false 33 | SplitEmptyFunction: false 34 | SplitEmptyRecord: true 35 | BreakBeforeBinaryOperators: None 36 | BreakBeforeTernaryOperators: true 37 | BreakConstructorInitializers: BeforeComma 38 | BreakInheritanceList: BeforeComma 39 | ColumnLimit: 0 40 | CompactNamespaces: true 41 | ContinuationIndentWidth: 4 42 | FixNamespaceComments: true 43 | IndentCaseLabels: true 44 | IndentPPDirectives: None 45 | IndentWidth: 2 46 | KeepEmptyLinesAtTheStartOfBlocks: true 47 | MaxEmptyLinesToKeep: 2 48 | NamespaceIndentation: All 49 | ObjCSpaceAfterProperty: false 50 | ObjCSpaceBeforeProtocolList: true 51 | PointerAlignment: Right 52 | ReflowComments: false 53 | SpaceAfterCStyleCast: true 54 | SpaceAfterLogicalNot: false 55 | SpaceAfterTemplateKeyword: false 56 | SpaceBeforeAssignmentOperators: true 57 | SpaceBeforeCpp11BracedList: false 58 | SpaceBeforeCtorInitializerColon: true 59 | SpaceBeforeInheritanceColon: true 60 | SpaceBeforeParens: ControlStatements 61 | SpaceBeforeRangeBasedForLoopColon: false 62 | SpaceInEmptyParentheses: false 63 | SpacesBeforeTrailingComments: 1 64 | SpacesInAngles: false 65 | SpacesInCStyleCastParentheses: false 66 | SpacesInContainerLiterals: false 67 | SpacesInParentheses: false 68 | SpacesInSquareBrackets: false 69 | TabWidth: 2 70 | UseTab: Never 71 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # Note #1: the full list of Clang-Tidy checks can be found at 2 | # https://clang.llvm.org/extra/clang-tidy/checks/list.html... 3 | # Note #2: performance-no-automatic-move shouldn't be disabled, but we have to 4 | # due to an issue with Qt (see 5 | # https://bugreports.qt.io/browse/QTBUG-85415)... 6 | # Note #3: readability-redundant-access-specifiers shouldn't normally be 7 | # disabled, but Clang-Tidy gets a bit confused with access specifiers 8 | # like "public" vs. "public slots"... 9 | 10 | # Note: if you make changes here, you may need to make changes in .clang-tidy 11 | # files elsewhere in the tree; clang-tidy-10 doesn't allow selective 12 | # inheritance of parent .clang-tidy files. 13 | 14 | 15 | --- 16 | Checks: >- 17 | -*, 18 | clang-diagnostic-*, 19 | llvm-*, 20 | misc-*, 21 | -misc-unused-parameters, 22 | -misc-non-private-member-variables-in-classes, 23 | -readability-identifier-naming 24 | -readability-redundant-access-specifiers 25 | 26 | # Note that the readability-identifier-naming check is disabled, there are too 27 | # many violations in the codebase and they create too much noise in clang-tidy 28 | # results. 29 | # Naming settings are kept for documentation purposes and allowing to run the 30 | # check if the users would override this file, e.g. via a command-line arg. 31 | CheckOptions: 32 | - key: readability-identifier-naming.ClassCase 33 | value: CamelCase 34 | - key: readability-identifier-naming.EnumCase 35 | value: CamelCase 36 | - key: readability-identifier-naming.FunctionCase 37 | value: camelBack 38 | - key: readability-identifier-naming.MemberCase 39 | value: CamelCase 40 | - key: readability-identifier-naming.ParameterCase 41 | value: CamelCase 42 | - key: readability-identifier-naming.UnionCase 43 | value: CamelCase 44 | - key: readability-identifier-naming.VariableCase 45 | value: CamelCase 46 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo. 2 | # * @hedzr 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: [hedzr] 4 | # open_collective: cmdr-cxx 5 | custom: https://paypal.me/hezr/5 6 | # custom: https://paypal.me/hezr/20 7 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md 3 | # 4 | default: true 5 | 6 | MD002: false # first-heading-h1 7 | MD003: # heading-style, https://github.com/DavidAnson/markdownlint/blob/main/doc/md003.md 8 | style: atx 9 | MD006: false # ul-start-left 10 | MD007: # ul-indent 11 | indent: 2 12 | 13 | no-hard-tabs: false # MD010 14 | 15 | MD012: false # no-multiple-blanks 16 | MD013: # https://github.com/DavidAnson/markdownlint/blob/main/doc/md013.md 17 | line_length: 256 18 | 19 | MD033: # no-inline-html 20 | allowed_elements: [details, summary, kbd, table, th, tr, td] 21 | 22 | MD041: false # first-line-h1 23 | -------------------------------------------------------------------------------- /.options.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | #option(CMDR_ENABLE_AUTO_COMPLETION_LOGFILE "" OFF) 6 | 7 | 8 | # TO DO - via cmdr::log::holder 9 | #option(CMDR_ENABLE_LOGFILE "" OFF) 10 | 11 | 12 | 13 | option(CMDR_NO_3RDPARTY "for cmdr-cxx, disable source codes and targets alternate to yaml-cpp and others" OFF) 14 | -------------------------------------------------------------------------------- /.version.cmake: -------------------------------------------------------------------------------- 1 | file(READ ".build-serial" BUILD_SERIAL) 2 | set(VERSION 0.6.3.${BUILD_SERIAL}) -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(lldb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/bin/app1", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${workspaceFolder}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "lldb" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", 3 | "terminal.integrated.allowMnemonics": true, 4 | "python.formatting.provider": "yapf", 5 | "cmake.configureArgs": [ 6 | "-DCMAKE_VERBOSE_DEBUG=ON -DENABLE_AUTOMATE_TESTS=OFF" 7 | ], 8 | // "cmake.buildToolArgs": ["--verbose"], 9 | "cmake.allowCommentsInPresetsFile": true 10 | } 11 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Status 4 | 5 | - v0.6.3 6 | - add a simple-app demo app 7 | - added `app::subtree(prefix)` to get the exact tree node by its dotted path key. 8 | - make `sub_cmd::get()` and `arg::get()` const 9 | - doc `bas::_long, _short, _aliases` 10 | - doc the `app::store()` 11 | - improved gh action scripts; 12 | 13 | - v0.6.1 14 | - improved cmake/config-base.h.in; 15 | - improved gh action scripts; 16 | - c++20 ready 17 | 18 | - v0.6.0 19 | - improved load-cmdr-cxx.cmake for cmdr-cxx users; 20 | - updated gh action scripts; 21 | - fix windows build again; 22 | - upgraded cmake/ scripts; 23 | - downward compatible with python 3.8-; 24 | - upgraded to catch2 3.7.1+; 25 | - improved compiler detectors and `-#`/`-V` outputs; 26 | - improved typo/lint pieces; 27 | - improved macro defs - fix _countof(); added offsetof(); ... 28 | - cleanup 29 | - c++20 ready 30 | 31 | - v0.5.11 - simple updates to follow the newest devenv 32 | - v0.5.9 - fixed `deps-cmdr11.cmake` for you, added `CMDR_NO_3RDPARTY` option to disable importing and linking with 3rd-party libraries 33 | - v0.5.8 - fixed unused `requires` in cmdr-chrono.hh 34 | - v0.5.7 - fixed all builds on c++20 (unused param; ambiguous operator << for time_point/duration; ...) 35 | - v0.5.5 - fixed importing cmdr11(-cxx) via cmake ExternalProject_Add 36 | - v0.5.3 - fixed upload-artifact in last release 37 | - v0.5.2 - fixed upload/download-artifact in last release; compliant with c++20 or higher 38 | - v0.5.1 - security patch the workflow script; fixed it; 39 | - v0.5.0 - upgraded to compliant with cxx20 and later 40 | 41 | - v0.3.1 - bugs fixed and added constexpr compiler_name and a new test: test-compiler; 42 | - v0.3.0 - bugs fixed and sync codes for main compilers; 43 | 44 | - v0.2.27 - LICENSE Changed to Apache 2.0; better adaptive in cmake import; 45 | - v0.2.25 - follow windows virtual environment changed in adaptation; format codes with better style 46 | - v0.2.23 - improved ci scripts, traits, detections, and more for better cross-platform portability; 47 | - v0.2.21 - bug fixed; add more utilities: mmap, thread pool, factory, pipeable, ...; 48 | - v0.2.20 - changed OS_xxx macros; added more portability; 49 | - v0.2.19 - bug fixed 50 | - v0.2.17 - added to homebrew. 51 | - v0.2.15 - bug fixed 52 | - v0.2.13 - any kind of fixes; added priority-queue; added `ASSERTIONS_ONLY`, `NO_ASSERTIONS_ONLY`; added `is_iterable`, added vector_to_string(vec); `defer` & `defer`; many improvements merged; 53 | - v0.2.11 - maintained 54 | - v0.2.10 - MSVC (Build Tool 16.7.2+, VS2019 passed), and others improvements (bash completion, ...) 55 | - v0.2.9 - various fixes, improvements 56 | - v0.2.8 - fixed cmdr11Config.cmake for importing transparently 57 | - v0.2.7 - `auto &cli = cmdr::create(...)` 58 | - v0.2.5 - public release starts 59 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # # TPL ## HEAD ########## 2 | cmake_minimum_required(VERSION 3.11) 3 | 4 | # ### INCLUDES ########################################################## 5 | include(${CMAKE_SOURCE_DIR}/cmake/prerequisites.cmake) 6 | 7 | # use_vcpkg() 8 | 9 | # ### DEFINITIONS ####################################################### 10 | set(PROJECT_MACRO_NAME cmdr-cxx) 11 | set(PROJECT_MACRO_SHORT_NAME cmdr) 12 | set(PROJECT_MACRO_MID_NAME cmdr11) 13 | set(PROJECT_MACRO_PREFIX "CMDR") 14 | set_property(GLOBAL PROPERTY PROJECT_MAINTAINER "hedzr ") 15 | 16 | # ### OPTIONS ########################################################### 17 | 18 | # option(OK "PL-OK" ON) 19 | 20 | # option(${PROJECT_MACRO_PREFIX}_BUILD_TESTS_EXAMPLES "Build Test Examples OK" OFF) 21 | # option(${PROJECT_MACRO_PREFIX}_BUILD_DOCS "Build Docs-OK" OFF) 22 | 23 | # the following options are just used for executables 24 | option(${PROJECT_MACRO_PREFIX}_ENABLE_ASSERTIONS "Enable Assertions" OFF) 25 | option(${PROJECT_MACRO_PREFIX}_ENABLE_PRECONDITION_CHECKS "Enable Precondition Checks" OFF) 26 | option(${PROJECT_MACRO_PREFIX}_ENABLE_THREAD_POOL_READY_SIGNAL "Enable ready signal actions in thread_pool template class" OFF) 27 | option(${PROJECT_MACRO_PREFIX}_ENABLE_VERBOSE_LOG "Enable `dbg_verbose_debug` macro definition (TRACE MODE)" OFF) 28 | option(${PROJECT_MACRO_PREFIX}_TEST_THREAD_POOL_DBGOUT "Enable `pool_debug` macro definition" OFF) 29 | option(${PROJECT_MACRO_PREFIX}_UNIT_TEST "Enable the extra unit-tests" OFF) 30 | 31 | 32 | # ### PROJECTS PREPARE ################################################## 33 | if(ENABLE_TESTS) 34 | include(CTest) 35 | endif() 36 | 37 | find_package(Threads REQUIRED) 38 | 39 | # ### PROJECTS ########################################################## 40 | project(cmdr-cxx 41 | VERSION ${VERSION} 42 | DESCRIPTION "cmdr-cxx is a POSIX-compliant command-line arguments parser in C++, its part of cmdr series." 43 | LANGUAGES CXX) 44 | debug_print_project_title() 45 | 46 | set(VERSION_H_NAME "cmdr-version.hh") 47 | 48 | # Enable C++ Standard 17/20 here. Change it on fist configuring, or update it with new value: 49 | # cmake -S. -Bbuild -DCXX_STANDARD:STRING=20 50 | set(CXX_STANDARD 17 CACHE STRING "Define The C++ Standard, default is 17") 51 | enable_cxx_standard(CXX_STANDARD) 52 | 53 | # if(ENABLE_TESTS) 54 | # include(load-catch2) 55 | # endif() 56 | 57 | # # when using compiler with cmake multi-config feature, a special build type 'Asan' can be used for sanitizing test. 58 | # enable_sanitizer_for_multi_config() 59 | 60 | # # include(cxx-standard-def) 61 | # include(cxx-detect-compilers) 62 | # include(setup-build-env) 63 | 64 | # debug_print_top_vars() 65 | 66 | gen_versions(${PROJECT_MACRO_NAME} ${PROJECT_MACRO_PREFIX} 67 | ${PROJECT_MACRO_SHORT_NAME}-version.hh 68 | ${PROJECT_MACRO_SHORT_NAME}-config-base.hh 69 | ${PROJECT_MACRO_SHORT_NAME}-${PROJECT_VERSION} 70 | ${CMAKE_SOURCE_DIR}/${CMAKE_SCRIPTS}/version.h.in 71 | ${CMAKE_SOURCE_DIR}/${CMAKE_SCRIPTS}/config-base.h.in 72 | ) 73 | 74 | # 75 | # add more subdirectories as submodules and sub-submodules HERE 76 | # 77 | 78 | # define libcmdr11 as a library 79 | add_subdirectory(libs) # adds cmdr-cxx target, and others 80 | 81 | if(${ENABLE_TESTS} OR(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)) 82 | add_subdirectory(tests) 83 | endif() 84 | 85 | if(${ENABLE_DOCS}) 86 | add_subdirectory(docs) 87 | attach_doxygen_to(${PROJECT_MACRO_MID_NAME}) 88 | endif() 89 | 90 | if(${ENABLE_EXAMPLES} OR(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)) 91 | add_subdirectory(examples) 92 | endif() 93 | 94 | # # TPL ## TAIL ########## 95 | message(STATUS "tail of top level : Using C++ Standard ${CMAKE_CXX_STANDARD}") 96 | apply_all_unit_tests(all_tests) # invoke CTest unittests automatically. 97 | dump_feature_summary() # tail print to cmake-debug/features.log 98 | 99 | # env var CTEST_OUTPUT_ON_FAILURE=1 to display ctest error verbosely. 100 | # ctest cmdline options: --verbose or --extra-verbose or --verbose-on-failure 101 | debug_print_value(DEBUG) 102 | debug_print_value(BUILD_DOCUMENTATION) 103 | -------------------------------------------------------------------------------- /addons/loaders/yaml_loader.cmake: -------------------------------------------------------------------------------- 1 | # message(STATUS "1. CI_RUNNING = $ENV{CI_RUNNING}") 2 | # if (!$ENV{CI_RUNNING}) 3 | # 4 | # include(ExternalProject) 5 | # ExternalProject_Add(third-yaml-cpp 6 | # GIT_REPOSITORY https://github.com/jbeder/yaml-cpp 7 | # GIT_TAG origin/master # yaml-cpp-0.6.3 8 | # GIT_SHALLOW 1 9 | # # STEP_TARGETS build 10 | # # SOURCE_DIR "${PROJECT_SOURCE_DIR}/third-party/yaml-cpp-src" 11 | # # BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/yaml-cpp-build" 12 | # CMAKE_ARGS 13 | # -DYAML_CPP_BUILD_TESTS=OFF 14 | # --no-warn-unused-cli 15 | # -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 16 | # # -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} 17 | # # -DCMAKE_INSTALL_PREFIX:PATH=${EXECUTABLE_OUTPUT_PATH} 18 | # BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $ build" 19 | # # COMMAND ${CMAKE_COMMAND} -E sudo "chmod a+w /usr/local/lib" 20 | # COMMAND ${CMAKE_COMMAND} --build --config $ 21 | # COMMAND ${CMAKE_COMMAND} -E echo "$ build complete" 22 | # ) 23 | # 24 | # endif () 25 | # 26 | # 27 | # macro(add_yaml_loader target) 28 | # if (${MACOS}) 29 | # target_include_directories(${target} PRIVATE 30 | # $ 31 | # $ 32 | # /usr/local/include 33 | # ) 34 | # target_link_directories(${target} PRIVATE 35 | # /usr/local/lib 36 | # # ${CMAKE_CURRENT_BINARY_DIR}/third-yaml-cpp-prefix/src/third-yaml-cpp-build 37 | # ) 38 | # target_link_libraries(${target} 39 | # PRIVATE 40 | # yaml-cpp 41 | # ) 42 | # endif () 43 | # 44 | # message(STATUS "2. CI_RUNNING = $ENV{CI_RUNNING}") 45 | # if ($ENV{CI_RUNNING}) 46 | # target_include_directories(${target} PRIVATE 47 | # $ 48 | # $ 49 | # /usr/local/include 50 | # ) 51 | # target_link_directories(${target} PRIVATE 52 | # /usr/local/lib 53 | # # ${CMAKE_CURRENT_BINARY_DIR}/third-yaml-cpp-prefix/src/third-yaml-cpp-build 54 | # ) 55 | # target_link_libraries(${target} 56 | # PRIVATE 57 | # yaml-cpp 58 | # ) 59 | # else () 60 | # message(STATUS "yaml-cpp: add_dependencies") 61 | # add_dependencies(${target} third-yaml-cpp) 62 | # endif () 63 | # endmacro() 64 | 65 | # message(STATUS "yaml_loader: defined macro add_cmdr_cxx_to") 66 | macro(add_yaml_loader_to target) 67 | find_package(yaml-cpp CONFIG REQUIRED) 68 | 69 | # ${YAML_CPP_INCLUDE_DIR} 70 | # ${YAML_CPP_LIBRARIES} 71 | if (NOT ${yaml-cppFOUND}) 72 | message(STATUS "yaml_loader: yaml-cpp not found, try to pick one...") 73 | 74 | set(YAML_PP_TGT_NAME "third-yaml-cpp") 75 | include(ExternalProject) 76 | ExternalProject_Add(${YAML_PP_TGT_NAME} 77 | GIT_REPOSITORY https://github.com/jbeder/yaml-cpp 78 | GIT_TAG yaml-cpp-0.6.3 79 | GIT_SHALLOW 1 80 | GIT_PROGRESS ON 81 | 82 | # STEP_TARGETS build 83 | # SOURCE_DIR "${PROJECT_SOURCE_DIR}/third-party/cmdr-cxx-src" 84 | # BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmdr-cxx-build" 85 | CMAKE_ARGS 86 | -DYAML_CPP_BUILD_TESTS=OFF 87 | --no-warn-unused-cli 88 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 89 | 90 | # -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} 91 | # -DCMAKE_INSTALL_PREFIX:PATH=${EXECUTABLE_OUTPUT_PATH} 92 | BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $ build" 93 | BUILD_COMMAND ${CMAKE_COMMAND} -E sudo "chmod a+w /usr/local/lib /usr/local/include" 94 | COMMAND ${CMAKE_COMMAND} --build --config $ 95 | COMMAND ${CMAKE_COMMAND} -E echo "$ build complete" 96 | ) 97 | 98 | # set(CMDR11_FOUND ON) 99 | message(STATUS "yaml_loader: add ${YAML_PP_TGT_NAME} module to '${target}' from building dir.") 100 | 101 | message(STATUS "yaml_loader: add_dependencies") 102 | add_dependencies(${target} ${YAML_PP_TGT_NAME}) 103 | target_include_directories(${target} PRIVATE ${YAML_CPP_INCLUDE_DIR}) 104 | target_link_directories(${target} PRIVATE ${YAML_CPP_LIBRARY_DIR}) 105 | target_link_libraries(${target} PRIVATE ${YAML_CPP_LIBRARIES}) 106 | 107 | # endif () 108 | else () 109 | message(STATUS "yaml_loader: cmake package found at ${YAML_CPP_INCLUDE_DIR} & ${YAML_CPP_LIBRARY_DIR}, LIBS: ${YAML_CPP_LIBRARIES}") 110 | message(STATUS "yaml_loader: add ${YAML_CPP_LIBRARIES} module to target '${target}' from CMake Modules registry.") 111 | target_include_directories(${target} PRIVATE ${YAML_CPP_INCLUDE_DIR}) 112 | target_link_directories(${target} PRIVATE ${YAML_CPP_LIBRARY_DIR}) 113 | target_link_libraries(${target} PRIVATE ${YAML_CPP_LIBRARIES}) 114 | endif () 115 | 116 | # if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin" OR APPLE) 117 | # message(STATUS "yaml_loader: for target '${target}', added /usr/local/{include,lib}.") 118 | # target_include_directories(${target} SYSTEM PRIVATE 119 | # /usr/local/include 120 | # ) 121 | # target_link_directories(${target} PRIVATE 122 | # /usr/local/lib 123 | # 124 | # # ${CMAKE_CURRENT_BINARY_DIR}/${YAML_PP_TGT_NAME}-prefix/src/${YAML_PP_TGT_NAME}-build 125 | # ) 126 | # 127 | # message(STATUS "yaml_loader: cpu = ${CMAKE_HOST_SYSTEM_PROCESSOR}") 128 | # 129 | # if (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64") 130 | # target_include_directories(${target} SYSTEM PRIVATE 131 | # /opt/homebrew/include 132 | # ) 133 | # target_link_directories(${target} PRIVATE 134 | # /opt/homebrew/lib 135 | # ) 136 | # endif () 137 | # 138 | # # target_link_libraries(${target} 139 | # # PRIVATE 140 | # # cmdr11::cmdr11 141 | # # ) 142 | # endif () 143 | endmacro() 144 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VERSION=$(cat .version.cmake|awk '{print substr($2,1,length($2)-1)}') 4 | 5 | rebuild(){ 6 | [[ -d ./build ]] && rm -rf ./build 7 | 8 | cmake -DENABLE_AUTOMATE_TESTS=OFF -G "Ninja" -S . -B build/ 9 | cmake --build build/ 10 | } 11 | 12 | build(){ 13 | cmake --build build/ 14 | } 15 | 16 | pack(){ 17 | [[ -f build/CPackConfig.cmake ]] && { 18 | cpack --config build/CPackConfig.cmake 19 | is_debian_series && dpkg --info dist/libcmdr11-dev_$VERSION_$(i386_amd64).deb 20 | is_redhat_series && rpm -qip dist/cmdr11-$VERSION-1.$(x86_64).rpm 21 | } 22 | } 23 | 24 | version(){ 25 | echo $VERSION 26 | } 27 | 28 | docs(){ 29 | [ -d build ] && rm -rf build 30 | cmake -DBUILD_DOCUMENTATION=ON -DCMAKE_BUILD_TYPE=Release -S . -B build 31 | cmake --build build/ 32 | } 33 | 34 | 35 | 36 | 37 | osid(){ # fedora / ubuntu 38 | [[ -f /etc/os-release ]] && { 39 | grep -Eo '^ID="?(.+)"?' /etc/os-release|sed -r -e 's/^ID="?(.+)"?/\1/' 40 | } 41 | } 42 | is_fedora(){ [[ "$osid" == fedora ]]; } 43 | is_centos(){ [[ "$osid" == centos ]]; } 44 | is_redhat(){ [[ "$osid" == redhat ]]; } 45 | is_debian(){ [[ "$osid" == debian ]]; } 46 | is_ubuntu(){ [[ "$osid" == ubuntu ]]; } 47 | is_debian(){ [[ "$osid" == debian ]]; } 48 | is_yum (){ which yum 2>/dev/null; } 49 | is_dnf (){ which dnf 2>/dev/null; } 50 | is_apt (){ which apt 2>/dev/null; } 51 | is_redhat_series(){ is_yum || is_dnf; } 52 | is_debian_series(){ is_apt; } 53 | i386_amd64(){ dpkg --print-architecture; } 54 | x86_64(){ uname -m; } 55 | 56 | 57 | $* -------------------------------------------------------------------------------- /ci/vcpkg/ports/cmdr-cxx/portfile.cmake: -------------------------------------------------------------------------------- 1 | # Common Ambient Variables: 2 | # CURRENT_BUILDTREES_DIR = ${VCPKG_ROOT_DIR}\buildtrees\${PORT} 3 | # CURRENT_PACKAGES_DIR = ${VCPKG_ROOT_DIR}\packages\${PORT}_${TARGET_TRIPLET} 4 | # CURRENT_PORT_DIR = ${VCPKG_ROOT_DIR}\ports\${PORT} 5 | # CURRENT_INSTALLED_DIR = ${VCPKG_ROOT_DIR}\installed\${TRIPLET} 6 | # DOWNLOADS = ${VCPKG_ROOT_DIR}\downloads 7 | # PORT = current port name (zlib, etc) 8 | # TARGET_TRIPLET = current triplet (x86-windows, x64-windows-static, etc) 9 | # VCPKG_CRT_LINKAGE = C runtime linkage type (static, dynamic) 10 | # VCPKG_LIBRARY_LINKAGE = target library linkage type (static, dynamic) 11 | # VCPKG_ROOT_DIR = 12 | # VCPKG_TARGET_ARCHITECTURE = target architecture (x64, x86, arm) 13 | # VCPKG_TOOLCHAIN = ON OFF 14 | # TRIPLET_SYSTEM_ARCH = arm x86 x64 15 | # BUILD_ARCH = "Win32" "x64" "ARM" 16 | # MSBUILD_PLATFORM = "Win32"/"x64"/${TRIPLET_SYSTEM_ARCH} 17 | # DEBUG_CONFIG = "Debug Static" "Debug Dll" 18 | # RELEASE_CONFIG = "Release Static"" "Release DLL" 19 | # VCPKG_TARGET_IS_WINDOWS 20 | # VCPKG_TARGET_IS_UWP 21 | # VCPKG_TARGET_IS_LINUX 22 | # VCPKG_TARGET_IS_OSX 23 | # VCPKG_TARGET_IS_FREEBSD 24 | # VCPKG_TARGET_IS_ANDROID 25 | # VCPKG_TARGET_IS_MINGW 26 | # VCPKG_TARGET_EXECUTABLE_SUFFIX 27 | # VCPKG_TARGET_STATIC_LIBRARY_SUFFIX 28 | # VCPKG_TARGET_SHARED_LIBRARY_SUFFIX 29 | # 30 | # See additional helpful variables in /docs/maintainers/vcpkg_common_definitions.md 31 | 32 | # # Specifies if the port install should fail immediately given a condition 33 | # vcpkg_fail_port_install(MESSAGE "cmdr-cxx currently only supports Linux and Mac platforms" ON_TARGET "Windows") 34 | 35 | #find_program(GIT git) 36 | # find git 37 | vcpkg_find_acquire_program( 38 | GIT 39 | ) 40 | #https://gitmemory.com/issue/microsoft/vcpkg/18422/863245438 41 | get_filename_component(GIT_EXE_PATH ${GIT} DIRECTORY) 42 | vcpkg_add_to_path(${GIT_EXE_PATH}) 43 | 44 | message(STATUS "downloading ...") 45 | vcpkg_download_distfile(ARCHIVE 46 | URLS "https://github.com/hedzr/cmdr-cxx/archive/refs/tags/v0.2.20.zip" 47 | FILENAME "cmdr-cxx-v0.2.20.zip" 48 | SHA512 805175d185fc2fc61b316eff0714fad1d50e9fb3619e319481a474fc1800e2594ef005e9fcb5998b16fe62a6996bed14c8a12800e75539e393866f9f20f280f9 49 | ) 50 | 51 | message(STATUS "extracting ...") 52 | vcpkg_extract_source_archive_ex( 53 | OUT_SOURCE_PATH SOURCE_PATH 54 | ARCHIVE ${ARCHIVE} 55 | # (Optional) A friendly name to use instead of the filename of the archive (e.g.: a version number or tag). 56 | # REF 1.0.0 57 | # (Optional) Read the docs for how to generate patches at: 58 | # https://github.com/Microsoft/vcpkg/blob/master/docs/examples/patching.md 59 | # PATCHES 60 | # 001_port_fixes.patch 61 | # 002_more_port_fixes.patch 62 | ) 63 | 64 | # # Check if one or more features are a part of a package installation. 65 | # # See /docs/maintainers/vcpkg_check_features.md for more details 66 | # vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS 67 | # FEATURES # <- Keyword FEATURES is required because INVERTED_FEATURES are being used 68 | # tbb WITH_TBB 69 | # INVERTED_FEATURES 70 | # tbb ROCKSDB_IGNORE_PACKAGE_TBB 71 | # ) 72 | 73 | message(STATUS "configuring ...") 74 | vcpkg_configure_cmake( 75 | SOURCE_PATH ${SOURCE_PATH} 76 | PREFER_NINJA # Disable this option if project cannot be built with Ninja 77 | OPTIONS -DENABLE_AUTOMATE_TESTS=OFF -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT_DIR}/scripts/buildsystems/vcpkg.cmake 78 | # OPTIONS -DUSE_THIS_IN_ALL_BUILDS=1 -DUSE_THIS_TOO=2 79 | # OPTIONS_RELEASE -DOPTIMIZE=1 80 | # OPTIONS_DEBUG -DDEBUGGABLE=1 81 | ) 82 | 83 | message(STATUS "building & installing ...") 84 | vcpkg_install_cmake() 85 | 86 | # # Moves all .cmake files from /debug/share/cmdr-cxx/ to /share/cmdr-cxx/ 87 | # # See /docs/maintainers/vcpkg_fixup_cmake_targets.md for more details 88 | vcpkg_fixup_cmake_targets(CONFIG_PATH cmake TARGET_PATH share/cmdr11) 89 | 90 | # # Handle copyright 91 | file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/cmdr-cxx RENAME copyright) 92 | 93 | 94 | message(STATUS "DONE.") -------------------------------------------------------------------------------- /ci/vcpkg/ports/cmdr-cxx/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cmdr-cxx", 3 | "version-string": "v0.2.21", 4 | "homepage": "https://github.com/hedzr/cmdr-cxx", 5 | "description": "cmdr cxx version, a C++17 header-only command-line parser with hierarchical config data manager here", 6 | "dependencies": [], 7 | "default-features": [], 8 | "features": [ 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /cmake/Modules/FindXXX.cmake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hedzr/cmdr-cxx/671c4b29d926ec986542d554f41c7f74471c99be/cmake/Modules/FindXXX.cmake -------------------------------------------------------------------------------- /cmake/add-policies.cmake: -------------------------------------------------------------------------------- 1 | # Set policies 2 | # https://www.mankier.com/7/cmake-policies 3 | 4 | # CMake Warning (dev) at CMakeLists.txt:5 (ADD_EXECUTABLE): 5 | # Policy CMP0049 is not set: Do not expand variables in target source 6 | # entries. Run "cmake --help-policy CMP0049" for policy details. Use the 7 | # cmake_policy command to set the policy and suppress this warning. 8 | if (POLICY CMP0049) 9 | cmake_policy(SET CMP0049 NEW) 10 | endif () 11 | 12 | if (COMMAND cmake_policy) 13 | # we prefer the more strict behavior, to find out more: 14 | # cmake --help-policy CMP0003 15 | cmake_policy(SET CMP0003 NEW) 16 | endif () 17 | 18 | # Compiler id for Apple Clang is now AppleClang. 19 | if (POLICY CMP0025) 20 | cmake_policy(SET CMP0025 NEW) 21 | endif (POLICY CMP0025) 22 | 23 | # MACOSX_RPATH is enabled by default. 24 | if (POLICY CMP0042) 25 | cmake_policy(SET CMP0042 NEW) 26 | endif () 27 | 28 | # Project version variables are the empty string if version is unspecified 29 | if (POLICY CMP0048) 30 | cmake_policy(SET CMP0048 NEW) 31 | endif (POLICY CMP0048) 32 | 33 | # Only interpret if() arguments as variables or keywords when unquoted. 34 | if (POLICY CMP0054) 35 | cmake_policy(SET CMP0054 NEW) 36 | endif () 37 | 38 | # if command can use IN_LIST 39 | if (POLICY CMP0057) 40 | cmake_policy(SET CMP0057 NEW) 41 | endif (POLICY CMP0057) 42 | 43 | # Honor visibility properties for all target types. 44 | if (POLICY CMP0063) 45 | cmake_policy(SET CMP0063 NEW) 46 | endif () 47 | 48 | if (POLICY CMP0068) 49 | cmake_policy(SET CMP0068 NEW) 50 | endif () 51 | 52 | if (POLICY CMP0069) 53 | cmake_policy(SET CMP0069 NEW) 54 | endif () 55 | 56 | # if (POLICY CMP0070) 57 | # cmake_policy(SET CMP0070 NEW) 58 | # endif () 59 | if (POLICY CMP0076) 60 | cmake_policy(SET CMP0076 NEW) # target_sources() command converts relative paths to absolute 61 | endif () 62 | 63 | # option() honors normal variables 64 | if (POLICY CMP0077) 65 | cmake_policy(SET CMP0077 NEW) 66 | endif (POLICY CMP0077) 67 | 68 | # if (POLICY CMP0086) 69 | # # UseSWIG honors SWIG_MODULE_NAME via -module flag 70 | # cmake_policy(SET CMP0086 NEW) 71 | # endif () 72 | 73 | # Allow the user to specify the MSVC runtime 74 | if (POLICY CMP0091) 75 | cmake_policy(SET CMP0091 NEW) 76 | endif (POLICY CMP0091) 77 | 78 | if (POLICY CMP0120) 79 | cmake_policy(SET CMP0120 NEW) # The WriteCompilerDetectionHeader module is removed 80 | endif () 81 | 82 | if (POLICY CMP0068) 83 | cmake_policy(SET CMP0068 NEW) 84 | endif () 85 | 86 | 87 | if ("${CMAKE_VERSION}" VERSION_LESS "3.12") 88 | cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) 89 | endif () 90 | -------------------------------------------------------------------------------- /cmake/cxx-detect-compilers.cmake: -------------------------------------------------------------------------------- 1 | include(CheckIncludeFile) 2 | include(CheckIncludeFiles) 3 | include(CheckFunctionExists) 4 | include(CheckTypeSize) 5 | include(CheckCCompilerFlag) 6 | include(CheckCXXSymbolExists) 7 | include(CheckCXXCompilerFlag) 8 | include(CheckLibraryExists) 9 | 10 | enable_language(CXX C) 11 | 12 | # https://cmake.org/cmake/help/latest/module/WriteCompilerDetectionHeader.html 13 | # include(WriteCompilerDetectionHeader) 14 | # https://cmake.org/cmake/help/v3.14/manual/cmake-compile-features.7.html#manual:cmake-compile-features(7) 15 | set(WriterCompilerDetectionHeaderFound NOTFOUND) 16 | 17 | # This module is only available with CMake >=3.1, so check whether it could be found 18 | # BUT in CMake 3.1 this module doesn't recognize AppleClang as compiler, so just use it as of CMake 3.2 19 | if ("${CMAKE_VERSION}" VERSION_GREATER "3.2") 20 | if ("${CMAKE_VERSION}" VERSION_LESS "3.19") 21 | if (WriterCompilerDetectionHeaderFound) 22 | include(WriteCompilerDetectionHeader OPTIONAL RESULT_VARIABLE WriterCompilerDetectionHeaderFound) 23 | endif () 24 | endif () 25 | endif () 26 | 27 | if (WriterCompilerDetectionHeaderFound) 28 | write_compiler_detection_header( 29 | FILE ${CMAKE_GENERATED_DIR}/the-compiler.h 30 | PREFIX The 31 | COMPILERS GNU Clang MSVC Intel AppleClang # SunPro 32 | FEATURES 33 | cxx_variadic_templates cxx_final cxx_override 34 | cxx_static_assert cxx_constexpr cxx_extern_templates 35 | cxx_noexcept cxx_thread_local 36 | ) 37 | endif () 38 | 39 | # string(REGEX MATCH ".*Clang.*" USING_CLANG ${CMAKE_CXX_COMPILER_ID}) 40 | if (CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$") 41 | # using regular Clang or AppleClang 42 | SET(USING_CLANG ON) 43 | 44 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 45 | if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") 46 | # using clang with clang-cl front end 47 | SET(USING_CLANG_FRONTEND_CL ON) 48 | elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") 49 | # using clang with regular front end 50 | SET(USING_CLANG_FRONTEND_GNU ON) 51 | else () 52 | SET(USING_CLANG_FRONTEND_OTHERS ON) 53 | endif () 54 | 55 | SET(USING_CLANG_LLVM ON) 56 | else () 57 | SET(USING_CLANG_APPLE ON) 58 | endif () 59 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 60 | # using GCC 61 | SET(USING_GCC ON) 62 | SET(USING_GNU ON) 63 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") 64 | # using Intel C++ 65 | SET(USING_Intel ON) 66 | elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 67 | # using Visual Studio C++ 68 | SET(USING_MSVC ON) 69 | add_compile_definitions(WIN32) 70 | else () 71 | SET(USING_UNKNOWN_COMPILER ON) 72 | endif () 73 | 74 | # 75 | # CMAKE_POSITION_INDEPENDENT_CODE 76 | # 77 | include(TestBigEndian) 78 | set(CMAKE_POSITION_INDEPENDENT_CODE 0) 79 | set(USING_POSITION_INDEPENDENT_CODE 0) 80 | set(USING_PIC 0) 81 | set(USING_BIG_ENDIAN 0) 82 | 83 | if (NOT (${WIN32})) 84 | TEST_BIG_ENDIAN(_bigendian) 85 | 86 | if ((${CMAKE_SIZEOF_VOID_P} GREATER 4) OR (${_bigendian})) 87 | message(STATUS ">>> Setting PIC (${CMAKE_CXX_COMPILE_OPTIONS_PIC}) for machine ${CMAKE_HOST_SYSTEM_PROCESSOR}") 88 | set(CMAKE_POSITION_INDEPENDENT_CODE 1) 89 | set(USING_POSITION_INDEPENDENT_CODE 1) 90 | set(USING_PIC 1) 91 | else () 92 | message(STATUS ">>> BigEndian is ${_bigendian} for machine ${CMAKE_HOST_SYSTEM_PROCESSOR}") 93 | endif () 94 | 95 | set(USING_BIG_ENDIAN ${_bigendian}) 96 | else () 97 | message(STATUS ">>> BigEndian skipped for machine ${CMAKE_HOST_SYSTEM_PROCESSOR}") 98 | endif () 99 | 100 | # 101 | # 102 | # 103 | set(ENABLE_CXX ON) 104 | set(ENABLE_CXX11 ON) 105 | 106 | if (ENABLE_CXX) 107 | check_cxx_symbol_exists(__cplusplus ciso646 SYSTEM_HAS_CXX) 108 | 109 | if (SYSTEM_HAS_CXX) 110 | check_cxx_compiler_flag("-std=c++11" SUPPORTS_STDCXX11) 111 | 112 | if (SUPPORTS_STDCXX11) 113 | # set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") 114 | if (ENABLE_CXX) 115 | set(ENABLE_CXX11 ON) 116 | endif () 117 | endif () 118 | 119 | check_cxx_compiler_flag("-std=c++17" SUPPORTS_STDCXX17) 120 | 121 | if (SUPPORTS_STDCXX17) 122 | # set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") 123 | if (ENABLE_CXX) 124 | set(ENABLE_CXX17 ON) 125 | endif () 126 | endif () 127 | 128 | check_cxx_compiler_flag("-std=c++20" SUPPORTS_STDCXX20) 129 | 130 | if (SUPPORTS_STDCXX20) 131 | # set (CMAKE_CXX_FLAGS "-std=c++20 ${CMAKE_CXX_FLAGS}") 132 | if (ENABLE_CXX) 133 | set(ENABLE_CXX20 ON) 134 | endif () 135 | endif () 136 | else () 137 | message(FATAL_ERROR "The compiler doesn't support CXX.") 138 | endif () 139 | endif () 140 | 141 | check_include_file(dlfcn.h HAVE_DLFCN_H) 142 | check_include_file(getopt.h HAVE_GETOPT_H) 143 | check_include_file(unistd.h HAVE_UNISTD_H) 144 | check_include_file(string.h HAVE_STRING_H) 145 | check_include_file(strings.h HAVE_STRINGS_H) 146 | check_include_file(inttypes.h HAVE_INTTYPES_H) 147 | check_include_file(memory.h HAVE_MEMORY_H) 148 | check_include_file(stdlib.h HAVE_STDLIB_H) 149 | check_include_file(stdint.h HAVE_STDINT_H) 150 | check_include_file(termios.h HAVE_TERMIOS_H) 151 | check_include_file(time.h HAVE_TIME_H) 152 | check_include_file(sys/types.h HAVE_SYS_TYPES_H) 153 | check_include_file(sys/stat.h HAVE_SYS_STAT_H) 154 | check_include_file(sys/time.h HAVE_SYS_TIME_H) 155 | 156 | if (HAVE_TIME_H AND HAVE_SYS_TIME_H) 157 | set(TIME_WITH_SYS_TIME ON) 158 | endif () 159 | 160 | check_function_exists(getpid HAVE_GETPID) 161 | check_function_exists(syscall HAVE_GETTID_SYSCALL) 162 | check_function_exists(isinf HAVE_ISINF) 163 | check_function_exists(isnan HAVE_ISNAN) 164 | check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) 165 | check_function_exists(qsort_r HAVE_QSORT_R) 166 | check_function_exists(time HAVE_TIME) 167 | check_function_exists(copysign HAVE_COPYSIGN) 168 | 169 | # check_type_size (int32_t SIZEOF_INT32_T) 170 | check_type_size(uint32_t SIZEOF_UINT32_T) 171 | set(HAVE_UINT32_T ${SIZEOF_UINT32_T}) 172 | check_type_size("unsigned int" SIZEOF_UNSIGNED_INT) 173 | check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG) 174 | message(STATUS " sizeof uint32_t = ${SIZEOF_UINT32_T}") 175 | message(STATUS " sizeof unsigned int = ${SIZEOF_UNSIGNED_INT}") 176 | message(STATUS " sizeof unsigned long = ${SIZEOF_UNSIGNED_LONG}") 177 | 178 | check_library_exists("m" sqrt "" HAVE_LIBM) 179 | 180 | if (HAVE_LIBM) 181 | set(M_LIBRARY m) 182 | endif () 183 | 184 | check_include_files("stdio.h;string.h" HAVE_STDIO_AND_STRING_H) 185 | check_include_files("stdio.h;unistd.h" HAVE_EX_UNISTD_H) 186 | -------------------------------------------------------------------------------- /cmake/debug-cmd.cmake: -------------------------------------------------------------------------------- 1 | 2 | macro (debug msg) 3 | message(STATUS "[DEBUG] ${msg}") 4 | endmacro () 5 | 6 | macro (debug_print_value variableName) 7 | debug("${variableName} = \${${variableName}}") 8 | endmacro () 9 | 10 | macro (debug_print_list_value listName) 11 | message(STATUS "- List of ${listName} -------------") 12 | 13 | foreach (lib ${${listName}}) 14 | message(STATUS " ${lib}") 15 | endforeach (lib) 16 | 17 | message(STATUS "- end -") 18 | endmacro () 19 | 20 | macro (safe_include cmakefilepath short_desc) 21 | if (EXISTS ${CMAKE_SOURCE_DIR}/${cmakefilepath}) 22 | include(${CMAKE_SOURCE_DIR}/${cmakefilepath}) 23 | message(STATUS ">>> ${short_desc} found and loaded: ./${cmakefilepath}") 24 | else () 25 | message(STATUS ">>> ${short_desc} ignored") 26 | endif () 27 | endmacro () 28 | -------------------------------------------------------------------------------- /cmake/detect-systems.cmake: -------------------------------------------------------------------------------- 1 | # https://github.com/Kitware/CMake/blob/master/Modules/CMakeDetermineSystem.cmake 2 | # 3 | # Expected uname -s output: 4 | # 5 | # AIX AIX 6 | # BSD/OS BSD/OS 7 | # FreeBSD FreeBSD 8 | # HP-UX HP-UX 9 | # Linux Linux 10 | # GNU/kFreeBSD GNU/kFreeBSD 11 | # NetBSD NetBSD 12 | # OpenBSD OpenBSD 13 | # OFS/1 (Digital Unix) OSF1 14 | # SCO OpenServer 5 SCO_SV 15 | # SCO UnixWare 7 UnixWare 16 | # SCO UnixWare (pre release 7) UNIX_SV 17 | # SCO XENIX Xenix 18 | # Solaris SunOS 19 | # SunOS SunOS 20 | # Tru64 Tru64 21 | # Ultrix ULTRIX 22 | # cygwin CYGWIN_NT-5.1 23 | # MacOSX Darwin 24 | 25 | # for MacOS X or iOS, watchOS, tvOS (since 3.10.3) 26 | if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin" OR APPLE) 27 | # MESSAGE("** Darwin detected.") 28 | SET(MACOSX TRUE) 29 | SET(MACOS TRUE) 30 | SET(macOS TRUE) 31 | SET(DARWIN TRUE) 32 | SET(MAC TRUE) 33 | SET(Mac TRUE) 34 | mark_as_advanced(MACOSX MACOS macOS DARWIN MAC Mac) 35 | endif () 36 | 37 | if (UNIX AND NOT macOS) 38 | # for Linux, BSD, Solaris, Minix 39 | if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux") 40 | set(LINUX TRUE) 41 | set(Linux TRUE) 42 | elseif (${CMAKE_HOST_SYSTEM_NAME} MATCHES "^GNU/kFreeBSD|NetBSD|OpenBSD") 43 | set(BSD TRUE) 44 | elseif (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Minix") 45 | set(Minix TRUE) 46 | set(MINIX TRUE) 47 | endif () 48 | 49 | mark_as_advanced(LINUX Linux BSD Minix MINUX) 50 | endif () 51 | 52 | if (WIN32) 53 | # do something 54 | endif (WIN32) 55 | 56 | if (MSVC OR MSYS OR MINGW) 57 | # for detecting Windows compilers 58 | endif () 59 | 60 | if (LINUX) 61 | # file(READ "/etc/issue" ETC_ISSUE) 62 | # string(REGEX MATCH "Debian|Ubuntu" DIST ${ETC_ISSUE}) 63 | file(STRINGS /etc/os-release distro REGEX "^NAME=") 64 | string(REGEX REPLACE "NAME=\"(.*)\"" "\\1" distro "${distro}") 65 | 66 | # if (string (FIND distro "NAME=" vd)) 67 | string(REGEX REPLACE "NAME=(.*)" "\\1" distro "${distro}") 68 | 69 | # endif () 70 | string(REGEX REPLACE "(.+) Linux" "\\1" distro "${distro}") 71 | file(STRINGS /etc/os-release distro_id REGEX "^ID=") 72 | string(REGEX REPLACE "ID=\"(.*)\"" "\\1" distro_id "${distro_id}") 73 | string(REGEX REPLACE "ID=(.*)" "\\1" distro_id "${distro_id}") 74 | file(STRINGS /etc/os-release disversion REGEX "^VERSION_ID=") 75 | string(REGEX REPLACE "VERSION_ID=\"(.*)\"" "\\1" disversion "${disversion}") 76 | string(REGEX REPLACE "VERSION_ID=(.*)" "\\1" disversion "${disversion}") 77 | message(">>> found ${distro}.${disversion} id=${distro_id}") 78 | set(DISTRO_NAME ${distro}) 79 | set(DISTRO_ID ${distro_id}) 80 | set(DISTRO_VERSION ${disversion}) 81 | mark_as_advanced(DISTRO_NAME DISTRO_ID DISTRO_VERSION) 82 | endif () 83 | 84 | message(STATUS ">>> CMAKE_HOST_SYSTEM_NAME = ${CMAKE_HOST_SYSTEM_NAME}") 85 | message(STATUS ">>> DISTRO_NAME = ${DISTRO_NAME}") 86 | 87 | if (LINUX) 88 | message(STATUS ">>> Linux" " (Distro: ${DISTRO_NAME})" " FOUND") 89 | elseif (MAC OR APPLE) 90 | message(STATUS ">>> macOS" " FOUND") 91 | elseif (UNIX) 92 | message(STATUS ">>> Unix (BSD+,Unix+)" " FOUND") 93 | elseif (MSVC) 94 | message(STATUS ">>> MSVC" " FOUND") 95 | elseif (WIN32) 96 | message(STATUS ">>> Win32" " FOUND") 97 | else () 98 | message(STATUS ">>> Unknown System" " '${CMAKE_SYSTEM}' FOUND") 99 | endif () 100 | 101 | if (MINGW) 102 | message(STATUS ">>> MinGW / MSYS2" " FOUND") 103 | elseif (MSYS) 104 | message(STATUS ">>> MSYS" " FOUND (${CMAKE_SYSTEM})") 105 | endif () 106 | 107 | message(STATUS "BUILD_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}") 108 | 109 | if (CYGWIN OR WIN32 OR APPLE) 110 | set(COMPILING_FS_CASE_INSENSITIVE TRUE) 111 | else () 112 | set(COMPILING_FS_CASE_INSENSITIVE FALSE) 113 | endif () 114 | 115 | string(TIMESTAMP BUILD_TIMESTAMP "%Y-%m-%dT%H:%M:%SZ") 116 | message(STATUS ">>> BUILD_TIMESTAMP = ${BUILD_TIMESTAMP}") 117 | 118 | # 119 | # 120 | # 121 | -------------------------------------------------------------------------------- /cmake/dummy-project.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # check CPU bits 3 | # 4 | 5 | project(dummy 6 | DESCRIPTION "dummy-project for sizeof_void_p detection and more." 7 | LANGUAGES CXX) 8 | 9 | if (${CMAKE_SIZEOF_VOID_P} EQUAL 8) 10 | # 64 bits 11 | set(CPU_ARCH "64" CACHE STRING "ARCH x86_64/arm64/..." FORCE) 12 | 13 | # set(CPU_ARCH_NAME "amd64" CACHE STRING "ARCH x86_64" FORCE) 14 | message(STATUS "CPU_ARCH 64bit | ${CMAKE_HOST_SYSTEM_PROCESSOR} ...") 15 | elseif (${CMAKE_SIZEOF_VOID_P} EQUAL 4) 16 | # 32 bits 17 | set(CPU_ARCH "32" CACHE STRING "ARCH x86" FORCE) 18 | 19 | # set(CPU_ARCH_NAME "x86" CACHE STRING "ARCH x86_64" FORCE) 20 | message(STATUS "CPU_ARCH 32bit | ${CMAKE_HOST_SYSTEM_PROCESSOR} ...") 21 | else () 22 | # message(STATUS "Unknown CMAKE_SIZEOF_VOID_P = '${CMAKE_SIZEOF_VOID_P}' ..?") 23 | if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" MATCHES "(amd64)|(AMD64)|(x86_64)|(arm64)|(aarch64)") 24 | set(CPU_ARCH "64" CACHE STRING "ARCH x86_64" FORCE) 25 | 26 | # set(CPU_ARCH_NAME "x86_64" CACHE STRING "ARCH x86_64" FORCE) 27 | # set(CPU_ARCH_NAME "amd64" CACHE STRING "ARCH x86_64" FORCE) 28 | message(STATUS "CPU_ARCH 64bit | ${CMAKE_HOST_SYSTEM_PROCESSOR} ...") 29 | else () 30 | set(CPU_ARCH "32" CACHE STRING "ARCH x86" FORCE) 31 | 32 | # set(CPU_ARCH_NAME "x86" CACHE STRING "ARCH x86_64" FORCE) 33 | message(STATUS "CPU_ARCH 32bit | ${CMAKE_HOST_SYSTEM_PROCESSOR} ...") 34 | endif () 35 | endif () 36 | 37 | set(CPU_NAME ${CMAKE_HOST_SYSTEM_PROCESSOR}) 38 | 39 | # 40 | # 41 | # 42 | include(target-dirs) 43 | include(cxx-detect-compilers) # detect cxx compiler 44 | include(detect-systems) # detect OS, ... 45 | include(cxx-macros) # macros: define_cxx_executable_project, ... 46 | include(version-def) # load .version.cmake 47 | include(versions-gen) # generate config.h and version.hh 48 | 49 | # when using compiler with cmake multi-config feature, a special build type 'Asan' can be used for sanitizing test. 50 | enable_sanitizer_for_multi_config() 51 | -------------------------------------------------------------------------------- /cmake/load-catch2.cmake: -------------------------------------------------------------------------------- 1 | # https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package 2 | 3 | # https://github.com/catchorg/Catch2/blob/devel/docs/cmake-integration.md 4 | # find_package(Catch2 3 REQUIRED) 5 | find_package(Catch2 3) # want Catch2 v3.x 6 | 7 | if (Catch2_FOUND) 8 | # if you've install Catch2 v3.x via package manager, such as: 9 | # macOS: brew install catch2 10 | # debian/ubuntu: sudo apt-get install catch2 11 | # opensuse: sudo zypper in Catch2-devel 12 | debug("Catch2 ${Catch2_VERSION} found.") 13 | else () 14 | include(FetchContent) 15 | 16 | debug("try loading catch2 v3.x library ...") 17 | 18 | # FetchContent_Declare( 19 | # googletest 20 | # GIT_REPOSITORY https://github.com/google/googletest.git 21 | # GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 22 | # FIND_PACKAGE_ARGS NAMES GTest 23 | # ) 24 | FetchContent_Declare( 25 | Catch2 26 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git 27 | GIT_TAG fa43b77429ba76c462b1898d6cd2f2d7a9416b14 # v3.7.1 28 | # GIT_TAG 605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1 29 | FIND_PACKAGE_ARGS 30 | ) 31 | 32 | # This will try calling find_package() first for both dependencies 33 | # FetchContent_MakeAvailable(googletest Catch2) 34 | FetchContent_MakeAvailable(Catch2) 35 | endif () -------------------------------------------------------------------------------- /cmake/load-cmdr-cxx.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # TO LOADING CMDR11 / CMDR-CXX EASILY: 3 | # 4 | # define_cxx_executable_project(myapp 5 | # PREFIX myapp 6 | # LIBRARIES ${myapp_libs} 7 | # SOURCES ${myapp_source_files} 8 | # INCLUDE_DIRECTORIES ${myapp_INCDIR} 9 | # ) 10 | # enable_version_increaser(myapp-cli myapp my MY_) 11 | # 12 | # include(load-cmdr-cxx) # load ME here. 13 | # add_cmdr_cxx_to(myapp) # attach cmdr11::cmdr11 14 | # 15 | 16 | # 17 | 18 | # message(STATUS "cmdr-cxx: defined macro add_cmdr_cxx_to") 19 | macro(add_cmdr_cxx_to target) 20 | find_package(cmdr11) 21 | 22 | set(CMDR_CXX_STAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmdr-cxx-stage") 23 | 24 | option(CMAKE_VERBOSE_DEBUG "for cmdr-cxx, enable CMAKE_VERBOSE_MAKEFILE to print command line before execute them" OFF) 25 | option(CMDR_NO_3RDPARTY "for cmdr-cxx, disable source codes and targets alternate to yaml-cpp and others" ON) 26 | 27 | if(${CMDR11_FOUND}) 28 | message(STATUS "cmdr-cxx: package FOUND at ${CMDR11_INCLUDE_DIR}, ${CMDR11_VERSION}") 29 | message(STATUS "cmdr-cxx: add cmdr-cxx v${CMDR11_VERSION_STRING} module to '${target}' from CMake Modules registry.") 30 | target_link_libraries(${target} 31 | # PRIVATE 32 | ${CMDR11_LIBRARIES} 33 | ) 34 | else() 35 | message(STATUS "cmdr-cxx: not found, try pulling a local one...") 36 | 37 | set(CMDR_CXX_TGT_NAME "third-cmdr-cxx") 38 | include(ExternalProject) 39 | ExternalProject_Add(${CMDR_CXX_TGT_NAME} 40 | GIT_REPOSITORY https://github.com/hedzr/cmdr-cxx 41 | GIT_TAG origin/master # v0.3.13 42 | GIT_SHALLOW 1 43 | GIT_PROGRESS ON 44 | 45 | # STEP_TARGETS build 46 | # SOURCE_DIR "${PROJECT_SOURCE_DIR}/third-party/cmdr-cxx-src" 47 | # BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmdr-cxx-build" 48 | CMAKE_ARGS 49 | -DCMAKE_VERBOSE_DEBUG:BOOL=${CMAKE_VERBOSE_DEBUG} 50 | -DCMDR_NO_3RDPARTY:BOOL=${CMDR_NO_3RDPARTY} 51 | -DENABLE_TESTS:BOOL=OFF 52 | -DENABLE_CLI_APP:BOOL=OFF 53 | -DENABLE_AUTOMATE_TESTS:BOOL=OFF 54 | -DBUILD_DOCUMENTATION:BOOL=OFF 55 | -DBUILD_EXAMPLES:BOOL=OFF 56 | --no-warn-unused-cli 57 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 58 | -DCMAKE_INSTALL_PREFIX:PATH=${CMDR_CXX_STAGE_DIR} 59 | 60 | # -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} 61 | # -DCMAKE_INSTALL_PREFIX:PATH=${EXECUTABLE_OUTPUT_PATH} 62 | BUILD_COMMAND ${CMAKE_COMMAND} -E echo "[cmdr-cxx] Starting $ build, install_prefix: ${CMAKE_INSTALL_PREFIX} or ${CMDR_CXX_STAGE_DIR}, BINARY_DIR: " 63 | 64 | # COMMAND ${CMAKE_COMMAND} -E sudo "chmod a+w /usr/local/lib" 65 | COMMAND ${CMAKE_COMMAND} --build --config $ 66 | COMMAND ${CMAKE_COMMAND} -E echo "[cmdr-cxx] $ build complete" 67 | ) 68 | 69 | message(STATUS "cmdr-cxx: add '${CMDR_CXX_TGT_NAME}' module to '${target}' from building dir.") 70 | message(STATUS "cmdr-cxx: CI_RUNNING = $ENV{CI_RUNNING}") 71 | message(STATUS "cmdr-cxx: add_dependencies") 72 | add_dependencies(${target} ${CMDR_CXX_TGT_NAME}) 73 | 74 | set(CMDR11_INCLUDE_DIR ${CMDR_CXX_STAGE_DIR}/include) 75 | set(CMDR11_LIB_DIR ${CMDR_CXX_STAGE_DIR}/lib) 76 | endif() 77 | 78 | target_include_directories(${target} PRIVATE 79 | $ 80 | $ 81 | /usr/local/include 82 | /opt/homebrew/include 83 | 84 | # ${CMDR_CXX_STAGE_DIR}/include 85 | ${CMDR11_INCLUDE_DIR} 86 | ) 87 | target_link_directories(${target} PRIVATE 88 | /usr/local/lib 89 | /opt/homebrew/lib 90 | 91 | # ${CMDR_CXX_STAGE_DIR}/lib 92 | ${CMDR11_LIBRARY_DIR} 93 | 94 | # ${CMAKE_CURRENT_BINARY_DIR}/${CMDR_CXX_TGT_NAME}-prefix/src/${CMDR_CXX_TGT_NAME}-build 95 | ) 96 | message(STATUS "cmdr-cxx: include-dir = ${CMDR11_INCLUDE_DIR}") 97 | endmacro() 98 | -------------------------------------------------------------------------------- /cmake/load-flex.cmake: -------------------------------------------------------------------------------- 1 | 2 | # just a sample 3 | 4 | 5 | find_package(BISON) 6 | find_package(FLEX) 7 | 8 | FLEX_TARGET(MyScanner 9 | ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner/lex.l 10 | ${CMAKE_CURRENT_BINARY_DIR}/my.lex.cpp COMPILE_FLAGS -w) 11 | BISON_TARGET(MyParser 12 | ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner/parser.y 13 | ${CMAKE_CURRENT_BINARY_DIR}/my.parser.cpp) 14 | ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser) 15 | -------------------------------------------------------------------------------- /cmake/load-googletest.cmake: -------------------------------------------------------------------------------- 1 | # https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package 2 | 3 | include(FetchContent) 4 | 5 | FetchContent_Declare( 6 | googletest 7 | GIT_REPOSITORY https://github.com/google/googletest.git 8 | GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 9 | FIND_PACKAGE_ARGS NAMES GTest 10 | ) 11 | 12 | # FetchContent_Declare( 13 | # Catch2 14 | # GIT_REPOSITORY https://github.com/catchorg/Catch2.git 15 | # GIT_TAG 605a34765aa5d5ecbf476b4598a862ada971b0cc # v3.0.1 16 | # FIND_PACKAGE_ARGS 17 | # ) 18 | 19 | # This will try calling find_package() first for both dependencies 20 | # FetchContent_MakeAvailable(googletest Catch2) 21 | FetchContent_MakeAvailable(googletest) 22 | -------------------------------------------------------------------------------- /cmake/load-llvm.cmake: -------------------------------------------------------------------------------- 1 | 2 | # set LLVM base directory 3 | # https://llvm.org/docs/CMake.html 4 | IF (${MAC}) 5 | if(EXISTS "${LLVM_ROOT}/bin/clang") 6 | else() 7 | set(LLVM_ROOT /opt/homebrew/opt/llvm) 8 | if(EXISTS "${LLVM_ROOT}/bin/clang") 9 | else() 10 | set(LLVM_ROOT /usr/local/opt/llvm) 11 | endif 12 | if(EXISTS "${LLVM_ROOT}/bin/clang") 13 | set(LLVM_DIR "${LLVM_ROOT}/share/cmake/modules") 14 | endif() 15 | endif() 16 | ELSEIF (${UNIX}) 17 | if(EXISTS "${LLVM_ROOT}/bin/clang") 18 | else() 19 | find_program(LLVM_CLANGXX clang++) 20 | if(LLVM_CLANGXX_FOUND) 21 | endif() 22 | endif() 23 | ELSE () 24 | #set(LLVM_CMAKE_DIR "/usr/share/llvm-3.6/share/llvm/cmake") 25 | #set(LLVM_CMAKE_DIR "${LLVM_DIR}/share/llvm/cmake") 26 | ENDIF () 27 | 28 | if(EXISTS "${LLVM_ROOT}/bin/clang") 29 | else() 30 | message(FATAL "CANNOT FOUND LLVM, TRY SPECIFY LLVM_ROOT MANUALLY.") 31 | endif() 32 | set(LLVM_CMAKE_DIR "${LLVM_DIR}") 33 | MESSAGE("LLVM_CMAKE_DIR = ${LLVM_CMAKE_DIR}") 34 | 35 | 36 | set(LLVM_TARGETS_TO_BUILD X86) 37 | set(LLVM_BUILD_RUNTIME OFF) 38 | set(LLVM_BUILD_TOOLS OFF) 39 | 40 | find_package(LLVM REQUIRED CONFIG) 41 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 42 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 43 | 44 | 45 | SET(CMAKE_CXX_COMPILER_ENV_VAR "clang++") 46 | SET(CMAKE_CXX_FLAGS "-std=c++11") 47 | SET(CMAKE_CXX_FLAGS_DEBUG "-g") 48 | SET(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") 49 | SET(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG") 50 | SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") 51 | 52 | #SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 53 | 54 | include_directories(${LLVM_INCLUDE_DIRS}) 55 | add_definitions(${LLVM_DEFINITIONS}) 56 | 57 | include_directories(${LLVM_INCLUDE_DIRS} Debug Release build include src src/Model src/Utils) 58 | message("LLVM_INCLUDE_DIRS = ${LLVM_INCLUDE_DIRS}") 59 | 60 | file(GLOB_RECURSE source_files 61 | ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp 62 | ${CMAKE_CURRENT_SOURCE_DIR}/src/Model/*.cpp 63 | ${CMAKE_CURRENT_SOURCE_DIR}/src/Macro/*.cpp 64 | ${CMAKE_CURRENT_SOURCE_DIR}/src/Utils/*.cpp) 65 | add_executable(xxv ${source_files} 66 | ${BISON_MyParser_OUTPUTS} 67 | ${FLEX_MyScanner_OUTPUTS}) 68 | 69 | install(TARGETS xxv RUNTIME DESTINATION bin) 70 | 71 | # Find the libraries that correspond to the LLVM components 72 | # that we wish to use 73 | llvm_map_components_to_libnames(llvm_libs 74 | support core irreader executionengine interpreter 75 | mc mcjit bitwriter x86codegen target) 76 | 77 | # Link against LLVM libraries 78 | target_link_libraries(xxv ${llvm_libs}) 79 | 80 | #add_executable(xxv main.cpp) 81 | # -------------------------------------------------------------------------------- /cmake/modules-dir.md: -------------------------------------------------------------------------------- 1 | ```cmake 2 | # macOS builtin cmake: /Applications/CLion.app/Contents/bin/cmake/mac/share/cmake-3.17/Modules 3 | # ll "/Applications/CLion.app/Contents/bin/cmake/mac/share/cmake-3.17/Modules/Find"* 4 | # brew cmake: $(brew --prefix cmake)/share/cmake/Modules 5 | #message("CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") 6 | 7 | ``` -------------------------------------------------------------------------------- /cmake/old/a-c-p-v.cmake.in: -------------------------------------------------------------------------------- 1 | set(PACKAGE_VERSION "${VERSION}") 2 | 3 | # Check whether the requested PACKAGE_FIND_VERSION is compatible 4 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") 5 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 6 | else() 7 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 8 | if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") 9 | set(PACKAGE_VERSION_EXACT TRUE) 10 | endif() 11 | endif() -------------------------------------------------------------------------------- /cmake/old/cxx-standard-def.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_CXX_STANDARD 20) 3 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 4 | set(CMAKE_CXX_EXTENSIONS OFF) 5 | 6 | # Just for QT app ... 7 | #set(CMAKE_AUTOMOC ON) # Qt moc, meta-object compiler 8 | #set(CMAKE_AUTORCC ON) # Qt rcc, resources compiler 9 | #set(CMAKE_AUTOUIC ON) # Qt uic, User-Interface compiler 10 | -------------------------------------------------------------------------------- /cmake/old/deps_inc_catch2.cmake: -------------------------------------------------------------------------------- 1 | 2 | find_package(Catch2 QUIET) 3 | message(STATUS "Catch2_FOUND = ${Catch2_FOUND}") 4 | message(STATUS "Catch2_VERSION = ${Catch2_VERSION}") 5 | if (NOT ${Catch2_FOUND}) 6 | include(FetchContent) 7 | 8 | message("fetch Catch2 from github ...") 9 | FetchContent_Declare( 10 | Catch2 11 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git 12 | GIT_TAG v2.13.3) 13 | 14 | message(STATUS "Downloading Catch2 and make it available (FetchContent) ") 15 | FetchContent_MakeAvailable(Catch2) 16 | endif () 17 | -------------------------------------------------------------------------------- /cmake/old/deps_inc_fmt.cmake: -------------------------------------------------------------------------------- 1 | 2 | #find_package(Catch2) 3 | #if (NOT (${Catch2_FOUND})) 4 | include(FetchContent) 5 | 6 | FetchContent_Declare( 7 | fmt 8 | GIT_REPOSITORY https://github.com/fmtlib/fmt.git 9 | GIT_TAG 7.1.3) 10 | 11 | FetchContent_MakeAvailable(fmt) 12 | #endif () 13 | -------------------------------------------------------------------------------- /cmake/old/deps_inc_spdlog.cmake: -------------------------------------------------------------------------------- 1 | 2 | #find_package(Catch2) 3 | #if (NOT Catch2_FOUND) 4 | include(FetchContent) 5 | 6 | FetchContent_Declare( 7 | spdlog 8 | GIT_REPOSITORY https://github.com/gabime/spdlog.git 9 | GIT_TAG v1.8.2) 10 | 11 | FetchContent_MakeAvailable(spdlog) 12 | #endif () 13 | -------------------------------------------------------------------------------- /cmake/old/install-pack-helpers.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | # https://stackoverflow.com/questions/57092692/how-to-fix-vcpkg-cmake-is-unable-to-determine-target-architecture-windows10-v 4 | if (DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET) 5 | set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "") 6 | message(STATUS ">> CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}") 7 | message(STATUS ">> VCPKG_TARGET_TRIPLET = $ENV{VCPKG_TARGET_TRIPLET}, ${VCPKG_TARGET_TRIPLET}") 8 | endif () 9 | 10 | 11 | macro(add_install_chapter target) 12 | 13 | include(GNUInstallDirs) 14 | include(CMakePackageConfigHelpers) 15 | 16 | set(CONFIG_PACKAGE_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 17 | 18 | get_target_property(target_type ${target} TYPE) 19 | 20 | #debug_print_value(CMAKE_PROJECT_VERSION) 21 | #debug_print_value(PROJECT_VERSION) 22 | message(STATUS " * CMAKE_PROJECT_VERSION = ${CMAKE_PROJECT_VERSION}") 23 | message(STATUS " * PROJECT_VERSION = ${PROJECT_VERSION}") 24 | 25 | write_basic_package_version_file( 26 | ${CMAKE_CURRENT_BINARY_DIR}/${target}-config-version.cmake 27 | VERSION ${PROJECT_VERSION} 28 | COMPATIBILITY SameMajorVersion 29 | ) 30 | 31 | install(TARGETS ${target} 32 | EXPORT ${target}Targets 33 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 34 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 35 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 36 | DESTINATION ${CMAKE_INSTALL_BINDIR} 37 | ) 38 | 39 | message(STATUS "configure install section for ${target_type} ${target}") 40 | if (target_type STREQUAL "EXECUTABLE") 41 | # Process executable target 42 | 43 | # dep libs 44 | # man 1, man 3, ... 45 | # shared stuffs 46 | 47 | else () 48 | 49 | # install(TARGETS ${CLI_NAME} 50 | # EXPORT ${PROJECT_NAME}Targets 51 | # DESTINATION ${CMAKE_INSTALL_BINDIR} 52 | # ) 53 | 54 | install(EXPORT ${target}Targets 55 | FILE ${target}Targets.cmake 56 | NAMESPACE ${target}:: 57 | DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR}) 58 | 59 | install(DIRECTORY include/${target} 60 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 61 | ) 62 | 63 | install(FILES 64 | ${CMAKE_CURRENT_LIST_DIR}/cmake/${target}Config.cmake 65 | DESTINATION 66 | ${CMAKE_INSTALL_LIBDIR}/cmake/${target}) 67 | 68 | # install(FILES 69 | # ${CMAKE_BINARY_DIR}/generated/cmdr-version.hh 70 | # DESTINATION 71 | # ${CMAKE_INSTALL_INCLUDEDIR}/${target}) 72 | # 73 | # install(FILES 74 | # ${CMAKE_CURRENT_SOURCE_DIR}/include/cmdr-cxx.hh 75 | # DESTINATION 76 | # ${CMAKE_INSTALL_INCLUDEDIR}) 77 | 78 | #install(TARGETS ${target} 79 | # # COMPONENT applications 80 | # # DESTINATION "bin" 81 | # RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 82 | # ) 83 | endif () 84 | 85 | endmacro() 86 | 87 | macro(add_cpack_chapter target) 88 | 89 | # https://cmake.org/cmake/help/latest/module/CPack.html 90 | 91 | # build a CPack driven installer package 92 | include(InstallRequiredSystemLibraries) 93 | set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) 94 | set(CPACK_PACKAGE_DIRECTORY ${CMAKE_SOURCE_DIR}/dist) 95 | set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") 96 | set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") 97 | set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") 98 | set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") 99 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") 100 | set(CPACK_PACKAGE_DESCRIPTION "${CMAKE_PROJECT_DESCRIPTION}") 101 | set(CPACK_PACKAGE_HOMEPAGE "${CMAKE_PROJECT_HOMEPAGE_URL}") 102 | set(CPACK_SOURCE_IGNORE_FILES 103 | ${PROJECT_SOURCE_DIR}/build 104 | ${PROJECT_SOURCE_DIR}/cmake-build-debug 105 | ${PROJECT_SOURCE_DIR}/dist 106 | ${PROJECT_SOURCE_DIR}/.idea 107 | ${PROJECT_SOURCE_DIR}/.DS_Store 108 | ${PROJECT_SOURCE_DIR}/.git 109 | ${PROJECT_SOURCE_DIR}/.gitignore 110 | ${PROJECT_SOURCE_DIR}/.vscode 111 | ${PROJECT_SOURCE_DIR}/.PIC 112 | ${PROJECT_SOURCE_DIR}/ref 113 | ${PROJECT_SOURCE_DIR}/_assets/*) 114 | #set(CPACK_SOURCE_GENERATOR "TXZ") 115 | #set(CPACK_SOURCE_PACKAGE_FILE_NAME ${ARCHIVE_NAME}) 116 | # set(CPACK_PACKAGE_DESCRIPTION "A C++17 header-only command-line parser with hierarchical config data manager") 117 | #set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "") 118 | # set(CPACK_PACKAGE_CONTACT "Hedzr Yeh ") 119 | # set(CPACK_PACKAGE_VENDOR "Hedzr Studio") 120 | # set(CPACK_PACKAGE_HOMEPAGE "https://github.com/hedzr/cmdr-cxx") 121 | 122 | get_target_property(target_type ${target} TYPE) 123 | 124 | if (DISTRO_ID STREQUAL "debian") 125 | message(STATUS ">>>> Found Debian <<<<") 126 | include(package-deb) 127 | elseif (DISTRO_ID STREQUAL "ubuntu") 128 | message(STATUS ">>>> Found Ubuntu <<<<") 129 | include(package-deb) 130 | if (target_type STREQUAL "EXECUTABLE") 131 | # Process executable target 132 | set(CPACK_DEBIAN_PACKAGE_NAME "${target}") 133 | else () 134 | set(CPACK_DEBIAN_PACKAGE_NAME "lib${target}-dev") 135 | endif () 136 | elseif (DISTRO_ID STREQUAL "fedora") 137 | message(STATUS ">>>> Found Fedora <<<<") 138 | include(package-rpm) 139 | elseif (DISTRO_ID STREQUAL "centos") # DISTRO_NAME = CentOS 140 | message(STATUS ">>>> Found Fedora <<<<") 141 | include(package-rpm) 142 | elseif (DISTRO_ID STREQUAL "redhat") # DISTRO_NAME = RehHat ? 143 | message(STATUS ">>>> Found RedHat <<<<") 144 | include(package-rpm) 145 | elseif (macOS) 146 | message(STATUS ">>>> Found macOS/Darwin <<<<") 147 | include(package-dmg) 148 | else () 149 | message(STATUS ">>>> Found unknown distribution (DISTRO_NAME=${DISTRO_NAME}, ID=${DISTRO_ID}) <<<<") 150 | endif () 151 | 152 | #if (NOT CPack_CMake_INCLUDED) 153 | include(CPack) 154 | #endif () 155 | 156 | endmacro() 157 | -------------------------------------------------------------------------------- /cmake/options-def.cmake: -------------------------------------------------------------------------------- 1 | # if (EXISTS ${CMAKE_SOURCE_DIR}/.options.cmake) 2 | # include(.options) 3 | # message(STATUS ">>> options decl file (.options.cmake) loaded") 4 | # else () 5 | # message(STATUS ">>> options decl file (.options.cmake) ignored") 6 | # set(BASENAME prj) 7 | # endif () 8 | 9 | # if (EXISTS ${CMAKE_SOURCE_DIR}/.options.local.cmake) 10 | # include(.options.local) 11 | # message(STATUS ">>> options.local decl file (.options.local.cmake) loaded") 12 | # endif () 13 | 14 | set(BASENAME prj) 15 | safe_include(.options.cmake "options definitions file") 16 | safe_include(.options.local.cmake "local options definitions file") -------------------------------------------------------------------------------- /cmake/package-deb.cmake: -------------------------------------------------------------------------------- 1 | set(CPACK_GENERATOR "DEB") 2 | set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) 3 | 4 | # https://cmake.org/cmake/help/latest/module/CPack.html 5 | # https://cmake.org/cmake/help/latest/cpack_gen/deb.html#cpack_gen:CPack%20DEB%20Generator 6 | 7 | set(CPACK_DEBIAN_PACKAGE_NAME "lib${CPACK_PACKAGE_NAME}-dev") 8 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT}) 9 | set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) 10 | 11 | #set(CPACK_DEBIAN_PACKAGE_VERSION ${PROJECT_VERSION}) 12 | 13 | #set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.4), libgcc-s1 (>= 3.0), libstdc++6 (>= 9)") 14 | ##set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libc6 (<< 3)") 15 | ##set(CPACK_DEBIAN_PACKAGE_DEPENDS "cssrobopec,libqt4-xml,libqt4-network,libqtgui4,treeupdatablereeti") 16 | #set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/Debian/postinst") 17 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) 18 | 19 | #set(CPACK_DEBIAN_PACKAGE_LICENSE ${CPACK_RESOURCE_FILE_LICENSE}) 20 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${CPACK_PACKAGE_HOMEPAGE}) 21 | 22 | 23 | if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "amd64.*|x86_64.*|AMD64.*") 24 | set(CPU_ARCH "x64" CACHE STRING "ARCH x86_64" FORCE) 25 | #set(CPU_ARCH_NAME "x86_64" CACHE STRING "ARCH x86_64" FORCE) 26 | set(CPU_ARCH_NAME "amd64" CACHE STRING "ARCH x86_64" FORCE) 27 | else() 28 | set(CPU_ARCH "x86" CACHE STRING "ARCH x86" FORCE) 29 | set(CPU_ARCH_NAME "x86" CACHE STRING "ARCH x86_64" FORCE) 30 | endif() 31 | 32 | set(CPACK_TARGET_FILE_NAME "${PROJECT_NAME}_${PROJECT_VERSION}_${CPU_ARCH_NAME}.deb") 33 | #set(CPACK_TARGET_FILE_NAME "${CPACK_DEBIAN_FILE_NAME}") 34 | message(STATUS "CPACK_DEB_FILE_NAME = ${CPACK_DEB_FILE_NAME}") 35 | -------------------------------------------------------------------------------- /cmake/package-dmg.cmake: -------------------------------------------------------------------------------- 1 | set(CPACK_GENERATOR "DragNDrop") # DMG 2 | set(CPACK_DMG_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-devel") 3 | set(CPACK_DMG_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT}) 4 | set(CPACK_DMG_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) 5 | 6 | #message(STATUS "CPACK_DMG_VOLUME_NAME = ${CPACK_DMG_VOLUME_NAME}") 7 | 8 | #set(CPACK_RPM_PACKAGE_VERSION ${PROJECT_VERSION}) 9 | 10 | 11 | set(CPACK_TARGET_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_HOST_SYSTEM_NAME}.dmg") 12 | 13 | 14 | #Generators 15 | #7Z = 7-Zip file format 16 | #Bundle = Mac OSX bundle 17 | #DragNDrop = Mac OSX Drag And Drop 18 | #External = CPack External packages 19 | #IFW = Qt Installer Framework 20 | #NSIS = Null Soft Installer 21 | #NSIS64 = Null Soft Installer (64-bit) 22 | #NuGet = NuGet packages 23 | #OSXX11 = Mac OSX X11 bundle 24 | #PackageMaker = Mac OSX Package Maker installer 25 | #STGZ = Self extracting Tar GZip compression 26 | #TBZ2 = Tar BZip2 compression 27 | #TGZ = Tar GZip compression 28 | #TXZ = Tar XZ compression 29 | #TZ = Tar Compress compression 30 | #TZST = Tar Zstandard compression 31 | #ZIP = ZIP file format 32 | #productbuild = Mac OSX pkg -------------------------------------------------------------------------------- /cmake/package-rpm.cmake: -------------------------------------------------------------------------------- 1 | set(CPACK_GENERATOR "RPM") 2 | set(CPACK_RPM_FILE_NAME RPM-DEFAULT) 3 | 4 | # https://cmake.org/cmake/help/latest/module/CPack.html 5 | # https://cmake.org/cmake/help/latest/cpack_gen/rpm.html#cpack_gen:CPack%20RPM%20Generator 6 | 7 | set(CPACK_RPM_PACKAGE_NAME "lib${CPACK_PACKAGE_NAME}-devel") 8 | set(CPACK_RPM_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT}) 9 | set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) 10 | set(CPACK_RPM_PACKAGE_VERSION ${PROJECT_VERSION}) 11 | 12 | #set(CPACK_RPM_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libc6 (<< 3)") 13 | #set(CPACK_RPM_PACKAGE_DEPENDS "cssrobopec,libqt4-xml,libqt4-network,libqtgui4,treeupdatablereeti") 14 | #set(CPACK_RPM_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/Debian/postinst") 15 | set(CPACK_RPM_PACKAGE_AUTOPROV YES) 16 | 17 | #set(CPACK_RPM_PACKAGE_LICENSE ${CPACK_RESOURCE_FILE_LICENSE}) 18 | set(CPACK_RPM_PACKAGE_HOMEPAGE ${CPACK_PACKAGE_HOMEPAGE}) 19 | 20 | 21 | set(CPACK_TARGET_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-1.${CMAKE_SYSTEM_PROCESSOR}.rpm") 22 | #set(CPACK_TARGET_FILE_NAME "${CPACK_RPM_FILE_NAME}") 23 | message(STATUS "CPACK_RPM_FILE_NAME = ${CPACK_RPM_FILE_NAME}") 24 | -------------------------------------------------------------------------------- /cmake/pkg-mgmt.cmake: -------------------------------------------------------------------------------- 1 | # ###################################################### 2 | option(USE_CONAN "enable package manager: conan" OFF) 3 | option(USE_VCPKG "enable package manager: vcpkg" OFF) 4 | 5 | macro (load_package_manager) 6 | # ###################################################### 7 | if (USE_CONAN) 8 | # run this : cd build && conan install .. 9 | # or: conan install . --install-folder build 10 | find_program(CONAN_CMD conan PATHS 11 | "/usr/local/bin" 12 | "$ENV{HOME}/.conan/bin" 13 | "$ENV{HOME}/.local/bin" 14 | ) 15 | 16 | if (NOT CONAN_CMD) 17 | message(FATAL_ERROR "Conan: not found!") 18 | set(USE_CONAN OFF FORCE) 19 | else () 20 | message(STATUS "Conan: FOUND at ${CONAN_CMD}") 21 | endif () 22 | 23 | if (NOT EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) 24 | exec_program(${CONAN_CMD} ${CMAKE_CURRENT_SOURCE_DIR} ARGS "install . --install-folder ${CMAKE_BINARY_DIR}") 25 | endif () 26 | 27 | include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) 28 | conan_basic_setup() 29 | 30 | output_conan_include_dirs() 31 | endif () 32 | 33 | # ###################################################### 34 | if (USE_VCPKG) 35 | if (NOT DEFINED ENV{VCPKG_ROOT}) 36 | find_program(VCPKG_CMD vcpkg PATHS 37 | /usr/local/opt/vcpkg/bin 38 | ) 39 | 40 | if (VCPKG_CMD_FOUND) 41 | get_filename_component(VCPKG_ROOT $VCPKG_CMD DIRECTORY) 42 | endif () 43 | else () 44 | set(VCPKG_ROOT $ENV{VCPKG_ROOT}) 45 | endif () 46 | 47 | if (DEFINED ENV{VCPKG_TARGET_TRIPLET}) 48 | set(VCPKG_TARGET_TRIPLET $ENV{VCPKG_TARGET_TRIPLET}) 49 | endif () 50 | 51 | if (DEFINED VCPKG_ROOT) 52 | set(VCPKG_FEATURE_FLAGS "versions") 53 | set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" 54 | CACHE STRING "Vcpkg toolchain file") 55 | message(STATUS ">>> Using vcpkg with VCPKG_ROOT = ${VCPKG_ROOT}") 56 | message(STATUS " CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}") 57 | message(STATUS " VCPKG_TARGET_TRIPLET = ${VCPKG_TARGET_TRIPLET}") # =x64-windows, ... 58 | else () 59 | message(STATUS ">>> vcpkg ignored - you may install it at first") 60 | endif () 61 | endif () 62 | endmacro () -------------------------------------------------------------------------------- /cmake/setup-build-env.cmake: -------------------------------------------------------------------------------- 1 | 2 | # FORCE gcc 3 | #if (${MACOS}) 4 | # set(CMAKE_C_COMPILER "gcc-9") 5 | # set(CMAKE_CXX_COMPILER "g++-9") 6 | #endif() 7 | #message("CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") 8 | #message("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") 9 | 10 | 11 | if (${MSVC}) 12 | # warning level 4 and all warnings as errors 13 | add_compile_options(/W4 /WX 14 | /D_CRT_SECURE_NO_WARNINGS 15 | ) 16 | else () 17 | # lots of warnings and all warnings as errors 18 | add_compile_options(-Wall -Wextra -pedantic -Werror 19 | -Wno-unknown-pragmas 20 | # -Weffc++ # warning: ‘operator=’ should return a reference to ‘*this’ 21 | ) 22 | endif () 23 | 24 | 25 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) 26 | # gcc-9: std::is_constructible 27 | add_compile_options(-D_LIBCPP_TESTING_FALLBACK_IS_CONSTRUCTIBLE) 28 | message("> GCC ${CMAKE_CXX_COMPILER_VERSION} FOUND") 29 | else () 30 | message("> ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} FOUND") 31 | endif () 32 | 33 | if ((${USE_DEBUG}==ON) AND (${MINGW}==ON)) 34 | add_link_options(--allow-multiple-definition) 35 | endif () 36 | 37 | if (${USE_DEBUG}) 38 | add_compile_options(-D_DEBUG -DDEBUG=1) 39 | else () 40 | add_compile_options(-DNDEBUG=1) 41 | endif () 42 | 43 | if (${USE_DEBUG}) 44 | #add_compile_options(-DUSE_DEBUG_MALLOC=${USE_DEBUG_MALLOC}) 45 | 46 | # enable google sanitizer 47 | # add_compile_options(-fsanitize=[sanitizer_name] [additional_options] [-g] [-OX]) 48 | endif () 49 | 50 | # 51 | # 52 | -------------------------------------------------------------------------------- /cmake/target-dirs.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${CMAKE_SCRIPTS}) 2 | get_filename_component(CMAKE_ROOT_DIR ${CMAKE_SCRIPTS_DIR} DIRECTORY) 3 | 4 | # set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") 5 | # set(LIBRARY_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin/lib") 6 | # set(ARCHIVE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin/lib") 7 | # #set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) 8 | # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") 9 | # 10 | # #link_directories(BEFORE ${LIBRARY_OUTPUT_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) 11 | if (${USE_DEBUG}) 12 | # set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/debug) 13 | set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") 14 | set(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/lib/${CMAKE_BUILD_NAME}") 15 | set(ARCHIVE_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/lib/${CMAKE_BUILD_NAME}") 16 | else () 17 | set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_NAME}") 18 | set(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/lib/${CMAKE_BUILD_NAME}") 19 | set(ARCHIVE_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}/lib/${CMAKE_BUILD_NAME}") 20 | endif () 21 | 22 | message(STATUS "EXECUTABLE_OUTPUT_PATH = ${EXECUTABLE_OUTPUT_PATH} ...") 23 | 24 | # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) 25 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${EXECUTABLE_OUTPUT_PATH}") 26 | 27 | # Note that CMAKE_GENERATED_DIR is NOT a cmake builtin variable. 28 | set(CMAKE_GENERATED_DIR "${CMAKE_BINARY_DIR}/generated") 29 | mark_as_advanced(CMAKE_GENERATED_DIR) 30 | 31 | message(" ./cmake/target-dirs.cmake:34 : ") 32 | message(" > CMAKE_SCRIPTS_DIR: ${CMAKE_SCRIPTS_DIR}") 33 | message(" > CMAKE_ROOT_DIR: ${CMAKE_ROOT_DIR}") 34 | message(" > CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}") 35 | message(" > CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") 36 | message(" > CMAKE_GENERATED_DIR: ${CMAKE_GENERATED_DIR}") 37 | message(" > EXECUTABLE_OUTPUT_PATH: ${EXECUTABLE_OUTPUT_PATH}") 38 | 39 | # set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/sm-lib) 40 | # set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/sm-lib) 41 | # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 42 | 43 | # set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") 44 | # set(LIBRARY_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/sm-lib") 45 | # link_directories(BEFORE "${CMAKE_SOURCE_DIR}/sm-lib") 46 | 47 | # set(V alpha beta gamma) 48 | # message(${V}) 49 | # 50 | # foreach(i ${V}) 51 | # message(${i}) 52 | # endforeach() 53 | -------------------------------------------------------------------------------- /cmake/vcpkg-integration.cmake: -------------------------------------------------------------------------------- 1 | 2 | macro (use_vcpkg) 3 | if (DEFINED ENV{VCPKG_ROOT}) 4 | set(VCPKG_FEATURE_FLAGS "versions") 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" 6 | CACHE STRING "Vcpkg toolchain file") 7 | message(STATUS ">>> Using vcpkg with VCPKG_ROOT = $ENV{VCPKG_ROOT}") 8 | message(STATUS " CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}") 9 | message(STATUS " VCPKG_TARGET_TRIPLET = $ENV{VCPKG_TARGET_TRIPLET}") # =x64-windows, ... 10 | endif () 11 | 12 | if (DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET) 13 | set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "") 14 | endif () 15 | 16 | # if (VCPKG_TARGET_TRIPLET) 17 | # elseif (CMAKE_GENERATOR_PLATFORM MATCHES "^[Ww][Ii][Nn]32$") 18 | # set(_VCPKG_TARGET_TRIPLET_ARCH x86) 19 | # elseif (CMAKE_GENERATOR_PLATFORM MATCHES "^[Xx]64$") 20 | # set(_VCPKG_TARGET_TRIPLET_ARCH x64) 21 | # elseif (CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]$") 22 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm) 23 | # elseif (CMAKE_GENERATOR_PLATFORM MATCHES "^[Aa][Rr][Mm]64$") 24 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm64) 25 | # else () 26 | # if (CMAKE_GENERATOR MATCHES "^Visual Studio 14 2015 Win64$") 27 | # set(_VCPKG_TARGET_TRIPLET_ARCH x64) 28 | # elseif (CMAKE_GENERATOR MATCHES "^Visual Studio 14 2015 ARM$") 29 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm) 30 | # elseif (CMAKE_GENERATOR MATCHES "^Visual Studio 14 2015$") 31 | # set(_VCPKG_TARGET_TRIPLET_ARCH x86) 32 | # elseif (CMAKE_GENERATOR MATCHES "^Visual Studio 15 2017 Win64$") 33 | # set(_VCPKG_TARGET_TRIPLET_ARCH x64) 34 | # elseif (CMAKE_GENERATOR MATCHES "^Visual Studio 15 2017 ARM$") 35 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm) 36 | # elseif (CMAKE_GENERATOR MATCHES "^Visual Studio 15 2017$") 37 | # set(_VCPKG_TARGET_TRIPLET_ARCH x86) 38 | # elseif (CMAKE_GENERATOR MATCHES "^Visual Studio 16 2019$") 39 | # if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^[Xx]86$") 40 | # set(_VCPKG_TARGET_TRIPLET_ARCH x86) 41 | # elseif (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^[Aa][Mm][Dd]64$") 42 | # set(_VCPKG_TARGET_TRIPLET_ARCH x64) 43 | # elseif (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]$") 44 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm) 45 | # elseif (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]64$") 46 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm64) 47 | # else () 48 | # 49 | # endif () 50 | # else () 51 | # find_program(_VCPKG_CL cl) 52 | # if (_VCPKG_CL MATCHES "amd64/cl.exe$" OR _VCPKG_CL MATCHES "x64/cl.exe$") 53 | # set(_VCPKG_TARGET_TRIPLET_ARCH x64) 54 | # elseif (_VCPKG_CL MATCHES "arm/cl.exe$") 55 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm) 56 | # elseif (_VCPKG_CL MATCHES "arm64/cl.exe$") 57 | # set(_VCPKG_TARGET_TRIPLET_ARCH arm64) 58 | # elseif (_VCPKG_CL MATCHES "bin/cl.exe$" OR _VCPKG_CL MATCHES "x86/cl.exe$") 59 | # set(_VCPKG_TARGET_TRIPLET_ARCH x86) 60 | # elseif (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") 61 | # set(_VCPKG_TARGET_TRIPLET_ARCH x64) 62 | # else () 63 | # if (_CMAKE_IN_TRY_COMPILE) 64 | # message(STATUS "Unable to determine target architecture, continuing without vcpkg.") 65 | # else () 66 | # message(WARNING "Unable to determine target architecture, continuing without vcpkg.") 67 | # endif () 68 | # set(VCPKG_TOOLCHAIN ON) 69 | # return() 70 | # endif () 71 | # endif () 72 | # endif () 73 | endmacro () 74 | -------------------------------------------------------------------------------- /cmake/version-def.cmake: -------------------------------------------------------------------------------- 1 | # if (EXISTS ${CMAKE_SOURCE_DIR}/.version.cmake) 2 | # include(.version) 3 | # message(STATUS ">>> version decl file found: ${CMAKE_SOURCE_DIR}/.version.cmake (V${VERSION})") 4 | # #elseif (EXIST) 5 | # else () 6 | # message(STATUS ">>> version decl file ignored") 7 | # set(VERSION 0.1.0.1) 8 | # endif () 9 | set(VERSION 0.1.0.1) 10 | if (EXISTS ${CMAKE_SOURCE_DIR}/.build-serial) 11 | message(STATUS ".build-serial found") 12 | else() 13 | file(WRITE ${CMAKE_SOURCE_DIR}/.build-serial "1") 14 | endif() 15 | safe_include(.version.cmake "version declaration file") 16 | safe_include(.version.local.cmake "local version declaration file") -------------------------------------------------------------------------------- /cmake/version.h.in: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2019-01-28. 3 | // 4 | 5 | #ifndef __@PROJECT_MACRO_PREFIX@_VERSION_H 6 | #define __@PROJECT_MACRO_PREFIX@_VERSION_H 7 | 8 | 9 | #ifndef xT 10 | #define xT(str) str 11 | #endif 12 | 13 | /* NB: this file is parsed by automatic tools so don't change its format! */ 14 | 15 | #define @PROJECT_MACRO_PREFIX@_MAJOR_VERSION @PROJECT_VERSION_MAJOR@ 16 | #define @PROJECT_MACRO_PREFIX@_MINOR_VERSION @PROJECT_VERSION_MINOR@ 17 | #define @PROJECT_MACRO_PREFIX@_PATCH_NUMBER @PROJECT_VERSION_PATCH@ 18 | #define @PROJECT_MACRO_PREFIX@_RELEASE_NUMBER @PROJECT_VERSION_TWEAK@ 19 | 20 | #define @PROJECT_MACRO_PREFIX@_PROJECT_NAME xT("@PROJECT_NAME@") 21 | #define @PROJECT_MACRO_PREFIX@_VERSION_STRING xT("@PROJECT_VERSION@") 22 | #define @PROJECT_MACRO_PREFIX@_VERSION_STR xT("@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@") 23 | #define @PROJECT_MACRO_PREFIX@_ARCHIVE_NAME xT("@ARCHIVE_NAME@") 24 | #define @PROJECT_MACRO_PREFIX@_DESCRIPTION xT("@PROJECT_DESCRIPTION@") 25 | 26 | #define @PROJECT_MACRO_PREFIX@_GIT_BRANCH xT("@GIT_BRANCH@") 27 | #define @PROJECT_MACRO_PREFIX@_GIT_TAG xT("@GIT_LAST_TAG@") 28 | #define @PROJECT_MACRO_PREFIX@_GIT_TAG_LONG xT("@GIT_LAST_TAG_LONG@") 29 | #define @PROJECT_MACRO_PREFIX@_GIT_REV xT("@GIT_COMMIT_REV@") 30 | #define @PROJECT_MACRO_PREFIX@_GIT_COMMIT_HASH xT("@GIT_COMMIT_HASH@") 31 | 32 | 33 | #endif //__@PROJECT_MACRO_PREFIX@_VERSION_H 34 | -------------------------------------------------------------------------------- /cmake/versions-gen.cmake: -------------------------------------------------------------------------------- 1 | # https://github.com/pmirshad/cmake-with-git-metadata/blob/master/CMakeLists.txt 2 | 3 | macro(gen_versions PROJ_NAME PROJECT_MACRO_PREFIX VERSION_H_NAME CONFIG_H_NAME ARCHIVE_NAME xVERSION_IN xCONFIG_BASE_IN) 4 | if (DEFINED PROJ_NAME) 5 | else () 6 | set(PROJ_NAME ${CMAKE_PROJECT_NAME}) 7 | endif () 8 | 9 | if (DEFINED PROJECT_MACRO_PREFIX) 10 | else () 11 | set(PROJECT_MACRO_PREFIX ${PROJ_NAME}) 12 | endif () 13 | 14 | if (DEFINED VERSION_H_NAME) 15 | else () 16 | set(VERSION_H_NAME "${PROJ_NAME}-version.hh") 17 | endif () 18 | 19 | if (DEFINED CONFIG_H_NAME) 20 | else () 21 | set(CONFIG_H_NAME "${PROJ_NAME}-config.hh") 22 | endif () 23 | 24 | if (DEFINED ARCHIVE_NAME) 25 | else () 26 | set(ARCHIVE_NAME ${PROJ_NAME}-${CMAKE_PROJECT_VERSION}) 27 | endif () 28 | 29 | if (DEFINED xVERSION_IN) 30 | else () 31 | set(xVERSION_IN ${CMAKE_SOURCE_DIR}/${CMAKE_SCRIPTS}/version.h.in) 32 | endif () 33 | 34 | if (DEFINED xCONFIG_BASE_IN) 35 | else () 36 | set(xCONFIG_BASE_IN ${CMAKE_SOURCE_DIR}/${CMAKE_SCRIPTS}/config-base.h.in) 37 | endif () 38 | 39 | set(xOUT_DIR ${CMAKE_GENERATED_DIR}) 40 | 41 | message("|| gen_version() : output-dir -> ${xOUT_DIR}") 42 | message("|| Using version.in file : ${xVERSION_IN}, ARCHIVE_NAME = ${ARCHIVE_NAME}, PROJECT_MACRO_PREFIX = ${PROJECT_MACRO_PREFIX}") 43 | message("|| CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}") 44 | 45 | if (EXISTS "${CMAKE_SOURCE_DIR}/.git") 46 | # git describe --tags --abbrev=0 # 0.1.0-dev 47 | # git describe --tags # 0.1.0-dev-93-g1416689 48 | # git describe --abbrev=0 # to get the most recent annotated tag 49 | execute_process( 50 | COMMAND git describe --abbrev=0 --tags 51 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 52 | OUTPUT_VARIABLE GIT_LAST_TAG 53 | OUTPUT_STRIP_TRAILING_WHITESPACE 54 | ERROR_QUIET 55 | ) 56 | execute_process( 57 | COMMAND git describe --tags 58 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 59 | OUTPUT_VARIABLE GIT_LAST_TAG_LONG 60 | OUTPUT_STRIP_TRAILING_WHITESPACE 61 | ERROR_QUIET 62 | ) 63 | execute_process( 64 | COMMAND git rev-parse --abbrev-ref HEAD 65 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 66 | OUTPUT_VARIABLE GIT_BRANCH 67 | OUTPUT_STRIP_TRAILING_WHITESPACE 68 | ERROR_QUIET 69 | ) 70 | execute_process( 71 | COMMAND git rev-parse HEAD 72 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 73 | OUTPUT_VARIABLE GIT_COMMIT_HASH 74 | OUTPUT_STRIP_TRAILING_WHITESPACE 75 | ERROR_QUIET 76 | ) 77 | execute_process( 78 | COMMAND git log -1 --format=%h 79 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 80 | OUTPUT_VARIABLE GIT_COMMIT_REV 81 | OUTPUT_STRIP_TRAILING_WHITESPACE 82 | ERROR_QUIET 83 | ) 84 | else () 85 | set(GIT_BRANCH "master") 86 | set(GIT_LAST_TAG "HEAD") 87 | set(GIT_LAST_TAG_LONG "HEAD") 88 | set(GIT_COMMIT_HASH "") 89 | set(GIT_COMMIT_REV "") 90 | endif () 91 | 92 | # # get_git_head_revision(GIT_REFSPEC GIT_SHA1) 93 | # string(SUBSTRING "${GIT_COMMIT_HASH}" 0 12 GIT_COMMIT_REV) 94 | # if (NOT GIT_COMMIT_HASH) 95 | # set(GIT_COMMIT_REV "0") 96 | # endif () 97 | message("|| Git current branch : ${GIT_BRANCH}") 98 | message("|| Git last tags : ${GIT_LAST_TAG}, Long: ${GIT_LAST_TAG_LONG}") 99 | message("|| Git commit hash : ${GIT_COMMIT_HASH}, revision: ${GIT_COMMIT_REV}") 100 | 101 | if (NOT "${xOUT_DIR}") 102 | else () 103 | message(FATAL " >> ERROR: please include target-dirs.cmake at first.") 104 | 105 | # we need CMAKE_GENERATED_DIR at present. 106 | endif () 107 | 108 | # include(CheckIncludeFile) 109 | # include(CheckIncludeFiles) 110 | # set(HAS_UNISTD_H 0) 111 | # check_include_file("unistd.h" HAS_UNISTD_H) 112 | # check_include_files("stdio.h;string.h" HAVE_STDIO_AND_STRING_H) 113 | message("|| unistd.h checked : HAS_UNISTD_H = ${HAS_UNISTD_H}") 114 | 115 | set(_output_dir ${xOUT_DIR}) 116 | # set(_output_dir ${CMAKE_CURRENT_BINARY_DIR}) 117 | 118 | if (EXISTS ${xVERSION_IN}) 119 | message("|| Generating version.h from ${xVERSION_IN} to ${_output_dir} - Version ${PROJECT_VERSION}...") 120 | configure_file( 121 | ${xVERSION_IN} 122 | ${_output_dir}/${VERSION_H_NAME} 123 | ) 124 | message("|| Generated: ${_output_dir}/${VERSION_H_NAME}") 125 | endif () 126 | 127 | if (EXISTS ${xCONFIG_BASE_IN}) 128 | message("|| Generating ${CONFIG_H_NAME} from ${xCONFIG_BASE_IN} to ${_output_dir} - Version ${PROJECT_VERSION}...") 129 | configure_file( 130 | ${xCONFIG_BASE_IN} 131 | ${_output_dir}/${CONFIG_H_NAME} 132 | ) 133 | message("|| Generated: ${_output_dir}/${CONFIG_H_NAME}") 134 | endif () 135 | endmacro() 136 | -------------------------------------------------------------------------------- /cmdr-cxx.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ 5 | 6 | Name: cmdr-cxx 7 | Description: A C++17 header-only command-line arguments parser, config manager, and application framework 8 | Version: @VERSION@ 9 | Requires: 10 | Libs: -L${libdir} 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | doxygen/ 3 | 4 | Doxyfile 5 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" OFF) 3 | 4 | if(BUILD_DOCUMENTATION) 5 | find_package(Doxygen) 6 | 7 | if(DEBUG OR NOT DOXYGEN_FOUND) 8 | set(BUILD_DOCUMENTATION OFF) 9 | endif() 10 | endif() 11 | 12 | if(BUILD_DOCUMENTATION) 13 | if(NOT DOXYGEN_FOUND) 14 | message(FATAL_ERROR "Doxygen is needed to build the documentation.") 15 | else() 16 | message("running doxygen...") 17 | endif() 18 | 19 | # Find all the public headers 20 | get_target_property(MY_PUBLIC_HEADER_DIR cmdr11 INTERFACE_INCLUDE_DIRECTORIES) 21 | file(GLOB_RECURSE MY_PUBLIC_HEADERS ${MY_PUBLIC_HEADER_DIR}/*.h) 22 | debug_print_list_value(MY_PUBLIC_HEADER_DIR) 23 | debug_print_value(PROJECT_SOURCE_DIR) 24 | 25 | # set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR} ) 26 | set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}/libs/cmdr11) 27 | 28 | # set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/docs/doxygen) 29 | set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../bin/doxygen) 30 | set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/html/index.html) 31 | set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/cmdr11-cxx.in.doxygen) 32 | set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 33 | 34 | # Replace variables inside @@ with the current values 35 | configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) 36 | 37 | file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}) # Doxygen won't create this for us 38 | add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} 39 | DEPENDS ${MY_PUBLIC_HEADERS} 40 | COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} 41 | 42 | # COMMAND 43 | # $<$:${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}> 44 | # $<$>:${CMAKE_COMMAND} -E "echo 'Only done in Release builds'"> 45 | MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} 46 | COMMENT "Generating docs" 47 | VERBATIM) 48 | 49 | add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) 50 | 51 | # install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc) 52 | endif() 53 | 54 | macro(attach_doxygen_to target) 55 | if(CMAKE_BUILD_TYPE MATCHES "^[Rr]elease") 56 | add_dependencies(${target} docs) 57 | endif() 58 | endmacro() 59 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | `cmdr-cxx` is a command-line arguments parser in C++17. 4 | 5 | 6 | 7 | ## Build 8 | 9 | ```bash 10 | mkdir build && cd build 11 | cmake .. 12 | cmake --build . 13 | ./cli 14 | ``` 15 | 16 | ## LICENSE 17 | 18 | Apache 2.0 19 | -------------------------------------------------------------------------------- /docs/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/header.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | $projectname: $title 10 | $title 11 | 12 | 13 | 14 | 15 | 16 | 17 | $treeview 18 | $search 19 | $mathjax 20 | 21 | $extrastylesheet 22 | 23 | 24 |
25 |
26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 43 | 44 | 45 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
37 |
$projectname 38 |  $projectnumber 39 |
40 | 41 |
$projectbrief
42 |
47 |
$projectbrief
48 |
$searchbox
59 |
60 | 61 | -------------------------------------------------------------------------------- /docs/release-v0.6.0.txt: -------------------------------------------------------------------------------- 1 | 2 | - v0.6.0 3 | - improved load-cmdr-cxx.cmake for cmdr-cxx users; 4 | - updated gh action scripts; 5 | - fix windows build again; 6 | - upgraded cmake/ scripts; 7 | - downward compatible with python 3.8-; 8 | - upgraded to catch2 3.7.1+; 9 | - improved compiler detectors and `-#`/`-V` outputs; 10 | - improved typo/lint pieces; 11 | - improved macro defs - fix _countof(); added offsetof(); ... 12 | - cleanup 13 | - c++20 ready 14 | -------------------------------------------------------------------------------- /docs/release-v0.6.1.txt: -------------------------------------------------------------------------------- 1 | 2 | - v0.6.1 3 | - improved cmake/config-base.h.in; 4 | - improved gh action scripts; 5 | - c++20 ready 6 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(examples 2 | VERSION ${VERSION} 3 | DESCRIPTION "examples - example-apps for cmdr cxx11 library" 4 | LANGUAGES CXX) 5 | 6 | # ################################### 7 | # dump_list(INCLUDE_DIRECTORIES) 8 | # debug_print_list_value(INCLUDE_DIRECTORIES) 9 | debug_print_hbar() 10 | debug(" tests ") 11 | message("!! entering subdir: ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") 12 | 13 | # debug_dump_cmake_environments() 14 | # debug_print_hbar() 15 | # debug_dump_cmake_variables() 16 | # debug_print_hbar_long() 17 | set(PROJECT_ARCHIVE_NAME ${PROJECT_NAME}s-${PROJECT_VERSION}) 18 | 19 | if (ENABLE_TESTS) 20 | # include(deps_inc_catch2) 21 | # include(deps_inc_fmt) 22 | endif () 23 | 24 | # # so_stuff: just a tester for ARGN 25 | # function(do_stuff arg1 arg2) 26 | # foreach (f ${ARGN}) 27 | # # do something interesting with file 'f' 28 | # message("f='${f}' arg1='${arg1}' arg2='${arg2}'") 29 | # endforeach () 30 | # message("f='${f}' arg1='${arg1}' arg2='${arg2}' ARGV2='${ARGV2}'") 31 | # endfunction() 32 | # do_stuff(A B C D E) 33 | find_package(Threads) 34 | 35 | function(define_example_program name) 36 | # set(src_list ) 37 | foreach (f ${ARGN}) 38 | list(APPEND src_list ${f}) 39 | endforeach () 40 | 41 | add_executable(${PROJECT_NAME}-${name} ${src_list}) 42 | add_cxx_standard_to(${PROJECT_NAME}-${name} ${CXX_STANDARD}) 43 | 44 | # target_compile_features(${PROJECT_NAME}-${name} PRIVATE cxx_std_11) 45 | target_compile_definitions(${PROJECT_NAME}-${name} INTERFACE 46 | CMDR_ENABLE_ASSERTIONS=${_cmdr_enable_assertions} 47 | CMDR_ENABLE_PRECONDITION_CHECKS=${_cmdr_enable_precondition_checks} 48 | CMDR_ENABLE_WRAPPER=0 49 | CMDR_TEST_THREAD_POOL_DBGOUT=0 50 | CMDR_UNIT_TEST=0 51 | ) 52 | target_include_directories(${PROJECT_NAME}-${name} PRIVATE 53 | $ 54 | ${CMAKE_SOURCE_DIR} 55 | $ 56 | $ 57 | $ 58 | 59 | SYSTEM PRIVATE 60 | $/include> 61 | ) 62 | target_link_libraries(${PROJECT_NAME}-${name} 63 | PRIVATE 64 | libs::cmdr11 65 | Threads::Threads 66 | 67 | # Catch2::Catch2 68 | # fmt::fmt-header-only 69 | ) 70 | 71 | # set_target_properties(${PROJECT_NAME}-${name} PROPERTIES 72 | # CXX_STANDARD 17 73 | # CXX_STANDARD_REQUIRED ON 74 | # CXX_EXTENSIONS OFF 75 | # ) 76 | if (MSVC) 77 | target_compile_options(${PROJECT_NAME}-${name} PRIVATE /W4 /WX /utf-8) 78 | else () 79 | target_compile_options(${PROJECT_NAME}-${name} PRIVATE 80 | -pedantic -Wall -Wextra -Wshadow -Werror 81 | ) 82 | 83 | if (DEBUG) 84 | target_compile_options(${PROJECT_NAME}-${name} PRIVATE 85 | -fsanitize=address 86 | 87 | # address(AddressSanitizer), leak(LeakSanitizer), thread(ThreadSanitizer), undefined(UndefinedBehaviorSanitizer), memory(MemorySanitizer) 88 | # [additional_options]: -fno-omit-frame-pointer, fsanitize-recover/fno-sanitize-recover, -fsanitize-blacklist, etc. 89 | # [-g] [-OX] 90 | ) 91 | target_link_options(${PROJECT_NAME}-${name} PRIVATE -fsanitize=address) 92 | endif () 93 | endif () 94 | endfunction() 95 | 96 | if (CMDR_NO_3RDPARTY) 97 | else () 98 | define_example_program(app1 app1.cc second_src.cc) 99 | # 100 | # For test-app2-c1, loading the dependency to yaml-cpp 101 | # 102 | include(loaders/yaml_loader) 103 | add_yaml_loader_to(examples-app1) 104 | target_compile_definitions(examples-app1 PRIVATE 105 | CMDR_ENABLE_VERBOSE_LOG=0) 106 | endif () 107 | 108 | define_example_program(app2 app2.cc second_src.cc) 109 | 110 | define_example_program(simple-app simple-app.cc) 111 | 112 | # 113 | # if (MSVC) 114 | # # target_compile_options(test-sso-1 PRIVATE /W4 /WX /utf-8) 115 | # target_compile_options(test-flags-c2 PRIVATE /bigobj) 116 | # else () 117 | # # target_compile_options(test-sso-1 PRIVATE -Werror=sized-deallocation) 118 | # endif () 119 | 120 | 121 | # target_compile_definitions(examples-app1 PRIVATE CMDR_ENABLE_VERBOSE_LOG=0) 122 | 123 | # target_compile_definitions(examples PRIVATE CMDR_ENABLE_VERBOSE_LOG=0) 124 | 125 | # if (BUILD_TESTING) 126 | # add_unit_test(${PROJECT_NAME} tests ${PROJECT_NAME}_tests) 127 | # endif () 128 | add_subdirectory(more) 129 | 130 | debug_print_value(ARCHIVE_NAME) 131 | debug_print_value(PROJECT_ARCHIVE_NAME) 132 | debug_print_value(BUILD_TESTING) 133 | debug_print_value(CMAKE_SOURCE_DIR) 134 | message(STATUS "end of examples") -------------------------------------------------------------------------------- /examples/app1.cc: -------------------------------------------------------------------------------- 1 | // cmdr-cxx Library 2 | // Copyright © 2021 Hedzr Yeh. 3 | // 4 | // This file is released under the terms of the MIT license. 5 | // Read /LICENSE for more information. 6 | 7 | // 8 | // Created by Hedzr Yeh on 2021/10/16. 9 | // 10 | 11 | #include "./addons/loaders/yaml_loader.hh" 12 | #include "cmdr-cxx.hh" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "second_src.hh" 25 | 26 | int main(int argc, char *argv[]) { 27 | auto &cli = cmdr::cli("app1", CMDR_VERSION_STRING, "hedzr", 28 | "Copyright © 2021 by hedzr, All Rights Reserved.", 29 | "A demo app for cmdr-c11 library.", 30 | "$ ~ --help"); 31 | 32 | try { 33 | using namespace cmdr::opt; 34 | 35 | // cli.opt(opt_dummy{}()); 36 | 37 | add_server_menu(cli); 38 | add_test_menu(cli); 39 | 40 | #if defined(_DEBUG) 41 | auto &cc = cli("server"); 42 | assert(cc.valid()); 43 | assert(cc["count"].valid()); 44 | assert(cc["host"].valid()); 45 | assert(cc("status").valid()); 46 | assert(cc("start").valid()); 47 | assert(cc("run", true).valid()); 48 | std::cout << cc.group_name() << '\n'; 49 | #endif 50 | 51 | #if CMDR_TEST_ON_COMMAND_NOT_HOOKED 52 | cli.set_global_on_command_not_hooked([](cmdr::opt::cmd const &, string_array const &) { 53 | cmdr::get_store().dump_full_keys(std::cout); 54 | cmdr::get_store().dump_tree(std::cout); 55 | return 0; 56 | }); 57 | #endif 58 | 59 | #if 1 60 | { 61 | using namespace cmdr::addons::loaders; 62 | cli.set_global_on_loading_externals(yaml_loader{}()); 63 | } 64 | #endif 65 | 66 | #if 1 67 | cli += sub_cmd{}("dup-test", "dup") 68 | .description("dup command/flag for testing") 69 | .group("Test"); 70 | { 71 | auto &t1 = *cli.last_added_command(); 72 | 73 | t1 += opt{""}("string", "str") 74 | .description("set the string-value"); 75 | t1 += opt{10}("int", "i") 76 | .description("set the int-value"); 77 | t1 += opt{10}("int", "i") 78 | .description("set the int-value"); 79 | } 80 | #endif 81 | 82 | } catch (std::exception &e) { 83 | std::cerr << "Exception caught for testing (NOT BUG) : " << e.what() << '\n'; 84 | CMDR_DUMP_STACK_TRACE(e); 85 | } 86 | 87 | #if !defined(OS_WIN) 88 | cmdr::debug::UnhandledExceptionHookInstaller _ueh{}; 89 | #endif 90 | return cli.run(argc, argv); 91 | } 92 | -------------------------------------------------------------------------------- /examples/app2.cc: -------------------------------------------------------------------------------- 1 | // cmdr-cxx Library 2 | // Copyright © 2021 Hedzr Yeh. 3 | // 4 | // This file is released under the terms of the MIT license. 5 | // Read /LICENSE for more information. 6 | 7 | // 8 | // Created by Hedzr Yeh on 2021/10/16. 9 | // 10 | 11 | // #include "./addons/loaders/yaml_loader.hh" 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "second_src.hh" 25 | 26 | int main(int argc, char *argv[]) { 27 | auto &cli = cmdr::cli("app2", CMDR_VERSION_STRING, "hedzr", 28 | "Copyright © 2021 by hedzr, All Rights Reserved.", 29 | "A demo app for cmdr-c11 library.", 30 | "$ ~ --help") 31 | // remove "Powered by cmdr-cxx" line 32 | .set_no_cmdr_endings() 33 | // customize the last line except cmdr endings 34 | .set_tail_line("") 35 | .set_no_tail_line(false); 36 | 37 | try { 38 | using namespace cmdr::opt; 39 | 40 | // cli.opt(opt_dummy{}()); 41 | 42 | add_server_menu(cli); 43 | add_test_menu(cli); 44 | add_main_menu(cli); 45 | 46 | // cli.set_minimal_tab_stop(55); 47 | using cmdr::terminal::colors::colorize; 48 | cli.set_alternate_text_color(colorize::Colors256::Green); 49 | 50 | #if defined(_DEBUG) 51 | auto &cc = cli("server"); 52 | CMDR_ASSERT(cc.valid()); 53 | CMDR_ASSERT(cc["count"].valid()); 54 | CMDR_ASSERT(cc["host"].valid()); 55 | CMDR_ASSERT(cc("status").valid()); 56 | CMDR_ASSERT(cc("start").valid()); 57 | CMDR_ASSERT(cc("run", true).valid()); 58 | #endif 59 | 60 | #if CMDR_TEST_ON_COMMAND_NOT_HOOKED 61 | cli.set_global_on_command_not_hooked([](cmdr::opt::cmd const &, string_array const &) { 62 | cmdr::get_store().dump_full_keys(std::cout); 63 | cmdr::get_store().dump_tree(std::cout); 64 | return 0; 65 | }); 66 | #endif 67 | 68 | #if 0 69 | { 70 | using namespace cmdr::addons::loaders; 71 | cli.set_global_on_loading_externals(yaml_loader{}()); 72 | } 73 | #endif 74 | 75 | #if 0 76 | cli += sub_cmd{}("dup", "dup") 77 | .description("dup command/flag for testing") 78 | .group("Test"); 79 | { 80 | auto &t1 = *cli.last_added_command(); 81 | 82 | t1 += opt{10}("int", "i") 83 | .description("set the int-value"); 84 | t1 += opt{10}("int", "i") 85 | .description("set the int-value"); 86 | t1 += opt{""}("string", "str") 87 | .description("set the string-value"); 88 | } 89 | #endif 90 | 91 | } catch (std::exception &e) { 92 | std::cerr << "Exception caught for testing (NOT BUG) : " << e.what() << '\n'; 93 | CMDR_DUMP_STACK_TRACE(e); 94 | } 95 | 96 | // cmdr::debug::UnhandledExceptionHookInstaller _ueh{}; 97 | // cmdr::debug::SigSegVInstaller _ssi{}; 98 | return cli.run(argc, argv); 99 | } 100 | -------------------------------------------------------------------------------- /examples/more/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #message(STATUS "This is lexer-BINARY dir " ${lexer_BINARY_DIR}) 3 | #message(STATUS "This is lexer-SOURCE dir " ${lexer_SOURCE_DIR}) 4 | #message(STATUS "This is lexer-INCLUDE dir " ${CMAKE_CURRENT_SOURCE_DIR}/include) 5 | #message(STATUS "This is PROJECT_SOURCE_DIR dir " ${PROJECT_SOURCE_DIR}) 6 | 7 | #debug_print_project_title() 8 | ##debug_print_value(LEXER_INCS) 9 | 10 | #debug_print_hbar() 11 | #debug_dump_cmake_environments() 12 | #debug_print_hbar() 13 | #debug_dump_cmake_variables() 14 | #debug_print_hbar_long() 15 | 16 | #message(" -> CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR}) 17 | cmake_subdir_list(SUBDIRS ".") 18 | foreach (subdir ${SUBDIRS}) 19 | message("") 20 | message("!! entering subdir: ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") 21 | add_subdirectory(${subdir}) 22 | endforeach () 23 | #MESSAGE() 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/more/app1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(app1 2 | VERSION ${VERSION} 3 | DESCRIPTION "app1 - test app for cmdr cxx11 library" 4 | LANGUAGES CXX) 5 | 6 | 7 | #################################### 8 | #dump_list(INCLUDE_DIRECTORIES) 9 | #debug_print_list_value(INCLUDE_DIRECTORIES) 10 | 11 | #debug_print_hbar() 12 | #debug_dump_cmake_environments() 13 | #debug_print_hbar() 14 | #debug_dump_cmake_variables() 15 | #debug_print_hbar_long() 16 | 17 | set(PROJECT_ARCHIVE_NAME ${PROJECT_NAME}-${PROJECT_VERSION}) 18 | add_executable(${PROJECT_NAME} main.cc small_cases.cc null_stream.cc) 19 | add_cxx_standard_to(${PROJECT_NAME} ${CXX_STANDARD}) 20 | #cxx_set_ipo(${PROJECT_NAME}) 21 | target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) 22 | target_include_directories(${PROJECT_NAME} PRIVATE 23 | $ 24 | ) 25 | target_link_libraries(${PROJECT_NAME} 26 | PRIVATE 27 | libs::cmdr11) 28 | 29 | #if (BUILD_TESTING) 30 | # add_unit_test(${PROJECT_NAME} tests ${PROJECT_NAME}_tests) 31 | #endif () 32 | debug_print_value(ARCHIVE_NAME) 33 | debug_print_value(PROJECT_ARCHIVE_NAME) 34 | debug_print_value(BUILD_TESTING) 35 | -------------------------------------------------------------------------------- /examples/more/app1/main.cc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include 6 | 7 | 8 | int main(int argc, char *argv[]) { 9 | #if defined(VERBOSE_DEBUG) || 1 10 | #if defined(_DEBUG) 11 | // extern void small_cases(); 12 | // small_cases(); 13 | #endif 14 | #endif 15 | 16 | try { 17 | using namespace cmdr::opt; 18 | return cmdr::cli("app1", CMDR_VERSION_STRING, "hedzr", 19 | "Copyright © 2021 by hedzr, All Rights Reserved.", 20 | "A demo app for cmdr-c11 library.", 21 | "$ ~ --help") 22 | .opt(sub_cmd{}("server", "s", "svr") 23 | .description("server operations for listening") 24 | .get()) 25 | .opt(opt{(int16_t) (3)}("count", "c") 26 | .description("set counter value") 27 | .get()) 28 | .opt(sub_cmd{}("host", "h", "hostname", "server-name") 29 | .description("hostname or ip address") 30 | .get()) 31 | .run(argc, argv); 32 | } catch (std::exception &e) { 33 | std::cerr << "Exception caught : " << e.what() << '\n'; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/more/app1/null_stream.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/14. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | template> 12 | class basic_nullbuf : public std::basic_streambuf { 13 | typename traits::int_type overflow(typename traits::int_type c) { 14 | return traits::not_eof(c); // indicate success 15 | } 16 | }; 17 | 18 | template> 19 | class basic_nullstream : public std::basic_ostream { 20 | public: 21 | basic_nullstream() 22 | : std::basic_ios(&m_sbuf) 23 | , std::basic_ostream(&m_sbuf) { 24 | init(&m_sbuf); 25 | } 26 | 27 | private: 28 | static void init(basic_nullbuf *sbuf) { 29 | UNUSED(sbuf); 30 | } 31 | 32 | private: 33 | basic_nullbuf m_sbuf; 34 | }; 35 | 36 | typedef basic_nullstream nullstream; 37 | typedef basic_nullstream wnullstream; 38 | 39 | // -------------- 40 | 41 | template> 42 | class basic_encoder_buf : public std::basic_streambuf { 43 | typename traits::int_type overflow(typename traits::int_type c) { 44 | return traits::not_eof(c); // indicate success 45 | } 46 | }; 47 | 48 | template> 49 | class basic_encoder : public std::basic_ostream { 50 | public: 51 | basic_encoder() 52 | : std::basic_ios(&m_sbuf) 53 | , std::basic_ostream(&m_sbuf) { 54 | init(&m_sbuf); 55 | } 56 | 57 | private: 58 | static void init(basic_nullbuf *sbuf) { 59 | UNUSED(sbuf); 60 | } 61 | 62 | private: 63 | basic_nullbuf m_sbuf; 64 | }; 65 | 66 | typedef basic_encoder encoder; 67 | typedef basic_encoder wencoder; 68 | 69 | void test_encoder() { 70 | encoder os; 71 | std::tuple mc; 72 | os << 666 << std::get<1>(mc); 73 | } 74 | 75 | // -------------- 76 | 77 | class MyClass { 78 | int a; 79 | 80 | friend std::ostream &operator<<(std::ostream &, MyClass const &); 81 | 82 | public: 83 | MyClass() = default; 84 | ~MyClass() = default; 85 | }; 86 | 87 | inline std::ostream &operator<<(std::ostream &out, MyClass const &b) { 88 | std::cout << "call format function!!" << '\n'; 89 | out << b.a; 90 | return out; 91 | } 92 | 93 | void test_null_stream() { 94 | nullstream os; 95 | MyClass mc{}; 96 | os << 666 << mc; 97 | } 98 | -------------------------------------------------------------------------------- /examples/more/app1/small_cases.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/13. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | 31 | #define ENABLE_VARIABLE 32 | #include "cmdr11/cmdr11.hh" 33 | 34 | #include "custom_iterator.hh" 35 | 36 | 37 | void small_cases() { 38 | cmdr::chrono::high_res_duration _timer; 39 | 40 | std::cout << "small_cases ------------" << '\n'; 41 | 42 | // std::cout << "test_literals ------------" << '\n'; 43 | // 44 | // extern void test_literals(); 45 | // test_literals(); 46 | // 47 | // std::cout << "test_null_stream ------------" << '\n'; 48 | // 49 | // extern void test_null_stream(); 50 | // test_null_stream(); 51 | // 52 | // std::cout << "test_inplace_and_emplace ------------" << '\n'; 53 | // 54 | // extern void test_inplace_and_emplace(); 55 | // test_inplace_and_emplace(); 56 | 57 | std::cout << "others ------------" << '\n'; 58 | 59 | // cmdr::vars::variable::test(); 60 | #if __clang__ 61 | cmdr::util::fixed_array::main(); 62 | #endif 63 | } 64 | -------------------------------------------------------------------------------- /examples/more/app2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(app2 2 | VERSION ${VERSION} 3 | DESCRIPTION "app1 - test app for cmdr cxx11 library" 4 | LANGUAGES CXX) 5 | 6 | 7 | #################################### 8 | #dump_list(INCLUDE_DIRECTORIES) 9 | #debug_print_list_value(INCLUDE_DIRECTORIES) 10 | 11 | #debug_print_hbar() 12 | #debug_dump_cmake_environments() 13 | #debug_print_hbar() 14 | #debug_dump_cmake_variables() 15 | #debug_print_hbar_long() 16 | 17 | set(PROJECT_ARCHIVE_NAME ${PROJECT_NAME}-${PROJECT_VERSION}) 18 | add_executable(${PROJECT_NAME} main.cc) 19 | add_cxx_standard_to(${PROJECT_NAME} ${CXX_STANDARD}) 20 | #cxx_set_ipo(${PROJECT_NAME}) 21 | target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_11) 22 | target_include_directories(${PROJECT_NAME} PRIVATE 23 | $ 24 | ) 25 | target_link_libraries(${PROJECT_NAME} 26 | PRIVATE 27 | libs::cmdr11) 28 | set_target_properties(${PROJECT_NAME} PROPERTIES 29 | CXX_STANDARD 17 30 | CXX_STANDARD_REQUIRED ON 31 | CXX_EXTENSIONS ON 32 | ) 33 | 34 | debug_print_value(ARCHIVE_NAME) 35 | debug_print_value(PROJECT_ARCHIVE_NAME) 36 | debug_print_value(BUILD_TESTING) 37 | -------------------------------------------------------------------------------- /examples/more/app2/main.cc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include 6 | 7 | void fatal_exit(const std::string &msg) { 8 | std::cerr << msg << '\n'; 9 | exit(-1); 10 | } 11 | 12 | int main(int argc, char *argv[]) { 13 | try { 14 | using namespace cmdr::opt; 15 | 16 | auto &cli = cmdr::cli("app2", CMDR_VERSION_STRING, "hedzr", 17 | "Copyright © 2021 by hedzr, All Rights Reserved.", 18 | "A demo app for cmdr-c11 library.", 19 | "$ ~ --help"); 20 | 21 | // cli.opt(opt_dummy{}()); 22 | 23 | cli += sub_cmd{}("server", "s", "svr") 24 | .description("server operations for listening"); 25 | 26 | cli += opt{1}("count", "c") 27 | .description("set counter value"); 28 | 29 | cli += opt{""}("host", "H", "hostname", "server-name") 30 | .description("hostname or ip address"); 31 | 32 | cmdr::set("wudao.count", 1); 33 | cmdr::set("wudao.string", "str"); 34 | cmdr::set("wudao.float", 3.14f); 35 | cmdr::set("wudao.double", 2.718); 36 | cmdr::set("wudao.array", std::vector{"a", "b", "c"}); 37 | cmdr::set("wudao.bool", false); 38 | 39 | std::cout << cmdr::get("wudao.count") << '\n'; 40 | auto const &aa = cmdr::get>("wudao.array"); 41 | std::cout << cmdr::string::join(aa, ", ", "[", "]") << '\n'; 42 | cmdr::vars::variable &ab = cmdr::get_app().get("wudao.array"); 43 | std::cout << ab << '\n'; 44 | 45 | return cli.run(argc, argv); 46 | 47 | } catch (std::exception &e) { 48 | std::cerr << "Exception caught : " << e.what() << '\n'; 49 | 50 | } catch (...) { 51 | cmdr::get_app().post_run(); // optional to post_run(), for the rare exception post processing if necessary 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/second_src.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/2/10. 3 | // 4 | 5 | #ifndef CMDR_CXX11_SECOND_SRC_HH 6 | #define CMDR_CXX11_SECOND_SRC_HH 7 | 8 | void second_test(); 9 | 10 | void fatal_exit(const std::string &msg); 11 | 12 | void add_sub1_menu(cmdr::app &cli, cmdr::opt::cmd &t1, const_chars title); 13 | void add_test_menu(cmdr::app &cli); 14 | void add_main_menu(cmdr::app &cli); 15 | void add_server_menu(cmdr::app &cli); 16 | 17 | 18 | #endif // CMDR_CXX11_SECOND_SRC_HH 19 | -------------------------------------------------------------------------------- /examples/simple-app.cc: -------------------------------------------------------------------------------- 1 | // cmdr-cxx Library 2 | // Copyright © 2021 Hedzr Yeh. 3 | // 4 | // This file is released under the terms of the MIT license. 5 | // Read /LICENSE for more information. 6 | 7 | // 8 | // Created by Hedzr Yeh on 2021/10/16. 9 | // 10 | 11 | // #include "./addons/loaders/yaml_loader.hh" 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "second_src.hh" 25 | 26 | int main(int argc, char *argv[]) { 27 | auto &cli = cmdr::cli("app2", CMDR_VERSION_STRING, "Sample Authors", 28 | "Copyright © 2021 by Sample Authors, All Rights Reserved.", 29 | "A demo app for cmdr-c11 library.", 30 | "$ ~ --help"); 31 | 32 | try { 33 | // using namespace cmdr::opt; 34 | add_test_menu(cli); 35 | } catch (std::exception &e) { 36 | std::cerr << "Exception caught for testing (NOT BUG) : " << e.what() << '\n'; 37 | CMDR_DUMP_STACK_TRACE(e); 38 | } 39 | 40 | return cli.run(argc, argv); 41 | } 42 | 43 | void add_test_menu(cmdr::app &cli) { 44 | using namespace cmdr::opt; 45 | 46 | cli += sub_cmd{}("test", "t", "test-command") 47 | .description("main tests commands for testing") 48 | .group("Test"); { 49 | auto &t1 = *(cli.last_added_command()); 50 | t1 += sub_cmd{}("hello", "hi") 51 | .description("hello world in cmdr-cxx subcmd way") 52 | .group("Test") 53 | .on_invoke([](cmd const &cc, string_array const &) -> int { 54 | std::cout << "Hello, World!\n"; 55 | 56 | // auto &s = cli.store(); 57 | auto &s = cmdr::get_store(); 58 | 59 | // get the final value of a option object, directly 60 | const auto &k = s.get_raw_p(DEFAULT_CLI_KEY_PREFIX, "test.int"); 61 | if (k.has_value()) 62 | std::cout << "int.val: " << k.as_string() << '\n'; 63 | 64 | // the recommendatory way is getting the option's node in the app-store at first, 65 | auto sc = s.subtree(DEFAULT_CLI_KEY_PREFIX); 66 | assert(sc->is_null() == false); 67 | std::cout << "string: " << sc->get_raw("test.string").as_string() << '\n'; 68 | std::cout << "float: " << sc->get_raw("test.float").as_string() << '\n'; 69 | std::cout << "double: " << sc->get_raw("test.double").as_string() << '\n'; 70 | std::cout << '\n' << "int: " << cc["int"].default_value() << '\n'; 71 | return 0; 72 | }); 73 | t1 += opt{10}("int", "i") 74 | .description("set the int-value"); 75 | t1 += opt{""}("string", "str") 76 | .description("set the string-value"); 77 | t1 += opt{3.13f}("float", "f") 78 | .description("flag float"); 79 | t1 += opt{3.12}("double", "d") 80 | .description("flag double"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /libs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake_minimum_required(VERSION 3.5) 2 | 3 | #add_subdirectory(cmdr11) 4 | 5 | #message(" -> CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR}) 6 | cmake_subdir_list(SUBDIRS "${CMAKE_CURRENT_SOURCE_DIR}") 7 | foreach (subdir ${SUBDIRS}) 8 | message("") 9 | message("!! entering subdir: ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") 10 | add_subdirectory(${subdir}) 11 | endforeach () 12 | #MESSAGE() 13 | 14 | -------------------------------------------------------------------------------- /libs/cmdr11/cmake/cmdr11Config.cmake: -------------------------------------------------------------------------------- 1 | ## Get the directory path of the .cmake file 2 | ## get_filename_component(CMDR11_CMAKE_DIR "cmdr11Config.cmake" DIRECTORY) 3 | get_filename_component(CMDR11_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 4 | get_filename_component(CMDR11_INCLUDE_DIR "${CMDR11_CMAKE_DIR}/../../../include" REALPATH) 5 | 6 | ## Add the dependencies of our library 7 | #include(CMakeFindDependencyMacro) 8 | ##find_dependency(ZLIB REQUIRED) 9 | ##find_dependency(fmt REQUIRED) 10 | 11 | 12 | # Compute paths 13 | #get_filename_component(CMDR_CXX_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 14 | #set(CMDR11_INCLUDE_DIR "${CMDR11_CMAKE_DIR}/../../../include") 15 | 16 | 17 | ## Import the targets 18 | if (NOT TARGET cmdr11::cmdr11) 19 | #include("${SM_LIB_CMAKE_DIR}/cmdr11Targets.cmake") 20 | include("${CMAKE_CURRENT_LIST_DIR}/cmdr11Targets.cmake") 21 | 22 | # These are IMPORTED targets created by cmdr11Targets.cmake 23 | set(CMDR11_LIBRARIES "cmdr11::cmdr11") 24 | 25 | if (EXISTS ${CMDR11_INCLUDE_DIR}/cmdr11/cmdr11.hh) 26 | set(CMDR11_FOUND ON) 27 | 28 | set(CMDR11_INCLUDE_DIRS ${CMDR11_INCLUDE_DIR}) 29 | get_filename_component(CMDR11_LIBRARY_DIR "${CMDR11_CMAKE_DIR}/../../../lib" REALPATH) 30 | set(CMDR11_LIBRARY_DIRS ${CMDR11_LIBRARY_DIR}) 31 | 32 | file(READ "${CMDR11_INCLUDE_DIR}/cmdr11/cmdr-version.hh" ver) 33 | 34 | string(REGEX MATCH "MAJOR_VERSION +([0-9]+)" _ ${ver}) 35 | set(CMDR11_VERSION_MAJOR ${CMAKE_MATCH_1}) 36 | 37 | string(REGEX MATCH "MINOR_VERSION +([0-9]+)" _ ${ver}) 38 | set(CMDR11_VERSION_MINOR ${CMAKE_MATCH_1}) 39 | 40 | string(REGEX MATCH "PATCH_NUMBER +([0-9]+)" _ ${ver}) 41 | set(CMDR11_VERSION_PATCH ${CMAKE_MATCH_1}) 42 | 43 | string(REGEX MATCH "CMDR_VERSION_STRING +xT\\(\\\"([0-9.]+)\\\"\\)" _ ${ver}) 44 | set(CMDR11_VERSION_STRING ${CMAKE_MATCH_1}) 45 | 46 | string(REGEX MATCH "CMDR_GIT_COMMIT_HASH +xT\\(\\\"([0-9a-f.-]+)\\\"\\)" _ ${ver}) 47 | set(CMDR11_VERSION_GIT_HASH ${CMAKE_MATCH_1}) 48 | 49 | message(">=< CMDR_VERSION = ${CMDR11_VERSION_MAJOR}.${CMDR11_VERSION_MINOR}.${CMDR11_VERSION_PATCH}") 50 | message(">=< CMDR_VERSION_STRING = ${CMDR11_VERSION_STRING} (HASH: ${CMDR11_VERSION_GIT_HASH})") 51 | message(">=< CMDR11_INCLUDE_DIR = ${CMDR11_INCLUDE_DIR}") 52 | message(">=< CMDR11_LIBRARY_DIR = ${CMDR11_LIBRARY_DIR}") 53 | message(">=< CMDR11_LIBRARIES = ${CMDR11_LIBRARIES}") 54 | endif () 55 | 56 | endif () 57 | -------------------------------------------------------------------------------- /libs/cmdr11/cmdr11-private.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/8. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR11_PRIVATE_HH 6 | #define CMDR_CXX11_CMDR11_PRIVATE_HH 7 | 8 | #endif // CMDR_CXX11_CMDR11_PRIVATE_HH 9 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr-cxx.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/21. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_CXX_HH 6 | #define CMDR_CXX11_CMDR_CXX_HH 7 | 8 | #include "cmdr11/cmdr11.hh" 9 | 10 | #if defined(__cpp_exceptions) 11 | #include "cmdr11/cmdr_if.hh" 12 | #endif 13 | 14 | #endif // CMDR_CXX11_CMDR_CXX_HH 15 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr11.hh: -------------------------------------------------------------------------------- 1 | /** 2 | * cmdr -- C++17 Command Line Arguments Parser 3 | * 4 | * @file 5 | * @brief Utilities for string operations. 6 | * 7 | * @ , copyright © 2016 - 2021 Hedzr Yeh. 8 | * @ , license {This project is released under the MIT License.} 9 | * 10 | * This file is part of cmdr (cmdr-c17 for C++ version). 11 | * 12 | * cmdr is free software: you can redistribute it and/or modify 13 | * it under the terms of the MIT License.. 14 | * 15 | * cmdr is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the MIT License 21 | * along with cmdr. If not, see . 22 | * 23 | * CHANGELOG 24 | * and additional copyright holders. 25 | * 26 | * 2021/1/8 27 | * - Initial version, written by hedzr @ CQ 28 | * 29 | */ 30 | 31 | #ifndef CMDR_CXX11_CMDR11_HH 32 | #define CMDR_CXX11_CMDR11_HH 33 | 34 | #pragma once 35 | 36 | 37 | // #define CMDR_CAST_CONST_CHARS_AS_STD_STRING 1 38 | // To cast a const char* string as a std::string instance in extracting 39 | // arg default value, uncomment the above line. 40 | 41 | // #define CMDR_ENABLE_VERBOSE_LOG 1 42 | // To enable internal very verbose logging, uncomment the above line. 43 | // see also cmdr_verbose_debug(...) in cmdr_log.hh 44 | 45 | // ## version info 46 | 47 | #include "cmdr-config-base.hh" 48 | #include "cmdr-version.hh" 49 | 50 | 51 | // ## all headers ... 52 | 53 | #include "cmdr_defs.hh" 54 | #include "cmdr_types.hh" 55 | #include "cmdr_types_check.hh" 56 | 57 | #include "cmdr_chrono.hh" 58 | #include "cmdr_common.hh" 59 | 60 | #include "cmdr_dbg.hh" 61 | 62 | 63 | #include "cmdr_log.hh" 64 | 65 | #include "cmdr_ios.hh" 66 | #include "cmdr_os_io_redirect.hh" 67 | #include "cmdr_path.hh" 68 | #include "cmdr_string.hh" 69 | #include "cmdr_terminal.hh" 70 | #include "cmdr_utils.hh" 71 | 72 | #include "cmdr_mmap.hh" 73 | #include "cmdr_pipeable.hh" 74 | #include "cmdr_pool.hh" 75 | #include "cmdr_priority_queue.hh" 76 | #include "cmdr_process.hh" 77 | #include "cmdr_small_string.hh" 78 | 79 | 80 | // 81 | 82 | 83 | #if defined(CMDR_CXX11_UNIT_TEST) && CMDR_CXX11_UNIT_TEST == 1 84 | #include "cmdr_x_test.hh" 85 | #endif 86 | #include "cmdr_z_test.hh" 87 | 88 | 89 | // 90 | 91 | #include "cmdr_var_t.hh" 92 | 93 | #include "cmdr_cmn.hh" 94 | 95 | #include "cmdr_arg.hh" 96 | #include "cmdr_cmd.hh" 97 | 98 | #include "cmdr_app.hh" 99 | 100 | #include "cmdr_internals.hh" 101 | #include "cmdr_public.hh" 102 | 103 | #include "cmdr_opts.hh" 104 | 105 | #include "cmdr_app_inl.h" 106 | #include "cmdr_cmd_inl.h" 107 | #include "cmdr_imp1.hh" // vars / variable / parse 108 | #include "cmdr_impl.hh" 109 | 110 | 111 | #endif // CMDR_CXX11_CMDR11_HH 112 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_imp1.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/29. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_IMP1_HH 6 | #define CMDR_CXX11_CMDR_IMP1_HH 7 | 8 | 9 | #include "cmdr_arg.hh" 10 | 11 | 12 | namespace cmdr::exception { 13 | 14 | [[maybe_unused]] inline dup_short_cmd_found::dup_short_cmd_found(const char *file, int line, opt::cmd const *c, opt::cmd const *owner) 15 | : dup_error{file, line, ""} 16 | , _o(owner) 17 | , _c(c) { 18 | char buf[512]; 19 | std::snprintf(buf, sizeof(buf), "duplicated short command found: \"%s\"/\"%s\" under command \"%s\"", 20 | _c->title_short().c_str(), 21 | _c->title().c_str(), 22 | _o->title_sequences().c_str()); 23 | msg = std::string((char const *) buf); 24 | } 25 | 26 | [[maybe_unused]] inline dup_long_cmd_found::dup_long_cmd_found(const char *file, int line, opt::cmd const *c, opt::cmd const *owner) 27 | : dup_error{file, line, ""} 28 | , _o(owner) 29 | , _c(c) { 30 | char buf[512]; 31 | std::snprintf(buf, sizeof(buf), "duplicated long command found: \"%s\"/\"%s\" under command \"%s\"", 32 | _c->title_long().c_str(), 33 | _c->title().c_str(), 34 | _o->title_sequences().c_str()); 35 | msg = std::string((char const *) buf); 36 | } 37 | 38 | [[maybe_unused]] inline dup_alias_cmd_found::dup_alias_cmd_found(const char *file, int line, const char *title, opt::cmd const *c, opt::cmd const *owner) 39 | : dup_error{file, line, ""} 40 | , _o(owner) 41 | , _c(c) { 42 | char buf[512]; 43 | std::snprintf(buf, sizeof(buf), "duplicated alias command found: \"%s\"/\"%s\" under command \"%s\"", 44 | title, 45 | _c->title().c_str(), 46 | _o->title_sequences().c_str()); 47 | msg = std::string((char const *) buf); 48 | } 49 | 50 | [[maybe_unused]] inline dup_short_flag_found::dup_short_flag_found(const char *file, int line, opt::arg const *a, opt::cmd const *c) 51 | : dup_error{file, line, ""} 52 | , _o(a) 53 | , _c(c) { 54 | char buf[512]; 55 | std::snprintf(buf, sizeof(buf), "duplicated short flag found: \"%s\"/\"%s\" under command \"%s\"", 56 | _o->title_short().c_str(), 57 | _o->title().c_str(), 58 | _c->title_sequences().c_str()); 59 | msg = std::string((char const *) buf); 60 | } 61 | 62 | [[maybe_unused]] inline dup_long_flag_found::dup_long_flag_found(const char *file, int line, opt::arg const *a, opt::cmd const *c) 63 | : dup_error{file, line, ""} 64 | , _o(a) 65 | , _c(c) { 66 | char buf[512]; 67 | std::snprintf(buf, sizeof(buf), "duplicated long flag found: \"%s\"/\"%s\" under command \"%s\"", 68 | _o->title_long().c_str(), 69 | _o->title().c_str(), 70 | _c->title_sequences().c_str()); 71 | msg = std::string((char const *) buf); 72 | } 73 | 74 | [[maybe_unused]] inline dup_alias_flag_found::dup_alias_flag_found(const char *file, int line, const char *title, opt::arg const *a, opt::cmd const *c) 75 | : dup_error{file, line, ""} 76 | , _o(a) 77 | , _c(c) { 78 | char buf[512]; 79 | std::snprintf(buf, sizeof(buf), "duplicated alias flag found: \"%s\"/\"%s\" under command \"%s\"", 80 | title, 81 | _o->title().c_str(), 82 | _c->title_sequences().c_str()); 83 | msg = std::string((char const *) buf); 84 | } 85 | 86 | } // namespace cmdr::exception 87 | 88 | namespace cmdr::opt { 89 | 90 | inline std::string arg::defaults() const { 91 | std::stringstream ss; 92 | bool tested{true}; 93 | if (_default->type() == typeid(bool)) { 94 | tested = !(_default->as() == false); 95 | } 96 | if (tested) { 97 | ss << ' ' << '[' << "DEFAULT"; 98 | if (!_placeholder.empty()) 99 | ss << ' ' << _placeholder; 100 | ss << '=' << *_default.get() << ']'; 101 | // if (!std::holds_alternative(_default)) { 102 | // ss << ' ' << '[' << "DEFAULT=" << variant_to_string(_default) << ']'; 103 | // } 104 | } 105 | return ss.str(); 106 | } 107 | inline const arg::var_type &arg::default_value() const { return _default; } 108 | inline arg::var_type &arg::default_value() { return _default; } 109 | 110 | inline arg &arg::default_value(const vars::variable &v) { 111 | if (_default.get() == nullptr) 112 | _default = std::make_shared(v); 113 | else 114 | #if __GNUC__ > 9 115 | _default->emplace(v); 116 | #else 117 | _default->emplace(v.underlying_value()); 118 | #endif 119 | return (*this); 120 | } 121 | inline arg &arg::default_value(const_chars v) { 122 | if (_default.get() == nullptr) 123 | _default = std::make_shared(std::string(v)); 124 | else 125 | _default->emplace(std::string(v)); 126 | return (*this); 127 | } 128 | template 129 | inline arg &arg::default_value(T const &v) { 130 | if (_default.get() == nullptr) 131 | _default = std::make_shared(v); 132 | else 133 | _default->template emplace(v); 134 | return (*this); 135 | } 136 | 137 | } // namespace cmdr::opt 138 | 139 | 140 | namespace cmdr::opt::types { 141 | 142 | inline cmd &parsing_context::curr_command() { 143 | if (_matched_commands.empty()) 144 | return *_root; 145 | return *_matched_commands.back(); 146 | } 147 | 148 | inline cmd &parsing_context::last_matched_cmd() { 149 | if (_matched_commands.empty()) 150 | return cmd::null_command(); 151 | return *_matched_commands.back(); 152 | } 153 | 154 | inline arg &parsing_context::last_matched_flg() { 155 | if (matched_flags.empty()) 156 | return cmd::null_arg(); 157 | return *matched_flags.back(); 158 | } 159 | 160 | // 161 | inline void parsing_context::add_matched_arg(arg *obj, std::shared_ptr const &v) { 162 | matched_flags.push_back(obj); 163 | _values_map.emplace(std::make_pair(obj, v)); 164 | } 165 | 166 | } // namespace cmdr::opt::types 167 | 168 | 169 | #endif // CMDR_CXX11_CMDR_IMP1_HH 170 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_internals.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/25. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_INTERNALS_HH 6 | #define CMDR_CXX11_CMDR_INTERNALS_HH 7 | 8 | #include "cmdr_utils.hh" 9 | 10 | 11 | namespace cmdr { 12 | 13 | class app; 14 | 15 | /** 16 | * @brief to hold the last app* instance. 17 | */ 18 | class app_holder final : public util::singleton { 19 | public: 20 | explicit app_holder(typename util::singleton::token) {} 21 | ~app_holder() = default; 22 | 23 | //#pragma clang diagnostic push 24 | //#pragma ide diagnostic ignored "readability-convert-member-functions-to-static" 25 | [[maybe_unused]] void use() const { std::cout << "in use" << '\n'; } 26 | //#pragma clang diagnostic pop 27 | 28 | public: 29 | app *get_ptr() { return _app; } 30 | app &operator*() { return *_app; } 31 | app *operator->() { return _app; } 32 | // explicit operator app() { return _app; } 33 | 34 | private: 35 | app *_app{}; 36 | void put(app *ptr) { _app = ptr; } 37 | friend class app; 38 | }; 39 | 40 | } // namespace cmdr 41 | 42 | #endif // CMDR_CXX11_CMDR_INTERNALS_HH 43 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_ios.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/21. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_IOS_HH 6 | #define CMDR_CXX11_CMDR_IOS_HH 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | template> 17 | inline std::basic_ostream<_CharT, _Traits> &operator<<(std::basic_ostream<_CharT, _Traits> &os, std::basic_ostringstream<_CharT, _Traits> const &iss) { 18 | return os << iss.str(); 19 | } 20 | template> 21 | inline std::basic_ostream<_CharT, _Traits> &operator<<(std::basic_ostream<_CharT, _Traits> &os, std::basic_ifstream<_CharT, _Traits> const &ifs) { 22 | return os << ifs.rdbuf(); 23 | } 24 | // template> 25 | // inline std::basic_ostream<_CharT, _Traits> &operator<<(std::basic_ostream<_CharT, _Traits> &os, std::ifstream const &ifs) { 26 | // return os << ifs.rdbuf(); 27 | // } 28 | template> 29 | inline std::basic_ostream<_CharT, _Traits> &operator<<(std::basic_ostream<_CharT, _Traits> &os, std::basic_istream<_CharT, _Traits> const &ifs) { 30 | 31 | // ifs >> std::noskipws; 32 | // std::copy(std::istream_iterator(ifs), std::istream_iterator(), std::ostream_iterator(std::cout)); 33 | 34 | if (ifs.rdbuf() != nullptr) 35 | os << ifs.rdbuf(); 36 | return os; 37 | } 38 | 39 | 40 | namespace cmdr::io { 41 | 42 | class ios_flags_saver { 43 | public: 44 | explicit ios_flags_saver(std::ostream &os) 45 | : ios(os) 46 | , f(os.flags()) {} 47 | ~ios_flags_saver() { ios.flags(f); } 48 | 49 | ios_flags_saver(const ios_flags_saver &rhs) = delete; 50 | ios_flags_saver &operator=(const ios_flags_saver &rhs) = delete; 51 | 52 | private: 53 | std::ostream &ios; 54 | std::ios::fmtflags f; 55 | }; 56 | 57 | class ios_state_saver { 58 | public: 59 | explicit ios_state_saver(std::ostream &os) 60 | : ios(os) { 61 | oldState.copyfmt(os); 62 | } 63 | ~ios_state_saver() { ios.copyfmt(oldState); } 64 | 65 | ios_state_saver(const ios_state_saver &rhs) = delete; 66 | ios_state_saver &operator=(const ios_state_saver &rhs) = delete; 67 | 68 | private: 69 | std::ostream &ios; 70 | std::ios oldState{nullptr}; 71 | }; 72 | 73 | } // namespace cmdr::io 74 | 75 | #endif // CMDR_CXX11_CMDR_IOS_HH 76 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_log.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/13. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_LOG_HH 6 | #define CMDR_CXX11_CMDR_LOG_HH 7 | 8 | // #include "cmdr_defs.hh" 9 | // #include "cmdr_terminal.hh" 10 | #include "cmdr_common.hh" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | namespace cmdr::log { 20 | 21 | namespace detail { 22 | class Log final : public util::singleton { 23 | public: 24 | explicit Log(typename util::singleton::token) {} 25 | ~Log() = default; 26 | 27 | // [[maybe_unused]] cmdr::terminal::colors::colorize _c; 28 | 29 | template 30 | void log([[maybe_unused]] const char *fmt, [[maybe_unused]] Args const &...args) { 31 | // std::fprintf(std::stderr) 32 | } 33 | void vdebug(const char *file, int line, const char *func, 34 | char const *fmt, va_list args) { 35 | // auto t = cross::time(nullptr); 36 | char time_buf[100]; 37 | #if _MSC_VER 38 | struct tm tm_ {}; 39 | auto _tm = &tm_; 40 | time_t vt = time(nullptr); 41 | gmtime_s(_tm, &vt); 42 | #else 43 | auto *_tm = cross::gmtime(); 44 | #endif 45 | std::strftime(time_buf, sizeof time_buf, "%D %T", _tm); 46 | 47 | va_list args2; 48 | va_copy(args2, args); 49 | std::vector buf((std::size_t) std::vsnprintf(nullptr, 0, fmt, args) + 1); 50 | std::vsnprintf(buf.data(), buf.size(), fmt, args2); 51 | va_end(args2); 52 | 53 | const char *const fg_reset_all = "\033[0m"; 54 | const char *const clr_magenta_bg_light = "\033[2;35m"; 55 | const char *const clr_cyan_bg_light = "\033[2;36m"; 56 | const char *const fg_light_gray = "\033[37m"; 57 | std::printf("%s" 58 | "%s %s:" 59 | "%s" 60 | " %s %s%s:%d " 61 | "%s" 62 | "(%s)" 63 | "%s" 64 | "\n", 65 | clr_magenta_bg_light, 66 | time_buf, 67 | // _c.dim().s("[debug]").as_string().c_str(), 68 | "[debug]", 69 | fg_reset_all, 70 | buf.data(), 71 | clr_cyan_bg_light, 72 | file, line, 73 | fg_light_gray, func, fg_reset_all); 74 | } 75 | }; 76 | } // namespace detail 77 | 78 | #if 0 79 | class log { 80 | public: 81 | template 82 | static void print(const char *fmt, Args const &...args) { 83 | xlog().template log(fmt, args...); 84 | } 85 | 86 | // static void vdebug(char const *fmt, va_list args) { 87 | // xlog().vdebug(fmt, args); 88 | // } 89 | static void debug(char const *fmt, ...) { 90 | // auto t = cross::time(nullptr); 91 | char time_buf[100]; 92 | // std::strftime(time_buf, sizeof time_buf, "%D %T", cross::gmtime()); 93 | #if _MSC_VER 94 | struct tm tm_ {}; 95 | auto _tm = &tm_; 96 | time_t vt = time(nullptr); 97 | gmtime_s(_tm, &vt); 98 | #else 99 | auto _tm = cross::gmtime(); 100 | #endif 101 | std::strftime(time_buf, sizeof time_buf, "%D %T", _tm); 102 | 103 | va_list args1; 104 | va_start(args1, fmt); 105 | va_list args2; 106 | va_copy(args2, args1); 107 | std::vector buf((std::size_t) std::vsnprintf(nullptr, 0, fmt, args1) + 1); 108 | va_end(args1); 109 | std::vsnprintf(buf.data(), buf.size(), fmt, args2); 110 | va_end(args2); 111 | 112 | std::printf("%s [debug]: %s\n", time_buf, buf.data()); 113 | } 114 | 115 | private: 116 | static detail::Log &xlog() { return detail::Log::instance(); } 117 | }; // class log 118 | #endif 119 | 120 | class holder { 121 | const char *_file; 122 | int _line; 123 | const char *_func; 124 | 125 | public: 126 | holder(const char *file, int line, const char *func) 127 | : _file(file) 128 | , _line(line) 129 | , _func(func) {} 130 | 131 | void operator()(char const *fmt, ...) { 132 | va_list va; 133 | va_start(va, fmt); 134 | xlog().vdebug(_file, _line, _func, fmt, va); 135 | va_end(va); 136 | } 137 | 138 | private: 139 | static detail::Log &xlog() { return detail::Log::instance(); } 140 | }; 141 | // Logger log; 142 | } // namespace cmdr::log 143 | 144 | #if defined(_MSC_VER) 145 | #define cmdr_print(...) cmdr::log::holder(__FILE__, __LINE__, __FUNCSIG__)(__VA_ARGS__) 146 | #else 147 | #define cmdr_print(...) cmdr::log::holder(__FILE__, __LINE__, __PRETTY_FUNCTION__)(__VA_ARGS__) 148 | #endif 149 | 150 | #if defined(_DEBUG) 151 | #if defined(_MSC_VER) 152 | #define cmdr_debug(...) cmdr::log::holder(__FILE__, __LINE__, __FUNCSIG__)(__VA_ARGS__) 153 | #else 154 | #define cmdr_debug(...) cmdr::log::holder(__FILE__, __LINE__, __PRETTY_FUNCTION__)(__VA_ARGS__) 155 | #endif 156 | #else 157 | #if defined(__GNUG__) || defined(_MSC_VER) 158 | #define cmdr_debug(...) \ 159 | (void) 0 160 | #else 161 | #define cmdr_debug(...) \ 162 | _Pragma("GCC diagnostic push") \ 163 | _Pragma("GCC diagnostic ignored \"-Wunused-value\"") do { (void) (__VA_ARGS__); } \ 164 | while (0) \ 165 | _Pragma("GCC diagnostic pop") 166 | #endif 167 | #endif 168 | 169 | #if defined(CMDR_ENABLE_VERBOSE_LOG) 170 | // inline void debug(char const *fmt, ...) { 171 | // va_list va; 172 | // va_start(va, fmt); 173 | // cmdr::log::log::vdebug(fmt, va); 174 | // va_end(va); 175 | // } 176 | #if defined(_MSC_VER) 177 | #define cmdr_verbose_debug(...) cmdr::log::holder(__FILE__, __LINE__, __FUNCSIG__)(__VA_ARGS__) 178 | #else 179 | #define cmdr_verbose_debug(...) cmdr::log::holder(__FILE__, __LINE__, __PRETTY_FUNCTION__)(__VA_ARGS__) 180 | #endif 181 | #else 182 | // #define cmdr_verbose_debug(...) 183 | // _Pragma("GCC diagnostic push") 184 | // _Pragma("GCC diagnostic ignored \"-Wunused-value\"") do { (void) (__VA_ARGS__); } 185 | // while (0) 186 | // _Pragma("GCC diagnostic pop") 187 | 188 | //#define cmdr_verbose_debug(...) (void)(__VA_ARGS__) 189 | 190 | template 191 | void cmdr_verbose_debug([[maybe_unused]] Args &&...args) { (void) (sizeof...(args)); } 192 | #endif 193 | #define cmdr_trace cmdr_verbose_debug 194 | 195 | #endif // CMDR_CXX11_CMDR_LOG_HH 196 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_opts.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/11. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_OPT_HH 6 | #define CMDR_CXX11_CMDR_OPT_HH 7 | 8 | #include "cmdr_var_t.hh" 9 | 10 | #include "cmdr_cmn.hh" 11 | 12 | #include "cmdr_arg.hh" 13 | #include "cmdr_cmd.hh" 14 | 15 | 16 | namespace cmdr::opt { 17 | 18 | 19 | class sub_cmd { 20 | public: 21 | sub_cmd() = default; 22 | ~sub_cmd() = default; 23 | 24 | types::option get() const { 25 | return [this](cmd &c) { 26 | c += _cmd; 27 | }; 28 | } 29 | 30 | public: 31 | sub_cmd &operator()(const char *long_, const char *short_ = nullptr) { 32 | _cmd.titles(long_, short_); 33 | return (*this); 34 | } 35 | 36 | template 37 | sub_cmd &operator()(const char *long_, const char *short_, Args... args) { 38 | _cmd.titles(long_, short_, args...); 39 | return (*this); 40 | } 41 | 42 | sub_cmd &group(const char *s) { 43 | _cmd.group(s); 44 | return (*this); 45 | } 46 | 47 | sub_cmd &hidden(bool b = true) { 48 | _cmd.hidden(b); 49 | return (*this); 50 | } 51 | 52 | sub_cmd &description(const char *desc, const char *long_desc = nullptr) { 53 | _cmd.description(desc, long_desc); 54 | return (*this); 55 | } 56 | 57 | sub_cmd &examples(const char *s) { 58 | _cmd.examples(s); 59 | return (*this); 60 | } 61 | 62 | sub_cmd &special(bool b = true) { 63 | _cmd.special(b); 64 | return (*this); 65 | } 66 | 67 | sub_cmd &no_non_special(bool b = true) { 68 | _cmd.no_non_special(b); 69 | return (*this); 70 | } 71 | 72 | sub_cmd &on_hit(types::on_command_hit const &cb) { 73 | _cmd.on_command_hit(cb); 74 | return (*this); 75 | } 76 | 77 | sub_cmd &on_pre_invoke(types::on_pre_invoke const &cb) { 78 | _cmd.on_pre_invoke(cb); 79 | return (*this); 80 | } 81 | 82 | sub_cmd &on_post_invoke(types::on_post_invoke const &cb) { 83 | _cmd.on_post_invoke(cb); 84 | return (*this); 85 | } 86 | 87 | sub_cmd &on_invoke(types::on_invoke const &cb) { 88 | _cmd.on_invoke(cb); 89 | return (*this); 90 | } 91 | 92 | 93 | cmd &underlying() { return _cmd; } 94 | [[nodiscard]] cmd const &underlying() const { return _cmd; } 95 | 96 | private: 97 | cmd _cmd; 98 | }; // class cmd 99 | 100 | 101 | class opt { 102 | public: 103 | opt() = default; 104 | // opt(opt const *) = delete; 105 | opt(opt &&o) noexcept 106 | : _arg(std::move(o._arg)) {} 107 | template::value && 110 | !std::is_same, opt>::value, 111 | int> = 0> 112 | explicit opt(A &&a0, Args &&...args) 113 | : _arg(std::forward(a0), std::forward(args)...) { 114 | } 115 | template::value && 117 | !std::is_same, opt>::value, 118 | int> = 0> 119 | explicit opt(A &&a) 120 | : _arg(std::forward(a)) {} 121 | #if defined(CMDR_CAST_CONST_CHARS_AS_STD_STRING) 122 | explicit opt(char const *&&a) 123 | : _arg(std::string(a)) {} 124 | #endif 125 | ~opt() = default; 126 | 127 | types::option get() const { 128 | return [this](cmd &c) { 129 | c += _arg; 130 | }; 131 | } 132 | 133 | public: 134 | opt &operator()(const char *long_, const char *short_ = nullptr) { 135 | _arg.titles(long_, short_); 136 | return (*this); 137 | } 138 | 139 | template 140 | opt &operator()(const char *long_, const char *short_, Args... args) { 141 | _arg.titles(long_, short_, args...); 142 | return (*this); 143 | } 144 | 145 | opt &operator()(const std::string &long_, const std::string &short_) { 146 | _arg.titles(long_.c_str(), short_.empty() ? nullptr : short_.c_str()); 147 | return (*this); 148 | } 149 | 150 | template 151 | opt &operator()(const std::string &long_, const std::string &short_, Args... args) { 152 | _arg.titles(long_, short_, args...); 153 | return (*this); 154 | } 155 | 156 | opt &group(const char *s) { 157 | _arg.group(s); 158 | return (*this); 159 | } 160 | 161 | opt &hidden(bool b = true) { 162 | _arg.hidden(b); 163 | return (*this); 164 | } 165 | 166 | opt &description(const char *desc, const char *long_desc = nullptr) { 167 | _arg.description(desc, long_desc); 168 | return (*this); 169 | } 170 | 171 | opt &examples(const char *s) { 172 | _arg.examples(s); 173 | return (*this); 174 | } 175 | 176 | opt &required(bool b = true) { 177 | _arg.required(b); 178 | return (*this); 179 | } 180 | 181 | opt &special(bool b = true) { 182 | _arg.special(b); 183 | return (*this); 184 | } 185 | 186 | opt &no_non_special(bool b = true) { 187 | _arg.no_non_special(b); 188 | return (*this); 189 | } 190 | 191 | opt &on_hit(types::on_flag_hit const &cb) { 192 | _arg.on_flag_hit(cb); 193 | return (*this); 194 | } 195 | 196 | opt &placeholder(const char *s) { 197 | _arg.placeholder(s); 198 | return (*this); 199 | } 200 | 201 | opt &toggle_group(const char *s) { 202 | _arg.toggle_group(s); 203 | return (*this); 204 | } 205 | 206 | template 207 | opt &env_vars(Args... args) { 208 | _arg.env_vars(args...); 209 | return (*this); 210 | } 211 | 212 | arg &underlying() { return _arg; } 213 | [[nodiscard]] const arg &underlying() const { return _arg; } 214 | 215 | private: 216 | arg _arg; 217 | // vars::variable _value{}; 218 | }; // class opt 219 | 220 | 221 | } // namespace cmdr::opt 222 | 223 | #endif // CMDR_CXX11_CMDR_OPT_HH 224 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_os_io_redirect.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/4/20. 3 | // 4 | 5 | #ifndef CMDR_CXX_CMDR_OS_IO_REDIRECT_HH 6 | #define CMDR_CXX_CMDR_OS_IO_REDIRECT_HH 7 | 8 | // #include "cmdr_process.hh" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | namespace cmdr::os { 23 | 24 | class pipe_stdin_to { 25 | std::streambuf *stream_buffer_cout; 26 | std::streambuf *stream_buffer_cin; 27 | 28 | public: 29 | pipe_stdin_to(std::streambuf *stream_buffer_file = nullptr) { 30 | stream_buffer_cout = std::cout.rdbuf(); 31 | stream_buffer_cin = std::cin.rdbuf(); 32 | if (stream_buffer_file) 33 | std::cin.rdbuf(stream_buffer_file); 34 | } 35 | virtual ~pipe_stdin_to() { 36 | std::cin.rdbuf(stream_buffer_cin); 37 | std::cout.rdbuf(stream_buffer_cout); 38 | // std::cout << "This line is written to screen" << std::endl; 39 | } 40 | }; 41 | 42 | template 43 | class pipe_std_dev_to { 44 | std::streambuf *stream_buffer_; 45 | 46 | public: 47 | pipe_std_dev_to(std::streambuf *stream_buffer_file = nullptr) { 48 | stream_buffer_ = (*std_out_device).rdbuf(); 49 | if (stream_buffer_file) 50 | (*std_out_device).rdbuf(stream_buffer_file); 51 | } 52 | virtual ~pipe_std_dev_to() { 53 | (*std_out_device).rdbuf(stream_buffer_); 54 | } 55 | }; 56 | 57 | 58 | typedef pipe_std_dev_to<&std::cout> pipe_stdout_to; 59 | typedef pipe_std_dev_to<&std::cerr> pipe_stderr_to; 60 | typedef pipe_std_dev_to<&std::clog> pipe_stdlog_to; 61 | 62 | 63 | class pipe_all_to : pipe_std_dev_to<&std::cout> 64 | , pipe_std_dev_to<&std::cerr> 65 | , pipe_std_dev_to<&std::clog> 66 | , pipe_stdin_to { 67 | public: 68 | pipe_all_to(std::streambuf *output_stream_buffer_file = nullptr, std::streambuf *input_stream_buffer_file = nullptr) 69 | : pipe_std_dev_to<&std::cout>(output_stream_buffer_file) 70 | , pipe_std_dev_to<&std::cerr>(output_stream_buffer_file) 71 | , pipe_std_dev_to<&std::clog>(output_stream_buffer_file) 72 | , pipe_stdin_to(input_stream_buffer_file) { 73 | } 74 | virtual ~pipe_all_to() {} 75 | }; 76 | 77 | } // namespace cmdr::os 78 | 79 | #endif // CMDR_CXX_CMDR_OS_IO_REDIRECT_HH 80 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_pipeable.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/8/21. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_PIPEABLE_HH 6 | #define CMDR_CXX11_CMDR_PIPEABLE_HH 7 | 8 | namespace cmdr::pipeable { 9 | 10 | template 11 | struct pipeable { 12 | private: 13 | F f; 14 | 15 | public: 16 | pipeable(F &&f_) 17 | : f(std::forward(f_)) {} 18 | 19 | template 20 | auto operator()(Xs &&...xs) -> decltype(std::bind(f, std::placeholders::_1, std::forward(xs)...)) const { 21 | return std::bind(f, std::placeholders::_1, std::forward(xs)...); 22 | } 23 | }; 24 | 25 | template 26 | pipeable piped(F &&f) { return pipeable{std::forward(f)}; } 27 | 28 | template 29 | auto operator|(T &&x, const F &f) -> decltype(f(std::forward(x))) { 30 | return f(std::forward(x)); 31 | } 32 | 33 | } // namespace cmdr::pipeable 34 | 35 | #endif // CMDR_CXX11_CMDR_PIPEABLE_HH 36 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_public.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/2/1. 3 | // 4 | 5 | #ifndef CMDR_CXX11_CMDR_PUBLIC_HH 6 | #define CMDR_CXX11_CMDR_PUBLIC_HH 7 | 8 | #include "cmdr_internals.hh" 9 | 10 | namespace cmdr { 11 | 12 | inline app &get_app() { return *app_holder::instance().get_ptr(); } 13 | inline auto &get_store() { return get_app().store(); } 14 | 15 | [[maybe_unused]] inline app &app::uniq() const { return get_app(); } 16 | 17 | inline app &cli(const_chars name, const_chars version, 18 | const_chars author = nullptr, const_chars copyright = nullptr, 19 | const_chars description = nullptr, 20 | const_chars examples = nullptr) { 21 | if (auto *ptr = app_holder::instance().get_ptr(); ptr) { 22 | return get_app(); 23 | } 24 | return app::create_new(name, version, author, copyright, description, examples); 25 | } 26 | 27 | inline app new_cli(const_chars name, const_chars version, 28 | const_chars author = nullptr, const_chars copyright = nullptr, 29 | const_chars description = nullptr, 30 | const_chars examples = nullptr) { 31 | #if !defined(CATCH_VERSION_MAJOR) 32 | if (auto *ptr = app_holder::instance().get_ptr(); ptr) { 33 | cmdr_throw_line("can't invoke create_app() multiple times."); 34 | } 35 | #endif 36 | return app::create(name, version, author, copyright, description, examples); 37 | } 38 | 39 | 40 | inline bool has(char const *key) { return get_app().has(key); } 41 | 42 | 43 | /** 44 | * @brief retrieve the config item value from store 45 | * 46 | * get() will wrap a prefix 'app.' to key for extracting the raw value in Option Store. 47 | * 48 | * @tparam T 49 | * @param key is a dotted string like 'server.start.foreground' 50 | * @return 51 | */ 52 | template 53 | inline T get(char const *key) { return get_app().get(key).cast_as(); } 54 | /** 55 | * @brief retrieve the config item value from store 56 | * 57 | * get() will wrap a prefix 'app.' to key for extracting the raw value in Option Store. 58 | * 59 | * @tparam T 60 | * @param key is a dotted string like 'server.start.foreground' 61 | * @return 62 | */ 63 | template 64 | inline T get(std::string const &key) { return get_app().get(key).cast_as(); } 65 | /** 66 | * @brief retrieve the cli-app args/flags value item from store. 67 | * 68 | * get_for_cli will wrap a prefix 'app.cli.' to key for extracting the raw value in Option Store. 69 | * 70 | * @tparam T 71 | * @param key is a dotted string like 'server.start.foreground' 72 | * @return 73 | */ 74 | template 75 | inline T get_for_cli(char const *key) { return get_app().get_for_cli(key).cast_as(); } 76 | /** 77 | * @brief retrieve the cli-app args/flags value item from store 78 | * 79 | * get_for_cli will wrap a prefix 'app.cli.' to key for extracting the raw value in Option Store. 80 | * 81 | * @tparam T 82 | * @param key is a dotted string like 'server.start.foreground' 83 | * @return 84 | */ 85 | template 86 | inline T get_for_cli(std::string const &key) { return get_app().get_for_cli(key).cast_as(); } 87 | 88 | 89 | template::value && 92 | !std::is_same, vars::variable>::value && 93 | !std::is_same, app>::value, 94 | int> = 0> 95 | inline void set(char const *key, A &&a0, Args &&...args) { 96 | get_app().set(key, a0, args...); 97 | } 98 | template::value && 100 | !std::is_same, vars::variable>::value && 101 | !std::is_same, app>::value, 102 | int> = 0> 103 | void set(char const *key, A &&a) { 104 | get_app().set(key, a); 105 | } 106 | inline void set(char const *key, vars::variable &&a) { get_app().set(key, a); } 107 | inline void set(char const *key, vars::variable const &a) { get_app().set(key, a); } 108 | 109 | 110 | inline bool is_debug() { return get_for_cli("debug"); } 111 | inline bool is_trace() { return get_for_cli("trace"); } 112 | inline bool is_verbose() { return get_for_cli("verbose"); } 113 | inline bool is_quiet() { return get_for_cli("quiet"); } 114 | inline bool is_no_color() { return get_for_cli("no-color"); } 115 | 116 | 117 | /** 118 | * @brief retrieve the verbose level from the hit data of a flag named as "verbose". 119 | * see also the initializations of the internal commands and flags. 120 | * @return 121 | */ 122 | inline int get_verbose_level() { return get_app()["verbose"].hit_count(); } 123 | inline bool is_help_hit() { return get_app()["help"].hit_count() > 0 && get_for_cli("help"); } 124 | 125 | } // namespace cmdr 126 | 127 | #endif // CMDR_CXX11_CMDR_PUBLIC_HH 128 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_x_class.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/7/16. 3 | // 4 | 5 | #ifndef CMDR_CXX11_X_CLASS_HH 6 | #define CMDR_CXX11_X_CLASS_HH 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | namespace cmdr::debug { 14 | 15 | class X { 16 | std::string _str; 17 | 18 | void _ct(const char *leading) { 19 | printf(" - %s: X[ptr=%p].str: %p, '%s'\n", leading, (void *) this, (void *) _str.c_str(), _str.c_str()); 20 | } 21 | 22 | public: 23 | X() { 24 | _ct("ctor()"); 25 | } 26 | ~X() { 27 | _ct("dtor"); 28 | } 29 | X(std::string &&s) 30 | : _str(std::move(s)) { 31 | _ct("ctor(s)"); 32 | } 33 | X(std::string const &s) 34 | : _str(s) { 35 | _ct("ctor(s(const&))"); 36 | } 37 | X &operator=(std::string &&s) { 38 | _str = std::move(s); 39 | _ct("operator=(&&s)"); 40 | return (*this); 41 | } 42 | X &operator=(std::string const &s) { 43 | _str = s; 44 | _ct("operator=(const&s)"); 45 | return (*this); 46 | } 47 | 48 | const char *c_str() const { return _str.c_str(); } 49 | operator const char *() const { return _str.c_str(); } 50 | }; 51 | 52 | } // namespace cmdr::debug 53 | 54 | #endif // CMDR_CXX11_X_CLASS_HH 55 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_x_test.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/8/6. 3 | // 4 | 5 | #ifndef CMDR_CXX11_X_TEST_HH 6 | #define CMDR_CXX11_X_TEST_HH 7 | 8 | #if defined(CMDR_CXX11_UNIT_TEST) && CMDR_CXX11_UNIT_TEST == 1 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "cmdr_chrono.hh" 16 | #include "cmdr_dbg.hh" 17 | #include "cmdr_log.hh" 18 | 19 | 20 | namespace cmdr::test { 21 | 22 | /** 23 | * @brief wrapper will wrap a test function to add pre-/post-process on it. 24 | * @tparam _Callable 25 | * @tparam _Args 26 | * @see CMDR_TEST_FOR 27 | * @note To use wrapper class, see also CMDR_TEST_FOR(func) macro. 28 | * In your test app, it'll be quoted as: 29 | * @code{c++} 30 | * void test_func_1(){ ... } 31 | * int main(){ 32 | * CMDR_TEST_FOR(test_func_1); 33 | * } 34 | * @endcode 35 | */ 36 | template 37 | class wrapper { 38 | public: 39 | explicit wrapper(const char *_fname_, _Callable &&f, _Args &&...args) { 40 | // auto filename = debug::type_name(); 41 | auto bound = std::bind(std::forward<_Callable>(f), std::forward<_Args>(args)...); 42 | chrono::high_res_duration hrd; 43 | before(_fname_); 44 | try { 45 | bound(); 46 | } catch (...) { 47 | after(_fname_); 48 | throw; 49 | } 50 | after(_fname_); 51 | } 52 | ~wrapper() = default; 53 | 54 | private: 55 | void before(const char *fname) { 56 | printf("\n--- BEGIN OF %-40s ----------------------\n", fname); 57 | } 58 | void after(const char *fname) { 59 | printf("--- END OF %-42s ----------------------\n\n", fname); 60 | } 61 | }; // class wrapper 62 | 63 | template 64 | inline auto bind(const char *funcname, _Callable &&f, _Args &&...args) { 65 | wrapper w{funcname, f, args...}; 66 | return w; 67 | } 68 | 69 | /** 70 | * @brief CMDR_TEST_FOR will wrap a test function to add pre-/post-process on it. 71 | * @details In your test app, it'll be quoted as: 72 | * @code{c++} 73 | * void test_func_1(){ ... } 74 | * int main(){ 75 | * CMDR_TEST_FOR(test_func_1); 76 | * } 77 | * @endcode 78 | */ 79 | #define CMDR_TEST_FOR(f) cmdr::test::bind(#f, f) 80 | 81 | namespace detail { 82 | inline void third_party(int n, std::function f) { 83 | f(n); 84 | } 85 | 86 | /** 87 | * @brief 88 | * 89 | * foo f; 90 | * f.invoke(1, 2); 91 | * 92 | */ 93 | struct foo { 94 | template 95 | void invoke(int n, Args &&...args) { 96 | auto bound = std::bind(&foo::invoke_impl, this, 97 | std::placeholders::_1, std::forward(args)...); 98 | 99 | third_party(n, bound); 100 | } 101 | 102 | template 103 | void invoke_impl(int, Args &&...) { 104 | } 105 | }; 106 | } // namespace detail 107 | 108 | } // namespace cmdr::test 109 | #endif 110 | 111 | #endif // CMDR_CXX11_X_TEST_HH 112 | -------------------------------------------------------------------------------- /libs/cmdr11/include/cmdr11/cmdr_z_test.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/8/6. 3 | // 4 | 5 | #ifndef CMDR_CXX11_Z_TEST_HH 6 | #define CMDR_CXX11_Z_TEST_HH 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "cmdr_chrono.hh" 14 | #include "cmdr_dbg.hh" 15 | #include "cmdr_log.hh" 16 | 17 | 18 | namespace cmdr::test { 19 | 20 | inline std::ostream &build_time(std::ostream &os) { 21 | std::tm t{}; 22 | std::istringstream tsi(__TIMESTAMP__); 23 | // tsi.imbue(std::locale("de_DE.utf-8")); 24 | tsi >> std::get_time(&t, "%a %b %d %H:%M:%S %Y"); 25 | // std::get_time(&t, "%Y-%m-%dT%H:%M:%S"); 26 | // std::ostringstream ts; 27 | // ts << std::put_time(&t, "%Y-%m-%dT%H:%M:%S"); 28 | return os << std::put_time(&t, "%FT%T%z"); 29 | } 30 | inline std::string build_time() { 31 | std::ostringstream ts; 32 | build_time(ts); 33 | return ts.str(); 34 | } 35 | 36 | inline void test_for_macros() { 37 | #if defined(CMDR_ENABLE_ASSERTIONS) 38 | std::cout << "CMDR_ENABLE_ASSERTIONS : " << CMDR_ENABLE_ASSERTIONS << '\n'; 39 | #endif 40 | #if defined(CMDR_ENABLE_PRECONDITION_CHECKS) 41 | std::cout << "CMDR_ENABLE_PRECONDITION_CHECKS : " << CMDR_ENABLE_PRECONDITION_CHECKS << '\n'; 42 | #endif 43 | #if defined(CMDR_ENABLE_THREAD_POOL_READY_SIGNAL) 44 | std::cout << "CMDR_ENABLE_THREAD_POOL_READY_SIGNAL : " << CMDR_ENABLE_THREAD_POOL_READY_SIGNAL << '\n'; 45 | #endif 46 | #if defined(CMDR_TEST_THREAD_POOL_DBGOUT) 47 | std::cout << "CMDR_TEST_THREAD_POOL_DBGOUT : " << CMDR_TEST_THREAD_POOL_DBGOUT << '\n'; 48 | #endif 49 | #if defined(CMDR_UNIT_TEST) 50 | std::cout << "CMDR_UNIT_TEST : " << CMDR_UNIT_TEST << '\n'; 51 | #endif 52 | #if defined(CMDR_ENABLE_VERBOSE_LOG) 53 | std::cout << "CMDR_ENABLE_VERBOSE_LOG : " << CMDR_ENABLE_VERBOSE_LOG << '\n'; 54 | #endif 55 | 56 | std::cout << '\n' 57 | << CMDR_PROJECT_NAME << " v" << CMDR_VERSION_STRING << '\n' 58 | << CMDR_ARCHIVE_NAME << ": " << CMDR_DESCRIPTION << '\n' 59 | << " version: " << CMDR_VERSION_STR << '\n' 60 | << " branch: " << CMDR_GIT_BRANCH << '\n' 61 | << " tag: " << CMDR_GIT_TAG << " (" << CMDR_GIT_TAG_LONG << ")" << '\n' 62 | << " hash: " << CMDR_GIT_REV << " (" << CMDR_GIT_COMMIT_HASH << ")" << '\n' 63 | << " cpu: " << CMDR_CPU << '\n' 64 | << " arch: " << CMDR_CPU_ARCH << '\n' 65 | << " arch-name: " << CMDR_CPU_ARCH_NAME << '\n' 66 | << " build-name: " << CMDR_BUILD_NAME << '\n' 67 | << " build-time: " << build_time() << '\n' 68 | << " timestamp: " << chrono::format_time_point() << '\n' 69 | << '\n' 70 | << " compiled by: " << cmdr::cross::compiler_name() << '\n' 71 | << " __cplusplus: 0x" << std::hex << std::setfill('0') << std::setw(8) << __cplusplus << ' ' << '(' << std::dec << __cplusplus << ')' << '\n' 72 | << '\n'; 73 | 74 | cmdr_debug("debug mode log enabled."); 75 | cmdr_trace("verbose log (trace mode) enabled."); 76 | } 77 | 78 | } // namespace cmdr::test 79 | 80 | #endif // CMDR_CXX11_Z_TEST_HH 81 | -------------------------------------------------------------------------------- /libs/cmdr11/src/main.cc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include 6 | 7 | void fatal_exit(const std::string &msg) { 8 | std::cerr << msg << '\n'; 9 | exit(-1); 10 | } 11 | 12 | int main(int argc, char *argv[]) { 13 | auto &cli = cmdr::cli("app2", CMDR_VERSION_STRING, "hedzr", 14 | "Copyright © 2021 by hedzr, All Rights Reserved.", 15 | "A demo app for cmdr-cxx library.", 16 | "$ ~ --help"); 17 | 18 | try { 19 | using namespace cmdr::opt; 20 | 21 | // cli.opt(opt_dummy{}()); 22 | 23 | cli += sub_cmd{}("server", "s", "svr") 24 | .description("server operations for listening"); 25 | 26 | cli += opt{1}("count", "c") 27 | .description("set counter value"); 28 | 29 | cli += opt{""}("host", "H", "hostname", "server-name") 30 | .description("hostname or ip address"); 31 | 32 | cmdr::set("wudao.count", 1); 33 | cmdr::set("wudao.string", "str"); 34 | cmdr::set("wudao.float", 3.14f); 35 | cmdr::set("wudao.double", 2.718); 36 | cmdr::set("wudao.array", std::vector{"a", "b", "c"}); 37 | cmdr::set("wudao.bool", false); 38 | 39 | #if defined(FORCE_ASSERTIONS) 40 | std::cout << cmdr::get("wudao.count") << '\n'; 41 | auto const &aa = cmdr::get>("wudao.array"); 42 | std::cout << cmdr::string::join(aa, ", ", "[", "]") << '\n'; 43 | cmdr::vars::variable &ab = cmdr::get_app().get("wudao.array"); 44 | std::cout << ab << '\n'; 45 | #endif 46 | 47 | } catch (std::exception &e) { 48 | std::cerr << "Exception caught : " << e.what() << '\n'; 49 | } 50 | 51 | return cli.run(argc, argv); 52 | } 53 | -------------------------------------------------------------------------------- /libs/cmdr11/src/private.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/8. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | static void test1() { 13 | cmdr::Nullable ii; 14 | CMDR_ASSERT(ii.is_null()); 15 | ii.val(9); 16 | 17 | cmdr::Nullable ss; 18 | ss.val("a string"); 19 | 20 | std::optional ov; 21 | std::cout << (int) ii << ',' << (std::string) ss << "||| " << ov << '\n'; 22 | } 23 | 24 | static void ingest_any(const std::any &any) { 25 | try { 26 | std::cout << std::any_cast(any) << '\n'; 27 | } catch (std::bad_any_cast const &) {} 28 | 29 | if (std::string *str = std::any_cast(&any)) { 30 | std::cout << *str << '\n'; 31 | } 32 | 33 | if (std::type_index{typeid(std::string)} == any.type()) { 34 | // Known not to throw, as previously checked. 35 | std::cout << std::any_cast(any) << '\n'; 36 | } 37 | } 38 | 39 | static void visit_any(const std::any &any) { 40 | // std::visit([](auto&& arg) {arg *= 2; }, v); 41 | std::visit([](auto &&arg) { std::cout << arg; }, any); 42 | } 43 | -------------------------------------------------------------------------------- /libs/cmdr11/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake_minimum_required(VERSION 3.5) 2 | 3 | project(cmdr11_tests) 4 | 5 | find_package(Threads) 6 | 7 | add_executable(${PROJECT_NAME} 8 | main.cxx 9 | test_store.cc 10 | ) 11 | add_cxx_standard_to(${PROJECT_NAME} ${CXX_STANDARD}) 12 | target_include_directories(${PROJECT_NAME} PRIVATE 13 | $ 14 | $ 15 | ) 16 | target_link_libraries(${PROJECT_NAME} 17 | PRIVATE 18 | Threads::Threads 19 | libs::cmdr11) 20 | 21 | #target_link_libraries(${PROJECT_NAME} 22 | # PRIVATE 23 | # libs::sm-lib 24 | # ) 25 | -------------------------------------------------------------------------------- /libs/cmdr11/tests/main.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2020/11/19. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "cmdr11/cmdr_if.hh" 14 | #include "cmdr11/cmdr_var_t.hh" 15 | 16 | #if JUST_FOR_REFERRING 17 | int main(int, char **) { 18 | std::cout << "Running tests...\n"; 19 | 20 | std::string input = "tests and strings"; 21 | std::string cstr = compress_string(input); 22 | if (cstr != "bad one") { 23 | return 1; 24 | } 25 | 26 | std::string dstr = decompress_string(cstr); 27 | 28 | return dstr == cstr ? 0 : 1; 29 | } 30 | #endif 31 | 32 | void test_types_check_1() { 33 | std::cout << std::boolalpha; 34 | 35 | std::cout << "cmdr::traits::is_vector_t: \n"; 36 | std::cout << std::boolalpha << cmdr::traits::is_vector_v> << std::endl; 37 | std::cout << std::boolalpha << cmdr::traits::is_vector_v << std::endl; 38 | 39 | std::cout << "cmdr::traits::is_container: \n"; 40 | std::cout << std::boolalpha << cmdr::traits::is_container::value << std::endl; 41 | std::cout << std::boolalpha << cmdr::traits::is_container>::value << std::endl; 42 | 43 | using namespace std::chrono_literals; 44 | 45 | auto v1 = std::vector{"example.com", "example.org"}; 46 | std::cout << "cmdr::traits::is_stl_container : " << cmdr::traits::is_stl_container::value << std::endl; 47 | auto v2 = 10s; 48 | std::cout << "type " << typeid(v2).name() << ". check: " << cmdr::traits::is_duration::value << std::endl; 49 | 50 | std::cout << "cmdr::traits::is_duration : " << cmdr::traits::is_duration::value << std::endl; 51 | std::cout << "cmdr::traits::is_duration : " << cmdr::traits::is_duration::value << std::endl; 52 | std::cout << "cmdr::traits::is_duration : " << cmdr::traits::is_duration::value << std::endl; 53 | std::cout << "cmdr::traits::is_duration : " << cmdr::traits::is_duration::value << std::endl; 54 | std::cout << "cmdr::traits::is_duration : " << cmdr::traits::is_duration::value << std::endl; 55 | std::cout << "cmdr::traits::is_duration : " << cmdr::traits::is_duration::value << std::endl; 56 | } 57 | 58 | void test_var_t_1() { 59 | // cmdr::vars::var_t vs; 60 | // std::cout << "var_t: " << vs << std::endl; 61 | } 62 | 63 | int main(int, char **) { 64 | std::cout << "Running tests..." << std::endl; 65 | 66 | // std::string input = "tests and strings"; 67 | // std::string cstr = compress_string(input); 68 | // 69 | // // if (cstr != "bad one") { 70 | // // std::cerr << "PRB\n"; 71 | // // return 1; 72 | // // } 73 | // 74 | // std::string dstr = decompress_string(cstr); 75 | 76 | auto *v = new std::vector(); 77 | v->push_back(1); 78 | v->push_back(2); 79 | v->push_back(3); 80 | v->push_back(4); 81 | 82 | // int ret = dstr == input ? 0 : 1; 83 | int ret = v->size() == 4 ? 0 : 1; 84 | std::cout << "return " << ret << ", " << v->size() << std::endl; 85 | 86 | 87 | test_types_check_1(); 88 | 89 | test_var_t_1(); 90 | 91 | extern void test_store_1(); 92 | test_store_1(); 93 | 94 | return ret; 95 | } -------------------------------------------------------------------------------- /libs/cmdr11/tests/test_store.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // #include "cmdr11/cmdr_defs.hh" 14 | #include "cmdr11/cmdr_var_t.hh" 15 | 16 | 17 | void fatal_exit(const std::string &msg) { 18 | std::cerr << msg << '\n'; 19 | exit(-1); 20 | } 21 | 22 | void test_store_1() { 23 | using namespace std::chrono_literals; 24 | 25 | std::cout << "\nstore testing... \n\n"; 26 | 27 | cmdr::vars::store store; 28 | 29 | store.set_raw("app.server.tls.enabled", true); 30 | store.set_raw("app.server.tls.ca.cert", "ca.cer"); 31 | store.set_raw("app.server.tls.server.cert", "server.cer"); 32 | store.set_raw("app.server.tls.server.key", "server.key"); 33 | store.set_raw("app.server.tls.client-auth", true); 34 | store.set_raw("app.server.tls.handshake.timeout", 10s); 35 | store.set_raw("app.server.tls.handshake.max-idle-time", 45min); 36 | store.set_raw("app.server.tls.domains", std::vector{"example.com", "example.org"}); 37 | store.set_raw("app.server.tls.fixed-list", std::array{"item1", "item2"}); 38 | 39 | store.set_raw("app.server.test.test-1-time", 0.75min); 40 | store.set_raw("app.server.test.test-2-time", 501ns); 41 | store.set_raw("app.server.test.test-3-time", 730us); 42 | store.set_raw("app.server.test.test-4-time", 233ms); 43 | store.set_raw("app.server.test.test-5-time", 7s); 44 | store.set_raw("app.server.test.test-6-time", 7.2s); 45 | store.set_raw("app.server.test.test-7-time", 1024h); 46 | 47 | store.set_raw("app.server.ii-1", 123u); 48 | store.set_raw("app.server.ii-2", 7.0); 49 | store.set_raw("app.server.ii-3", 3.14159f); 50 | store.set_raw("app.server.ii-4", 2.71828); 51 | store.set_raw("app.server.ii-5", "a string"); 52 | store.set_raw("app.server.vv-1", std::vector{"a string", "b", "c"}); 53 | 54 | #if defined(_DEBUG) 55 | store.dump_full_keys(std::cout); 56 | store.dump_tree(std::cout); 57 | #endif 58 | 59 | auto vv = store.get_raw("app.server.tls.handshake.max-idle-time"); 60 | std::cout << "max-idle-time: " << vv << '\n'; 61 | if (vv.as_string() != "45m") 62 | fatal_exit(" ^-- ERR: expect '45m'."); 63 | } 64 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | third-party/ 2 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(test 2 | VERSION ${VERSION} 3 | DESCRIPTION "tests - test apps for cmdr cxx11 library" 4 | LANGUAGES C CXX) 5 | 6 | # ################################### 7 | # dump_list(INCLUDE_DIRECTORIES) 8 | # debug_print_list_value(INCLUDE_DIRECTORIES) 9 | debug_print_hbar() 10 | debug(" tests ") 11 | message("!! entering subdir: ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}") 12 | 13 | # debug_dump_cmake_environments() 14 | # debug_print_hbar() 15 | # debug_dump_cmake_variables() 16 | # debug_print_hbar_long() 17 | set(PROJECT_ARCHIVE_NAME ${PROJECT_NAME}s-${PROJECT_VERSION}) 18 | 19 | if (ENABLE_TESTS) 20 | # include(deps_inc_catch2) 21 | # include(deps_inc_fmt) 22 | endif () 23 | 24 | # # so_stuff: just a tester for ARGN 25 | # function(do_stuff arg1 arg2) 26 | # foreach (f ${ARGN}) 27 | # # do something interesting with file 'f' 28 | # message("f='${f}' arg1='${arg1}' arg2='${arg2}'") 29 | # endforeach () 30 | # message("f='${f}' arg1='${arg1}' arg2='${arg2}' ARGV2='${ARGV2}'") 31 | # endfunction() 32 | # do_stuff(A B C D E) 33 | find_package(Threads) 34 | 35 | function(define_test_program name) 36 | # set(src_list ) 37 | foreach (f ${ARGN}) 38 | list(APPEND src_list ${f}) 39 | endforeach () 40 | 41 | add_executable(${PROJECT_NAME}-${name} ${src_list}) 42 | add_cxx_standard_to(${PROJECT_NAME}-${name} ${CXX_STANDARD}) 43 | 44 | # target_compile_features(${PROJECT_NAME}-${name} PRIVATE cxx_std_11) 45 | target_compile_definitions(${PROJECT_NAME}-${name} INTERFACE 46 | CMDR_ENABLE_ASSERTIONS=${_cmdr_enable_assertions} 47 | CMDR_ENABLE_PRECONDITION_CHECKS=${_cmdr_enable_precondition_checks} 48 | CMDR_ENABLE_WRAPPER=${_cmdr_enable_wrapper} 49 | CMDR_TEST_THREAD_POOL_DBGOUT=${_cmdr_test_thread_pool_dbgout} 50 | CMDR_UNIT_TEST=${_cmdr_enable_unit_test} 51 | CMDR_ENABLE_VERBOSE_LOG=1 52 | ) 53 | target_include_directories(${PROJECT_NAME}-${name} PRIVATE 54 | $ 55 | $ 56 | ${CMAKE_SOURCE_DIR} 57 | ) 58 | target_link_libraries(${PROJECT_NAME}-${name} 59 | PRIVATE 60 | libs::cmdr11 61 | Threads::Threads 62 | 63 | # Catch2::Catch2 64 | # fmt::fmt-header-only 65 | ) 66 | 67 | # set_target_properties(${PROJECT_NAME}-${name} PROPERTIES 68 | # CXX_STANDARD 17 69 | # CXX_STANDARD_REQUIRED ON 70 | # CXX_EXTENSIONS OFF 71 | # ) 72 | if (MSVC) 73 | target_compile_options(${PROJECT_NAME}-${name} PRIVATE /W4 /WX /utf-8 /DCMDR_CXX11_UNIT_TEST=1) 74 | else () 75 | target_compile_options(${PROJECT_NAME}-${name} PRIVATE 76 | -pedantic -Wall -Wextra -Wshadow -Werror -DCMDR_CXX11_UNIT_TEST=1 77 | ) 78 | 79 | if (DEBUG) 80 | target_compile_options(${PROJECT_NAME}-${name} PRIVATE 81 | -fsanitize=address 82 | 83 | # address(AddressSanitizer), leak(LeakSanitizer), thread(ThreadSanitizer), undefined(UndefinedBehaviorSanitizer), memory(MemorySanitizer) 84 | # [additional_options]: -fno-omit-frame-pointer, fsanitize-recover/fno-sanitize-recover, -fsanitize-blacklist, etc. 85 | # [-g] [-OX] 86 | ) 87 | target_link_options(${PROJECT_NAME}-${name} PRIVATE -fsanitize=address) 88 | endif () 89 | endif () 90 | 91 | if (${ENABLE_AUTOMATE_TESTS}) 92 | get_property(tmp GLOBAL PROPERTY UNIT_TEST_TARGETS) 93 | set(tmp ${UNIT_TEST_TARGETS} ${PROJECT_NAME}-${name}) 94 | set_property(GLOBAL PROPERTY UNIT_TEST_TARGETS "${tmp}") 95 | message(">> add_test(${PROJECT_NAME}-${name}) ...") 96 | endif () 97 | 98 | if (ANDROID) 99 | add_test(NAME ${PROJECT_NAME}-${name} 100 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 101 | COMMAND ${CMAKE_COMMAND} "-DANDROID_NDK=${ANDROID_NDK}" 102 | "-DTEST_RESOURCES_DIR=${CMAKE_SOURCE_DIR}" 103 | "-DTEST_RESOURCES=tests/data;tests/file_data.txt;Makefile" 104 | "-DUNITTEST=${PROJECT_NAME}-${name}" 105 | -P ${CMAKE_CURRENT_SOURCE_DIR}/ExecuteOnAndroid.cmake) 106 | else () 107 | add_test(NAME ${PROJECT_NAME}-${name} 108 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 109 | COMMAND $) 110 | endif () 111 | endfunction() 112 | 113 | define_test_program(basic basic.cc) 114 | define_test_program(compiler compiler.cc) 115 | 116 | define_test_program(sso-1 sso_test_1.cc) 117 | define_test_program(sso-2 sso_test_2.cc) 118 | define_test_program(any-1 any_1.cc) 119 | define_test_program(traits traits.cc) 120 | define_test_program(observer observer.cc) 121 | define_test_program(factory factory.cc) 122 | 123 | define_test_program(visit-any 124 | visit_any.cc 125 | second_src.cc) 126 | define_test_program(chrono chrono_test.cc) 127 | define_test_program(chrono-literals chrono_literals_test.cc) 128 | define_test_program(inplace-constructions inplace_constructions.cc) 129 | define_test_program(valarray-test valarray_test.cc) 130 | define_test_program(complex-test complex_test.cc) 131 | define_test_program(mem-singleton-1 mem_test_for_singleton.cc) 132 | 133 | define_test_program(priority-queue priority_queue.cc) 134 | 135 | # skip Catch2-deps tests 136 | # define_test_program(store-c2 store_c2.cc) 137 | # define_test_program(flags-c2 flags_c2.cc second_src.cc) 138 | # define_test_program(jaro-c2 jaro_c2.cc) 139 | if (${ENABLE_LONG_TESTS}) 140 | define_test_program(pool pool.cc) 141 | endif () 142 | 143 | define_test_program(process process.cc) 144 | 145 | if (CMDR_NO_3RDPARTY) 146 | else () 147 | # app2 c1 148 | define_test_program(app2-c1 app1.cc second_src.cc) 149 | # 150 | # For test-app-c1, loading the dependency to yaml-cpp 151 | # 152 | include(loaders/yaml_loader) 153 | add_yaml_loader_to(test-app2-c1) 154 | target_compile_definitions(test-app2-c1 PRIVATE 155 | CMDR_ENABLE_VERBOSE_LOG=1) 156 | endif () 157 | 158 | # app2 c2 159 | define_test_program(app2-c2 app2.cc second_src.cc) 160 | 161 | # 162 | # if (MSVC) 163 | # # target_compile_options(test-sso-1 PRIVATE /W4 /WX /utf-8) 164 | # target_compile_options(test-flags-c2 PRIVATE /bigobj) 165 | # else () 166 | # # target_compile_options(test-sso-1 PRIVATE -Werror=sized-deallocation) 167 | # endif () 168 | 169 | target_compile_definitions(test-app2-c2 PRIVATE 170 | CMDR_ENABLE_VERBOSE_LOG=1) 171 | 172 | # if (BUILD_TESTING) 173 | # add_unit_test(${PROJECT_NAME} tests ${PROJECT_NAME}_tests) 174 | # endif () 175 | debug_print_value(ARCHIVE_NAME) 176 | debug_print_value(PROJECT_ARCHIVE_NAME) 177 | debug_print_value(BUILD_TESTING) 178 | debug_print_value(CMAKE_SOURCE_DIR) 179 | message(STATUS "end of tests") -------------------------------------------------------------------------------- /tests/app1.cc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include "./addons/loaders/yaml_loader.hh" 6 | #include "cmdr-cxx.hh" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "second_src.hh" 19 | 20 | 21 | int main(int argc, char *argv[]) { 22 | auto &cli = cmdr::cli("app1", CMDR_VERSION_STRING, "hedzr", 23 | "Copyright © 2021 by hedzr, All Rights Reserved.", 24 | "A demo app for cmdr-c11 library.", 25 | "$ ~ --help"); 26 | 27 | try { 28 | using namespace cmdr::opt; 29 | 30 | // cli.opt(opt_dummy{}()); 31 | 32 | add_server_menu(cli); 33 | add_test_menu(cli); 34 | 35 | #if defined(_DEBUG) 36 | auto &cc = cli("server"); 37 | assert(cc.valid()); 38 | assert(cc["count"].valid()); 39 | assert(cc["host"].valid()); 40 | assert(cc("status").valid()); 41 | assert(cc("start").valid()); 42 | assert(cc("run", true).valid()); 43 | std::cout << cc.group_name() << '\n'; 44 | #endif 45 | 46 | #if CMDR_TEST_ON_COMMAND_NOT_HOOKED 47 | cli.set_global_on_command_not_hooked([](cmdr::opt::cmd const &, string_array const &) { 48 | cmdr::get_store().dump_full_keys(std::cout); 49 | cmdr::get_store().dump_tree(std::cout); 50 | return 0; 51 | }); 52 | #endif 53 | 54 | #if 1 55 | { 56 | using namespace cmdr::addons::loaders; 57 | cli.set_global_on_loading_externals(yaml_loader{}()); 58 | } 59 | #endif 60 | 61 | #if 1 62 | cli += sub_cmd{}("dup-test", "dup") 63 | .description("dup command/flag for testing") 64 | .group("Test"); 65 | { 66 | auto &t1 = *cli.last_added_command(); 67 | 68 | t1 += opt{""}("string", "str") 69 | .description("set the string-value"); 70 | t1 += opt{10}("int", "i") 71 | .description("set the int-value"); 72 | t1 += opt{10}("int", "i") 73 | .description("set the int-value"); 74 | } 75 | #endif 76 | 77 | } catch (std::exception &e) { 78 | std::cerr << "Exception caught for testing (NOT BUG) : " << e.what() << '\n'; 79 | CMDR_DUMP_STACK_TRACE(e); 80 | } 81 | 82 | #if !defined(OS_WIN) 83 | cmdr::debug::UnhandledExceptionHookInstaller _ueh{}; 84 | #endif 85 | return cli.run(argc, argv); 86 | } 87 | -------------------------------------------------------------------------------- /tests/app2.cc: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | // #include "./addons/loaders/yaml_loader.hh" 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "second_src.hh" 19 | 20 | int main(int argc, char *argv[]) { 21 | auto &cli = cmdr::cli("app2", CMDR_VERSION_STRING, "hedzr", 22 | "Copyright © 2021 by hedzr, All Rights Reserved.", 23 | "A demo app for cmdr-c11 library.", 24 | "$ ~ --help") 25 | // remove "Powered by cmdr-cxx" line 26 | .set_no_cmdr_endings() 27 | // customize the last line except cmdr endings 28 | .set_tail_line("") 29 | .set_no_tail_line(false); 30 | 31 | try { 32 | using namespace cmdr::opt; 33 | 34 | // cli.opt(opt_dummy{}()); 35 | 36 | add_server_menu(cli); 37 | add_test_menu(cli); 38 | add_main_menu(cli); 39 | 40 | // cli.set_minimal_tab_stop(55); 41 | using cmdr::terminal::colors::colorize; 42 | cli.set_alternate_text_color(colorize::Colors256::Green); 43 | 44 | #if defined(_DEBUG) 45 | auto &cc = cli("server"); 46 | CMDR_ASSERT(cc.valid()); 47 | CMDR_ASSERT(cc["count"].valid()); 48 | CMDR_ASSERT(cc["host"].valid()); 49 | CMDR_ASSERT(cc("status").valid()); 50 | CMDR_ASSERT(cc("start").valid()); 51 | CMDR_ASSERT(cc("run", true).valid()); 52 | #endif 53 | 54 | #if CMDR_TEST_ON_COMMAND_NOT_HOOKED 55 | cli.set_global_on_command_not_hooked([](cmdr::opt::cmd const &, string_array const &) { 56 | cmdr::get_store().dump_full_keys(std::cout); 57 | cmdr::get_store().dump_tree(std::cout); 58 | return 0; 59 | }); 60 | #endif 61 | 62 | #if 0 63 | { 64 | using namespace cmdr::addons::loaders; 65 | cli.set_global_on_loading_externals(yaml_loader{}()); 66 | } 67 | #endif 68 | 69 | #if 0 70 | cli += sub_cmd{}("dup", "dup") 71 | .description("dup command/flag for testing") 72 | .group("Test"); 73 | { 74 | auto &t1 = *cli.last_added_command(); 75 | 76 | t1 += opt{10}("int", "i") 77 | .description("set the int-value"); 78 | t1 += opt{10}("int", "i") 79 | .description("set the int-value"); 80 | t1 += opt{""}("string", "str") 81 | .description("set the string-value"); 82 | } 83 | #endif 84 | 85 | } catch (std::exception &e) { 86 | std::cerr << "Exception caught for testing (NOT BUG) : " << e.what() << '\n'; 87 | CMDR_DUMP_STACK_TRACE(e); 88 | } 89 | 90 | // cmdr::debug::UnhandledExceptionHookInstaller _ueh{}; 91 | // cmdr::debug::SigSegVInstaller _ssi{}; 92 | return cli.run(argc, argv); 93 | } 94 | -------------------------------------------------------------------------------- /tests/basic.cc: -------------------------------------------------------------------------------- 1 | // cmdr-cxx Library 2 | // Copyright © 2021 Hedzr Yeh. 3 | // 4 | // This file is released under the terms of the MIT license. 5 | // Read /LICENSE for more information. 6 | 7 | // 8 | // Created by Hedzr Yeh on 2021/10/25. 9 | // 10 | 11 | #include "cmdr-cxx.hh" 12 | #include 13 | #include 14 | 15 | int main() { 16 | cmdr::test::test_for_macros(); 17 | } -------------------------------------------------------------------------------- /tests/chrono_literals_test.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "cmdr11/cmdr_chrono.hh" 11 | 12 | 13 | void test_literals() { 14 | using namespace std::chrono_literals; 15 | 16 | auto lesson = 45min; 17 | auto half_min = 0.5min; 18 | std::cout << "one lesson is " << lesson.count() << " minutes\n" 19 | << "half a minute is " << half_min.count() << " minutes\n"; 20 | 21 | auto d1 = 250ms; 22 | std::chrono::milliseconds d2 = 1s; 23 | std::cout << "250ms = " << d1.count() << " milliseconds\n" 24 | << "1s = " << d2.count() << " milliseconds\n"; 25 | 26 | auto aa = std::vector>>{ 27 | 3ns, 28 | 800ms, 29 | 59.739us, 30 | 0.75min, 31 | 501ns, 32 | 730us, 33 | 233ms, 34 | 7s, 35 | 7.2s, 36 | 1024h, 37 | 89.843204843s, 38 | }; 39 | 40 | static_assert(cmdr::chrono::is_duration::value); 41 | std::cout << 7.5min; 42 | 43 | for (auto const &vxa: aa) { 44 | std::cout << vxa << '\n'; 45 | } 46 | 47 | std::cout << 918734032564785ns << "\n"; 48 | std::cout << "3. " << std::setprecision(3) << 918734032564785ns << "\n"; 49 | std::cout << std::setprecision(9) << 918734032564785ns << "\n"; 50 | std::cout << std::setprecision(0) << 918734032564785ns << "\n"; 51 | std::cout << std::setprecision(3) << 432034ms << "\n"; 52 | std::cout << 14h + 32min + 37s + 645ms << "\n"; 53 | std::cout << 86472s << "\n"; 54 | std::cout << 4324ms << "\n"; 55 | 56 | // using namespace std::literals; 57 | // std::cout 58 | // << int(2020y) << ' ' 59 | // << int(-220y) << ' ' 60 | // << int(3000y) << ' ' 61 | // << int(32768y) << ' ' // 未指定 62 | // << int(65578y) << '\n'; // 未指定 63 | } 64 | 65 | #if FMT_ENABLED 66 | #include 67 | 68 | void test_fmt() { 69 | using namespace std::literals::chrono_literals; 70 | fmt::print("Default format: {} {}\n", 42s, 100ms); 71 | fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s); 72 | } 73 | 74 | #else 75 | 76 | void test_fmt() {} 77 | 78 | #endif 79 | 80 | int main() { 81 | test_literals(); 82 | test_fmt(); 83 | } -------------------------------------------------------------------------------- /tests/compiler.cc: -------------------------------------------------------------------------------- 1 | 2 | // #include "cmdr11/cmdr-all.hh" 3 | 4 | #include "cmdr11/cmdr_chrono.hh" // 5 | #include "cmdr11/cmdr_common.hh" // 6 | #include "cmdr11/cmdr_string.hh" // to_string<>() 7 | 8 | #include 9 | #include 10 | 11 | //inline std::ostream &operator<<(std::ostream &os, std::chrono::system_clock::time_point const &time) { 12 | // // std::size_t ns = cmdr::chrono::time_point_get_ns(time); 13 | // return cmdr::chrono::serialize_time_point(os, time, "%F %T"); 14 | // //return os << time; 15 | //} 16 | // 17 | //template 18 | //inline std::ostream &operator<<(std::ostream &os, std::chrono::time_point<_Clock, _Duration> const &time) { 19 | // // std::size_t ns = cmdr::chrono::time_point_get_ns(time); 20 | // // return cmdr::chrono::serialize_time_point(os, time, "%F %T"); 21 | // return os << time; 22 | //} 23 | 24 | int main() { 25 | std::cout << "Hello, World!" << '\n' 26 | << "I was built by " << cmdr::cross::compiler_name() << '\n' 27 | << "__cplusplus = 0x" << std::hex << std::setfill('0') << std::setw(8) << __cplusplus << ' ' << '(' << std::dec << __cplusplus << ')' << '\n'; 28 | 29 | { 30 | //std::chrono::steady_clock::time_point tp; 31 | std::chrono::system_clock::time_point now2 = std::chrono::system_clock::now(); 32 | using iom = cmdr::chrono::iom; 33 | using fmtflags = iom::fmtflags; 34 | std::cout << fmtflags::gmt << fmtflags::ns << "time_point (ns): os << " << now2 << '\n'; 35 | std::cout << fmtflags::gmt << fmtflags::us << "time_point (us): os << " << now2 << '\n'; 36 | std::cout << fmtflags::gmt << fmtflags::ms << "time_point (ms): os << " << now2 << '\n'; 37 | std::cout << "time point of now: "; 38 | std::cout << now2; 39 | //operator<<(std::cout, now2); 40 | std::cout << '\n'; 41 | 42 | auto duration = now2.time_since_epoch(); 43 | std::cout << "duration: os << " << duration << '\n'; 44 | std::cout << "duration: os << " << cmdr::chrono::format_duration(duration) << '\n'; 45 | } 46 | } -------------------------------------------------------------------------------- /tests/complex_test.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/29. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | using namespace std::complex_literals; 12 | std::cout << std::fixed << std::setprecision(1); 13 | 14 | std::complex z1 = 1i * 1i; // 虚数单位平方 15 | std::cout << "i * i = " << z1 << '\n'; 16 | 17 | std::complex z2 = std::pow(1i, 2); // 虚数单位平方 18 | std::cout << "pow(i, 2) = " << z2 << '\n'; 19 | 20 | double PI = std::acos(-1); 21 | std::complex z3 = std::exp(1i * PI); // 欧拉方程 22 | std::cout << "exp(i * pi) = " << z3 << '\n'; 23 | 24 | std::complex z4 = 1. + 2i, z5 = 1. - 2i; // 共轭 25 | std::cout << "(1+2i)*(1-2i) = " << z4 * z5 << '\n'; 26 | } -------------------------------------------------------------------------------- /tests/etc/app1/app1.yml: -------------------------------------------------------------------------------- 1 | app: 2 | debug: true 3 | file: 4 | test-string: hello 5 | test-map: 6 | val-1: true 7 | val-2: 8s 8 | val-3: [ a,b,c ] 9 | val-4: 10 | small-little: just a demo 11 | val-5: [ 1.9,3.1,2.7 ] 12 | val-6: 45.7min 13 | val-7: 9.8 14 | this: 15 | is: 16 | a: 17 | string: yes 18 | string-2: "yes" 19 | string-3: "no" 20 | string-4: "T" 21 | string-5: "F" 22 | string-6: "on" 23 | string-7: "off" 24 | string-8: "y" 25 | string-9: "n" 26 | -------------------------------------------------------------------------------- /tests/etc/ex-app1.yml: -------------------------------------------------------------------------------- 1 | app: 2 | fixed-position: true 3 | 4 | -------------------------------------------------------------------------------- /tests/inplace_constructions.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "cmdr11/cmdr_var_t.hh" 14 | 15 | void test_inplace_and_emplace() { 16 | // emplace in map 17 | std::map id_name_map; 18 | id_name_map.insert({10, std::string("name 1")}); 19 | id_name_map.emplace(11, std::string("name 2")); 20 | id_name_map.emplace(std::piecewise_construct, std::forward_as_tuple(12), std::forward_as_tuple("name 3")); 21 | for (const auto &it: id_name_map) { 22 | std::cout << it.first << ':' << it.second << '\n'; 23 | } 24 | 25 | // emplace in optional 26 | std::optional o2(std::in_place, "a string"); 27 | std::cout << o2.value() << '\n'; 28 | o2.emplace(5, ' '); 29 | std::cout << o2.value() << '\n'; 30 | o2.emplace({'s', 'a', 'b'}); 31 | std::cout << o2.value() << '\n'; 32 | 33 | #if defined(VERBOSE_DEBUG) 34 | std::optional oo(std::in_place, "a string"); 35 | std::cout << oo.value() << '\n'; 36 | #endif 37 | 38 | // inplace construction in optional 39 | std::optional o3(std::in_place, 8, 'c'); 40 | std::cout << o3.value() << '\n'; 41 | } 42 | 43 | void test_variant() { 44 | std::variant z = 0L; 45 | z = 0.0; 46 | } 47 | 48 | void test_any() { 49 | std::any z = 0; 50 | z = 0.0; 51 | z = "str"; 52 | } 53 | 54 | void test_streamable_any() { 55 | #if NOT_YET 56 | cmdr::opt::vars::var_t v("yes"); 57 | std::cout << v << '\n'; 58 | 59 | v = 123; 60 | std::cout << v << '\n'; 61 | #endif 62 | } 63 | 64 | int main() { 65 | test_variant(); 66 | test_any(); 67 | test_inplace_and_emplace(); 68 | test_streamable_any(); 69 | } -------------------------------------------------------------------------------- /tests/jaro_c2.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/2/10. 3 | // 4 | 5 | 6 | #define CATCH_CONFIG_MAIN 7 | 8 | #include 9 | 10 | 11 | #include "cmdr11/cmdr_string.hh" 12 | 13 | 14 | TEST_CASE("jaro-winkler test", "[text][edit][distance]") { 15 | 16 | using namespace cmdr::text; 17 | 18 | jaro_winkler_distance jaro{}; 19 | 20 | struct test_case { 21 | const char *s1; 22 | const char *s2; 23 | Approx d; 24 | }; 25 | using namespace Catch::literals; 26 | static test_case cases[] = { 27 | // {"TRATE", "TRACE", 0.906667_a}, 28 | {"TRATE", "TRACE", 0.8666666667_a}, 29 | {"CRATE", "TRACE", 0.73333333333333339_a}, 30 | {"DwAyNE", "DuANE", 0.8222222222222223_a}, 31 | {"developer", "developers", 0.96666666666666667_a}, 32 | {"developer", "seveloper", 0.92592592592592593_a}, 33 | {"mame", "name", 0.8333333333_a}, 34 | {"mv", "mx", 0.6666666666666666_a}, 35 | {"mv", "mx-test", 0.5476190476190476_a}, 36 | {"mv", "micro-service", 0.5256410256_a}, 37 | {"update-cc", "update-cv", 0.9259259259_a}, 38 | {"AL", "AL", 1_a}, 39 | {"MARTHA", "MARHTA", 0.9444444444_a}, 40 | {"JONES", "JOHNSON", 0.7904761905_a}, 41 | {"POTATO", "POTATTO", 0.9523809524_a}, 42 | {"kitten", "sitting", 0.7460317460317460_a}, 43 | {"MOUSE", "HOUSE", 0.8666666666666667_a}, 44 | }; 45 | 46 | for (const auto &case1: cases // { 47 | // std::make_tuple(1, 2), 48 | // std::make_tuple(2, 4), 49 | // std::make_tuple(3, 6), 50 | // std::make_tuple(4, 8), 51 | // } 52 | ) { 53 | SECTION("comparing: " + std::string(case1.s1) + std::string(" - ") + std::string(case1.s2)) { 54 | auto d = jaro(case1.s1, case1.s2); 55 | if (d != case1.d) 56 | std::cout << "expecting " << case1.d.toString() << ", but got " << d << '\n'; 57 | CHECK(d == case1.d); 58 | } 59 | } 60 | 61 | // for (int i = 0; i < (int) countof(cases); i++) { 62 | // SECTION("comparing s1 and s2") { 63 | // auto d = jaro(cases[i].s1, cases[i].s2); 64 | // REQUIRE(d == cases[i].d); 65 | // // REQUIRE(is_double_eq(jaro(argv[0], argv[1]), 0.9002777778)); 66 | // } 67 | // } 68 | 69 | SECTION("developer - developers") { 70 | const char *argv[] = {"developer", "developers"}; 71 | REQUIRE(jaro(argv[0], argv[1]) == Approx(0.96666666666666667)); 72 | // REQUIRE(detail::is_double_eq(jaro(argv[0], argv[1]), 0.9002777778)); 73 | } 74 | SECTION("developer - seveloper") { 75 | const char *argv[] = {"developer", "seveloper"}; 76 | REQUIRE(jaro(argv[0], argv[1]) == 0.92592592592592593); 77 | // REQUIRE(detail::is_double_eq(jaro(argv[0], argv[1]), 0.92592592592592593)); 78 | } 79 | SECTION("CRATE - TRACE") { 80 | const char *argv[] = {"CRATE", "TRACE"}; 81 | REQUIRE(jaro(argv[0], argv[1]) == 0.73333333333333339); 82 | // REQUIRE(detail::is_double_eq(jaro(argv[0], argv[1]), 0.73333333333333339)); 83 | } 84 | SECTION("DwAyNE - DuANE") { 85 | const char *argv[] = {"DwAyNE", "DuANE"}; 86 | REQUIRE(jaro(argv[0], argv[1]) == 0.8222222222222223); 87 | // REQUIRE(detail::is_double_eq(jaro(argv[0], argv[1]), 0.8222222222222223)); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /tests/mem_test_for_singleton.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/2/15. 3 | // 4 | 5 | // This file is a "Hello, world!" in C++ language by GCC for wandbox. 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | template 32 | class singleton { 33 | public: 34 | static T &instance(); 35 | 36 | singleton(const singleton &) = delete; 37 | singleton &operator=(const singleton) = delete; 38 | 39 | protected: 40 | struct token {}; 41 | singleton() = default; 42 | }; 43 | 44 | template 45 | inline T &singleton::instance() { 46 | static const std::unique_ptr instance{new T{token{}}}; 47 | return *instance; 48 | } 49 | 50 | 51 | class app { 52 | public: 53 | app() { 54 | std::cout << this << " | app::app()\n"; 55 | } 56 | ~app() { 57 | std::cout << this << " | ~app::app()\n"; 58 | } 59 | static app create() { 60 | app a; 61 | return a; 62 | } 63 | void use() {} 64 | }; 65 | 66 | class app_holder final : public singleton { 67 | public: 68 | explicit app_holder(typename singleton::token) {} 69 | ~app_holder() = default; 70 | 71 | [[maybe_unused]] void use() const { std::cout << "in use" << '\n'; } 72 | 73 | public: 74 | app *get_ptr() { return _app; } 75 | app &operator*() { return *_app; } 76 | app *operator->() { return _app; } 77 | // explicit operator app() { return _app; } 78 | 79 | private: 80 | app *_app{}; 81 | void put(app *ptr) { _app = ptr; } 82 | friend class app; 83 | }; 84 | 85 | inline app &get_app() { return *app_holder::instance().get_ptr(); } 86 | 87 | inline app create_cli_app() { 88 | if (auto ptr = app_holder::instance().get_ptr(); ptr) { 89 | throw std::runtime_error("can't invoke create_app() multiple times."); 90 | } 91 | 92 | return app::create(); 93 | } 94 | 95 | void test() { 96 | auto cli = create_cli_app(); 97 | cli.use(); 98 | } 99 | 100 | // 101 | 102 | // 103 | // 104 | 105 | // 106 | 107 | 108 | std::size_t allocated = 0; 109 | std::size_t released = 0; 110 | std::size_t released_size = 0; 111 | 112 | void *operator new(size_t sz) { 113 | void *p = std::malloc(sz); 114 | allocated += sz; 115 | return p; 116 | } 117 | 118 | void operator delete(void *p) noexcept { 119 | released++; 120 | return std::free(p); 121 | } 122 | 123 | void operator delete(void *p, std::size_t sz) noexcept { 124 | released++; 125 | released_size += sz; 126 | return std::free(p); 127 | } 128 | 129 | 130 | // 131 | // 132 | // 133 | 134 | 135 | int main() { 136 | std::cout << std::boolalpha; 137 | 138 | test(); 139 | 140 | std::cout << "test() END.\n"; 141 | 142 | std::printf("stack space = %zu, heap space = %zu (released: %zu)n", 143 | sizeof(get_app()), allocated, released); 144 | 145 | return 0; 146 | } 147 | 148 | 149 | // GCC reference: 150 | // https://gcc.gnu.org/ 151 | 152 | // C++ language references: 153 | // https://cppreference.com/ 154 | // https://isocpp.org/ 155 | // http://www.open-std.org/jtc1/sc22/wg21/ 156 | 157 | // Boost libraries references: 158 | // https://www.boost.org/doc/ 159 | -------------------------------------------------------------------------------- /tests/priority_queue.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/2/28. 3 | // 4 | 5 | #include "cmdr11/cmdr_priority_queue.hh" 6 | #include "cmdr11/cmdr_utils.hh" 7 | 8 | 9 | void test_pq() { 10 | std::list vi; 11 | // vi.pop_front(); 12 | 13 | struct pq_comp { 14 | std::function _comp = [](std::string const &lhs, std::string const &rhs) -> int { 15 | if (lhs.substr(0, 4) == "CMD:") { 16 | if (rhs.substr(0, 4) == "CMD:") 17 | return 0; // return std::less()(lhs, rhs) ? -1 : 1; 18 | } else { 19 | if (rhs.substr(0, 4) == "CMD:") 20 | return -1; 21 | 22 | return std::less()(lhs, rhs) ? -1 : 1; 23 | } 24 | return 0; 25 | }; 26 | int operator()(std::string const &lhs, std::string const &rhs) const { 27 | return _comp(lhs, rhs); 28 | } 29 | }; 30 | 31 | using pqueue = cmdr::queue::priority_queue; 32 | pqueue pq; 33 | pq.push("CMD:CONNECT TO"); 34 | pq.push("data:a123"); 35 | pq.push("data:a125"); 36 | pq.push("data:b1"); 37 | pq.push("CMD:SEND"); 38 | pq.push("data:tv1"); 39 | pq.push("data:c3"); 40 | pq.push("CMD:CLOSE"); 41 | 42 | std::cout << "DUMP..." << '\n'; 43 | pq.dump([](pqueue::element *el) { 44 | for (auto const &it: el->_list) { 45 | std::cout << it << ','; 46 | } 47 | std::cout << '\n'; 48 | }); 49 | std::cout << "ITER..." << '\n'; 50 | for (auto &it: pq) { 51 | std::cout << it << '\n'; 52 | } 53 | std::cout << "POP..." << '\n'; 54 | while (!pq.empty()) 55 | std::cout << pq.pop() << '\n'; 56 | 57 | #if 1 58 | std::cout << '\n'; 59 | std::cout << '\n'; 60 | std::cout << "Multi-level..." << '\n'; 61 | using nested_pqueue = cmdr::queue::priority_queue>; 63 | nested_pqueue pq2; 64 | pq2.push("CMD:CONNECT TO"); 65 | pq2.push("data:a123"); 66 | pq2.push("data:a125"); 67 | pq2.push("data:b1"); 68 | pq2.push("CMD:SEND"); 69 | pq2.push("data:tv1"); 70 | pq2.push("data:c3"); 71 | pq2.push("CMD:CLOSE"); 72 | 73 | std::cout << "- DUMP..." << '\n'; 74 | pq2.dump([](nested_pqueue::element *el) { 75 | for (auto const &it: el->_list) { 76 | std::cout << it << ','; 77 | } 78 | std::cout << '\n'; 79 | }); 80 | std::cout << "- POP..." << '\n'; 81 | while (!pq2.empty()) 82 | std::cout << pq2.pop() << '\n'; 83 | #endif 84 | } 85 | 86 | int main() { 87 | test_pq(); 88 | } 89 | -------------------------------------------------------------------------------- /tests/process.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/4/20. 3 | // 4 | 5 | #include "cmdr11/cmdr_ios.hh" // allow ostream << istream, ... 6 | #include "cmdr11/cmdr_os_io_redirect.hh" 7 | #include "cmdr11/cmdr_path.hh" 8 | #include "cmdr11/cmdr_process.hh" 9 | 10 | #include 11 | #include 12 | 13 | void test_stdout_capture() { 14 | cmdr::process::exec ex("ls -la /tmp/"); 15 | 16 | std::cout << "stdout:" << '\n'; 17 | std::cout << ex; 18 | std::cout.flush(); 19 | // std::cout.good(); 20 | 21 | std::cout << '\n'; 22 | std::cout << "done!" << '\n'; 23 | std::cout << '\n'; 24 | std::cout << '\n'; 25 | std::cout.flush(); 26 | } 27 | 28 | void test_stderr_capture() { 29 | { 30 | cmdr::process::exec ex("ls -la /unknown"); 31 | 32 | std::cout << "executed: rec-code = " << ex.ret_code() << '\n'; 33 | 34 | std::cout << "stderr:" << '\n'; 35 | // ex.stderr_stream() >> std::noskipws; 36 | // std::copy(std::istream_iterator(ex.stderr_stream()), std::istream_iterator(), std::ostream_iterator(std::cout)); 37 | std::cout << ex.stderr_stream(); 38 | 39 | std::cout << "stdout:" << '\n'; 40 | std::cout << ex; 41 | std::cout.flush(); 42 | } 43 | std::cout << '\n'; 44 | std::cout << "done!" << '\n'; 45 | std::cout.flush(); 46 | std::cout << '\n'; 47 | std::cout << '\n'; 48 | } 49 | 50 | int main() { 51 | 52 | std::fstream file; 53 | file.open("cout.txt.log", std::ios::out); 54 | 55 | std::cout << "This line written to screen, pwd: "; 56 | std::cout << cmdr::path::get_current_dir(); 57 | std::cout << "\n"; 58 | { 59 | cmdr::os::pipe_all_to p1(file.rdbuf()); 60 | std::cout << "This line written to file " 61 | << "\n"; 62 | std::clog << "hello" 63 | << "\n"; 64 | } 65 | std::cout << "This line written to screen too" 66 | << "\n"; 67 | std::clog << "world" 68 | << "\n"; 69 | test_stdout_capture(); 70 | test_stderr_capture(); 71 | } -------------------------------------------------------------------------------- /tests/second_src.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/2/10. 3 | // 4 | 5 | #ifndef CMDR_CXX11_SECOND_SRC_HH 6 | #define CMDR_CXX11_SECOND_SRC_HH 7 | 8 | void second_test(); 9 | 10 | void fatal_exit(const std::string &msg); 11 | 12 | void add_sub1_menu(cmdr::app &cli, cmdr::opt::cmd &t1, const_chars title); 13 | void add_test_menu(cmdr::app &cli); 14 | void add_main_menu(cmdr::app &cli); 15 | void add_server_menu(cmdr::app &cli); 16 | 17 | 18 | #endif // CMDR_CXX11_SECOND_SRC_HH 19 | -------------------------------------------------------------------------------- /tests/sso_test_1.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/17. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | std::size_t allocated = 0; 15 | std::size_t released = 0; 16 | std::size_t released_size = 0; 17 | 18 | void *operator new(size_t sz) { 19 | void *p = std::malloc(sz); 20 | allocated += sz; 21 | return p; 22 | } 23 | 24 | void operator delete(void *p) noexcept { 25 | released++; 26 | return std::free(p); 27 | } 28 | 29 | void operator delete(void *p, std::size_t sz) noexcept { 30 | released++; 31 | released_size += sz; 32 | return std::free(p); 33 | } 34 | 35 | int main() { 36 | std::cout << std::boolalpha; 37 | 38 | std::string s("hi"); 39 | std::printf("stack space = %zu, heap space = %zu (released: %zu), capacity = %zu\n", 40 | sizeof(s), allocated, released, s.capacity()); 41 | 42 | auto re1 = new std::string("moli"); 43 | delete re1; 44 | std::printf("stack space = %zu, heap space = %zu (released: %zu, %zu), capacity = %zu\n", 45 | sizeof(s), allocated, released, released_size, s.capacity()); 46 | } 47 | -------------------------------------------------------------------------------- /tests/sso_test_2.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/17. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "cmdr11/cmdr_process.hh" 11 | #include "cmdr11/cmdr_var_t.hh" 12 | 13 | 14 | std::size_t allocated = 0; 15 | std::size_t released = 0; 16 | std::size_t released_size = 0; 17 | 18 | void *operator new(size_t sz) { 19 | void *p = std::malloc(sz); 20 | allocated += sz; 21 | return p; 22 | } 23 | 24 | void operator delete(void *p) noexcept { 25 | return std::free(p); 26 | } 27 | 28 | void operator delete(void *p, std::size_t sz) noexcept { 29 | released++; 30 | released_size += sz; 31 | return std::free(p); 32 | } 33 | 34 | int main() { 35 | allocated = 0; 36 | std::string s("hi"); 37 | std::printf("stack space = %zu, heap space = %zu, capacity = %zu\n", 38 | sizeof(s), allocated, s.capacity()); 39 | 40 | auto re1 = new std::string("moli"); 41 | delete re1; 42 | std::printf("stack space = %zu, heap space = %zu (released: %zu, %zu), capacity = %zu\n", 43 | sizeof(s), allocated, released, released_size, s.capacity()); 44 | 45 | // cmdr:::vars::var_t vs; 46 | // std::cout << "var_t: " << vs << '\n'; 47 | 48 | 49 | using namespace std::chrono_literals; 50 | 51 | cmdr::vars::store store; 52 | 53 | store.set_raw("app.server.tls.enabled", true); 54 | store.set_raw("app.server.tls.ca.cert", "ca.cer"); 55 | store.set_raw("app.server.tls.server.cert", "server.cer"); 56 | store.set_raw("app.server.tls.server.key", "server.key"); 57 | store.set_raw("app.server.tls.client-auth", true); 58 | store.set_raw("app.server.tls.handshake.timeout", 10s); 59 | store.set_raw("app.server.tls.handshake.max-idle-time", 45min); 60 | store.set_raw("app.server.tls.domains", std::vector{"example.com", "example.org"}); 61 | store.set_raw("app.server.tls.fixed-list", std::array{"item1", "item2"}); 62 | 63 | store.set_raw("app.server.test.test-1-time", 0.75min); 64 | store.set_raw("app.server.test.test-2-time", 501ns); 65 | store.set_raw("app.server.test.test-3-time", 730us); 66 | store.set_raw("app.server.test.test-4-time", 233ms); 67 | store.set_raw("app.server.test.test-5-time", 7s); 68 | store.set_raw("app.server.test.test-6-time", 7.2s); 69 | store.set_raw("app.server.test.test-7-time", 1024h); 70 | 71 | store.set_raw("app.server.ii-1", 123u); 72 | store.set_raw("app.server.ii-2", 7.0); 73 | store.set_raw("app.server.ii-3", 3.14159f); 74 | store.set_raw("app.server.ii-4", 2.71828); 75 | store.set_raw("app.server.ii-5", "a string"); 76 | store.set_raw("app.server.vv-1", std::vector{"a string", "b", "c"}); 77 | 78 | std::cout << "store: " << store << '\n'; 79 | 80 | #if defined(_DEBUG) 81 | store.dump_full_keys(std::cout); 82 | store.dump_tree(std::cout); 83 | #endif 84 | 85 | std::cout << std::boolalpha; 86 | std::cout << cmdr::checks::is_vector_v> << '\n'; 87 | std::cout << cmdr::checks::is_vector_v << '\n'; 88 | std::cout << cmdr::checks::is_container::value << '\n'; 89 | std::cout << cmdr::checks::is_container>::value << '\n'; 90 | 91 | auto v1 = std::vector{"example.com", "example.org"}; 92 | std::cout << "cmdr::is_stl_container : " << cmdr::checks::is_stl_container::value << '\n'; 93 | auto v2 = 10s; 94 | std::cout << "type " << typeid(v2).name() << ". check: " << cmdr::checks::is_duration::value << '\n'; 95 | 96 | std::cout << "cmdr::is_duration : " << cmdr::checks::is_duration::value << '\n'; 97 | std::cout << "cmdr::is_duration : " << cmdr::checks::is_duration::value << '\n'; 98 | std::cout << "cmdr::is_duration : " << cmdr::checks::is_duration::value << '\n'; 99 | std::cout << "cmdr::is_duration : " << cmdr::checks::is_duration::value << '\n'; 100 | std::cout << "cmdr::is_duration : " << cmdr::checks::is_duration::value << '\n'; 101 | std::cout << "cmdr::is_duration : " << cmdr::checks::is_duration::value << '\n'; 102 | 103 | // 104 | std::string str1 = "body install it"; 105 | std::cout << cmdr::string::trim_left_space(str1.substr(4)) << '\n'; 106 | 107 | #if OS_WIN 108 | cmdr::process::exec r("ls -la C:/Users"); 109 | #elif OS_APPLE 110 | cmdr::process::exec r("ls -la /Users"); 111 | #else 112 | cmdr::process::exec r("ls -la /home"); 113 | #endif 114 | std::cout << r.rdbuf(); 115 | 116 | #if defined(_WIN32) || defined(_WIN64) 117 | std::string szbuf1; 118 | { 119 | char* buf1 = nullptr; 120 | size_t sz = 0; 121 | if (_dupenv_s(&buf1, &sz, "CI_RUNNING") == 0 && buf1 != nullptr) { 122 | szbuf1 = buf1; 123 | free(buf1); 124 | } 125 | } 126 | auto* str = szbuf1.c_str(); 127 | #else 128 | auto *str = std::getenv("CI_RUNNING"); 129 | #endif 130 | // if (str == nullptr) 131 | // cmdr::process::wait_a_key("soon to exit..."); 132 | std::cout << "END." << (str ? str : "") << '\n'; 133 | } -------------------------------------------------------------------------------- /tests/store_c2.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/21. 3 | // 4 | 5 | #define CATCH_CONFIG_MAIN 6 | 7 | #include 8 | 9 | 10 | // // Standard C/C++ main entry point 11 | // int main (int argc, char * argv[]) { 12 | // return Catch::Session().run( argc, argv ); 13 | // } 14 | 15 | 16 | int Factorial(int number) { 17 | // return number <= 1 ? number : Factorial(number - 1) * number; // fail 18 | return number <= 1 ? 1 : Factorial(number - 1) * number; // pass 19 | } 20 | 21 | TEST_CASE("Factorial of 0 is 1 (fail)", "[single-file]") { 22 | REQUIRE(Factorial(0) == 1); 23 | } 24 | 25 | TEST_CASE("Factorials of 1 and higher are computed (pass)", "[single-file]") { 26 | REQUIRE(Factorial(1) == 1); 27 | REQUIRE(Factorial(2) == 2); 28 | REQUIRE(Factorial(3) == 6); 29 | REQUIRE(Factorial(10) == 3628800); 30 | } 31 | 32 | TEST_CASE("vectors can be sized and resized", "[vector]") { 33 | 34 | // For each section, vector v is anew: 35 | 36 | std::vector v(5); 37 | 38 | REQUIRE(v.size() == 5); 39 | REQUIRE(v.capacity() >= 5); 40 | 41 | SECTION("resizing bigger changes size and capacity") { 42 | v.resize(10); 43 | 44 | REQUIRE(v.size() == 10); 45 | REQUIRE(v.capacity() >= 10); 46 | } 47 | SECTION("resizing smaller changes size but not capacity") { 48 | v.resize(0); 49 | 50 | REQUIRE(v.size() == 0); 51 | REQUIRE(v.capacity() >= 5); 52 | } 53 | SECTION("reserving bigger changes capacity but not size") { 54 | v.reserve(10); 55 | 56 | REQUIRE(v.size() == 5); 57 | REQUIRE(v.capacity() >= 10); 58 | } 59 | SECTION("reserving smaller does not change size or capacity") { 60 | v.reserve(0); 61 | 62 | REQUIRE(v.size() == 5); 63 | REQUIRE(v.capacity() >= 5); 64 | } 65 | } 66 | 67 | SCENARIO("vectors can be sized and resized", "[vector]") { 68 | 69 | GIVEN("A vector with some items") { 70 | std::vector v(5); 71 | 72 | REQUIRE(v.size() == 5); 73 | REQUIRE(v.capacity() >= 5); 74 | 75 | WHEN("the size is increased") { 76 | v.resize(10); 77 | 78 | THEN("the size and capacity change") { 79 | REQUIRE(v.size() == 10); 80 | REQUIRE(v.capacity() >= 10); 81 | } 82 | } 83 | WHEN("the size is reduced") { 84 | v.resize(0); 85 | 86 | THEN("the size changes but not capacity") { 87 | REQUIRE(v.size() == 0); 88 | REQUIRE(v.capacity() >= 5); 89 | } 90 | } 91 | WHEN("more capacity is reserved") { 92 | v.reserve(10); 93 | 94 | THEN("the capacity changes but not the size") { 95 | REQUIRE(v.size() == 5); 96 | REQUIRE(v.capacity() >= 10); 97 | } 98 | } 99 | WHEN("less capacity is reserved") { 100 | v.reserve(0); 101 | 102 | THEN("neither size nor capacity are changed") { 103 | REQUIRE(v.size() == 5); 104 | REQUIRE(v.capacity() >= 5); 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tests/traits.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/9/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | #include "cmdr11/cmdr_defs.hh" 23 | #include "cmdr11/cmdr_utils.hh" 24 | #include "cmdr11/cmdr_var_t.hh" 25 | 26 | #include "cmdr11/cmdr_x_test.hh" 27 | 28 | void test_tuple_to_string() { 29 | auto tup = std::make_tuple(1, "hello", 4.5); 30 | std::cout << tup << '\n'; 31 | } 32 | 33 | void test_vector_to_string() { 34 | auto vec = {"a", "b", "v"}; 35 | std::cout << vec << '\n'; 36 | } 37 | 38 | int main() { 39 | CMDR_TEST_FOR(test_tuple_to_string); 40 | CMDR_TEST_FOR(test_vector_to_string); 41 | } -------------------------------------------------------------------------------- /tests/valarray_test.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/29. 3 | // 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | namespace bet { 20 | 21 | template 22 | class ti_queue { 23 | public: 24 | struct element { 25 | T _data{}; 26 | element *_last{}; 27 | element *_next{}; 28 | }; 29 | 30 | public: 31 | ti_queue() { 32 | _head = new element; 33 | _tail = new element; 34 | _head->_next = _tail; 35 | _tail->_last = _head; 36 | } 37 | ~ti_queue() { 38 | auto *p = _head; 39 | while (p != nullptr) { 40 | auto *t = p; 41 | p = p->_next; 42 | delete t; 43 | } 44 | } 45 | 46 | void push(T const &data) { 47 | auto h = _tail->_last; 48 | auto *ptr = new element{data, h, _tail}; 49 | _tail->_last = ptr; 50 | h->_next = ptr; 51 | } 52 | 53 | T pop() { 54 | auto p = _head->_next; 55 | if (p == _tail) { 56 | return T{}; 57 | } 58 | p->_last->_next = p->_next; 59 | p->_next->_last = p->_last; 60 | T t = p->_data; 61 | delete p; 62 | return t; 63 | } 64 | 65 | bool empty() const { return _tail->_last == _head; } 66 | 67 | T const &peek() const { 68 | if (empty()) return _tail->_data; 69 | return _tail->_last->_data; 70 | } 71 | 72 | private: 73 | element *_head{}; 74 | element *_tail{}; 75 | }; 76 | 77 | 78 | class Matrix { 79 | std::valarray data; 80 | int dim; 81 | 82 | public: 83 | Matrix(int r, int c) 84 | : data(r * c) 85 | , dim(c) {} 86 | int &operator()(int r, int c) { return data[r * dim + c]; } 87 | [[nodiscard]] int trace() const { 88 | return data[std::slice(0, dim, dim + 1)].sum(); 89 | } 90 | }; 91 | 92 | } // namespace bet 93 | 94 | int main() { 95 | bet::Matrix m(3, 3); 96 | int n = 0; 97 | for (int r = 0; r < 3; ++r) 98 | for (int c = 0; c < 3; ++c) 99 | m(r, c) = ++n; 100 | std::cout << "Trace of the matrix (1,2,3) (4,5,6) (7,8,9) is " << m.trace() << '\n'; 101 | 102 | std::cout << '\n' 103 | << "queue: "; 104 | bet::ti_queue tiq; 105 | tiq.push(31); 106 | tiq.push(17); 107 | tiq.push(19); 108 | tiq.push(73); 109 | 110 | auto tmp = tiq.pop(); 111 | std::cout << tmp; 112 | 113 | while (!tiq.empty()) { 114 | tmp = tiq.pop(); 115 | std::cout << ',' << tmp; 116 | } 117 | 118 | std::cout << '\n' 119 | << '\n'; 120 | } 121 | -------------------------------------------------------------------------------- /tests/visit_any.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/20. 3 | // 4 | 5 | 6 | #include "visit_any.hh" 7 | 8 | #include "cmdr11/cmdr_ios.hh" 9 | #include "cmdr11/cmdr_utils.hh" 10 | 11 | void test_any() { 12 | std::any o1{std::string("a string")}; 13 | std::cout << std::any_cast(o1) << '\n'; 14 | // std::visit([](auto &&arg) { std::cout << arg; }, o1); 15 | std::cout << '\n'; 16 | 17 | std::any any{-1LL}; 18 | try { 19 | cmdr::util::visit_any_as(any, [](auto const &x) { 20 | std::cout << x << '\n'; 21 | }); 22 | } catch (std::exception const &e) { 23 | std::cout << e.what() << '\n'; 24 | } 25 | } 26 | 27 | void test_streamer_any() { 28 | std::vector va{ 29 | {}, 30 | 42, 31 | 123u, 32 | 3.14159f, 33 | 2.71828, 34 | "C++17", 35 | }; 36 | 37 | study::streamer_any os; 38 | 39 | std::cout << "{ "; 40 | for (const std::any &a: va) { 41 | os.process(std::cout, a); 42 | std::cout << ", "; 43 | } 44 | std::cout << "}\n"; 45 | 46 | os.process(std::cout, std::any(0xFULL)); //< Unregistered type "y" (unsigned long long) 47 | std::cout << '\n'; 48 | 49 | os.register_any_visitor([](std::ostream &os1, auto x) { 50 | cmdr::io::ios_state_saver _saver(os1); 51 | os1 << std::hex << std::showbase << x; 52 | }); 53 | 54 | std::cout << std::dec << 13 << '\n'; 55 | 56 | os.process(std::cout, std::any(0xFULL)); //< OK: 0xf 57 | std::cout << '\n'; 58 | 59 | using namespace std::chrono_literals; 60 | 61 | os.process(std::cout, std::any(31s)); //< OK: 0xf 62 | std::cout << '\n'; 63 | } 64 | 65 | auto main() -> int { 66 | test_any(); 67 | 68 | test_streamer_any(); 69 | 70 | extern void second_test(); 71 | second_test(); 72 | } -------------------------------------------------------------------------------- /tests/visit_any.hh: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Hedzr Yeh on 2021/1/20. 3 | // 4 | 5 | #ifndef CMDR_CXX11_VISIT_ANY_HH 6 | #define CMDR_CXX11_VISIT_ANY_HH 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "cmdr11/cmdr_types.hh" 19 | 20 | 21 | namespace study { 22 | 23 | // SFINAE assertion class here: is_streamable 24 | // original: https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream 25 | template 26 | class is_streamable_old { 27 | template 28 | static auto test(int) 29 | -> decltype(std::declval() << std::declval(), std::true_type()); 30 | 31 | template 32 | static auto test(...) -> std::false_type; 33 | 34 | public: 35 | static const bool value = decltype(test(0))::value; 36 | }; 37 | 38 | template 39 | class is_streamable { 40 | // c++17 41 | template 42 | struct test : std::false_type {}; 43 | 44 | // c++17 45 | template 46 | struct test() << std::declval())>> 47 | : std::true_type {}; 48 | 49 | public: 50 | static const bool value = decltype(test(0))::value; 51 | }; 52 | 53 | 54 | template 55 | class streamer_any { 56 | public: 57 | // OS &os; 58 | typedef std::unordered_map> R; 59 | static R &any_visitors() { 60 | static R _visitors = { 61 | to_any_visitor([](std::ostream &os) { os << "{}"; }), 62 | to_any_visitor([](std::ostream &os, int x) { os << x; }), 63 | to_any_visitor([](std::ostream &os, unsigned x) { os << x; }), 64 | to_any_visitor([](std::ostream &os, float x) { os << x; }), 65 | to_any_visitor([](std::ostream &os, double x) { os << x; }), 66 | to_any_visitor([](std::ostream &os, char const *s) { os << std::quoted(s); }), 67 | // ... add more handlers for your types ... 68 | to_any_visitor([](std::ostream &os, const std::chrono::nanoseconds &x) { cmdr::chrono::format_duration(os, x); }), 69 | to_any_visitor([](std::ostream &os, const std::chrono::seconds &x) { cmdr::chrono::format_duration(os, x); }), 70 | }; 71 | return _visitors; 72 | } 73 | streamer_any() = default; 74 | 75 | template 76 | static inline std::pair> 77 | to_any_visitor(F const &f) { 78 | return { 79 | std::type_index(typeid(T)), 80 | [g = f](std::ostream &os, std::any const &a) { 81 | if constexpr (std::is_void_v) 82 | g(os); 83 | else 84 | g(os, std::any_cast(a)); 85 | UNUSED(a); 86 | }}; 87 | } 88 | 89 | inline void process(std::ostream &os, const std::any &a) { 90 | if (const auto it = any_visitors().find(std::type_index(a.type())); 91 | it != any_visitors().cend()) { 92 | it->second(os, a); 93 | } else { 94 | std::cout << "Unregistered type " << std::quoted(a.type().name()); 95 | } 96 | } 97 | 98 | template 99 | inline void register_any_visitor(F const &f) { 100 | std::cout << "Register visitor for type " 101 | << std::quoted(typeid(T).name()) << '\n'; 102 | any_visitors().insert(to_any_visitor(f)); 103 | } 104 | }; 105 | 106 | // template 107 | // inline template streamer_any::R streamer_any::any_visitors; 108 | 109 | } // namespace study 110 | 111 | 112 | #endif // CMDR_CXX11_VISIT_ANY_HH 113 | --------------------------------------------------------------------------------