├── .clang-format ├── .github └── workflows │ ├── javascript.yml │ ├── lua.yml │ ├── style.yml │ └── test.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── CPM.cmake ├── TranspileTypeScript.cmake └── tools.cmake ├── codecov.yaml ├── declarations ├── CMakeLists.txt └── source │ └── main.cpp ├── include └── greeter │ ├── glue.h │ └── greeter.h ├── package-lock.json ├── package.json ├── source ├── glue.cpp └── greeter.cpp ├── standaloneJS ├── CMakeLists.txt ├── source │ └── main.cpp └── tsconfig.json ├── standaloneLua ├── CMakeLists.txt ├── source │ ├── main.cpp │ ├── watch.cpp │ └── watch.h └── tsconfig.json ├── test ├── CMakeLists.txt └── source │ ├── glue.cpp │ ├── greeter.cpp │ └── main.cpp ├── tsconfig.json └── typescript └── index.ts /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | AccessModifierOffset: '-2' 4 | AlignTrailingComments: 'true' 5 | AllowAllParametersOfDeclarationOnNextLine: 'false' 6 | AlwaysBreakTemplateDeclarations: 'No' 7 | BreakBeforeBraces: Attach 8 | ColumnLimit: '100' 9 | ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' 10 | IncludeBlocks: Regroup 11 | IndentPPDirectives: AfterHash 12 | IndentWidth: '2' 13 | NamespaceIndentation: All 14 | BreakBeforeBinaryOperators: All 15 | BreakBeforeTernaryOperators: 'true' 16 | --- 17 | # we use prettier for formatting TS code 18 | Language: JavaScript 19 | DisableFormat: true 20 | SortIncludes: false 21 | ... 22 | -------------------------------------------------------------------------------- /.github/workflows/javascript.yml: -------------------------------------------------------------------------------- 1 | name: JavaScript 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: mymindstorm/setup-emsdk@v6 18 | with: 19 | version: 1.39.20 20 | 21 | - uses: actions/checkout@v1 22 | 23 | - name: configure 24 | run: emcmake cmake -HstandaloneJS -Bbuild 25 | 26 | - name: build 27 | run: cmake --build build -j4 28 | 29 | - name: test 30 | run: node build/TypeScriptXX.js --script dist/js 31 | -------------------------------------------------------------------------------- /.github/workflows/lua.yml: -------------------------------------------------------------------------------- 1 | name: Lua 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v1 18 | 19 | - name: configure 20 | run: CC=gcc-9 CXX=g++-9 cmake -HstandaloneLua -Bbuild 21 | 22 | - name: build 23 | run: cmake --build build -j4 24 | 25 | - name: run 26 | run: ./build/TypeScriptXX -s dist/lua 27 | -------------------------------------------------------------------------------- /.github/workflows/style.yml: -------------------------------------------------------------------------------- 1 | name: Check style 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: macos-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v1 18 | 19 | - name: Install clang-format 20 | run: brew install clang-format 21 | 22 | - name: Configure 23 | run: | 24 | cmake -Htest -Bbuild 25 | npm install 26 | 27 | - name: Check cpp format 28 | run: cmake --build build --target check-format 29 | 30 | - name: check ts style 31 | run: npm run check:style -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | env: 12 | CTEST_OUTPUT_ON_FAILURE: 1 13 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v1 22 | 23 | - name: configure 24 | run: CC=gcc-9 CXX=g++-9 cmake -Htest -Bbuild -DENABLE_TEST_COVERAGE=1 25 | 26 | - name: build 27 | run: cmake --build build -j4 28 | 29 | - name: test 30 | run: cmake --build build --target test 31 | 32 | - name: collect code coverage 33 | run: bash <(curl -s https://codecov.io/bash) -x gcov-9 || echo "Codecov did not collect coverage reports" 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /node_modules 3 | /build* 4 | /typescript/cpplib.d.ts 5 | .DS_Store 6 | /.vscode -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | 3 | project( 4 | Greeter 5 | VERSION 1.0 6 | LANGUAGES CXX 7 | ) 8 | 9 | # ---- Add Tools ---- 10 | 11 | include(cmake/tools.cmake) 12 | 13 | # ---- Dependencies ---- 14 | 15 | include(cmake/CPM.cmake) 16 | 17 | # helper to create an installable target 18 | CPMAddPackage( 19 | NAME PackageProject.cmake 20 | GITHUB_REPOSITORY TheLartians/PackageProject.cmake 21 | VERSION 1.2 22 | ) 23 | 24 | CPMAddPackage( 25 | NAME Glue 26 | VERSION 1.3.2 27 | GITHUB_REPOSITORY TheLartians/Glue 28 | ) 29 | 30 | # ---- Add source files ---- 31 | 32 | FILE(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") 33 | FILE(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp") 34 | 35 | # ---- Create library ---- 36 | 37 | add_library(Greeter ${headers} ${sources}) 38 | 39 | set_target_properties(Greeter PROPERTIES CXX_STANDARD 17) 40 | 41 | # beeing a cross-platform target, we enforce enforce standards conformance on MSVC 42 | target_compile_options(Greeter PUBLIC "$<$:/permissive->") 43 | 44 | target_link_libraries(Greeter PUBLIC Glue) 45 | 46 | target_include_directories(Greeter 47 | PUBLIC 48 | $ 49 | $ 50 | ) 51 | 52 | # ---- Create an installable target ---- 53 | # this allows users to install and find the library via `find_package()`. 54 | 55 | packageProject( 56 | NAME ${PROJECT_NAME} 57 | VERSION ${PROJECT_VERSION} 58 | BINARY_DIR ${PROJECT_BINARY_DIR} 59 | INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include 60 | INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION} 61 | DEPENDENCIES Glue 62 | ) 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Actions Status](https://github.com/TheLartians/TypeScriptXX/workflows/Lua/badge.svg)](https://github.com/TheLartians/TypeScriptXX/actions) 2 | [![Actions Status](https://github.com/TheLartians/TypeScriptXX/workflows/JavaScript/badge.svg)](https://github.com/TheLartians/TypeScriptXX/actions) 3 | [![Actions Status](https://github.com/TheLartians/TypeScriptXX/workflows/Test/badge.svg)](https://github.com/TheLartians/TypeScriptXX/actions) 4 | [![Actions Status](https://github.com/TheLartians/TypeScriptXX/workflows/Check%20style/badge.svg)](https://github.com/TheLartians/TypeScriptXX/actions) 5 | [![codecov](https://codecov.io/gh/TheLartians/TypeScriptXX/branch/master/graph/badge.svg)](https://codecov.io/gh/TheLartians/TypeScriptXX) 6 | 7 | # TypeScriptXX 8 | 9 | ## About 10 | 11 | This is a template project that uses the [Glue](https://github.com/TheLartians/Glue) library to add type-safe scripting capability to a C++ project. 12 | Scrips are coded in [TypeScript](https://www.typescriptlang.org), transpiled using [tsc](https://www.typescriptlang.org/docs/handbook/compiler-options.html) or [TSTL](https://typescripttolua.github.io) and run in by [node.js](https://nodejs.org) or an an embedded [Lua](https://www.lua.org) engine. 13 | The built JavaScript target can also be run in a browser and used on a website. 14 | The TypeScript declarations are automatically generated and updated by CMake. 15 | 16 | ## Usage 17 | 18 | ### Transpile to Lua and run natively 19 | 20 | The following commands build the project and run the [typescript script](typescript/index.ts). 21 | 22 | ```bash 23 | cmake -HstandaloneLua -Bbuild/lua 24 | 25 | # Compiles C++ code, updates the declarations and transpiles TypeScript 26 | cmake --build build/lua -j8 27 | 28 | # runs the transpiled lua script at dist/lua/index.lua 29 | ./build/lua/TypeScriptXX --script dist/lua 30 | ``` 31 | 32 | Is is also possible to enable watch mode for hot reloading. 33 | This way any code changes to the TypeScript source will be transpiled and run automatically. 34 | 35 | ```bash 36 | npx concurrently "npm run watch:lua" "./build/lua/TypeScriptXX -s dist/lua --watch" 37 | ``` 38 | 39 | ### Transpile to JavaScript and run in node.js 40 | 41 | First, [install and activate](https://emscripten.org/docs/getting_started/downloads.html) the emsdk. 42 | The following commands build the project and run the [typescript script](typescript/index.ts). 43 | 44 | ```bash 45 | emcmake cmake -HstandaloneJS -Bbuild/js 46 | 47 | # Compiles C++ code, updates the declarations and transpiles TypeScript 48 | cmake --build build/js -j8 49 | 50 | # runs the transpiled lua script at dist/js/index.js 51 | node ./build/js/TypeScriptXX.js --script dist/js 52 | ``` 53 | 54 | ### How it works 55 | 56 | The example C++ [library](include/greeter/greeter.h) is exposed to TypeScript using [Glue bindings](source/glue.cpp). 57 | 58 | The projects contains four standalone subprojects: 59 | 60 | - [test](test), that check the library code 61 | - [declarations](declarations), that simply prints the declarations 62 | - [standaloneLua](standaloneLua), that uses [LuaGlue](https://github.com/TheLartians/LuaGlue) to bind and run lua code. 63 | - [standaloneJS](standaloneJS), that uses [EmGlue](https://github.com/TheLartians/EmGlue) to bind to a JavaScript runtime such as node.js. 64 | 65 | After building, CMake will use the latter to ensure that the declarations at `typescript/cpplib.d.ts` are up-to-date and then transpile the TypeScript code to Lua or JavaScript. 66 | -------------------------------------------------------------------------------- /cmake/CPM.cmake: -------------------------------------------------------------------------------- 1 | # CPM.cmake - CMake's missing package manager 2 | # =========================================== 3 | # See https://github.com/TheLartians/CPM.cmake for usage and update instructions. 4 | # 5 | # MIT License 6 | # ----------- 7 | #[[ 8 | Copyright (c) 2019 Lars Melchior 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | ]] 28 | 29 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 30 | 31 | set(CURRENT_CPM_VERSION 0.22) 32 | 33 | if(CPM_DIRECTORY) 34 | if(NOT ${CPM_DIRECTORY} MATCHES ${CMAKE_CURRENT_LIST_DIR}) 35 | if (${CPM_VERSION} VERSION_LESS ${CURRENT_CPM_VERSION}) 36 | message(AUTHOR_WARNING "${CPM_INDENT} \ 37 | A dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \ 38 | It is recommended to upgrade CPM to the most recent version. \ 39 | See https://github.com/TheLartians/CPM.cmake for more information." 40 | ) 41 | endif() 42 | return() 43 | endif() 44 | 45 | get_property(CPM_INITIALIZED GLOBAL "" PROPERTY CPM_INITIALIZED SET) 46 | if (CPM_INITIALIZED) 47 | return() 48 | endif() 49 | endif() 50 | 51 | set_property(GLOBAL PROPERTY CPM_INITIALIZED true) 52 | 53 | option(CPM_USE_LOCAL_PACKAGES "Always try to use `find_package` to get dependencies" $ENV{CPM_USE_LOCAL_PACKAGES}) 54 | option(CPM_LOCAL_PACKAGES_ONLY "Only use `find_package` to get dependencies" $ENV{CPM_LOCAL_PACKAGES_ONLY}) 55 | option(CPM_DOWNLOAD_ALL "Always download dependencies from source" $ENV{CPM_DOWNLOAD_ALL}) 56 | option(CPM_DONT_UPDATE_MODULE_PATH "Don't update the module path to allow using find_package" $ENV{CPM_DONT_UPDATE_MODULE_PATH}) 57 | 58 | set(CPM_VERSION ${CURRENT_CPM_VERSION} CACHE INTERNAL "") 59 | set(CPM_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "") 60 | set(CPM_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE INTERNAL "") 61 | set(CPM_PACKAGES "" CACHE INTERNAL "") 62 | set(CPM_DRY_RUN OFF CACHE INTERNAL "Don't download or configure dependencies (for testing)") 63 | 64 | if(DEFINED ENV{CPM_SOURCE_CACHE}) 65 | set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE}) 66 | else() 67 | set(CPM_SOURCE_CACHE_DEFAULT OFF) 68 | endif() 69 | 70 | set(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE_DEFAULT} CACHE PATH "Directory to downlaod CPM dependencies") 71 | 72 | if (NOT CPM_DONT_UPDATE_MODULE_PATH) 73 | set(CPM_MODULE_PATH "${CMAKE_BINARY_DIR}/CPM_modules" CACHE INTERNAL "") 74 | # remove old modules 75 | FILE(REMOVE_RECURSE ${CPM_MODULE_PATH}) 76 | file(MAKE_DIRECTORY ${CPM_MODULE_PATH}) 77 | # locally added CPM modules should override global packages 78 | set(CMAKE_MODULE_PATH "${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}") 79 | endif() 80 | 81 | include(FetchContent) 82 | include(CMakeParseArguments) 83 | 84 | # Initialize logging prefix 85 | if(NOT CPM_INDENT) 86 | set(CPM_INDENT "CPM:") 87 | endif() 88 | 89 | function(cpm_find_package NAME VERSION) 90 | string(REPLACE " " ";" EXTRA_ARGS "${ARGN}") 91 | find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET) 92 | if(${CPM_ARGS_NAME}_FOUND) 93 | message(STATUS "${CPM_INDENT} using local package ${CPM_ARGS_NAME}@${${CPM_ARGS_NAME}_VERSION}") 94 | CPMRegisterPackage(${CPM_ARGS_NAME} "${${CPM_ARGS_NAME}_VERSION}") 95 | set(CPM_PACKAGE_FOUND YES PARENT_SCOPE) 96 | else() 97 | set(CPM_PACKAGE_FOUND NO PARENT_SCOPE) 98 | endif() 99 | endfunction() 100 | 101 | # Create a custom FindXXX.cmake module for a CPM package 102 | # This prevents `find_package(NAME)` from finding the system library 103 | function(CPMCreateModuleFile Name) 104 | if (NOT CPM_DONT_UPDATE_MODULE_PATH) 105 | # erase any previous modules 106 | FILE(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake "include(${CPM_FILE})\n${ARGN}\nset(${Name}_FOUND TRUE)") 107 | endif() 108 | endfunction() 109 | 110 | # Find a package locally or fallback to CPMAddPackage 111 | function(CPMFindPackage) 112 | set(oneValueArgs 113 | NAME 114 | VERSION 115 | FIND_PACKAGE_ARGUMENTS 116 | ) 117 | 118 | cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN}) 119 | 120 | if (CPM_DOWNLOAD_ALL) 121 | CPMAddPackage(${ARGN}) 122 | cpm_export_variables() 123 | return() 124 | endif() 125 | 126 | cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) 127 | 128 | if(NOT CPM_PACKAGE_FOUND) 129 | CPMAddPackage(${ARGN}) 130 | cpm_export_variables() 131 | endif() 132 | 133 | endfunction() 134 | 135 | # Download and add a package from source 136 | function(CPMAddPackage) 137 | 138 | set(oneValueArgs 139 | NAME 140 | VERSION 141 | GIT_TAG 142 | DOWNLOAD_ONLY 143 | GITHUB_REPOSITORY 144 | GITLAB_REPOSITORY 145 | SOURCE_DIR 146 | DOWNLOAD_COMMAND 147 | FIND_PACKAGE_ARGUMENTS 148 | ) 149 | 150 | set(multiValueArgs 151 | OPTIONS 152 | ) 153 | 154 | cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") 155 | 156 | if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY) 157 | cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS}) 158 | 159 | if(CPM_PACKAGE_FOUND) 160 | return() 161 | endif() 162 | 163 | if(CPM_LOCAL_PACKAGES_ONLY) 164 | message(SEND_ERROR "CPM: ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})") 165 | endif() 166 | endif() 167 | 168 | if (NOT DEFINED CPM_ARGS_VERSION) 169 | if (DEFINED CPM_ARGS_GIT_TAG) 170 | cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) 171 | endif() 172 | if (NOT DEFINED CPM_ARGS_VERSION) 173 | set(CPM_ARGS_VERSION 0) 174 | endif() 175 | endif() 176 | 177 | if (NOT DEFINED CPM_ARGS_GIT_TAG) 178 | set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) 179 | endif() 180 | 181 | list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG}) 182 | 183 | if(CPM_ARGS_DOWNLOAD_ONLY) 184 | set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY}) 185 | else() 186 | set(DOWNLOAD_ONLY NO) 187 | endif() 188 | 189 | if (CPM_ARGS_GITHUB_REPOSITORY) 190 | list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY "https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git") 191 | endif() 192 | 193 | if (CPM_ARGS_GITLAB_REPOSITORY) 194 | list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git") 195 | endif() 196 | 197 | if ("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) 198 | CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) 199 | if(${CPM_PACKAGE_VERSION} VERSION_LESS ${CPM_ARGS_VERSION}) 200 | message(WARNING "${CPM_INDENT} requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION}).") 201 | endif() 202 | if (CPM_ARGS_OPTIONS) 203 | foreach(OPTION ${CPM_ARGS_OPTIONS}) 204 | cpm_parse_option(${OPTION}) 205 | if(NOT "${${OPTION_KEY}}" STREQUAL ${OPTION_VALUE}) 206 | message(WARNING "${CPM_INDENT} ignoring package option for ${CPM_ARGS_NAME}: ${OPTION_KEY} = ${OPTION_VALUE} (${${OPTION_KEY}})") 207 | endif() 208 | endforeach() 209 | endif() 210 | cpm_fetch_package(${CPM_ARGS_NAME} ${DOWNLOAD_ONLY}) 211 | cpm_get_fetch_properties(${CPM_ARGS_NAME}) 212 | SET(${CPM_ARGS_NAME}_SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}") 213 | SET(${CPM_ARGS_NAME}_BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}") 214 | SET(${CPM_ARGS_NAME}_ADDED NO) 215 | cpm_export_variables() 216 | return() 217 | endif() 218 | 219 | CPMRegisterPackage(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION}) 220 | 221 | if (CPM_ARGS_OPTIONS) 222 | foreach(OPTION ${CPM_ARGS_OPTIONS}) 223 | cpm_parse_option(${OPTION}) 224 | set(${OPTION_KEY} ${OPTION_VALUE} CACHE INTERNAL "") 225 | endforeach() 226 | endif() 227 | 228 | set(FETCH_CONTENT_DECLARE_EXTRA_OPTS "") 229 | 230 | if (DEFINED CPM_ARGS_GIT_TAG) 231 | set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") 232 | else() 233 | set(PACKAGE_INFO "${CPM_ARGS_VERSION}") 234 | endif() 235 | 236 | if (DEFINED CPM_ARGS_DOWNLOAD_COMMAND) 237 | set(FETCH_CONTENT_DECLARE_EXTRA_OPTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) 238 | elseif(DEFINED CPM_ARGS_SOURCE_DIR) 239 | set(FETCH_CONTENT_DECLARE_EXTRA_OPTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR}) 240 | elseif (CPM_SOURCE_CACHE) 241 | string(TOLOWER ${CPM_ARGS_NAME} lower_case_name) 242 | set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS}) 243 | list(SORT origin_parameters) 244 | string(SHA1 origin_hash "${origin_parameters}") 245 | set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}) 246 | list(APPEND FETCH_CONTENT_DECLARE_EXTRA_OPTS SOURCE_DIR ${download_directory}) 247 | if (EXISTS ${download_directory}) 248 | # disable the download command to allow offline builds 249 | list(APPEND FETCH_CONTENT_DECLARE_EXTRA_OPTS DOWNLOAD_COMMAND "${CMAKE_COMMAND}") 250 | set(PACKAGE_INFO "${download_directory}") 251 | else() 252 | # remove timestamps so CMake will re-download the dependency 253 | file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/_deps/${lower_case_name}-subbuild) 254 | set(PACKAGE_INFO "${PACKAGE_INFO} -> ${download_directory}") 255 | endif() 256 | endif() 257 | 258 | cpm_declare_fetch(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION} ${PACKAGE_INFO} "${CPM_ARGS_UNPARSED_ARGUMENTS}" ${FETCH_CONTENT_DECLARE_EXTRA_OPTS}) 259 | cpm_fetch_package(${CPM_ARGS_NAME} ${DOWNLOAD_ONLY}) 260 | cpm_get_fetch_properties(${CPM_ARGS_NAME}) 261 | CPMCreateModuleFile(${CPM_ARGS_NAME} "CPMAddPackage(${ARGN})") 262 | SET(${CPM_ARGS_NAME}_ADDED YES) 263 | cpm_export_variables() 264 | endfunction() 265 | 266 | # export variables available to the caller to the parent scope 267 | # expects ${CPM_ARGS_NAME} to be set 268 | macro(cpm_export_variables) 269 | SET(${CPM_ARGS_NAME}_SOURCE_DIR "${${CPM_ARGS_NAME}_SOURCE_DIR}" PARENT_SCOPE) 270 | SET(${CPM_ARGS_NAME}_BINARY_DIR "${${CPM_ARGS_NAME}_BINARY_DIR}" PARENT_SCOPE) 271 | SET(${CPM_ARGS_NAME}_ADDED "${${CPM_ARGS_NAME}_ADDED}" PARENT_SCOPE) 272 | endmacro() 273 | 274 | # declares that a package has been added to CPM 275 | function(CPMRegisterPackage PACKAGE VERSION) 276 | list(APPEND CPM_PACKAGES ${PACKAGE}) 277 | set(CPM_PACKAGES ${CPM_PACKAGES} CACHE INTERNAL "") 278 | set("CPM_PACKAGE_${PACKAGE}_VERSION" ${VERSION} CACHE INTERNAL "") 279 | endfunction() 280 | 281 | # retrieve the current version of the package to ${OUTPUT} 282 | function(CPMGetPackageVersion PACKAGE OUTPUT) 283 | set(${OUTPUT} "${CPM_PACKAGE_${PACKAGE}_VERSION}" PARENT_SCOPE) 284 | endfunction() 285 | 286 | # declares a package in FetchContent_Declare 287 | function (cpm_declare_fetch PACKAGE VERSION INFO) 288 | message(STATUS "${CPM_INDENT} adding package ${PACKAGE}@${VERSION} (${INFO})") 289 | 290 | if (${CPM_DRY_RUN}) 291 | message(STATUS "${CPM_INDENT} package not declared (dry run)") 292 | return() 293 | endif() 294 | 295 | FetchContent_Declare( 296 | ${PACKAGE} 297 | ${ARGN} 298 | ) 299 | endfunction() 300 | 301 | # returns properties for a package previously defined by cpm_declare_fetch 302 | function (cpm_get_fetch_properties PACKAGE) 303 | if (${CPM_DRY_RUN}) 304 | return() 305 | endif() 306 | FetchContent_GetProperties(${PACKAGE}) 307 | string(TOLOWER ${PACKAGE} lpackage) 308 | SET(${PACKAGE}_SOURCE_DIR "${${lpackage}_SOURCE_DIR}" PARENT_SCOPE) 309 | SET(${PACKAGE}_BINARY_DIR "${${lpackage}_BINARY_DIR}" PARENT_SCOPE) 310 | endfunction() 311 | 312 | # downloads a previously declared package via FetchContent 313 | function (cpm_fetch_package PACKAGE DOWNLOAD_ONLY) 314 | 315 | if (${CPM_DRY_RUN}) 316 | message(STATUS "${CPM_INDENT} package ${PACKAGE} not fetched (dry run)") 317 | return() 318 | endif() 319 | 320 | set(CPM_OLD_INDENT "${CPM_INDENT}") 321 | set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:") 322 | if(${DOWNLOAD_ONLY}) 323 | FetchContent_GetProperties(${PACKAGE}) 324 | if(NOT ${PACKAGE}_POPULATED) 325 | FetchContent_Populate(${PACKAGE}) 326 | endif() 327 | else() 328 | FetchContent_MakeAvailable(${PACKAGE}) 329 | endif() 330 | set(CPM_INDENT "${CPM_OLD_INDENT}") 331 | endfunction() 332 | 333 | # splits a package option 334 | function(cpm_parse_option OPTION) 335 | string(REGEX MATCH "^[^ ]+" OPTION_KEY ${OPTION}) 336 | string(LENGTH ${OPTION} OPTION_LENGTH) 337 | string(LENGTH ${OPTION_KEY} OPTION_KEY_LENGTH) 338 | if (OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH) 339 | # no value for key provided, assume user wants to set option to "ON" 340 | set(OPTION_VALUE "ON") 341 | else() 342 | math(EXPR OPTION_KEY_LENGTH "${OPTION_KEY_LENGTH}+1") 343 | string(SUBSTRING ${OPTION} "${OPTION_KEY_LENGTH}" "-1" OPTION_VALUE) 344 | endif() 345 | set(OPTION_KEY "${OPTION_KEY}" PARENT_SCOPE) 346 | set(OPTION_VALUE "${OPTION_VALUE}" PARENT_SCOPE) 347 | endfunction() 348 | 349 | # guesses the package version from a git tag 350 | function(cpm_get_version_from_git_tag GIT_TAG RESULT) 351 | string(LENGTH ${GIT_TAG} length) 352 | if (length EQUAL 40) 353 | # GIT_TAG is probably a git hash 354 | SET(${RESULT} 0 PARENT_SCOPE) 355 | else() 356 | string(REGEX MATCH "v?([0123456789.]*).*" _ ${GIT_TAG}) 357 | SET(${RESULT} ${CMAKE_MATCH_1} PARENT_SCOPE) 358 | endif() 359 | endfunction() 360 | -------------------------------------------------------------------------------- /cmake/TranspileTypeScript.cmake: -------------------------------------------------------------------------------- 1 | 2 | function(TranspileTypeScript) 3 | 4 | set(oneValueArgs 5 | NAME 6 | DIRECTORY 7 | RESULT 8 | COMMAND 9 | ) 10 | 11 | set(multiValueArgs 12 | DEPENDS 13 | ) 14 | 15 | cmake_parse_arguments(TS_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 16 | 17 | ADD_CUSTOM_COMMAND( 18 | OUTPUT ${TS_ARGS_DIRECTORY}/node_modules 19 | DEPENDS ${TS_ARGS_DIRECTORY}/package.json 20 | COMMAND npm install 21 | COMMAND touch node_modules 22 | WORKING_DIRECTORY ${TS_ARGS_DIRECTORY} 23 | ) 24 | 25 | file(GLOB_RECURSE typescriptSources CONFIGURE_DEPENDS "${TS_ARGS_DIRECTORY}/*.ts") 26 | 27 | ADD_CUSTOM_COMMAND( 28 | OUTPUT ${TS_ARGS_RESULT} 29 | DEPENDS ${TS_ARGS_DIRECTORY} "${TS_ARGS_DIRECTORY}/tsconfig.json" ${TS_ARGS_DIRECTORY}/node_modules ${TS_ARGS_DEPENDS} ${typescriptSources} 30 | COMMAND npm run ${TS_ARGS_COMMAND} 31 | COMMAND touch ${TS_ARGS_RESULT} 32 | WORKING_DIRECTORY ${TS_ARGS_DIRECTORY} 33 | ) 34 | 35 | endfunction() 36 | -------------------------------------------------------------------------------- /cmake/tools.cmake: -------------------------------------------------------------------------------- 1 | # this file contains a list of tools that can be activated and downloaded on-demand 2 | # each tool is enabled during configuration by passing an additional `-DUSE_=` argument to CMake 3 | 4 | # only activate tools for top level project 5 | if (NOT PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 6 | return() 7 | endif() 8 | 9 | include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake) 10 | 11 | # enables sanitizers support using the the `USE_SANITIZER` flag 12 | # available values are: Address, Memory, MemoryWithOrigins, Undefined, Thread, Leak, 'Address;Undefined' 13 | if (USE_SANITIZER) 14 | CPMAddPackage( 15 | NAME StableCoder-cmake-scripts 16 | GITHUB_REPOSITORY StableCoder/cmake-scripts 17 | GIT_TAG 3a469d8251660a97dbf9e0afff0a242965d40277 18 | ) 19 | 20 | include(${StableCoder-cmake-scripts_SOURCE_DIR}/sanitizers.cmake) 21 | endif() 22 | 23 | # enables CCACHE support through the USE_CCACHE flag 24 | # possible values are: YES, NO or equivalent 25 | if (USE_CCACHE) 26 | CPMAddPackage( 27 | NAME Ccache.cmake 28 | GITHUB_REPOSITORY TheLartians/Ccache.cmake 29 | VERSION 1.1 30 | ) 31 | endif() 32 | -------------------------------------------------------------------------------- /codecov.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "test" 3 | 4 | comment: 5 | require_changes: true -------------------------------------------------------------------------------- /declarations/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR) 2 | 3 | project(TypeScriptXXDeclarations 4 | LANGUAGES CXX 5 | ) 6 | 7 | # ---- Dependencies ---- 8 | 9 | include(../cmake/CPM.cmake) 10 | 11 | CPMAddPackage( 12 | NAME Greeter 13 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/.. 14 | ) 15 | 16 | # ---- Create standalone executable ---- 17 | 18 | file(GLOB sources CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp) 19 | 20 | add_executable(TypeScriptXXDeclarations ${sources}) 21 | 22 | set_target_properties(TypeScriptXXDeclarations PROPERTIES CXX_STANDARD 17) 23 | target_link_libraries(TypeScriptXXDeclarations Greeter) 24 | -------------------------------------------------------------------------------- /declarations/source/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | int main() { 8 | auto glue = glue::createAnyMap(); 9 | glue["greeter"] = greeter::glue(); 10 | 11 | // dummy function for declarations, will be implemented by the runtime 12 | glue["deleteValue"] = [](glue::Any) {}; 13 | 14 | glue::Context context; 15 | context.addRootMap(glue); 16 | 17 | glue::DeclarationPrinter printer; 18 | printer.init(); 19 | printer.print(std::cout, glue, &context); 20 | std::cout << std::endl; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /include/greeter/glue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace greeter { 6 | 7 | glue::MapValue glue(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /include/greeter/greeter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace greeter { 6 | 7 | enum class LanguageCode { EN, DE, ES, FR }; 8 | 9 | class Greeter { 10 | std::string name; 11 | 12 | public: 13 | Greeter(std::string name); 14 | std::string greet(LanguageCode lang = LanguageCode::EN) const; 15 | }; 16 | 17 | } // namespace greeter 18 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "ansi-regex": { 6 | "version": "4.1.0", 7 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 8 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 9 | "dev": true 10 | }, 11 | "ansi-styles": { 12 | "version": "3.2.1", 13 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 14 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 15 | "dev": true, 16 | "requires": { 17 | "color-convert": "^1.9.0" 18 | } 19 | }, 20 | "camelcase": { 21 | "version": "5.3.1", 22 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 23 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 24 | "dev": true 25 | }, 26 | "chalk": { 27 | "version": "2.4.2", 28 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 29 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 30 | "dev": true, 31 | "requires": { 32 | "ansi-styles": "^3.2.1", 33 | "escape-string-regexp": "^1.0.5", 34 | "supports-color": "^5.3.0" 35 | }, 36 | "dependencies": { 37 | "supports-color": { 38 | "version": "5.5.0", 39 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 40 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 41 | "dev": true, 42 | "requires": { 43 | "has-flag": "^3.0.0" 44 | } 45 | } 46 | } 47 | }, 48 | "cliui": { 49 | "version": "5.0.0", 50 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 51 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 52 | "dev": true, 53 | "requires": { 54 | "string-width": "^3.1.0", 55 | "strip-ansi": "^5.2.0", 56 | "wrap-ansi": "^5.1.0" 57 | } 58 | }, 59 | "color-convert": { 60 | "version": "1.9.3", 61 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 62 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 63 | "dev": true, 64 | "requires": { 65 | "color-name": "1.1.3" 66 | } 67 | }, 68 | "color-name": { 69 | "version": "1.1.3", 70 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 71 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 72 | "dev": true 73 | }, 74 | "concurrently": { 75 | "version": "5.1.0", 76 | "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.1.0.tgz", 77 | "integrity": "sha512-9ViZMu3OOCID3rBgU31mjBftro2chOop0G2u1olq1OuwRBVRw/GxHTg80TVJBUTJfoswMmEUeuOg1g1yu1X2dA==", 78 | "dev": true, 79 | "requires": { 80 | "chalk": "^2.4.2", 81 | "date-fns": "^2.0.1", 82 | "lodash": "^4.17.15", 83 | "read-pkg": "^4.0.1", 84 | "rxjs": "^6.5.2", 85 | "spawn-command": "^0.0.2-1", 86 | "supports-color": "^6.1.0", 87 | "tree-kill": "^1.2.2", 88 | "yargs": "^13.3.0" 89 | } 90 | }, 91 | "date-fns": { 92 | "version": "2.9.0", 93 | "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.9.0.tgz", 94 | "integrity": "sha512-khbFLu/MlzLjEzy9Gh8oY1hNt/Dvxw3J6Rbc28cVoYWQaC1S3YI4xwkF9ZWcjDLscbZlY9hISMr66RFzZagLsA==", 95 | "dev": true 96 | }, 97 | "decamelize": { 98 | "version": "1.2.0", 99 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 100 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 101 | "dev": true 102 | }, 103 | "emoji-regex": { 104 | "version": "7.0.3", 105 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 106 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 107 | "dev": true 108 | }, 109 | "error-ex": { 110 | "version": "1.3.2", 111 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 112 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 113 | "dev": true, 114 | "requires": { 115 | "is-arrayish": "^0.2.1" 116 | } 117 | }, 118 | "escape-string-regexp": { 119 | "version": "1.0.5", 120 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 121 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 122 | "dev": true 123 | }, 124 | "find-up": { 125 | "version": "3.0.0", 126 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 127 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 128 | "dev": true, 129 | "requires": { 130 | "locate-path": "^3.0.0" 131 | } 132 | }, 133 | "get-caller-file": { 134 | "version": "2.0.5", 135 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 136 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 137 | "dev": true 138 | }, 139 | "has-flag": { 140 | "version": "3.0.0", 141 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 142 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 143 | "dev": true 144 | }, 145 | "hosted-git-info": { 146 | "version": "2.8.5", 147 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", 148 | "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", 149 | "dev": true 150 | }, 151 | "is-arrayish": { 152 | "version": "0.2.1", 153 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 154 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 155 | "dev": true 156 | }, 157 | "is-fullwidth-code-point": { 158 | "version": "2.0.0", 159 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 160 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 161 | "dev": true 162 | }, 163 | "json-parse-better-errors": { 164 | "version": "1.0.2", 165 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 166 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", 167 | "dev": true 168 | }, 169 | "locate-path": { 170 | "version": "3.0.0", 171 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 172 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 173 | "dev": true, 174 | "requires": { 175 | "p-locate": "^3.0.0", 176 | "path-exists": "^3.0.0" 177 | } 178 | }, 179 | "lodash": { 180 | "version": "4.17.20", 181 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 182 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", 183 | "dev": true 184 | }, 185 | "normalize-package-data": { 186 | "version": "2.5.0", 187 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 188 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 189 | "dev": true, 190 | "requires": { 191 | "hosted-git-info": "^2.1.4", 192 | "resolve": "^1.10.0", 193 | "semver": "2 || 3 || 4 || 5", 194 | "validate-npm-package-license": "^3.0.1" 195 | } 196 | }, 197 | "p-limit": { 198 | "version": "2.2.2", 199 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", 200 | "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", 201 | "dev": true, 202 | "requires": { 203 | "p-try": "^2.0.0" 204 | } 205 | }, 206 | "p-locate": { 207 | "version": "3.0.0", 208 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 209 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 210 | "dev": true, 211 | "requires": { 212 | "p-limit": "^2.0.0" 213 | } 214 | }, 215 | "p-try": { 216 | "version": "2.2.0", 217 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 218 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 219 | "dev": true 220 | }, 221 | "parse-json": { 222 | "version": "4.0.0", 223 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", 224 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", 225 | "dev": true, 226 | "requires": { 227 | "error-ex": "^1.3.1", 228 | "json-parse-better-errors": "^1.0.1" 229 | } 230 | }, 231 | "path-exists": { 232 | "version": "3.0.0", 233 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 234 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 235 | "dev": true 236 | }, 237 | "path-parse": { 238 | "version": "1.0.6", 239 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 240 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 241 | "dev": true 242 | }, 243 | "pify": { 244 | "version": "3.0.0", 245 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 246 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 247 | "dev": true 248 | }, 249 | "prettier": { 250 | "version": "1.19.1", 251 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", 252 | "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", 253 | "dev": true 254 | }, 255 | "read-pkg": { 256 | "version": "4.0.1", 257 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", 258 | "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", 259 | "dev": true, 260 | "requires": { 261 | "normalize-package-data": "^2.3.2", 262 | "parse-json": "^4.0.0", 263 | "pify": "^3.0.0" 264 | } 265 | }, 266 | "require-directory": { 267 | "version": "2.1.1", 268 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 269 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 270 | "dev": true 271 | }, 272 | "require-main-filename": { 273 | "version": "2.0.0", 274 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 275 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 276 | "dev": true 277 | }, 278 | "resolve": { 279 | "version": "1.15.1", 280 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", 281 | "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", 282 | "dev": true, 283 | "requires": { 284 | "path-parse": "^1.0.6" 285 | } 286 | }, 287 | "rxjs": { 288 | "version": "6.5.4", 289 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", 290 | "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", 291 | "dev": true, 292 | "requires": { 293 | "tslib": "^1.9.0" 294 | } 295 | }, 296 | "semver": { 297 | "version": "5.7.1", 298 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 299 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 300 | "dev": true 301 | }, 302 | "set-blocking": { 303 | "version": "2.0.0", 304 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 305 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 306 | "dev": true 307 | }, 308 | "source-map": { 309 | "version": "0.7.3", 310 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", 311 | "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", 312 | "dev": true 313 | }, 314 | "spawn-command": { 315 | "version": "0.0.2-1", 316 | "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", 317 | "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", 318 | "dev": true 319 | }, 320 | "spdx-correct": { 321 | "version": "3.1.0", 322 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", 323 | "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", 324 | "dev": true, 325 | "requires": { 326 | "spdx-expression-parse": "^3.0.0", 327 | "spdx-license-ids": "^3.0.0" 328 | } 329 | }, 330 | "spdx-exceptions": { 331 | "version": "2.2.0", 332 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", 333 | "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", 334 | "dev": true 335 | }, 336 | "spdx-expression-parse": { 337 | "version": "3.0.0", 338 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 339 | "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 340 | "dev": true, 341 | "requires": { 342 | "spdx-exceptions": "^2.1.0", 343 | "spdx-license-ids": "^3.0.0" 344 | } 345 | }, 346 | "spdx-license-ids": { 347 | "version": "3.0.5", 348 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 349 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", 350 | "dev": true 351 | }, 352 | "string-width": { 353 | "version": "3.1.0", 354 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 355 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 356 | "dev": true, 357 | "requires": { 358 | "emoji-regex": "^7.0.1", 359 | "is-fullwidth-code-point": "^2.0.0", 360 | "strip-ansi": "^5.1.0" 361 | } 362 | }, 363 | "strip-ansi": { 364 | "version": "5.2.0", 365 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 366 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 367 | "dev": true, 368 | "requires": { 369 | "ansi-regex": "^4.1.0" 370 | } 371 | }, 372 | "supports-color": { 373 | "version": "6.1.0", 374 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", 375 | "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", 376 | "dev": true, 377 | "requires": { 378 | "has-flag": "^3.0.0" 379 | } 380 | }, 381 | "tree-kill": { 382 | "version": "1.2.2", 383 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", 384 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", 385 | "dev": true 386 | }, 387 | "tslib": { 388 | "version": "1.11.0", 389 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", 390 | "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", 391 | "dev": true 392 | }, 393 | "typescript": { 394 | "version": "3.8.3", 395 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", 396 | "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", 397 | "dev": true 398 | }, 399 | "typescript-to-lua": { 400 | "version": "0.32.2", 401 | "resolved": "https://registry.npmjs.org/typescript-to-lua/-/typescript-to-lua-0.32.2.tgz", 402 | "integrity": "sha512-X50SJ5HXUH6qqRF0EJ1UKDMgM8E36JOyf/1XDXXm1m5YWlDS9s4NDpkAB/jtbt6OwEExFzQE5HDikkKyBFQnAw==", 403 | "dev": true, 404 | "requires": { 405 | "resolve": "^1.15.1", 406 | "source-map": "^0.7.3", 407 | "typescript": "^3.8.3" 408 | } 409 | }, 410 | "validate-npm-package-license": { 411 | "version": "3.0.4", 412 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 413 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 414 | "dev": true, 415 | "requires": { 416 | "spdx-correct": "^3.0.0", 417 | "spdx-expression-parse": "^3.0.0" 418 | } 419 | }, 420 | "which-module": { 421 | "version": "2.0.0", 422 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 423 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 424 | "dev": true 425 | }, 426 | "wrap-ansi": { 427 | "version": "5.1.0", 428 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 429 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 430 | "dev": true, 431 | "requires": { 432 | "ansi-styles": "^3.2.0", 433 | "string-width": "^3.0.0", 434 | "strip-ansi": "^5.0.0" 435 | } 436 | }, 437 | "y18n": { 438 | "version": "4.0.0", 439 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 440 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 441 | "dev": true 442 | }, 443 | "yargs": { 444 | "version": "13.3.0", 445 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", 446 | "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", 447 | "dev": true, 448 | "requires": { 449 | "cliui": "^5.0.0", 450 | "find-up": "^3.0.0", 451 | "get-caller-file": "^2.0.1", 452 | "require-directory": "^2.1.1", 453 | "require-main-filename": "^2.0.0", 454 | "set-blocking": "^2.0.0", 455 | "string-width": "^3.0.0", 456 | "which-module": "^2.0.0", 457 | "y18n": "^4.0.0", 458 | "yargs-parser": "^13.1.1" 459 | } 460 | }, 461 | "yargs-parser": { 462 | "version": "13.1.2", 463 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 464 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 465 | "dev": true, 466 | "requires": { 467 | "camelcase": "^5.0.0", 468 | "decamelize": "^1.2.0" 469 | } 470 | } 471 | } 472 | } 473 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "typescript-to-lua": "^0.32.0", 4 | "prettier": "^1.19.1", 5 | "concurrently": "^5.1.0" 6 | }, 7 | "scripts": { 8 | "build:lua": "tstl -p standaloneLua", 9 | "watch:lua": "tstl -w -p standaloneLua", 10 | "build:js": "tsc -p standaloneJS", 11 | "check:style": "prettier --check \"typescript/**/*[!.d].ts\"", 12 | "fix:style": "prettier --check \"typescript/**/*.ts\" --write" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /source/glue.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | glue::MapValue greeter::glue() { 8 | auto lib = glue::createAnyMap(); 9 | 10 | // clang-format off 11 | 12 | lib["Greeter"] = glue::createClass() 13 | .addConstructor() 14 | .addMethod("greet", &Greeter::greet) 15 | ; 16 | 17 | lib["LanguageCode"] = glue::createEnum() 18 | .addValue("EN", LanguageCode::EN) 19 | .addValue("DE", LanguageCode::DE) 20 | .addValue("ES", LanguageCode::ES) 21 | .addValue("FR", LanguageCode::FR) 22 | ; 23 | 24 | // clang-format on 25 | 26 | return lib; 27 | } 28 | -------------------------------------------------------------------------------- /source/greeter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace greeter; 4 | 5 | Greeter::Greeter(std::string _name) : name(_name) {} 6 | 7 | std::string Greeter::greet(LanguageCode lang) const { 8 | switch (lang) { 9 | default: 10 | case LanguageCode::EN: 11 | return "Hello, " + name + "!"; 12 | case LanguageCode::DE: 13 | return "Hallo " + name + "!"; 14 | case LanguageCode::ES: 15 | return "¡Hola " + name + "!"; 16 | case LanguageCode::FR: 17 | return "Bonjour " + name + "!"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /standaloneJS/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR) 2 | 3 | project(TypeScriptXX 4 | LANGUAGES CXX 5 | ) 6 | 7 | # --- Import tools ---- 8 | 9 | include(../cmake/tools.cmake) 10 | 11 | # --- Set CMake flags 12 | 13 | # disable closure as it currently breaks the script 14 | set(CMAKE_CXX_FLAGS_RELEASE "-Oz -g0 --llvm-lto 3 --closure 0") 15 | set(CMAKE_CXX_FLAGS "-s DISABLE_EXCEPTION_CATCHING=0") 16 | 17 | # ---- Dependencies ---- 18 | 19 | include(../cmake/CPM.cmake) 20 | 21 | CPMAddPackage( 22 | NAME Greeter 23 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/.. 24 | ) 25 | 26 | CPMAddPackage( 27 | NAME cxxopts 28 | GITHUB_REPOSITORY jarro2783/cxxopts 29 | VERSION 2.2.0 30 | OPTIONS 31 | "CXXOPTS_BUILD_EXAMPLES NO" 32 | "CXXOPTS_BUILD_TESTS NO" 33 | ) 34 | 35 | CPMAddPackage( 36 | NAME EmGlue 37 | VERSION 0.2 38 | GITHUB_REPOSITORY TheLartians/EmGlue 39 | ) 40 | 41 | CPMAddPackage( 42 | NAME TypeScriptXXDeclarations 43 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../declarations 44 | ) 45 | 46 | # ---- Create standalone executable ---- 47 | 48 | file(GLOB sources CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp) 49 | 50 | add_executable(TypeScriptXX ${sources}) 51 | 52 | set_target_properties(TypeScriptXX PROPERTIES 53 | CXX_STANDARD 17 54 | OUTPUT_NAME "TypeScriptXX" 55 | ) 56 | 57 | target_link_libraries(TypeScriptXX Greeter EmGlue cxxopts) 58 | 59 | # ---- Create typescript declarations ---- 60 | 61 | add_custom_command( 62 | OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../typescript/cpplib.d.ts 63 | DEPENDS TypeScriptXXDeclarations 64 | COMMAND node ${TypeScriptXXDeclarations_BINARY_DIR}/TypeScriptXXDeclarations.js > ${CMAKE_CURRENT_SOURCE_DIR}/../typescript/cpplib.d.ts 65 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.. 66 | COMMENT "update typescript declarations" 67 | ) 68 | 69 | # ---- Compile typescript code ---- 70 | 71 | include(../cmake/TranspileTypeScript.cmake) 72 | 73 | TranspileTypeScript( 74 | NAME TypeScriptXX 75 | DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.. 76 | RESULT ${CMAKE_CURRENT_SOURCE_DIR}/../dist/js 77 | COMMAND build:js 78 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../typescript/cpplib.d.ts 79 | ) 80 | 81 | add_custom_target(BuildTypeScript ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../dist/js) 82 | -------------------------------------------------------------------------------- /standaloneJS/source/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char** argv) { 10 | // parse command line options 11 | cxxopts::Options options("Glue Typescript Example"); 12 | 13 | // clang-format off 14 | options.add_options() 15 | ("h,help", "Show help") 16 | ("s,script", "path to a lua script or a directory containing an `index.lua` script", cxxopts::value()); 17 | // clang-format on 18 | 19 | auto opts = options.parse(argc, argv); 20 | 21 | if (opts.arguments().size() == 0 || opts["help"].as()) { 22 | std::cout << options.help() << std::endl; 23 | return 0; 24 | } 25 | 26 | glue::emscripten::State state; 27 | 28 | // create glue 29 | auto glue = glue::createAnyMap(); 30 | glue["greeter"] = greeter::glue(); 31 | glue["deleteValue"] = state.getValueDeleter(); 32 | 33 | // add glue to state 34 | state.addModule(glue, state.root()); 35 | 36 | // load js script 37 | if (opts["script"].count() > 0) { 38 | try { 39 | auto path = opts["script"].as(); 40 | auto mainMethod = glue::View(state.run("require(process.cwd() + '/" + path + "')"))["main"]; 41 | mainMethod(); 42 | } catch (const std::exception& e) { 43 | std::cerr << e.what() << '\n'; 44 | } 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /standaloneJS/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "..", 3 | "compilerOptions": { 4 | "outDir": "../dist/js", 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /standaloneLua/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR) 2 | 3 | project(TypeScriptXX 4 | LANGUAGES CXX 5 | ) 6 | 7 | # --- Import tools ---- 8 | 9 | include(../cmake/tools.cmake) 10 | 11 | # ---- Dependencies ---- 12 | 13 | include(../cmake/CPM.cmake) 14 | 15 | CPMAddPackage( 16 | NAME cxxopts 17 | GITHUB_REPOSITORY jarro2783/cxxopts 18 | VERSION 2.2.0 19 | OPTIONS 20 | "CXXOPTS_BUILD_EXAMPLES NO" 21 | "CXXOPTS_BUILD_TESTS NO" 22 | ) 23 | 24 | CPMAddPackage( 25 | NAME FileWatcher 26 | GIT_TAG ee0b97efd206282ef8bb4b9c10c90c941de4a52b 27 | GITHUB_REPOSITORY apetrone/simplefilewatcher 28 | ) 29 | 30 | if (FileWatcher_ADDED) 31 | file (GLOB FileWatcherSources ${FileWatcher_SOURCE_DIR}/source/*.cpp) 32 | add_library(FileWatcher ${FileWatcherSources}) 33 | target_include_directories(FileWatcher PUBLIC ${FileWatcher_SOURCE_DIR}/include) 34 | 35 | install( 36 | TARGETS FileWatcher 37 | ARCHIVE DESTINATION lib 38 | ) 39 | endif() 40 | 41 | CPMAddPackage( 42 | NAME Greeter 43 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/.. 44 | ) 45 | 46 | CPMAddPackage( 47 | NAME TypeScriptXXDeclarations 48 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../declarations 49 | ) 50 | 51 | CPMAddPackage( 52 | NAME LuaGlue 53 | VERSION 1.1.1 54 | GITHUB_REPOSITORY TheLartians/LuaGlue 55 | ) 56 | 57 | # ---- Create standalone executable ---- 58 | 59 | file(GLOB sources CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp) 60 | 61 | add_executable(TypeScriptXX ${sources}) 62 | 63 | set_target_properties(TypeScriptXX PROPERTIES 64 | CXX_STANDARD 17 65 | OUTPUT_NAME "TypeScriptXX" 66 | ) 67 | 68 | target_link_libraries(TypeScriptXX Greeter LuaGlue cxxopts FileWatcher) 69 | 70 | # ---- Create typescript declarations ---- 71 | 72 | add_custom_command( 73 | OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../typescript/cpplib.d.ts 74 | DEPENDS TypeScriptXXDeclarations 75 | COMMAND TypeScriptXXDeclarations > ${CMAKE_CURRENT_SOURCE_DIR}/../typescript/cpplib.d.ts 76 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.. 77 | COMMENT "update typescript declarations" 78 | ) 79 | 80 | # ---- Compile typescript code ---- 81 | 82 | include(../cmake/TranspileTypeScript.cmake) 83 | 84 | TranspileTypeScript( 85 | NAME TypeScriptXX 86 | DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.. 87 | RESULT ${CMAKE_CURRENT_SOURCE_DIR}/../dist/lua 88 | COMMAND build:lua 89 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../typescript/cpplib.d.ts 90 | ) 91 | 92 | add_custom_target(BuildTypeScript ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../dist/lua) 93 | -------------------------------------------------------------------------------- /standaloneLua/source/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "watch.h" 8 | 9 | int main(int argc, char **argv) { 10 | // parse command line options 11 | cxxopts::Options options("Glue Typescript Example"); 12 | 13 | // clang-format off 14 | options.add_options() 15 | ("h,help", "Show help") 16 | ("w,watch", "Run in watch mode") 17 | ("s,script", "path to a lua script or a directory containing an `index.lua` script", cxxopts::value()); 18 | // clang-format on 19 | 20 | auto opts = options.parse(argc, argv); 21 | 22 | if (opts.arguments().size() == 0 || opts["help"].as()) { 23 | std::cout << options.help() << std::endl; 24 | return 0; 25 | } 26 | 27 | // create glue 28 | auto glue = glue::createAnyMap(); 29 | glue["greeter"] = greeter::glue(); 30 | 31 | // run lua 32 | if (opts["script"].count() > 0) { 33 | auto path = opts["script"].as(); 34 | 35 | auto runMainScript = [&]() { 36 | // create Lua state 37 | glue::lua::State lua; 38 | lua.openStandardLibs(); 39 | glue["deleteValue"] = lua.getValueDeleter(); 40 | 41 | // add Glue and set include path 42 | lua.addModule(glue); 43 | lua.root()["package"].asMap()["path"] = path + "/?.lua;" + path + "/?/index.lua;"; 44 | 45 | // load the script from the path via require 46 | auto result = *glue::View(lua.run("return require('.')"))["main"](); 47 | return result.get(); 48 | }; 49 | 50 | if (opts["watch"].count() > 0) { 51 | return watch(path, runMainScript); 52 | } else { 53 | return runMainScript(); 54 | } 55 | } 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /standaloneLua/source/watch.cpp: -------------------------------------------------------------------------------- 1 | #include "watch.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int watch(std::string path, const std::function callback) { 10 | std::cout << "Enter watch mode. watching: " << path << std::endl; 11 | struct ChangeListener : public FW::FileWatchListener { 12 | bool changed; 13 | void handleFileAction(FW::WatchID, const FW::String &, const FW::String &, FW::Action) { 14 | changed = true; 15 | } 16 | } listener; 17 | FW::FileWatcher fileWatcher; 18 | fileWatcher.addWatch(path, &listener, true); 19 | while (true) { 20 | listener.changed = false; 21 | fileWatcher.update(); 22 | if (listener.changed) { 23 | try { 24 | callback(); 25 | } catch (const std::exception &e) { 26 | std::cerr << e.what() << '\n'; 27 | } 28 | } 29 | std::this_thread::sleep_for(std::chrono::seconds(1)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /standaloneLua/source/watch.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int watch(std::string path, const std::function callback); 5 | -------------------------------------------------------------------------------- /standaloneLua/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "..", 3 | "compilerOptions": { 4 | "outDir": "../dist/lua", 5 | }, 6 | "tstl": { 7 | "luaTarget": "5.3", 8 | "luaLibImport": "require" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR) 2 | 3 | project(GreeterTests 4 | LANGUAGES CXX 5 | ) 6 | 7 | # ---- Options ---- 8 | 9 | option(ENABLE_TEST_COVERAGE "Enable test coverage" OFF) 10 | option(TEST_INSTALLED_VERSION "Test the version found by find_package" OFF) 11 | 12 | # --- Import tools ---- 13 | 14 | include(../cmake/tools.cmake) 15 | 16 | # ---- Dependencies ---- 17 | 18 | include(../cmake/CPM.cmake) 19 | 20 | CPMAddPackage( 21 | NAME doctest 22 | GITHUB_REPOSITORY onqtam/doctest 23 | GIT_TAG 2.3.7 24 | ) 25 | 26 | if (TEST_INSTALLED_VERSION) 27 | find_package(Greeter REQUIRED) 28 | else() 29 | CPMAddPackage( 30 | NAME Greeter 31 | SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/.. 32 | ) 33 | endif() 34 | 35 | CPMAddPackage( 36 | NAME Format.cmake 37 | GITHUB_REPOSITORY TheLartians/Format.cmake 38 | VERSION 1.3 39 | ) 40 | 41 | # ---- Create binary ---- 42 | 43 | file(GLOB sources CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp) 44 | add_executable(GreeterTests ${sources}) 45 | target_link_libraries(GreeterTests doctest Greeter) 46 | 47 | set_target_properties(GreeterTests PROPERTIES CXX_STANDARD 17) 48 | 49 | # enable compiler warnings 50 | if (NOT TEST_INSTALLED_VERSION) 51 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") 52 | target_compile_options(Greeter PUBLIC -Wall -pedantic -Wextra -Werror) 53 | elseif(MSVC) 54 | target_compile_options(Greeter PUBLIC /W4 /WX) 55 | target_compile_definitions(GreeterTests PUBLIC DOCTEST_CONFIG_USE_STD_HEADERS) 56 | endif() 57 | endif() 58 | 59 | # ---- Add GreeterTests ---- 60 | 61 | ENABLE_TESTING() 62 | 63 | # Note: doctest and similar testing frameworks can automatically configure CMake tests 64 | # For other testing frameworks add the tests target instead: 65 | # ADD_TEST(GreeterTests GreeterTests) 66 | 67 | include(${doctest_SOURCE_DIR}/scripts/cmake/doctest.cmake) 68 | doctest_discover_tests(GreeterTests) 69 | 70 | # ---- code coverage ---- 71 | 72 | if (ENABLE_TEST_COVERAGE) 73 | target_compile_options(Greeter PUBLIC -O0 -g -fprofile-arcs -ftest-coverage) 74 | target_link_options(Greeter PUBLIC -fprofile-arcs -ftest-coverage) 75 | endif() 76 | -------------------------------------------------------------------------------- /test/source/glue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST_CASE("Glue bindings") { 6 | glue::Context context; 7 | auto greeterGlue = greeter::glue(); 8 | context.addRootMap(greeterGlue); 9 | auto greeterInstance 10 | = context.createInstance(greeterGlue["Greeter"][glue::keys::constructorKey]("Glue")); 11 | REQUIRE(greeterInstance); 12 | CHECK(greeterInstance["greet"](greeterGlue["LanguageCode"]["EN"]).as() 13 | == "Hello, Glue!"); 14 | } 15 | -------------------------------------------------------------------------------- /test/source/greeter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | TEST_CASE("Greeter") { 5 | using namespace greeter; 6 | 7 | Greeter greeter("World"); 8 | 9 | CHECK(greeter.greet(LanguageCode::EN) == "Hello, World!"); 10 | CHECK(greeter.greet(LanguageCode::DE) == "Hallo World!"); 11 | CHECK(greeter.greet(LanguageCode::ES) == "¡Hola World!"); 12 | CHECK(greeter.greet(LanguageCode::FR) == "Bonjour World!"); 13 | } 14 | -------------------------------------------------------------------------------- /test/source/main.cpp: -------------------------------------------------------------------------------- 1 | #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "pretty": true, 4 | "removeComments":true, 5 | "target":"es6", 6 | "types": [], 7 | "strict" : true, 8 | "rootDir":"typescript", 9 | "baseUrl": "typescript", 10 | "module": "commonjs" 11 | }, 12 | 13 | "include": ["typescript"], 14 | "exclude": ["node_modules"], 15 | } 16 | -------------------------------------------------------------------------------- /typescript/index.ts: -------------------------------------------------------------------------------- 1 | export function main() { 2 | const myGreeter = new greeter.Greeter("TypeScript"); 3 | console.log(myGreeter.greet(greeter.LanguageCode.EN)); 4 | // we need to manually delete C++ classes as there are no destructors in JavaScript 5 | deleteValue(myGreeter); 6 | return 0; 7 | } 8 | --------------------------------------------------------------------------------