diff --git a/.github/workflows/test-cpp.yml b/.github/workflows/test-cpp.yml index 30118c1b7..0ea60fd06 100644 --- a/.github/workflows/test-cpp.yml +++ b/.github/workflows/test-cpp.yml @@ -6,37 +6,37 @@ on: - main - renovate/** paths: - - cpp/** + - cpp* - testdata/** - gherkin-languages.json pull_request: branches: - main paths: - - cpp/** + - cpp* - testdata/** - gherkin-languages.json workflow_call: jobs: test-cpp: - runs-on: ubuntu-latest - + strategy: + matrix: + os: + #- ubuntu-20.04 + #- ubuntu-22.04 + #- windows-2019 + - windows-2022 + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - - name: install cmake and libraries + - name: install dependencies + working-directory: cpp run: | - sudo apt-get update - sudo apt-get install ninja-build cmake - sudo apt-get install nlohmann-json3-dev - ninja --version - cmake --version - gcc --version + cmake -P cmake/cmate update - name: configure and build - env: - NPROCS: 1 - run: | - make acceptance working-directory: cpp + run: | + cmake -P cmake/cmate configure + cmake -P cmake/cmate build diff --git a/cpp/.gitignore b/cpp/.gitignore index 5abb1e17c..8bba1c4da 100644 --- a/cpp/.gitignore +++ b/cpp/.gitignore @@ -2,6 +2,8 @@ ext/ build/ acceptance/ stage/ +.cenv/ +.cmate/ .built .configured .deps-installed diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 85bc7d396..6b07b3b2a 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -1,16 +1,16 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR) -project(gherkin-cpp VERSION 1.0.0 LANGUAGES C CXX) +project(cucumber_gherkin VERSION 0.1.0 LANGUAGES C CXX) include(GNUInstallDirs) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) find_package(nlohmann_json CONFIG REQUIRED) -find_package(cucumber-messages CONFIG REQUIRED) +find_package(cucumber_messages CONFIG REQUIRED) add_subdirectory(src/lib/gherkin) add_subdirectory(src/bin/gherkin) @@ -18,23 +18,23 @@ add_subdirectory(src/bin/gherkin-generate-tokens) install( TARGETS - gherkin-cpp - gherkin-bin - gherkin-generate-tokens-bin - EXPORT gherkin-cpp-config + cucumber_gherkin_lib + cucumber_gherkin_bin + cucumber_gherkin_generate_tokens_bin + EXPORT cucumber_gherkin-config RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install( - DIRECTORY "${CMAKE_SOURCE_DIR}/include/" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gherkin + EXPORT cucumber_gherkin-config + FILE cucumber_gherkin-config.cmake + NAMESPACE cucumber:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cucumber_gherkin ) install( - EXPORT gherkin-cpp-config - FILE gherkin-cpp-config.cmake - NAMESPACE gherkin-cpp:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/gherkin-cpp + DIRECTORY "${PROJECT_SOURCE_DIR}/include/gherkin/" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cucumber ) diff --git a/cpp/Makefile b/cpp/Makefile index 8bbb0c5ef..159492366 100644 --- a/cpp/Makefile +++ b/cpp/Makefile @@ -1,10 +1,12 @@ SHELL := /usr/bin/env bash +SUB_DIR = gherkin/cucumber/gherkin + GRAMMAR_GENERATED = \ - include/gherkin/rule_type.hpp \ - include/gherkin/parser.hpp + include/$(SUB_DIR)/rule_type.hpp \ + include/$(SUB_DIR)/parser.hpp LANGUAGE_GENERATED = \ - src/lib/gherkin/dialect.cpp + src/lib/$(SUB_DIR)/dialect.cpp ALL_GENERATED := $(GRAMMAR_GENERATED) $(LANGUAGE_GENERATED) ALL_SOURCE_FILES = $(shell find include src -name "*.[ch]*") SOURCE_FILES := $(filter-out $(ALL_GENERATED),$(ALL_SOURCE_FILES)) @@ -53,32 +55,24 @@ clean: clean-deps ## Remove all build artifacts and files generated by the accep acceptance: .built $(TOKENS) $(ASTS) $(PICKLES) $(ERRORS) $(SOURCES) ## Build acceptance test dir and compare results with reference .built: .configured $(SOURCE_FILES) - cmake --build build/gherkin --parallel $(NPROCS) - cmake --install build/gherkin + ./cmake/cmate build touch $@ .configured: .deps-installed - rm -rf build/gherkin && mkdir -p build/gherkin - cmake \ - -G Ninja \ - -DCMAKE_PREFIX_PATH=$(CMAKE_BUILDROOT) \ - -DCMAKE_INSTALL_PREFIX=$(HERE)/stage \ - -S . \ - -B build/gherkin \ - --toolchain cmake/toolchains/ext.cmake + ./cmake/cmate configure touch $@ define berp-generate-parser = berp -g ../gherkin.berp -t $< -o $@ --noBOM endef -include/gherkin/rule_type.hpp: gherkin-cpp-rule-type.razor ../gherkin.berp +include/$(SUB_DIR)/rule_type.hpp: gherkin-cpp-rule-type.razor ../gherkin.berp $(berp-generate-parser) -include/gherkin/parser.hpp: gherkin-cpp-parser.razor ../gherkin.berp +include/$(SUB_DIR)/parser.hpp: gherkin-cpp-parser.razor ../gherkin.berp $(berp-generate-parser) -src/lib/gherkin/dialect.cpp: ../gherkin-languages.json dialect.cpp.jq +src/lib/$(SUB_DIR)/dialect.cpp: ../gherkin-languages.json dialect.cpp.jq jq -f dialect.cpp.jq -r -c < $< > $@ acceptance/testdata/%.tokens: ../testdata/% ../testdata/%.tokens @@ -113,7 +107,7 @@ install-deps: .deps-installed .PHONY: install-deps .deps-installed: - ./scripts/build-externals deps.txt + ./cmake/cmade install touch $@ clean-deps: diff --git a/cpp/cmake/cmate b/cpp/cmake/cmate new file mode 100755 index 000000000..69dff0f13 --- /dev/null +++ b/cpp/cmake/cmate @@ -0,0 +1,1402 @@ +#!/usr/bin/env -S cmake -P +# -*- CMake -*- + +set(CMATE "cmate") +set(CMATE_VER "X.Y.Z") +set(CMATE_TARGETS "") +set(CMATE_CMDS "") +set(CMATE_DEPSFILE "deps.txt") +set(CMATE_PRJFILE "project.json") +set(CMATE_LINKFILE "link.json") +set(CMATE_GIT_HOST "GH") +set(CMATE_GH "https://github.com") +set(CMATE_GL "https://gitlab.com") +set(CMATE_BB "https://bitbucket.org") +cmake_policy(SET CMP0057 NEW) + +############################################################################### +# +# Content of cmate/utilities.cmake +# +############################################################################### +function(cmate_die MSG) + message(FATAL_ERROR "CMate: error: ${MSG}") +endfunction() + +function(cmate_msg) + list(JOIN ARGV "" MSGS) + message("CMate: ${MSGS}") +endfunction() + +function(cmate_warn MSG) + message(WARNING "CMate: ${MSG}") +endfunction() + +function(cmate_info MSG) + if(CMATE_VERBOSE) + cmate_msg(${MSG}) + endif() +endfunction() + +function(cmate_setg VAR VAL) + set(${VAR} "${VAL}" CACHE INTERNAL "${VAR}") +endfunction() + +function(cmate_state_file STATE VAR) + set(${VAR} "${CMATE_STATE_DIR}/.${STATE}" PARENT_SCOPE) +endfunction() + +function(cmate_clear_state STATE) + file(MAKE_DIRECTORY ${CMATE_STATE_DIR}) + cmate_state_file(${STATE} FILE) + file(REMOVE ${FILE}) +endfunction() + +function(cmate_set_state STATE) + file(MAKE_DIRECTORY ${CMATE_STATE_DIR}) + cmate_state_file(${STATE} FILE) + file(TOUCH ${FILE}) +endfunction() + +function(cmate_clear_states) + if (IS_DIRECTORY ${CMATE_STATE_DIR}) + file(REMOVE_RECURSE ${CMATE_STATE_DIR}) + endif() +endfunction() + +function(cmate_load_version) + if(NOT "${CMATE_VERSION}" STREQUAL "") + return() + endif() + + if("${CMATE_VERSION_FILE}" STREQUAL "") + cmate_setg( + CMATE_VERSION_FILE + "${CMATE_ROOT_DIR}/version.txt" + ) + endif() + + if(EXISTS ${CMATE_VERSION_FILE}) + file( + STRINGS ${CMATE_VERSION_FILE} VER + REGEX "^[^\\.]+\\.[^\\.]+\\.[^\\.]+$" + LIMIT_COUNT 1 + ) + + cmate_setg(CMATE_VERSION ${VER}) + endif() +endfunction() + +function(cmate_set_version) + cmate_load_version() + + if("${CMATE_PROJECT_VERSION}" STREQUAL "") + cmate_warn("using default version: 0.1.0") + cmate_setg(CMATE_PROJECT_VERSION "0.1.0") + endif() + + if("${CMATE_PROJECT_VERSION}" MATCHES "^([^\\.]+)\\.([^\\.]+)\\.([^\\.]+)$") + cmate_setg(CMATE_PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) + cmate_setg(CMATE_PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) + cmate_setg(CMATE_PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) + else() + cmate_die("unable to parse version: ${CMATE_PROJECT_VERSION}") + endif() +endfunction() + +macro(cmate_setv VAR VAL) + if("${${VAR}}" STREQUAL "") + set(${VAR} ${VAL}) + endif() +endmacro() + +function(cmate_json_get_array JSON KEY VAR) + string(JSON ARRAY ERROR_VARIABLE ERR GET ${JSON} ${KEY}) + set(ITEMS "") + + if (NOT ERR) + string(JSON N LENGTH ${ARRAY}) + + if(${N} GREATER_EQUAL 1) + math(EXPR N "${N}-1") + + foreach(I RANGE ${N}) + string(JSON ITEM GET ${ARRAY} ${I}) + list(APPEND ITEMS ${ITEM}) + endforeach() + endif() + endif() + + set(${VAR} ${ITEMS} PARENT_SCOPE) +endfunction() + +function(cmate_load_conf FILE) + set(PKGS "") + + if(EXISTS ${FILE}) + file(READ ${FILE} JSON) + + string(JSON PROJECT GET ${JSON} "name") + cmate_setg(CMATE_PROJECT_NAME ${PROJECT}) + string(JSON VERSION GET ${JSON} "version") + cmate_setg(CMATE_PROJECT_VERSION "${VERSION}") + cmate_set_version() + string(JSON NAMESPACE GET ${JSON} "namespace") + cmate_setg(CMATE_PROJECT_NAMESPACE ${NAMESPACE}) + + string(JSON PKGS GET ${JSON} "packages") + endif() + + cmate_setg(CMATE_PACKAGES "${PKGS}") +endfunction() + +function(cmate_run_prog) + cmake_parse_arguments(RUN "" "DIR" "CMD" ${ARGN}) + + if(CMATE_SIMULATE) + list(PREPEND RUN_CMD "echo") + endif() + + execute_process( + COMMAND ${RUN_CMD} + WORKING_DIRECTORY "${RUN_DIR}" + RESULTS_VARIABLE RC + ) + + if(RC) + list(JOIN ARGV " " RUN_CMD) + cmate_die("command failed: ${RUN_CMD}") + endif() +endfunction() + +function(cmate_unique_dir PATH VAR) + file(GLOB PATHS "${PATH}/*") + + foreach(PATH ${PATHS}) + if(IS_DIRECTORY ${PATH}) + list(APPEND ALL_DIRS ${PATH}) + endif() + endforeach() + + list(LENGTH ALL_DIRS DIRS) + + if(DIRS EQUAL 0) + cmate_die("no directories found in ${PATH}") + elseif(DIRS GREATER 1) + cmate_die("multiple directories found ${PATH}") + endif() + + list(GET ALL_DIRS 0 DIR) + set(${VAR} ${DIR} PARENT_SCOPE) +endfunction() + +function(cmate_download URL FILE) + if(CMATE_SIMULATE) + cmate_msg("download ${URL} to ${FILE}") + else() + file(DOWNLOAD ${URL} ${FILE} STATUS ST) + endif() + + list(GET ST 0 RC) + + if(RC) + cmate_die("download of ${URL} failed: ${ST}") + endif() +endfunction() +############################################################################### +# +# Content of cmate/args.cmake +# +############################################################################### +function(cmate_check_option OPT OPTS LABEL) + list(FIND OPTS ${OPT} IDX) + + if (IDX LESS 0) + cmate_die("unknown ${LABEL} option: ${OPT}") + endif() +endfunction() + +function(cmate_locate_cmate_arguments) + set(FOUND OFF) + + foreach(POS RANGE ${CMAKE_ARGC}) + string(TOLOWER "${CMAKE_ARGV${POS}}" ARG) + math(EXPR POS "${POS}+1") + + if (ARG MATCHES "${CMATE}$") + # Script args follow us, POS already incremented + set(FOUND ON) + cmate_setg(CMATE_POS ${POS}) + break() + endif() + endforeach() + + if(NOT FOUND) + # Should not happen if script has correct name (see CMATE at top) + cmate_die("parse_argument") + endif() +endfunction() + +function(cmate_parse_arguments) + cmate_locate_cmate_arguments() + set(OPTS_LABEL "generic") + set(OPTS ${CMATE_OPTIONS}) + + while(CMATE_POS LESS ${CMAKE_ARGC}) + if ("${CMAKE_ARGV${CMATE_POS}}" MATCHES "^--?([A-Za-z0-9_-]+)(=(.+))?$") + #cmate_check_option(${CMAKE_MATCH_1} "${OPTS}" ${OPTS_LABEL}) + set(OPT "CMATE") + + if(CMATE_CMD) + string(APPEND OPT "_${CMATE_CMD}") + endif() + + string(APPEND OPT "_${CMAKE_MATCH_1}") + string(REPLACE "-" "_" OPT "${OPT}") + string(TOUPPER ${OPT} OPT) + + if("${CMAKE_MATCH_3}" STREQUAL "") + cmate_setg(${OPT} 1) + else() + cmate_setg(${OPT} "${CMAKE_MATCH_3}") + endif() + elseif("${CMATE_CMD}" STREQUAL "") + set(CMATE_CMD "${CMAKE_ARGV${CMATE_POS}}") + set(OPTS_LABEL ${CMATE_CMD}) + set(OPTS_VAR CMATE_${CMATE_CMD}_OPTIONS) + string(TOUPPER "${OPTS_VAR}" OPTS_VAR) + set(OPTS ${${OPTS_VAR}}) + else() + list(APPEND CMATE_ARGS "${CMAKE_ARGV${CMATE_POS}}") + endif() + + math(EXPR CMATE_POS "${CMATE_POS}+1") + endwhile() + + list(LENGTH CMATE_ARGS CMATE_ARGC) + + cmate_setg(CMATE_CMD "${CMATE_CMD}") + cmate_setg(CMATE_ARGS "${CMATE_ARGS}") + cmate_setg(CMATE_ARGC ${CMATE_ARGC}) + get_filename_component(CMATE_ENV "${CMATE_ENV}" REALPATH) + cmate_setg(CMATE_ENV ${CMATE_ENV}) +endfunction() +############################################################################### +# +# Content of cmate/target_deps.cmake +# +############################################################################### +function(cmate_load_cmake_package_deps JSON PREFIX) + cmate_json_get_array("${JSON}" "cmake" "PKGS") + set(PACKAGES "") + + foreach(PKG ${PKGS}) + set(PKGTYPE "STRING") + + if("${PKG}" MATCHES "^[[{].*$") + string(JSON PKGTYPE TYPE ${PKG}) + endif() + + if(${PKGTYPE} STREQUAL "STRING") + # Simple module + list(APPEND PACKAGES ${PKG}) + elseif(${PKGTYPE} STREQUAL "OBJECT") + # Module and components + string(JSON PKGNAME MEMBER ${PKG} 0) + list(APPEND PACKAGES ${PKGNAME}) + + cmate_json_get_array(${PKG} ${PKGNAME} "COMPS") + + set("${PREFIX}_CMAKE_${PKGNAME}_COMPS" ${COMPS} PARENT_SCOPE) + endif() + endforeach() + + set("${PREFIX}_CMAKE_PACKAGES" ${PACKAGES} PARENT_SCOPE) +endfunction() + +function(cmate_load_pkgconfig_package_deps JSON PREFIX) + cmate_json_get_array("${JSON}" "pkgconfig" "PKGS") + set("${PREFIX}_PKGCONFIG_PACKAGES" ${PKGS} PARENT_SCOPE) +endfunction() + +function(cmate_load_link_deps FILE PREFIX) + set(PUBLIC_DEPS "") + set(PRIVATE_DEPS "") + set(LVAR "PUBLIC_DEPS") + + if(EXISTS ${FILE}) + file(READ ${FILE} JSON) + string(JSON LIBS GET ${JSON} "libs") + + foreach(TYPE PUBLIC PRIVATE) + # TODO: add more checks for correct JSON structure + string(TOLOWER ${TYPE} KEY) + cmate_json_get_array(${LIBS} ${KEY} "${TYPE}_DEPS") + endforeach() + endif() + + set(${PREFIX}_PUBLIC_DEPS ${PUBLIC_DEPS} PARENT_SCOPE) + list(LENGTH PUBLIC_DEPS PUBLIC_DEPS_COUNT) + set(${PREFIX}_PUBLIC_DEPS_COUNT ${PUBLIC_DEPS_COUNT} PARENT_SCOPE) + + set(${PREFIX}_PRIVATE_DEPS ${PRIVATE_DEPS} PARENT_SCOPE) + list(LENGTH PRIVATE_DEPS PRIVATE_DEPS_COUNT) + set(${PREFIX}_PRIVATE_DEPS_COUNT ${PRIVATE_DEPS_COUNT} PARENT_SCOPE) + + math(EXPR DEPS_COUNT "${PUBLIC_DEPS_COUNT} + ${PRIVATE_DEPS_COUNT}") + set(${PREFIX}_DEPS_COUNT ${DEPS_COUNT} PARENT_SCOPE) +endfunction() + +function(cmate_target_link_deps NAME FILE VAR) + cmate_load_link_deps(${FILE} TGT) + + if(${TGT_DEPS_COUNT} GREATER 0) + set(TDEPS "\ntarget_link_libraries(\n ${NAME}") + + foreach(TYPE PUBLIC PRIVATE) + if(${TGT_${TYPE}_DEPS_COUNT} GREATER 0) + string(APPEND TDEPS "\n ${TYPE}") + + foreach(DEP ${TGT_${TYPE}_DEPS}) + string(APPEND TDEPS "\n ${DEP}") + endforeach() + endif() + endforeach() + + string(APPEND TDEPS "\n)\n") + set(${VAR} ${TDEPS} PARENT_SCOPE) + endif() +endfunction() + +function(cmate_target_name NAME TYPE VAR) + string(TOLOWER "${CMATE_PROJECT_NAMESPACE}_${NAME}_${TYPE}" TBASE) + string(REPLACE "-" "_" TBASE ${TBASE}) + set(${VAR} ${TBASE} PARENT_SCOPE) +endfunction() +############################################################################### +# +# Content of cmate/deps.cmake +# +############################################################################### +function(cmate_dep_set_cache_dir NAME) + string(REPLACE "/" "_" DIR ${NAME}) + set(DIR "${CMATE_DEPS_DIR}/${DIR}") + cmate_setg(CMATE_DEP_CACHE_DIR ${DIR}) + cmate_setg(CMATE_DEP_SOURCE_DIR "${DIR}/sources") + cmate_setg(CMATE_DEP_BUILD_DIR "${DIR}/build") + cmate_setg(CMATE_DEP_STATE_DIR "${DIR}/state") +endfunction() + +function(cmate_dep_state_file STATE VAR) + set(${VAR} "${CMATE_DEP_STATE_DIR}/.${STATE}" PARENT_SCOPE) +endfunction() + +function(cmate_dep_set_state STATE) + file(MAKE_DIRECTORY ${CMATE_DEP_STATE_DIR}) + cmate_dep_state_file(${STATE} FILE) + file(TOUCH ${FILE}) +endfunction() + +function(cmate_dep_get_repo HOST REPO REF) + if(HOST MATCHES "^\\$\\{(.+)\\}$") + # Dereference variable + set(HOST ${${CMAKE_MATCH_1}}) + endif() + + if(HOST STREQUAL "GH") + set(HOST "https://github.com") + elseif(TYPE STREQUAL "GL") + set(HOST "https://gitlab.com") + endif() + + set(URL "${HOST}/${REPO}.git") + + set(GIT_ARGS "clone") + list( + APPEND GIT_ARGS + -c advice.detachedHead=false + --depth 1 + ) + + if(REF) + list(APPEND GIT_ARGS --branch "${REF}") + endif() + + cmate_dep_set_cache_dir(${REPO}) + cmate_dep_state_file("fetched" FETCHED) + + if(NOT IS_DIRECTORY ${CMATE_DEP_SOURCE_DIR} OR NOT EXISTS ${FETCHED}) + # Whatever the reason, we're (re-)fetching + file(REMOVE_RECURSE ${CMATE_DEP_SOURCE_DIR}) + cmate_info("cloning ${URL} in ${CMATE_DEP_SOURCE_DIR}") + cmate_run_prog(CMD git ${GIT_ARGS} ${URL} ${CMATE_DEP_SOURCE_DIR}) + cmate_dep_set_state("fetched") + endif() +endfunction() + +function(cmate_dep_get_url URL) + string(MD5 HASH ${URL}) + + if(URL MATCHES "/([^/]+)$") + set(FILE ${CMAKE_MATCH_1}) + else() + cmate_die("can't find filename from URL: ${URL}") + endif() + + cmate_dep_set_cache_dir(${HASH}) + cmate_dep_state_file("fetched" FETCHED) + cmate_dep_state_file("extracted" EXTRACTED) + set(CFILE "${CMATE_DEP_CACHE_DIR}/${FILE}") + + if(NOT EXISTS ${CFILE}) + cmate_info("downloading ${URL} in ${CDIR}") + cmate_download(${URL} ${CFILE}) + cmate_set_state("fetched") + endif() + + if(NOT IS_DIRECTORY ${CMATE_DEP_SOURCE_DIR} OR NOT EXISTS ${EXTRACTED}) + file(REMOVE_RECURSE ${CMATE_DEP_SOURCE_DIR}) + cmate_info("extracting ${FILE}") + file( + ARCHIVE_EXTRACT + INPUT ${CFILE} + DESTINATION ${CMATE_DEP_SOURCE_DIR} + ) + cmate_dep_set_state("extracted") + endif() + + cmate_unique_dir(${CMATE_DEP_SOURCE_DIR} SDIR) + cmate_setg(CMATE_DEP_SOURCE_DIR ${SDIR}) +endfunction() +############################################################################### +# +# Content of cmate/commands/configure.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "configure") +list( + APPEND + CMATE_CONFIGURE_OPTIONS + "dry-run" + "dump" + "namespace" + "version" + "version-file" + "source-pat" + "header-pat" +) +set(CMATE_CONFIGURE_SHORT_HELP "Configure local project") +set( + CMATE_CONFIGURE_HELP + " +Usage: cmate configure [OPTIONS] + +${CMATE_CONFIGURE_SHORT_HELP} + +Options: + --toolchain=FILE CMake toolchain file + --dry-run Don't touch anything + --dump Dump generated CMakeLists.txt + --namespace=NS CMake package namespace + --version=SEMVER CMake package version + --version-file=FILE CMake package version from FILE + --version-file=FILE CMake package version from FILE + --source-pat=PATTERN CMate targets source file glob pattern + (default: \$CACHE{CMATE_SOURCE_PAT}) + --header-pat=PATTERN CMate targets header file glob pattern + (default: \$CACHE{CMATE_HEADER_PAT})" +) + +function(cmate_configure_lib NAME TBASE INC_BASE SRC_BASE) + string(TOUPPER ${TBASE} VBASE) + + if(${CMATE_DRY_RUN}) + cmate_msg( + "found library ${NAME}" + " (I:${INC_BASE}/${NAME}" + ", S:${SRC_BASE}/${NAME})" + ) + return() + endif() + + list(APPEND CMATE_TARGETS ${TBASE}) + + set(HDIR "${CMATE_ROOT_DIR}/${INC_BASE}/${NAME}") + set(SDIR "${CMATE_ROOT_DIR}/${SRC_BASE}/${NAME}") + set(CM_FILE "${SDIR}/CMakeLists.txt") + set(LINK_FILE "${SDIR}/${CMATE_LINKFILE}") + + file(GLOB_RECURSE HEADERS "${HDIR}/${CMATE_HEADER_PAT}") + file(GLOB_RECURSE SOURCES "${SDIR}/${CMATE_SOURCE_PAT}") + + string(APPEND CONTENT "add_library(${TBASE})\n") + + if(CMATE_PROJECT_NAMESPACE) + string( + APPEND + CONTENT + "add_library(${CMATE_PROJECT_NAMESPACE}::${NAME} ALIAS ${TBASE})\n" + ) + endif() + + string( + APPEND + CONTENT + " +set(${VBASE}_INC_DIR \"\${PROJECT_SOURCE_DIR}/${INC_BASE}/${NAME}\") +file(GLOB_RECURSE ${VBASE}_HEADERS \${${VBASE}_INC_DIR}/${CMATE_HEADER_PAT}) +list(APPEND ${VBASE}_ALL_SOURCES \${${VBASE}_HEADERS}) + +set(${VBASE}_SRC_DIR \"\${CMAKE_CURRENT_SOURCE_DIR}\") +file(GLOB_RECURSE ${VBASE}_SOURCES \${${VBASE}_SRC_DIR}/${CMATE_SOURCE_PAT}) +list(APPEND ${VBASE}_ALL_SOURCES \${${VBASE}_SOURCES}) + +target_sources( + ${TBASE} + PRIVATE + \${${VBASE}_ALL_SOURCES} +) + +target_include_directories( + ${TBASE} + PUBLIC + $ + $ + PRIVATE + \${CMAKE_CURRENT_SOURCE_DIR} +) +" + ) + + cmate_target_link_deps(${TBASE} ${LINK_FILE} DEPS) + string(APPEND CONTENT ${DEPS}) + + string( + APPEND + CONTENT + " +set_target_properties( + ${TBASE} + PROPERTIES + VERSION ${CMATE_PROJECT_VERSION} + SOVERSION ${CMATE_PROJECT_VERSION_MAJOR}.${CMATE_PROJECT_VERSION_MINOR} + EXPORT_NAME ${NAME} + OUTPUT_NAME ${CMATE_PROJECT_NAMESPACE}_${NAME} +) +" + ) + + if(${CMATE_DUMP}) + message(${CONTENT}) + endif() + + file(WRITE ${CM_FILE} ${CONTENT}) +endfunction() + +function(cmate_configure_prog TYPE NAME TBASE SRC_BASE) + string(TOUPPER ${TBASE} VBASE) + + if(${CMATE_DRY_RUN}) + cmate_msg("found ${TYPE} ${NAME} (${SRC_BASE}/${NAME})") + return() + endif() + + set(SDIR "${CMATE_ROOT_DIR}/${SRC_BASE}/${NAME}") + set(CM_FILE "${SDIR}/CMakeLists.txt") + set(LINK_FILE "${SDIR}/${CMATE_LINKFILE}") + file(GLOB_RECURSE SOURCES "${SDIR}/${CMATE_SOURCE_PAT}") + + string(APPEND CONTENT "add_${TYPE}(${TBASE})\n") + + string( + APPEND + CONTENT + " +set(${VBASE}_SRC_DIR \"\${CMAKE_CURRENT_SOURCE_DIR}\") +file(GLOB_RECURSE ${VBASE}_SOURCES \${${VBASE}_SRC_DIR}/${CMATE_SOURCE_PAT}) +list(APPEND ${VBASE}_ALL_SOURCES \${${VBASE}_SOURCES}) + +target_sources( + ${TBASE} + PRIVATE + \${${VBASE}_ALL_SOURCES} +) + +target_include_directories( + ${TBASE} + PRIVATE + \${CMAKE_CURRENT_SOURCE_DIR} +) +" + ) + + cmate_target_link_deps(${TBASE} ${LINK_FILE} DEPS) + string(APPEND CONTENT ${DEPS}) + + string( + APPEND + CONTENT + " +set_target_properties( + ${TBASE} + PROPERTIES + OUTPUT_NAME ${NAME} +) +" + ) + + if(${CMATE_DUMP}) + message(${CONTENT}) + endif() + + file(WRITE ${CM_FILE} ${CONTENT}) +endfunction() + +function(cmate_configure_bin NAME TBASE SRC_BASE) + cmate_configure_prog("executable" ${NAME} ${TBASE} ${SRC_BASE}) +endfunction() + +function(cmate_configure_test NAME TBASE SRC_BASE) + cmate_configure_prog("test" ${NAME} ${TBASE} ${SRC_BASE}) +endfunction() + +function(cmate_configure_project_packages VAR) + # CMake style packages + cmate_load_cmake_package_deps("${CMATE_PACKAGES}" "PRJ") + set(CONTENT "") + + if(PRJ_CMAKE_PACKAGES) + string(APPEND CONTENT "\n") + endif() + + foreach(PKG ${PRJ_CMAKE_PACKAGES}) + if(PRJ_CMAKE_${PKG}_COMPS) + string( + APPEND + CONTENT + "find_package( + ${PKG} CONFIG REQUIRED + COMPONENTS +" + ) + + foreach(PC ${PRJ_CMAKE_${PKG}_COMPS}) + string(APPEND CONTENT " ${PC}\n") + endforeach() + + string(APPEND CONTENT ")\n") + else() + string(APPEND CONTENT "find_package(${PKG} CONFIG REQUIRED)\n") + endif() + endforeach() + + # PkgConfig style packages + cmate_load_pkgconfig_package_deps("${CMATE_PACKAGES}" "PRJ") + + if(PRJ_PKGCONFIG_PACKAGES) + string(APPEND CONTENT "find_package(PkgConfig REQUIRED)\n") + endif() + + foreach(PKG ${PRJ_PKGCONFIG_PACKAGES}) + string( + APPEND + CONTENT + "pkg_check_modules(${PKG} REQUIRED IMPORTED_TARGET ${PKG})\n" + ) + endforeach() + + set(${VAR} ${CONTENT} PARENT_SCOPE) +endfunction() + +function(cmate_configure_project TARGETS SUBDIRS) + if(${CMATE_DRY_RUN}) + return() + endif() + + set(CM_FILE "${CMATE_ROOT_DIR}/CMakeLists.txt") + + string( + APPEND + CONTENT + "cmake_minimum_required(VERSION 3.12 FATAL_ERROR) + +project(${CMATE_PROJECT_NAME} VERSION ${CMATE_PROJECT_VERSION} LANGUAGES C CXX) + +include(GNUInstallDirs) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +" + ) + + cmate_configure_project_packages(PKGS) + + if(PKGS) + string(APPEND CONTENT "${PKGS}") + endif() + + # Target subdirs + if(SUBDIRS) + string(APPEND CONTENT "\n") + + foreach(SUBDIR ${SUBDIRS}) + string(APPEND CONTENT "add_subdirectory(${SUBDIR})\n") + endforeach() + endif() + + string( + APPEND + CONTENT + " +install( + TARGETS" + ) + + foreach(TARGET ${TARGETS}) + string(APPEND CONTENT "\n ${TARGET}") + endforeach() + + string( + APPEND + CONTENT + " + EXPORT ${CMATE_PROJECT_NAME}-config + RUNTIME DESTINATION \${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION \${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION \${CMAKE_INSTALL_LIBDIR} +) + +install( + EXPORT ${CMATE_PROJECT_NAME}-config + FILE ${CMATE_PROJECT_NAME}-config.cmake + NAMESPACE ${CMATE_PROJECT_NAMESPACE}:: + DESTINATION \${CMAKE_INSTALL_LIBDIR}/cmake/${CMATE_PROJECT_NAME} +) +" + ) + + if (IS_DIRECTORY "${CMATE_ROOT_DIR}/include") + foreach(LIB ${CMATE_LIBS}) + string( + APPEND + CONTENT + " +install( + DIRECTORY \"\${PROJECT_SOURCE_DIR}/include/${LIB}/\" + DESTINATION \${CMAKE_INSTALL_INCLUDEDIR}/${CMATE_PROJECT_NAMESPACE} +) +" + ) + endforeach() + endif() + + file(WRITE ${CM_FILE} ${CONTENT}) +endfunction() + +function(cmate_configure) + # Find libraries (libraries have headers) + file(GLOB LIB_INC_DIRS "${CMATE_ROOT_DIR}/include/*") + set(TARGETS "") + set(LIBS "") + set(SUBDIRS "") + + foreach(LIB_INC_DIR ${LIB_INC_DIRS}) + string(REPLACE "${CMATE_ROOT_DIR}/include/" "" NAME ${LIB_INC_DIR}) + cmate_target_name(${NAME} "lib" "TNAME") + cmate_configure_lib(${NAME} ${TNAME} "include" "src/lib") + list(APPEND TARGETS ${TNAME}) + list(APPEND LIBS ${NAME}) + list(APPEND SUBDIRS "src/lib/${NAME}") + endforeach() + + cmate_setg(CMATE_LIBS "${LIBS}") + + # Binaries and tests + foreach(TYPE bin test) + file(GLOB SRC_DIRS "${CMATE_ROOT_DIR}/src/${TYPE}/*") + + foreach(SRC_DIR ${SRC_DIRS}) + string(REPLACE "${CMATE_ROOT_DIR}/src/${TYPE}/" "" NAME ${SRC_DIR}) + cmate_target_name(${NAME} ${TYPE} "TNAME") + cmake_language( + CALL "cmate_configure_${TYPE}" + ${NAME} ${TNAME} "src/${TYPE}" + ) + + if(NOT "${TYPE}" STREQUAL "test") + list(APPEND TARGETS ${TNAME}) + endif() + + list(APPEND SUBDIRS "src/${TYPE}/${NAME}") + endforeach() + endforeach() + + # Top-level project + cmate_configure_project("${TARGETS}" "${SUBDIRS}") + + cmate_state_file("configured" CONFIGURED) + + if(NOT EXISTS ${CONFIGURED}) + set(BUILD_DIR "${CMATE_ROOT_DIR}/build") + set(STAGE_DIR "${CMATE_ROOT_DIR}/stage") + file(MAKE_DIRECTORY ${BUILD_DIR}) + + set(ARGS "") + + if (EXISTS "${CMATE_ENV_DIR}") + list(APPEND ARGS "-DCMAKE_PREFIX_PATH=${CMATE_ENV_DIR}") + endif() + + list(APPEND ARGS "-DCMAKE_INSTALL_PREFIX=${STAGE_DIR}") + list(APPEND ARGS "-DCMAKE_BUILD_TYPE:STRING=Release") + + find_program(CMATE_CCACHE ccache) + + if(CMATE_CCACHE) + list(APPEND ARGS "-DCMAKE_C_COMPILER_LAUNCHER=${CMATE_CCACHE}") + list(APPEND ARGS "-DCMAKE_CXX_COMPILER_LAUNCHER=${CMATE_CCACHE}") + endif() + + find_program(CMATE_NINJA ninja) + + if(CMATE_NINJA) + list(APPEND ARGS "-G" "Ninja") + endif() + + if(CMATE_TOOLCHAIN) + list(APPEND ARGS "--toolchain" "${CMATE_TOOLCHAIN}") + endif() + + list(APPEND ARGS "-S" "${CMATE_ROOT_DIR}") + list(APPEND ARGS "-B" "${BUILD_DIR}") + + execute_process( + COMMAND + ${CMAKE_COMMAND} + ${ARGS} + WORKING_DIRECTORY "${BUILD_DIR}" + RESULTS_VARIABLE RC + ) + + if(RC) + list(JOIN ARGS " " RUN_CMD) + cmate_die("command failed: ${RUN_CMD}") + endif() + + cmate_set_state("configured") + endif() +endfunction() +############################################################################### +# +# Content of cmate/commands/reconfigure.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "reconfigure") +set(CMATE_RECONFIGURE_SHORT_HELP "Clean + configure") +set( + CMATE_RECONFIGURE_HELP + " +Usage: cmate reconfigure + +${CMATE_RECONFIGURE_SHORT_HELP}" +) + +function(cmate_reconfigure) + cmate_clean() + cmate_configure() +endfunction() +############################################################################### +# +# Content of cmate/commands/build.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "build") +set(CMATE_BUILD_SHORT_HELP "Build local project") +set( + CMATE_BUILD_HELP + " +Usage: cmate build + +${CMATE_BUILD_SHORT_HELP}" +) + +function(cmate_build) + cmate_state_file("configured" CONFIGURED) + + if(NOT EXISTS ${CONFIGURED}) + cmate_die("please configure first") + endif() + + set(BUILD_DIR "${CMATE_ROOT_DIR}/build") + set(STAGE_DIR "${CMATE_ROOT_DIR}/stage") + set(ARGS "") + + list(APPEND ARGS "--build" "${BUILD_DIR}") + list(APPEND ARGS "--parallel") + + execute_process( + COMMAND + ${CMAKE_COMMAND} + ${ARGS} + RESULTS_VARIABLE RC + ) + + if(RC) + list(JOIN ARGS " " RUN_CMD) + cmate_die("command failed: ${RUN_CMD}") + endif() +endfunction() +############################################################################### +# +# Content of cmate/commands/rebuild.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "rebuild") +set(CMATE_REBUILD_SHORT_HELP "Reconfigure + build") +set( + CMATE_REBUILD_HELP + " +Usage: cmate rebuild + +${CMATE_REBUILD_SHORT_HELP}" +) + +function(cmate_rebuild) + cmate_reconfigure() + cmate_build() +endfunction() +############################################################################### +# +# Content of cmate/commands/stage.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "stage") +set(CMATE_STAGE_SHORT_HELP "Stage local project") +set( + CMATE_STAGE_HELP + " +Usage: cmate stage + +${CMATE_STAGE_SHORT_HELP}" +) + +function(cmate_stage) + set(BUILD_DIR "${CMATE_ROOT_DIR}/build") + set(ARGS "") + + list(APPEND ARGS "--install" "${BUILD_DIR}") + + execute_process( + COMMAND + ${CMAKE_COMMAND} + ${ARGS} + RESULTS_VARIABLE RC + ) + + if(RC) + list(JOIN ARGS " " RUN_CMD) + cmate_die("command failed: ${RUN_CMD}") + endif() +endfunction() +############################################################################### +# +# Content of cmate/commands/clean.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "clean") +set(CMATE_CLEAN_SHORT_HELP "Clean local project") +set( + CMATE_CLEAN_HELP + " +Usage: cmate clean + +${CMATE_CLEAN_SHORT_HELP} + +Options: + --purge Remove everything: cenv, dependencies, ..." +) + +function(cmate_clean) + set(DIRS "BUILD" "STAGE" "STATE") + + if(${CMATE_CLEAN_PURGE}) + list(APPEND DIRS "ENV" "DEPS") + endif() + + foreach(DIR ${DIRS}) + set(DVAR "CMATE_${DIR}_DIR") + + if (IS_DIRECTORY ${${DVAR}}) + cmate_msg("cleaning: ${${DVAR}}") + file(REMOVE_RECURSE ${${DVAR}}) + endif() + endforeach() +endfunction() +############################################################################### +# +# Content of cmate/commands/update.cmake +# +############################################################################### +list(APPEND CMATE_CMDS "update") +set(CMATE_UPDATE_SHORT_HELP "Update dependencies listed in deps.txt") +set( + CMATE_UPDATE_HELP + " +Usage: cmate update + +${CMATE_UPDATE_SHORT_HELP}" +) + +function(cmate_update_cmake_dep) + cmate_dep_state_file("configured" CONFIGURED) + cmate_dep_state_file("built" BUILT) + cmate_dep_state_file("installed" INSTALLED) + + if(NOT EXISTS ${CONFIGURED}) + cmate_msg("building with: ${ARGV}") + + set(ARGS "") + + find_program(CMATE_CCACHE ccache) + + if(CMATE_CCACHE) + list(APPEND ARGS "-DCMAKE_C_COMPILER_LAUNCHER=${CMATE_CCACHE}") + list(APPEND ARGS "-DCMAKE_CXX_COMPILER_LAUNCHER=${CMATE_CCACHE}") + endif() + + find_program(CMATE_NINJA ninja) + + if(CMATE_NINJA) + list(APPEND ARGS "-G" "Ninja") + endif() + + cmate_run_prog( + CMD + ${CMAKE_COMMAND} + -DCMAKE_PREFIX_PATH=${CMATE_ENV_DIR} + -DCMAKE_INSTALL_PREFIX=${CMATE_ENV_DIR} + -DCMAKE_BUILD_TYPE:STRING=Release + ${ARGS} + -S ${CMATE_DEP_SOURCE_DIR} -B ${CMATE_DEP_BUILD_DIR} + ${ARGV} + ) + cmate_dep_set_state("configured") + endif() + if(NOT EXISTS ${BUILT}) + cmate_run_prog( + CMD + ${CMAKE_COMMAND} + --build ${CMATE_DEP_BUILD_DIR} + --parallel + ) + cmate_dep_set_state("built") + endif() + if(NOT EXISTS ${INSTALLED}) + cmate_run_prog(CMD ${CMAKE_COMMAND} --install ${CMATE_DEP_BUILD_DIR}) + cmate_dep_set_state("installed") + endif() +endfunction() + +function(cmate_update_meson_dep) + cmate_dep_state_file("configured" CONFIGURED) + cmate_dep_state_file("installed" INSTALLED) + file(MAKE_DIRECTORY ${CMATE_DEP_BUILD_DIR}) + + if(NOT EXISTS ${CONFIGURED}) + cmate_run_prog( + DIR ${CMATE_DEP_BUILD_DIR} + CMD + meson + --prefix=${CMATE_ENV_DIR} + --pkg-config-path=${CMATE_ENV_DIR} + --cmake-prefix-path=${CMATE_ENV_DIR} + ${ARGV} + . ${SRCDIR} + ) + cmate_dep_set_state("configured") + endif() + if(NOT EXISTS ${INSTALLED}) + cmate_run_prog(meson install) + cmate_dep_set_state("installed") + endif() +endfunction() + +function(cmate_update_autotools_dep) + cmate_dep_state_file("configured" CONFIGURED) + cmate_dep_state_file("installed" INSTALLED) + file(MAKE_DIRECTORY ${CMATE_DEP_BUILD_DIR}) + + if(NOT EXISTS ${CONFIGURED}) + cmate_run_prog( + DIR ${CMATE_DEP_BUILD_DIR} + CMD + ${CMATE_DEP_SOURCE_DIR}/configure + --prefix=${CMATE_ENV_DIR} + ${ARGV} + ) + cmate_dep_set_state("configured") + endif() + if(NOT EXISTS ${INSTALLED}) + cmate_run_prog( + DIR ${CMATE_DEP_BUILD_DIR} + CMD make install + ) + cmate_dep_set_state("installed") + endif() +endfunction() + +function(cmate_update_makefile_dep) + cmate_dep_state_file("built" BUILT) + cmate_dep_state_file("installed" INSTALLED) + file(MAKE_DIRECTORY ${CMATE_DEP_BUILD_DIR}) + + if(NOT EXISTS ${BUILT}) + cmate_run_prog( + DIR ${CMATE_DEP_SOURCE_DIR} + CMD make + ) + cmate_dep_set_state("built") + endif() + if(NOT EXISTS ${INSTALLED}) + cmate_run_prog( + DIR ${CMATE_DEP_SOURCE_DIR} + CMD make prefix=${CMATE_ENV_DIR} install + ) + cmate_dep_set_state("installed") + endif() +endfunction() + +function(cmate_update_dep ARGS) + set(OPT_PROC ON) + string(REGEX MATCHALL "[^ \"']+|\"([^\"]*)\"|'([^']*)'" ARGS "${ARGS}") + + foreach(ARG ${ARGS}) + if(OPT_PROC AND ARG MATCHES "^--") + if(ARG STREQUAL "--") + set(OPT_PROC OFF) + elseif(ARG MATCHES "^--srcdir=(.+)") + cmate_setg( + CMATE_DEP_SOURCE_DIR + "${CMATE_DEP_SOURCE_DIR}/${CMAKE_MATCH_1}" + ) + endif() + else() + list(APPEND CONF_ARGS ${ARG}) + endif() + endforeach() + + if(NOT IS_DIRECTORY "${CMATE_DEP_SOURCE_DIR}") + cmate_die("invalid source directory: ${CMATE_DEP_SOURCE_DIR}") + endif() + + if(EXISTS "${CMATE_DEP_SOURCE_DIR}/CMakeLists.txt") + cmate_update_cmake_dep(${CONF_ARGS}) + elseif(EXISTS "${CMATE_DEP_SOURCE_DIR}/meson.build") + cmate_update_meson_dep(${CONF_ARGS}) + elseif(EXISTS "${CMATE_DEP_SOURCE_DIR}/configure") + cmate_update_autotools_dep(${CONF_ARGS}) + elseif(EXISTS "${CMATE_DEP_SOURCE_DIR}/Makefile") + cmate_update_makefile_dep(${CONF_ARGS}) + else() + cmate_die("don't know how to build in ${CMATE_DEP_SOURCE_DIR}") + endif() +endfunction() + +function(cmate_update_repo HOST REPO TAG ARGS) + cmate_dep_get_repo(${HOST} ${REPO} "${TAG}") + cmate_update_dep("${ARGS}") +endfunction() + +function(cmate_update_url URL ARGS) + cmate_deps_get_url(${URL}) + cmate_update_dep("${ARGS}") +endfunction() + +function(cmate_update) + if(NOT EXISTS ${CMATE_DEPSFILE}) + cmate_msg("no dependencies") + return() + endif() + + file(STRINGS ${CMATE_DEPSFILE} DEPS) + + foreach(SPEC ${DEPS}) + if(SPEC MATCHES "^#") + # Skip comments + continue() + elseif(SPEC MATCHES "^([A-Za-z0-9_-]+)=(.+)$") + # Variable assignment + cmate_setg("CMATE_${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}") + elseif(SPEC MATCHES "^([a-z]+://[^ ]+)([ ](.+))?$") + # URL + set(URL ${CMAKE_MATCH_1}) + set(ARGS "${CMAKE_MATCH_3}") + cmate_msg("checking ${URL}") + cmate_update_url(${URL} "${ARGS}") + elseif(SPEC MATCHES "^(([^: ]+):)?([^@ ]+)(@([^ ]+))?([ ](.+))?$") + # GitHub/GitLab style project short ref + if(CMAKE_MATCH_2) + if(CMATE_${CMAKE_MATCH_2}) + set(HOST ${CMATE_${CMAKE_MATCH_2}}) + else() + cmate_die("unknown id: ${CMAKE_MATCH_2}") + endif() + else() + set(HOST ${CMATE_${CMATE_GIT_HOST}}) + endif() + + set(REPO ${CMAKE_MATCH_3}) + set(TAG ${CMAKE_MATCH_5}) + set(ARGS "${CMAKE_MATCH_7}") + cmate_msg("checking ${REPO}") + cmate_update_repo(${HOST} ${REPO} "${TAG}" "${ARGS}") + else() + cmate_die("invalid dependency line: ${SPEC}") + endif() + endforeach() +endfunction() +############################################################################### +# +# Content of cmate/commands/help.cmake +# +############################################################################### +set(CMATE_HELP_HEADER "CMate v${CMATE_VER}") +list(APPEND CMATE_CMDS "help") + +list( + APPEND + CMATE_OPTIONS + "verbose" +) + +function(cmate_build_help VAR) + set( + CMATE_HELP_PRE + " +Usage: cmate [OPTIONS] COMMAND + +Options: + --verbose Verbose operation + +Commands: +" + ) + set( + CMATE_HELP_POST + "See 'cmate help ' to read about a specific subcommand." + ) + set(LENGTH 0) + string(APPEND HELP ${CMATE_HELP_PRE}) + + foreach(CMD ${CMATE_CMDS}) + string(LENGTH "${CMD}" CL) + + if(CL GREATER ${LENGTH}) + set(LENGTH ${CL}) + endif() + endforeach() + + foreach(CMD ${CMATE_CMDS}) + string(LENGTH "${CMD}" CL) + math(EXPR PAD "${LENGTH}-${CL}") + string(TOUPPER ${CMD} UCMD) + set(CHVAR "CMATE_${UCMD}_SHORT_HELP") + + string(REPEAT " " ${PAD} CPAD) + string(APPEND HELP " ${CMD}${CPAD} ${${CHVAR}}\n") + endforeach() + + string(APPEND HELP "\n${CMATE_HELP_POST}") + set(${VAR} ${HELP} PARENT_SCOPE) +endfunction() + +function(cmate_help) + set(HVAR "CMATE") + if(CMATE_ARGC GREATER 0) + # Sub command help + list(GET CMATE_ARGS 0 HCMD) + + if(${HCMD} IN_LIST CMATE_CMDS) + string(TOUPPER "${HCMD}" HCMD) + string(APPEND HVAR "_${HCMD}_HELP") + set(HELP ${${HVAR}}) + else() + cmate_die("no such command: ${HCMD}") + endif() + else() + # Global help + cmate_build_help("HELP") + endif() + + string(CONFIGURE ${HELP} HELP) + + message("${CMATE_HELP_HEADER}") + message(${HELP}) +endfunction() + +############################################################################## +# +# Target common functions +# +############################################################################## + + +############################################################################## +# +# Configuration functions +# +############################################################################## +function(cmate_set_defaults) + get_filename_component(DIR "." ABSOLUTE) + cmate_setg(CMATE_ROOT_DIR ${DIR}) + + get_filename_component(DIR ".cenv" ABSOLUTE) + cmate_setg(CMATE_ENV_DIR ${DIR}) + + get_filename_component(DIR ".cmate" ABSOLUTE) + cmate_setg(CMATE_HOME_DIR ${DIR}) + cmate_setg(CMATE_DEPS_DIR "${CMATE_HOME_DIR}/deps") + cmate_setg(CMATE_STATE_DIR "${CMATE_HOME_DIR}/state") + cmate_setg(CMATE_TOOLCHAINS_DIR "${CMATE_HOME_DIR}/toolchains") + + cmate_setg(CMATE_BUILD_DIR "${CMATE_ROOT_DIR}/build") + cmate_setg(CMATE_STAGE_DIR "${CMATE_ROOT_DIR}/stage") + + cmate_setg(CMATE_HEADER_PAT "*.hpp") + cmate_setg(CMATE_SOURCE_PAT "*.[ch]pp") +endfunction() + +############################################################################## +# +# Command processing +# +############################################################################## +function(cmate_process_cmd) + if (CMATE_CMD STREQUAL "version") + message(${CMATE_VERSION}) + elseif (CMATE_CMD) + set(CMATE_COMMAND "cmate_${CMATE_CMD}") + + if(COMMAND "${CMATE_COMMAND}") + cmake_language(CALL ${CMATE_COMMAND}) + else() + cmate_msg("unknown command: ${CMATE_CMD}") + endif() + else() + cmate_msg("no command") + endif() +endfunction() + +############################################################################## +# +# Main part +# +############################################################################## +if(CMAKE_SCRIPT_MODE_FILE) + cmate_set_defaults() + cmate_parse_arguments() + cmate_load_conf("${CMATE_ROOT_DIR}/${CMATE_PRJFILE}") + cmate_process_cmd() +endif() diff --git a/cpp/deps.txt b/cpp/deps.txt index 3800d82aa..268b6aa96 100644 --- a/cpp/deps.txt +++ b/cpp/deps.txt @@ -1,2 +1,2 @@ -https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.zip -DJSON_BuildTests=OFF -https://github.com/cucumber/messages/archive/refs/tags/v24.0.1.zip --src-dir=cpp +nlohmann/json@v3.11.3 -DJSON_BuildTests=OFF +cucumber/messages --srcdir=cpp \ No newline at end of file diff --git a/cpp/include/gherkin/app.hpp b/cpp/include/gherkin/cucumber/gherkin/app.hpp similarity index 70% rename from cpp/include/gherkin/app.hpp rename to cpp/include/gherkin/cucumber/gherkin/app.hpp index a9f254936..8eb4ef5d2 100644 --- a/cpp/include/gherkin/app.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/app.hpp @@ -2,19 +2,19 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { class app { public: - using parser = gherkin::parser<>; + using parser = cucumber::gherkin::parser<>; using parser_result = typename parser::result_type; - using callbacks = gherkin::callbacks; + using callbacks = cucumber::gherkin::callbacks; app(); virtual ~app(); diff --git a/cpp/include/gherkin/ast_builder.hpp b/cpp/include/gherkin/cucumber/gherkin/ast_builder.hpp similarity index 91% rename from cpp/include/gherkin/ast_builder.hpp rename to cpp/include/gherkin/cucumber/gherkin/ast_builder.hpp index a63dabeac..a8263025e 100644 --- a/cpp/include/gherkin/ast_builder.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/ast_builder.hpp @@ -7,12 +7,12 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; diff --git a/cpp/include/gherkin/ast_node.hpp b/cpp/include/gherkin/cucumber/gherkin/ast_node.hpp similarity index 92% rename from cpp/include/gherkin/ast_node.hpp rename to cpp/include/gherkin/cucumber/gherkin/ast_node.hpp index eb282c30a..8fba04b98 100644 --- a/cpp/include/gherkin/ast_node.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/ast_node.hpp @@ -8,11 +8,11 @@ #include #include -#include -#include -#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { template struct sub_node @@ -120,7 +120,7 @@ class ast_node { using type = std::decay_t; - if constexpr (is_container_v) { + if constexpr (is_specialization_of_v) { using value_type = typename type::value_type; using vector_type = std::vector; @@ -147,7 +147,7 @@ class ast_node { using type = std::decay_t; - if constexpr (is_container_v) { + if constexpr (is_specialization_of_v) { using value_type = typename type::value_type; set_value(rule_type, v); diff --git a/cpp/include/gherkin/builder.hpp b/cpp/include/gherkin/cucumber/gherkin/builder.hpp similarity index 85% rename from cpp/include/gherkin/builder.hpp rename to cpp/include/gherkin/cucumber/gherkin/builder.hpp index cba657c00..ef7de3ca3 100644 --- a/cpp/include/gherkin/builder.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/builder.hpp @@ -3,10 +3,10 @@ #include #include -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { template struct builder diff --git a/cpp/include/gherkin/cb_types.hpp b/cpp/include/gherkin/cucumber/gherkin/cb_types.hpp similarity index 84% rename from cpp/include/gherkin/cb_types.hpp rename to cpp/include/gherkin/cucumber/gherkin/cb_types.hpp index ec53e2af0..31810d8ce 100644 --- a/cpp/include/gherkin/cb_types.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/cb_types.hpp @@ -7,9 +7,9 @@ #include #include -#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; @@ -22,9 +22,9 @@ struct callbacks { using ast_cb = std::function; - gherkin::source_cb source; + source_cb source; ast_cb ast; - gherkin::pickle_cb pickle; + pickle_cb pickle; error_cb error; }; diff --git a/cpp/include/gherkin/container_helpers.hpp b/cpp/include/gherkin/cucumber/gherkin/container_helpers.hpp similarity index 97% rename from cpp/include/gherkin/container_helpers.hpp rename to cpp/include/gherkin/cucumber/gherkin/container_helpers.hpp index feceb9dd9..0b4867f0b 100644 --- a/cpp/include/gherkin/container_helpers.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/container_helpers.hpp @@ -4,7 +4,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { template struct is_vector : public std::false_type{}; diff --git a/cpp/include/gherkin/demangle.hpp b/cpp/include/gherkin/cucumber/gherkin/demangle.hpp similarity index 91% rename from cpp/include/gherkin/demangle.hpp rename to cpp/include/gherkin/cucumber/gherkin/demangle.hpp index d6f2b2f6c..fe4630801 100644 --- a/cpp/include/gherkin/demangle.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/demangle.hpp @@ -3,7 +3,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { namespace detail { diff --git a/cpp/include/gherkin/dialect.hpp b/cpp/include/gherkin/cucumber/gherkin/dialect.hpp similarity index 91% rename from cpp/include/gherkin/dialect.hpp rename to cpp/include/gherkin/cucumber/gherkin/dialect.hpp index b7d59d4aa..ab0b917f2 100644 --- a/cpp/include/gherkin/dialect.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/dialect.hpp @@ -1,8 +1,8 @@ #pragma once -#include +#include -namespace gherkin { +namespace cucumber::gherkin { using keywords_map = std::unordered_map; using keywords_maps = std::unordered_map; diff --git a/cpp/include/gherkin/exceptions.hpp b/cpp/include/gherkin/cucumber/gherkin/exceptions.hpp similarity index 95% rename from cpp/include/gherkin/exceptions.hpp rename to cpp/include/gherkin/cucumber/gherkin/exceptions.hpp index 770547936..f715dc06a 100644 --- a/cpp/include/gherkin/exceptions.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/exceptions.hpp @@ -5,10 +5,10 @@ #include -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; diff --git a/cpp/include/gherkin/file.hpp b/cpp/include/gherkin/cucumber/gherkin/file.hpp similarity index 71% rename from cpp/include/gherkin/file.hpp rename to cpp/include/gherkin/cucumber/gherkin/file.hpp index e616e0c6c..9cb3ead90 100644 --- a/cpp/include/gherkin/file.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/file.hpp @@ -2,7 +2,7 @@ #include -namespace gherkin { +namespace cucumber::gherkin { struct file { diff --git a/cpp/include/gherkin/id_generator.hpp b/cpp/include/gherkin/cucumber/gherkin/id_generator.hpp similarity index 95% rename from cpp/include/gherkin/id_generator.hpp rename to cpp/include/gherkin/cucumber/gherkin/id_generator.hpp index 5e7941d55..1be437412 100644 --- a/cpp/include/gherkin/id_generator.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/id_generator.hpp @@ -3,7 +3,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { class id_generator_base { diff --git a/cpp/include/gherkin/items.hpp b/cpp/include/gherkin/cucumber/gherkin/items.hpp similarity index 81% rename from cpp/include/gherkin/items.hpp rename to cpp/include/gherkin/cucumber/gherkin/items.hpp index 8b01b5144..ff60ddfa6 100644 --- a/cpp/include/gherkin/items.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/items.hpp @@ -2,7 +2,7 @@ #include -namespace gherkin { +namespace cucumber::gherkin { struct item { diff --git a/cpp/include/gherkin/join_utils.hpp b/cpp/include/gherkin/cucumber/gherkin/join_utils.hpp similarity index 95% rename from cpp/include/gherkin/join_utils.hpp rename to cpp/include/gherkin/cucumber/gherkin/join_utils.hpp index fdc4cca96..1e91cbdd8 100644 --- a/cpp/include/gherkin/join_utils.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/join_utils.hpp @@ -3,9 +3,9 @@ #include #include -#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace detail { diff --git a/cpp/include/gherkin/keywords.hpp b/cpp/include/gherkin/cucumber/gherkin/keywords.hpp similarity index 77% rename from cpp/include/gherkin/keywords.hpp rename to cpp/include/gherkin/cucumber/gherkin/keywords.hpp index 13a011d32..b3faef207 100644 --- a/cpp/include/gherkin/keywords.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/keywords.hpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { const string_views& keywords(const std::string_view& language, const std::string_view& kw); diff --git a/cpp/include/gherkin/line.hpp b/cpp/include/gherkin/cucumber/gherkin/line.hpp similarity index 88% rename from cpp/include/gherkin/line.hpp rename to cpp/include/gherkin/cucumber/gherkin/line.hpp index 727129b63..5d4c6faf5 100644 --- a/cpp/include/gherkin/line.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/line.hpp @@ -2,10 +2,10 @@ #include -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { class line { diff --git a/cpp/include/gherkin/log.hpp b/cpp/include/gherkin/cucumber/gherkin/log.hpp similarity index 97% rename from cpp/include/gherkin/log.hpp rename to cpp/include/gherkin/cucumber/gherkin/log.hpp index fa0a0670b..9dd8d8984 100644 --- a/cpp/include/gherkin/log.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/log.hpp @@ -4,7 +4,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { template std::string diff --git a/cpp/include/gherkin/msg_types.hpp b/cpp/include/gherkin/cucumber/gherkin/msg_types.hpp similarity index 94% rename from cpp/include/gherkin/msg_types.hpp rename to cpp/include/gherkin/cucumber/gherkin/msg_types.hpp index 0e755ce3b..ac15d3c5e 100644 --- a/cpp/include/gherkin/msg_types.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/msg_types.hpp @@ -4,7 +4,7 @@ #include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; diff --git a/cpp/include/gherkin/parse_error.hpp b/cpp/include/gherkin/cucumber/gherkin/parse_error.hpp similarity index 90% rename from cpp/include/gherkin/parse_error.hpp rename to cpp/include/gherkin/cucumber/gherkin/parse_error.hpp index aaddf2605..8f044c9f4 100644 --- a/cpp/include/gherkin/parse_error.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/parse_error.hpp @@ -6,7 +6,7 @@ #include -namespace gherkin { +namespace cucumber::gherkin { using json = nlohmann::json; namespace cms = cucumber::messages; diff --git a/cpp/include/gherkin/parser.hpp b/cpp/include/gherkin/cucumber/gherkin/parser.hpp similarity index 99% rename from cpp/include/gherkin/parser.hpp rename to cpp/include/gherkin/cucumber/gherkin/parser.hpp index 127a96483..340de1a02 100644 --- a/cpp/include/gherkin/parser.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/parser.hpp @@ -1,8 +1,8 @@ // This file is generated. Do not edit! Edit gherkin-cpp-parser.razor instead. -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { template < typename Builder = ast_builder, diff --git a/cpp/include/gherkin/parser_base.hpp b/cpp/include/gherkin/cucumber/gherkin/parser_base.hpp similarity index 82% rename from cpp/include/gherkin/parser_base.hpp rename to cpp/include/gherkin/cucumber/gherkin/parser_base.hpp index 68afa814a..4f1f65d91 100644 --- a/cpp/include/gherkin/parser_base.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/parser_base.hpp @@ -4,13 +4,13 @@ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; diff --git a/cpp/include/gherkin/parser_context.hpp b/cpp/include/gherkin/cucumber/gherkin/parser_context.hpp similarity index 85% rename from cpp/include/gherkin/parser_context.hpp rename to cpp/include/gherkin/cucumber/gherkin/parser_context.hpp index 2fd0cdb8c..9631f3b36 100644 --- a/cpp/include/gherkin/parser_context.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/parser_context.hpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { template < typename Builder, diff --git a/cpp/include/gherkin/parser_info.hpp b/cpp/include/gherkin/cucumber/gherkin/parser_info.hpp similarity index 87% rename from cpp/include/gherkin/parser_info.hpp rename to cpp/include/gherkin/cucumber/gherkin/parser_info.hpp index 0ef64b5b5..865b58ead 100644 --- a/cpp/include/gherkin/parser_info.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/parser_info.hpp @@ -3,7 +3,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { using id_generator_func = std::function; diff --git a/cpp/include/gherkin/pickle_compiler.hpp b/cpp/include/gherkin/cucumber/gherkin/pickle_compiler.hpp similarity index 89% rename from cpp/include/gherkin/pickle_compiler.hpp rename to cpp/include/gherkin/cucumber/gherkin/pickle_compiler.hpp index b471ab01c..0f5478923 100644 --- a/cpp/include/gherkin/pickle_compiler.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/pickle_compiler.hpp @@ -2,13 +2,13 @@ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { class pickle_compiler { diff --git a/cpp/include/gherkin/pickle_compiler_context.hpp b/cpp/include/gherkin/cucumber/gherkin/pickle_compiler_context.hpp similarity index 54% rename from cpp/include/gherkin/pickle_compiler_context.hpp rename to cpp/include/gherkin/cucumber/gherkin/pickle_compiler_context.hpp index 7f8600107..c1d6c19d9 100644 --- a/cpp/include/gherkin/pickle_compiler_context.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/pickle_compiler_context.hpp @@ -3,11 +3,11 @@ #include #include -#include -#include -#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { struct pickle_compiler_context { @@ -17,7 +17,7 @@ struct pickle_compiler_context id_generator_ptr idp; pickle_cb sink; - gherkin::pickles pickles; + cucumber::gherkin::pickles pickles; std::size_t id_counter_ = 0; }; diff --git a/cpp/include/gherkin/regex.hpp b/cpp/include/gherkin/cucumber/gherkin/regex.hpp similarity index 95% rename from cpp/include/gherkin/regex.hpp rename to cpp/include/gherkin/cucumber/gherkin/regex.hpp index e17c9dd4c..4f0acbc09 100644 --- a/cpp/include/gherkin/regex.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/regex.hpp @@ -3,12 +3,12 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { struct regex_result { diff --git a/cpp/include/gherkin/rule_type.hpp b/cpp/include/gherkin/cucumber/gherkin/rule_type.hpp similarity index 96% rename from cpp/include/gherkin/rule_type.hpp rename to cpp/include/gherkin/cucumber/gherkin/rule_type.hpp index 2a56400c3..2f07b3aad 100644 --- a/cpp/include/gherkin/rule_type.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/rule_type.hpp @@ -4,7 +4,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { enum class rule_type { diff --git a/cpp/include/gherkin/sink.hpp b/cpp/include/gherkin/cucumber/gherkin/sink.hpp similarity index 83% rename from cpp/include/gherkin/sink.hpp rename to cpp/include/gherkin/cucumber/gherkin/sink.hpp index fff214e0e..2eaf68dd8 100644 --- a/cpp/include/gherkin/sink.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/sink.hpp @@ -3,7 +3,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { using json = nlohmann::json; diff --git a/cpp/include/gherkin/token.hpp b/cpp/include/gherkin/cucumber/gherkin/token.hpp similarity index 76% rename from cpp/include/gherkin/token.hpp rename to cpp/include/gherkin/cucumber/gherkin/token.hpp index 99e156776..d96d00788 100644 --- a/cpp/include/gherkin/token.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/token.hpp @@ -9,23 +9,23 @@ #include #include -#include -#include -#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; struct token { bool eof = false; - gherkin::line line; + cucumber::gherkin::line line; rule_type matched_type; std::optional matched_keyword; std::optional matched_keyword_type; std::size_t matched_indent = 0; - gherkin::items matched_items; + cucumber::gherkin::items matched_items; std::string matched_text; std::string matched_gherkin_dialect; cms::location location; diff --git a/cpp/include/gherkin/token_formatter_builder.hpp b/cpp/include/gherkin/cucumber/gherkin/token_formatter_builder.hpp similarity index 79% rename from cpp/include/gherkin/token_formatter_builder.hpp rename to cpp/include/gherkin/cucumber/gherkin/token_formatter_builder.hpp index db1c50cf8..209f73f57 100644 --- a/cpp/include/gherkin/token_formatter_builder.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/token_formatter_builder.hpp @@ -2,12 +2,12 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace cms = cucumber::messages; diff --git a/cpp/include/gherkin/token_matcher.hpp b/cpp/include/gherkin/cucumber/gherkin/token_matcher.hpp similarity index 90% rename from cpp/include/gherkin/token_matcher.hpp rename to cpp/include/gherkin/cucumber/gherkin/token_matcher.hpp index 8421d91ec..60ec70051 100644 --- a/cpp/include/gherkin/token_matcher.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/token_matcher.hpp @@ -5,12 +5,12 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { using keyword_types = std::vector; using keyword_types_map = std::unordered_map; @@ -57,7 +57,7 @@ class token_matcher std::optional keyword; std::optional keyword_type; std::optional indent; - gherkin::items items; + cucumber::gherkin::items items; }; void set_token_matched( diff --git a/cpp/include/gherkin/token_scanner.hpp b/cpp/include/gherkin/cucumber/gherkin/token_scanner.hpp similarity index 84% rename from cpp/include/gherkin/token_scanner.hpp rename to cpp/include/gherkin/cucumber/gherkin/token_scanner.hpp index 514f0fa1d..638d66704 100644 --- a/cpp/include/gherkin/token_scanner.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/token_scanner.hpp @@ -3,11 +3,11 @@ #include #include -#include -#include -#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { struct next_line_result { diff --git a/cpp/include/gherkin/cucumber/gherkin/type_traits.hpp b/cpp/include/gherkin/cucumber/gherkin/type_traits.hpp new file mode 100644 index 000000000..3694690e1 --- /dev/null +++ b/cpp/include/gherkin/cucumber/gherkin/type_traits.hpp @@ -0,0 +1,32 @@ +#include + +namespace cucumber::gherkin { + +template < + typename T, + template typename Primary +> +struct is_specialization_of : std::false_type {}; + +template < + template typename Primary, + typename... Args +> +struct is_specialization_of, Primary> : std::true_type {}; + +template < + typename T, + template class Primary +> +using +is_specialization_of_t = is_specialization_of; + +template < + typename T, + template class Primary +> +inline +constexpr bool +is_specialization_of_v = is_specialization_of_t::value; + +} diff --git a/cpp/include/gherkin/types.hpp b/cpp/include/gherkin/cucumber/gherkin/types.hpp similarity index 94% rename from cpp/include/gherkin/types.hpp rename to cpp/include/gherkin/cucumber/gherkin/types.hpp index c6d975fa5..80e821f44 100644 --- a/cpp/include/gherkin/types.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/types.hpp @@ -6,7 +6,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { using strings = std::vector; using strings_map = std::unordered_map; diff --git a/cpp/include/gherkin/utils.hpp b/cpp/include/gherkin/cucumber/gherkin/utils.hpp similarity index 99% rename from cpp/include/gherkin/utils.hpp rename to cpp/include/gherkin/cucumber/gherkin/utils.hpp index a9c53e492..4161b00cf 100644 --- a/cpp/include/gherkin/utils.hpp +++ b/cpp/include/gherkin/cucumber/gherkin/utils.hpp @@ -5,7 +5,7 @@ #include #include -namespace gherkin { +namespace cucumber::gherkin { // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert template diff --git a/cpp/include/gherkin/type_traits.hpp b/cpp/include/gherkin/type_traits.hpp deleted file mode 100644 index 34bf5667d..000000000 --- a/cpp/include/gherkin/type_traits.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#include - -namespace gherkin { - -namespace detail { - -template < - template class Container, - template class Other, - typename T -> -std::is_same, Other> -test_is_container(Other*); - -template < - template class Container, - typename T -> -std::false_type test_is_container(T*); - -} // namespace detail - -template < - template class C, - typename T -> -using is_container = decltype( - detail::test_is_container(static_cast(nullptr)) -); - -template < - template class C, - typename T -> -inline -constexpr bool is_container_v = is_container::value; - -} diff --git a/cpp/project.json b/cpp/project.json new file mode 100644 index 000000000..15f29f6a5 --- /dev/null +++ b/cpp/project.json @@ -0,0 +1,11 @@ +{ + "name": "cucumber_gherkin", + "version": "0.1.0", + "namespace": "cucumber", + "packages": { + "cmake": [ + "nlohmann_json", + "cucumber_messages" + ] + } +} diff --git a/cpp/src/bin/gherkin-generate-tokens/CMakeLists.txt b/cpp/src/bin/gherkin-generate-tokens/CMakeLists.txt index 8060f2dcb..ecfbe488c 100644 --- a/cpp/src/bin/gherkin-generate-tokens/CMakeLists.txt +++ b/cpp/src/bin/gherkin-generate-tokens/CMakeLists.txt @@ -1,26 +1,29 @@ -add_executable(gherkin-generate-tokens-bin) +add_executable(cucumber_gherkin_generate_tokens_bin) + +set(CUCUMBER_GHERKIN_GENERATE_TOKENS_BIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +file(GLOB_RECURSE CUCUMBER_GHERKIN_GENERATE_TOKENS_BIN_SOURCES ${CUCUMBER_GHERKIN_GENERATE_TOKENS_BIN_SRC_DIR}/*.[ch]pp) +list(APPEND CUCUMBER_GHERKIN_GENERATE_TOKENS_BIN_ALL_SOURCES ${CUCUMBER_GHERKIN_GENERATE_TOKENS_BIN_SOURCES}) target_sources( - gherkin-generate-tokens-bin + cucumber_gherkin_generate_tokens_bin PRIVATE - ${CMAKE_SOURCE_DIR}/src/bin/gherkin-generate-tokens/gherkin-generate-tokens.cpp + ${CUCUMBER_GHERKIN_GENERATE_TOKENS_BIN_ALL_SOURCES} ) target_include_directories( - gherkin-generate-tokens-bin + cucumber_gherkin_generate_tokens_bin PRIVATE - ${CMAKE_SOURCE_DIR}/ - ${CMAKE_SOURCE_DIR}/src/bin/gherkin-generate-tokens + ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries( - gherkin-generate-tokens-bin + cucumber_gherkin_generate_tokens_bin PUBLIC - gherkin-cpp + cucumber::gherkin ) set_target_properties( - gherkin-generate-tokens-bin + cucumber_gherkin_generate_tokens_bin PROPERTIES - OUTPUT_NAME gherkin-generate-tokens + OUTPUT_NAME gherkin-generate-tokens ) diff --git a/cpp/src/bin/gherkin-generate-tokens/gherkin-generate-tokens.cpp b/cpp/src/bin/gherkin-generate-tokens/gherkin-generate-tokens.cpp index 3c265c953..f25cd466b 100644 --- a/cpp/src/bin/gherkin-generate-tokens/gherkin-generate-tokens.cpp +++ b/cpp/src/bin/gherkin-generate-tokens/gherkin-generate-tokens.cpp @@ -1,26 +1,26 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include int main(int ac, char** av) { - using builder = gherkin::token_formatter_builder; - using parser = gherkin::parser; + using builder = cucumber::gherkin::token_formatter_builder; + using parser = cucumber::gherkin::parser; parser p; for (std::size_t i = 1; i < ac; ++i) { std::string file(av[i]); - auto data = gherkin::slurp(file); + auto data = cucumber::gherkin::slurp(file); auto ss = p.parse(file, data); - std::cout << gherkin::join("\n", ss); + std::cout << cucumber::gherkin::join("\n", ss); } std::cout << std::endl; diff --git a/cpp/src/bin/gherkin-generate-tokens/link.json b/cpp/src/bin/gherkin-generate-tokens/link.json new file mode 100644 index 000000000..c0bb75fe8 --- /dev/null +++ b/cpp/src/bin/gherkin-generate-tokens/link.json @@ -0,0 +1,7 @@ +{ + "libs": { + "public": [ + "cucumber::gherkin" + ] + } +} diff --git a/cpp/src/bin/gherkin/CMakeLists.txt b/cpp/src/bin/gherkin/CMakeLists.txt index a20251a90..1f8edfc0b 100644 --- a/cpp/src/bin/gherkin/CMakeLists.txt +++ b/cpp/src/bin/gherkin/CMakeLists.txt @@ -1,26 +1,29 @@ -add_executable(gherkin-bin) +add_executable(cucumber_gherkin_bin) + +set(CUCUMBER_GHERKIN_BIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +file(GLOB_RECURSE CUCUMBER_GHERKIN_BIN_SOURCES ${CUCUMBER_GHERKIN_BIN_SRC_DIR}/*.[ch]pp) +list(APPEND CUCUMBER_GHERKIN_BIN_ALL_SOURCES ${CUCUMBER_GHERKIN_BIN_SOURCES}) target_sources( - gherkin-bin + cucumber_gherkin_bin PRIVATE - ${CMAKE_SOURCE_DIR}/src/bin/gherkin/gherkin.cpp + ${CUCUMBER_GHERKIN_BIN_ALL_SOURCES} ) target_include_directories( - gherkin-bin + cucumber_gherkin_bin PRIVATE - ${CMAKE_SOURCE_DIR}/ - ${CMAKE_SOURCE_DIR}/src/bin/gherkin + ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries( - gherkin-bin + cucumber_gherkin_bin PUBLIC - gherkin-cpp + cucumber::gherkin ) set_target_properties( - gherkin-bin + cucumber_gherkin_bin PROPERTIES - OUTPUT_NAME gherkin + OUTPUT_NAME gherkin ) diff --git a/cpp/src/bin/gherkin/gherkin.cpp b/cpp/src/bin/gherkin/gherkin.cpp index 57d95d410..c7e92be4b 100644 --- a/cpp/src/bin/gherkin/gherkin.cpp +++ b/cpp/src/bin/gherkin/gherkin.cpp @@ -1,7 +1,7 @@ #include -#include -#include +#include +#include struct options { @@ -72,8 +72,8 @@ int main(int ac, char** av) return opts.exit_code; } - gherkin::app app; - gherkin::app::callbacks cbs{ + cucumber::gherkin::app app; + cucumber::gherkin::app::callbacks cbs{ .source = [&](const auto& m) { print_json_obj("source", m); }, .ast = [&](const auto& m) { print_json_obj("gherkinDocument", m); }, .pickle = [&](const auto& m) { print_json_obj("pickle", m); }, @@ -85,7 +85,7 @@ int main(int ac, char** av) app.include_pickles(opts.include_pickles); for ( ; opts.last_arg < ac; ++opts.last_arg) { - app.parse(gherkin::file{ av[opts.last_arg] }, cbs); + app.parse(cucumber::gherkin::file{ av[opts.last_arg] }, cbs); } return 0; diff --git a/cpp/src/bin/gherkin/link.json b/cpp/src/bin/gherkin/link.json new file mode 100644 index 000000000..c0bb75fe8 --- /dev/null +++ b/cpp/src/bin/gherkin/link.json @@ -0,0 +1,7 @@ +{ + "libs": { + "public": [ + "cucumber::gherkin" + ] + } +} diff --git a/cpp/src/lib/gherkin/CMakeLists.txt b/cpp/src/lib/gherkin/CMakeLists.txt index fda4c0584..b48993629 100644 --- a/cpp/src/lib/gherkin/CMakeLists.txt +++ b/cpp/src/lib/gherkin/CMakeLists.txt @@ -1,38 +1,41 @@ -add_library(gherkin-cpp) -add_library(gherkin::gherkin-cpp ALIAS gherkin-cpp) +add_library(cucumber_gherkin_lib) +add_library(cucumber::gherkin ALIAS cucumber_gherkin_lib) -set(INC_DIR "${CMAKE_SOURCE_DIR}/include") +set(CUCUMBER_GHERKIN_LIB_INC_DIR "${PROJECT_SOURCE_DIR}/include/gherkin") +file(GLOB_RECURSE CUCUMBER_GHERKIN_LIB_HEADERS ${CUCUMBER_GHERKIN_LIB_INC_DIR}/*.hpp) +list(APPEND CUCUMBER_GHERKIN_LIB_ALL_SOURCES ${CUCUMBER_GHERKIN_LIB_HEADERS}) -# We prefer it that way... -file(GLOB_RECURSE GHERKIN_CPP_HEADERS ${INC_DIR}/*.[ch]pp) -file(GLOB_RECURSE GHERKIN_CPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[ch]pp) +set(CUCUMBER_GHERKIN_LIB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +file(GLOB_RECURSE CUCUMBER_GHERKIN_LIB_SOURCES ${CUCUMBER_GHERKIN_LIB_SRC_DIR}/*.[ch]pp) +list(APPEND CUCUMBER_GHERKIN_LIB_ALL_SOURCES ${CUCUMBER_GHERKIN_LIB_SOURCES}) target_sources( - gherkin-cpp + cucumber_gherkin_lib PRIVATE - ${GHERKIN_CPP_HEADERS} - ${GHERKIN_CPP_SOURCES} + ${CUCUMBER_GHERKIN_LIB_ALL_SOURCES} ) target_include_directories( - gherkin-cpp + cucumber_gherkin_lib PUBLIC - $ - $ + $ + $ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) target_link_libraries( - gherkin-cpp + cucumber_gherkin_lib PUBLIC - cucumber::cucumber-messages nlohmann_json::nlohmann_json + cucumber::messages ) set_target_properties( - gherkin-cpp + cucumber_gherkin_lib PROPERTIES - OUTPUT_NAME gherkin-cpp + VERSION 0.1.0 + SOVERSION 0.1 + EXPORT_NAME gherkin + OUTPUT_NAME cucumber_gherkin ) - diff --git a/cpp/src/lib/gherkin/app.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/app.cpp similarity index 87% rename from cpp/src/lib/gherkin/app.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/app.cpp index 8b351644b..73e018744 100644 --- a/cpp/src/lib/gherkin/app.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/app.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { app::app() : idp_(new_id_generator()), diff --git a/cpp/src/lib/gherkin/ast_builder.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/ast_builder.cpp similarity index 98% rename from cpp/src/lib/gherkin/ast_builder.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/ast_builder.cpp index 84d473af3..da1e281c6 100644 --- a/cpp/src/lib/gherkin/ast_builder.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/ast_builder.cpp @@ -2,12 +2,12 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { ast_builder::ast_builder() : ast_builder(new_id_generator()) diff --git a/cpp/src/lib/gherkin/ast_node.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/ast_node.cpp similarity index 91% rename from cpp/src/lib/gherkin/ast_node.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/ast_node.cpp index 4511958d8..cd7637c29 100644 --- a/cpp/src/lib/gherkin/ast_node.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/ast_node.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { ast_node::ast_node(rule_type rule_type) : rule_type_(rule_type) diff --git a/cpp/src/lib/gherkin/demangle.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/demangle.cpp similarity index 85% rename from cpp/src/lib/gherkin/demangle.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/demangle.cpp index c87ff22bc..aed508929 100644 --- a/cpp/src/lib/gherkin/demangle.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/demangle.cpp @@ -3,9 +3,9 @@ #include // gcc and clang… #include -#include +#include -namespace gherkin { +namespace cucumber::gherkin { namespace detail { diff --git a/cpp/src/lib/gherkin/dialect.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/dialect.cpp similarity index 99% rename from cpp/src/lib/gherkin/dialect.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/dialect.cpp index 89abfb5b5..f42014478 100644 --- a/cpp/src/lib/gherkin/dialect.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/dialect.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { const keywords_maps& all_keywords() diff --git a/cpp/src/lib/gherkin/exceptions.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/exceptions.cpp similarity index 96% rename from cpp/src/lib/gherkin/exceptions.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/exceptions.cpp index 1dced3398..0497842fc 100644 --- a/cpp/src/lib/gherkin/exceptions.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/exceptions.cpp @@ -1,10 +1,10 @@ #include -#include -#include -#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { /////////////////////////////////////////////////////////////////////////////// // diff --git a/cpp/src/lib/gherkin/id_generator.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/id_generator.cpp similarity index 75% rename from cpp/src/lib/gherkin/id_generator.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/id_generator.cpp index 5cdebc069..a83184087 100644 --- a/cpp/src/lib/gherkin/id_generator.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/id_generator.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { id_generator_base::id_generator_base() {} diff --git a/cpp/src/lib/gherkin/keywords.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/keywords.cpp similarity index 90% rename from cpp/src/lib/gherkin/keywords.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/keywords.cpp index ca5a276ba..8ac66e9df 100644 --- a/cpp/src/lib/gherkin/keywords.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/keywords.cpp @@ -1,7 +1,7 @@ -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { const string_views& keywords(const std::string_view& language, const std::string_view& kw) diff --git a/cpp/src/lib/gherkin/line.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/line.cpp similarity index 95% rename from cpp/src/lib/gherkin/line.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/line.cpp index c3657373d..c7b92874a 100644 --- a/cpp/src/lib/gherkin/line.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/line.cpp @@ -1,12 +1,12 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { using unescape_pair = std::pair; using unescapes = std::vector; diff --git a/cpp/src/lib/gherkin/parse_error.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/parse_error.cpp similarity index 74% rename from cpp/src/lib/gherkin/parse_error.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/parse_error.cpp index d194f4a1d..70ae6b960 100644 --- a/cpp/src/lib/gherkin/parse_error.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/parse_error.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { json parse_error::to_json() const diff --git a/cpp/src/lib/gherkin/pickle_compiler.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/pickle_compiler.cpp similarity index 98% rename from cpp/src/lib/gherkin/pickle_compiler.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/pickle_compiler.cpp index 29e1a3a70..ae4457417 100644 --- a/cpp/src/lib/gherkin/pickle_compiler.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/pickle_compiler.cpp @@ -1,8 +1,8 @@ -#include -#include -#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { cms::pickle_step_type to_pickle_step_type(cms::step_keyword_type keyword_type) diff --git a/cpp/src/lib/gherkin/pickle_compiler_context.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/pickle_compiler_context.cpp similarity index 71% rename from cpp/src/lib/gherkin/pickle_compiler_context.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/pickle_compiler_context.cpp index a7455ec70..666673f30 100644 --- a/cpp/src/lib/gherkin/pickle_compiler_context.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/pickle_compiler_context.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { std::string pickle_compiler_context::next_id() diff --git a/cpp/src/lib/gherkin/regex.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/regex.cpp similarity index 93% rename from cpp/src/lib/gherkin/regex.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/regex.cpp index a71a371c1..27dc83c09 100644 --- a/cpp/src/lib/gherkin/regex.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/regex.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { void split(const std::string& re, const std::string& expr, strings& list) diff --git a/cpp/src/lib/gherkin/rule_type.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/rule_type.cpp similarity index 96% rename from cpp/src/lib/gherkin/rule_type.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/rule_type.cpp index 4b7233414..54b488c6e 100644 --- a/cpp/src/lib/gherkin/rule_type.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/rule_type.cpp @@ -1,8 +1,8 @@ #include -#include +#include -namespace gherkin { +namespace cucumber::gherkin { std::string_view to_string(rule_type r) diff --git a/cpp/src/lib/gherkin/token.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/token.cpp similarity index 70% rename from cpp/src/lib/gherkin/token.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/token.cpp index 8efd28137..1191600e9 100644 --- a/cpp/src/lib/gherkin/token.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/token.cpp @@ -1,6 +1,6 @@ -#include +#include -namespace gherkin { +namespace cucumber::gherkin { bool token::is_eof() const diff --git a/cpp/src/lib/gherkin/token_formatter_builder.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/token_formatter_builder.cpp similarity index 91% rename from cpp/src/lib/gherkin/token_formatter_builder.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/token_formatter_builder.cpp index 179762809..609190738 100644 --- a/cpp/src/lib/gherkin/token_formatter_builder.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/token_formatter_builder.cpp @@ -1,9 +1,9 @@ #include -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { token_formatter_builder::token_formatter_builder(id_generator_ptr idp) : idp_(idp) diff --git a/cpp/src/lib/gherkin/token_matcher.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/token_matcher.cpp similarity index 95% rename from cpp/src/lib/gherkin/token_matcher.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/token_matcher.cpp index 9d8928e3f..24b614c6d 100644 --- a/cpp/src/lib/gherkin/token_matcher.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/token_matcher.cpp @@ -1,11 +1,11 @@ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { static const std::regex language_re{ "^\\s*#\\s*language\\s*:\\s*([a-zA-Z\\-_]+)\\s*$" @@ -211,7 +211,7 @@ bool token_matcher::match_step_line(token& token) { string_views kws = { "given", "when", "then", "and", "but" }; - auto keywords = gherkin::keywords(dialect_name_, kws); + auto keywords = cucumber::gherkin::keywords(dialect_name_, kws); for (const auto& keyword : keywords) { if (!token.line.startswith(keyword)) { @@ -319,7 +319,7 @@ token_matcher::set_token_matched( const string_views& token_matcher::keywords(std::string_view kw) const -{ return gherkin::keywords(dialect_name_, kw); } +{ return cucumber::gherkin::keywords(dialect_name_, kw); } cucumber::messages::step_keyword_type token_matcher::keyword_type(std::string_view keyword) const diff --git a/cpp/src/lib/gherkin/token_scanner.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/token_scanner.cpp similarity index 86% rename from cpp/src/lib/gherkin/token_scanner.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/token_scanner.cpp index de90b59c8..78b49af91 100644 --- a/cpp/src/lib/gherkin/token_scanner.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/token_scanner.cpp @@ -2,10 +2,10 @@ #include #include -#include -#include +#include +#include -namespace gherkin { +namespace cucumber::gherkin { token_scanner::token_scanner() {} @@ -28,7 +28,7 @@ token_scanner::read() return token{ .eof = r.eof, - .line = gherkin::line(r.text, line_), + .line = cucumber::gherkin::line(r.text, line_), .location = { .line = line_ } diff --git a/cpp/src/lib/gherkin/utils.cpp b/cpp/src/lib/gherkin/cucumber/gherkin/utils.cpp similarity index 92% rename from cpp/src/lib/gherkin/utils.cpp rename to cpp/src/lib/gherkin/cucumber/gherkin/utils.cpp index 3b827a2c5..a4cf8c1d3 100644 --- a/cpp/src/lib/gherkin/utils.cpp +++ b/cpp/src/lib/gherkin/cucumber/gherkin/utils.cpp @@ -5,9 +5,9 @@ #include #include -#include +#include -namespace gherkin { +namespace cucumber::gherkin { std::string slurp(const std::string& path) diff --git a/cpp/src/lib/gherkin/link.json b/cpp/src/lib/gherkin/link.json new file mode 100644 index 000000000..d9e9634d7 --- /dev/null +++ b/cpp/src/lib/gherkin/link.json @@ -0,0 +1,8 @@ +{ + "libs": { + "public": [ + "nlohmann_json::nlohmann_json", + "cucumber::messages" + ] + } +}