Skip to content

5x swifter CPython bindings and first NodeJS bindings #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 86 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
bc4d2e9
Ver First Binding Draft in CPython
r2rSahakyan Sep 2, 2023
4e45ccd
Merge pull request #34 from r2rSahakyan/r2rSahakyan-patch-1
ashvardanian Sep 2, 2023
f633d12
Refactor: Restarting CPython bindings
ashvardanian Sep 10, 2023
c984e88
Merge branch 'main-dev' into 35-pure-cpython-rewrite-of-the-bindings
ashvardanian Sep 10, 2023
963cd4d
Docs: Annotate SWAR methods
ashvardanian Sep 11, 2023
aa57b4f
Add: `MemoryMappedFile`
ashvardanian Sep 11, 2023
21a3737
Make: Switch to pure C
ashvardanian Sep 11, 2023
45cb82b
Improve: Passing basic tests
ashvardanian Sep 16, 2023
faacdd1
Improve: Vectorized function calls
ashvardanian Sep 16, 2023
9a38259
Add: Slices and rich comparisons
ashvardanian Sep 16, 2023
6f9a9bd
Make: Remove PyBind11 dependency
ashvardanian Sep 17, 2023
b5689b7
Add: Vectorized `count`
ashvardanian Sep 17, 2023
4ed2e9a
Fix: Bounded Levenstein distance
ashvardanian Sep 17, 2023
d37b342
Break: Shorter function prefixes
ashvardanian Sep 17, 2023
cf324fb
Refactor: `start` and `length` common member names
ashvardanian Sep 17, 2023
21200c8
Fix: Benchmarks compilation
ashvardanian Sep 17, 2023
12b6d0b
Add: `Strs` structure in CPython
ashvardanian Sep 17, 2023
8f76c29
Add: Purely `qsort`-based hybrid sort benchmark
ashvardanian Sep 17, 2023
e53e1b9
Add: Vectorized `split` for Python
ashvardanian Sep 17, 2023
6f6b389
Add: Split into consecutive slices
ashvardanian Sep 18, 2023
c5241b2
Merge pull request #43 from ashvardanian/main
ashvardanian Sep 18, 2023
be8bc9b
Merge branch 'main' into 35-pure-cpython-rewrite-of-the-bindings
ashvardanian Sep 18, 2023
febbdf5
Improve: Same functions as global and members
ashvardanian Sep 19, 2023
b69f070
Merge branch '35-pure-cpython-rewrite-of-the-bindings' of https://git…
ashvardanian Sep 19, 2023
7dc3b28
Add: Buffer protocol support
ashvardanian Sep 19, 2023
177005e
Format: Compact code style
ashvardanian Sep 19, 2023
b771739
Add: `startswith` & `endswith`
ashvardanian Sep 19, 2023
173197f
Improve: Faster `Str` constructor
ashvardanian Sep 19, 2023
a480c0b
Add: `Str` concatenation
ashvardanian Sep 19, 2023
4f69e66
Add: `partition` method in Python
ashvardanian Sep 19, 2023
d7f1f37
Draft verison of CountSubstrAPI
nairihar Sep 21, 2023
ca77b0a
Add count_char function
nairihar Sep 21, 2023
8abb762
Fix issues
nairihar Sep 21, 2023
c1953fa
remove stdio
nairihar Sep 21, 2023
2758c3c
In JavaScript if find unable to find the specified value then it shou…
nairihar Sep 21, 2023
c7eb668
Add: Shuffling method in Python
ashvardanian Sep 22, 2023
5a2f72d
Make: Colorful diagnostics
ashvardanian Sep 22, 2023
c023b27
Merge pull request #44 from nairihar/dev-CountSubstrAPI
ashvardanian Sep 22, 2023
be84abf
Merge branch '25-nodejs-bindings-and-an-npm-package' into dev-FindAPI
ashvardanian Sep 22, 2023
4b1d44f
Merge pull request #47 from nairihar/dev-FindAPI
ashvardanian Sep 22, 2023
577554c
Make: `AlwaysBreakBeforeMultilineStrings`
ashvardanian Sep 22, 2023
021b298
Fix: Memory leak and extra `strlen` calls
ashvardanian Sep 22, 2023
880f437
Improvements, add test cases
nairihar Sep 22, 2023
5b39596
Fix condition in find function
nairihar Sep 22, 2023
1a6a8e4
Improve: Use less temp. variables to count matches
ashvardanian Sep 23, 2023
abbc9dd
Merge pull request #48 from nairihar/25-nodejs-bindings-and-an-npm-pa…
ashvardanian Sep 23, 2023
98fb43b
Make: Deduplicate `.clang-format` settings
ashvardanian Sep 23, 2023
48213a8
Make: Add NumPy dependency
ashvardanian Sep 23, 2023
d67a005
Add: `sort()` and `order()` efficient Py methods
ashvardanian Sep 23, 2023
1265fce
Add: Subscript methods
ashvardanian Sep 24, 2023
876a726
Break: Deprecate multi-source `Strs`; split tests
ashvardanian Sep 24, 2023
ccaa1d2
Minor fixes
nairihar Sep 27, 2023
730948a
Add CI for JavaScript
nairihar Sep 27, 2023
35051f3
Rename countSubstr to count
nairihar Sep 29, 2023
4fcd790
Merge pull request #50 from nairihar/25-nodejs-bindings-and-an-npm-pa…
ashvardanian Sep 30, 2023
ff76eaf
Fix: Applying sort order in Python
ashvardanian Oct 5, 2023
69636f0
Fix: Reverse order
ashvardanian Oct 5, 2023
87f72bd
Merge pull request #37 from ashvardanian/35-pure-cpython-rewrite-of-t…
ashvardanian Oct 5, 2023
41ada28
Merge branch 'main-dev' into 25-nodejs-bindings-and-an-npm-package
ashvardanian Oct 5, 2023
014257c
Merge pull request #51 from ashvardanian/25-nodejs-bindings-and-an-np…
ashvardanian Oct 5, 2023
b1cf5e5
Fix: Buffer width for NodeJS bindings
ashvardanian Oct 5, 2023
7a317c0
Make: Shift JavaScript CI
ashvardanian Oct 5, 2023
61588cc
Improve: Silence type-casting warnings
ashvardanian Oct 5, 2023
b5a0ccf
Fix: Overflow bug in Arm NEON
ashvardanian Oct 5, 2023
e278b45
Make: Dependencies for testing
ashvardanian Oct 5, 2023
b281bf0
Improve: Avoid inner `for`-loop on Arm NEON
ashvardanian Oct 5, 2023
305cec8
Add: Micro-benchmarking notebook
ashvardanian Oct 5, 2023
b09cb3d
Make: `numpy` dependency
ashvardanian Oct 7, 2023
779dded
Improve: drop `ctype`, `stddef`, `stdint` headers
ashvardanian Oct 8, 2023
d102bdf
Fix: SWAR search bug
ashvardanian Oct 8, 2023
9b3c63d
Improve: avoiding nested loop in AVX2
ashvardanian Oct 8, 2023
fa7984a
Break: Avoiding LibC and new API
ashvardanian Oct 9, 2023
a7796a1
Improve: Intro-sort
ashvardanian Oct 9, 2023
51c47fd
Refactor: New C API for JS
ashvardanian Oct 9, 2023
eadad4e
Refactor: Sync up Py and JS bindings
ashvardanian Oct 9, 2023
b0a280d
Make: Formatting and docs
ashvardanian Oct 9, 2023
c8a5b14
Merge pull request #54 from ashvardanian/53-remove-libc-dependency
ashvardanian Oct 9, 2023
bcaf791
Add: Benchmarks notebook
ashvardanian Oct 10, 2023
9bdbf23
Make: Automate major releases
ashvardanian Oct 10, 2023
a878eba
Fix: MSVC-compliant initialization
ashvardanian Oct 10, 2023
5d333d5
Fix: Missing `__builtin_clzll` symbol
ashvardanian Oct 10, 2023
8f9ca8b
Improve: Identical bit-counting intrinsics
ashvardanian Oct 10, 2023
1a5b726
Add: SSE and Arm variants of CRC32
ashvardanian Oct 10, 2023
7b1e170
Improve: BitScan dispatch on Windows
ashvardanian Oct 10, 2023
051f0a8
Test: Printing failed cases
ashvardanian Oct 10, 2023
9a575ce
Fix: `sz_size_t` size in MSVC
ashvardanian Oct 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortIfStatementsOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: true
AllowShortLoopsOnASingleLine: false
AlwaysBreakBeforeMultilineStrings: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakTemplateDeclarations: Yes
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakAfterReturnType: None
PenaltyReturnTypeOnItsOwnLine: 200

Expand All @@ -47,7 +45,7 @@ BraceWrapping:
IndentBraces: false


SortIncludes: false
SortIncludes: true
SortUsingDeclarations: true

SpaceAfterCStyleCast: false
Expand Down
26 changes: 22 additions & 4 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --no-cache-dir --upgrade pip
python -m pip install --no-cache-dir --upgrade pip numpy
pip install --no-cache-dir pytest
- name: Build locally
run: python -m pip install .
- name: Test with PyTest
run: pytest scripts/test.py
run: pytest scripts/


test_python_37:
Expand All @@ -61,13 +61,31 @@ jobs:

- name: Install dependencies
run: |
python -m pip install --no-cache-dir --upgrade pip
python -m pip install --no-cache-dir --upgrade pip numpy
pip install --no-cache-dir pytest

- name: Build locally
run: python -m pip install .

- name: Test with PyTest
run: pytest scripts/test.py
run: pytest scripts/

test_javascript:
name: Test JavaScript
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:

- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'

- name: Build locally
run: npm i

- name: Test
run: npm test
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,4 @@ jobs:
- run: npm test
- uses: JS-DevTools/npm-publish@v2
with:
token: ${{ secrets.NPM_TOKEN }}
token: ${{ secrets.NPM_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ substr_search_cpp
*.so
*.egg-info
*.whl
*.pyd
node_modules/

leipzig1M.txt
8 changes: 8 additions & 0 deletions .releaserc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
{
"preset": "eslint",
"releaseRules": [
{
"tag": "Break",
"release": "major"
},
{
"tag": "Add",
"release": "minor"
Expand All @@ -35,6 +39,10 @@
{
"preset": "eslint",
"releaseRules": [
{
"tag": "Break",
"release": "major"
},
{
"tag": "Add",
"release": "minor"
Expand Down
35 changes: 34 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,29 +116,62 @@
"stop_token": "cpp",
"__verbose_abort": "cpp",
"strstream": "cpp",
"filesystem": "cpp"
"filesystem": "cpp",
"stringzilla.h": "c",
"__memory": "c",
"charconv": "c"
},
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"cSpell.words": [
"abababab",
"allowoverlap",
"basicsize",
"bigram",
"cibuildwheel",
"endregion",
"endswith",
"getitem",
"getslice",
"initproc",
"intp",
"itemsize",
"keeplinebreaks",
"keepseparator",
"kwargs",
"kwds",
"kwnames",
"levenstein",
"maxsplit",
"memcpy",
"MODINIT",
"napi",
"nargsf",
"ndim",
"newfunc",
"NOARGS",
"NOMINMAX",
"NOTIMPLEMENTED",
"numpy",
"octogram",
"pytest",
"Pythonic",
"quadgram",
"readlines",
"releasebuffer",
"richcompare",
"SIMD",
"splitlines",
"startswith",
"stringzilla",
"Strs",
"strzl",
"substr",
"SWAR",
"TPFLAGS",
"unigram",
"Vardanian",
"vectorcallfunc",
"XDECREF",
"Zilla"
]
}
138 changes: 71 additions & 67 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,105 +1,109 @@
# This CMake file is heavily inspired by following `stringzilla` CMake:
# https://github.com/nlohmann/json/blob/develop/CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(stringzilla VERSION 0.1.0 LANGUAGES C CXX)
project(
stringzilla
VERSION 0.1.0
LANGUAGES C CXX)

set (CMAKE_C_STANDARD 11)
set (CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Determine if USearch is built as a subproject (using `add_subdirectory`) or if it is the main project
# Determine if USearch is built as a subproject (using `add_subdirectory`) or if
# it is the main project
set(STRINGZILLA_IS_MAIN_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(STRINGZILLA_IS_MAIN_PROJECT ON)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(STRINGZILLA_IS_MAIN_PROJECT ON)
endif()

# Options
option(STRINGZILLA_INSTALL "Install CMake targets" OFF)
option(STRINGZILLA_BUILD_TEST "Compile a native unit test in C++" ${STRINGZILLA_IS_MAIN_PROJECT})
option(STRINGZILLA_BUILD_BENCHMARK "Compile a native benchmark in C++" ${STRINGZILLA_IS_MAIN_PROJECT})
option(STRINGZILLA_BUILD_TEST "Compile a native unit test in C++"
${STRINGZILLA_IS_MAIN_PROJECT})
option(STRINGZILLA_BUILD_BENCHMARK "Compile a native benchmark in C++"
${STRINGZILLA_IS_MAIN_PROJECT})
option(STRINGZILLA_BUILD_WOLFRAM "Compile Wolfram Language bindings" OFF)

# Includes
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
include(ExternalProject)

# Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif ()
# Allow CMake 3.13+ to override options when using FetchContent /
# add_subdirectory
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()

# Configuration
include(GNUInstallDirs)
set(STRINGZILLA_TARGET_NAME ${PROJECT_NAME})
set(STRINGZILLA_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "")
set(STRINGZILLA_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(STRINGZILLA_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(STRINGZILLA_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
set(STRINGZILLA_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(STRINGZILLA_CMAKE_VERSION_CONFIG_FILE "${STRINGZILLA_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(STRINGZILLA_CMAKE_PROJECT_CONFIG_FILE "${STRINGZILLA_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(STRINGZILLA_CMAKE_PROJECT_TARGETS_FILE "${STRINGZILLA_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
set(STRINGZILLA_PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/pkgconfig")

set(STRINGZILLA_TARGET_NAME ${PROJECT_NAME})
set(STRINGZILLA_CONFIG_INSTALL_DIR
"${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}"
CACHE INTERNAL "")
set(STRINGZILLA_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(STRINGZILLA_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(STRINGZILLA_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
set(STRINGZILLA_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(STRINGZILLA_CMAKE_VERSION_CONFIG_FILE
"${STRINGZILLA_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(STRINGZILLA_CMAKE_PROJECT_CONFIG_FILE
"${STRINGZILLA_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(STRINGZILLA_CMAKE_PROJECT_TARGETS_FILE
"${STRINGZILLA_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
set(STRINGZILLA_PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/pkgconfig")

# Define our header-only library
add_library(${STRINGZILLA_TARGET_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${STRINGZILLA_TARGET_NAME} ALIAS ${STRINGZILLA_TARGET_NAME})
add_library(${PROJECT_NAME}::${STRINGZILLA_TARGET_NAME} ALIAS
${STRINGZILLA_TARGET_NAME})
set(STRINGZILLA_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")

target_compile_definitions(
${STRINGZILLA_TARGET_NAME}
INTERFACE
$<$<NOT:$<BOOL:${JSON_GlobalUDLs}>>:STRINGZILLA_USE_OPENMP=0>
)
${STRINGZILLA_TARGET_NAME}
INTERFACE $<$<NOT:$<BOOL:${JSON_GlobalUDLs}>>:STRINGZILLA_USE_OPENMP=0>)
target_include_directories(
${STRINGZILLA_TARGET_NAME}
${STRINGZILLA_SYSTEM_INCLUDE} INTERFACE
$<BUILD_INTERFACE:${STRINGZILLA_INCLUDE_BUILD_DIR}>
$<INSTALL_INTERFACE:include>
)
${STRINGZILLA_TARGET_NAME} ${STRINGZILLA_SYSTEM_INCLUDE}
INTERFACE $<BUILD_INTERFACE:${STRINGZILLA_INCLUDE_BUILD_DIR}>
$<INSTALL_INTERFACE:include>)

if(STRINGZILLA_INSTALL)
install(
DIRECTORY ${STRINGZILLA_INCLUDE_BUILD_DIR}
DESTINATION ${STRINGZILLA_INCLUDE_INSTALL_DIR}
)
install(
FILES ${STRINGZILLA_CMAKE_PROJECT_CONFIG_FILE} ${STRINGZILLA_CMAKE_VERSION_CONFIG_FILE}
DESTINATION ${STRINGZILLA_CONFIG_INSTALL_DIR}
)
export(
TARGETS ${STRINGZILLA_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${STRINGZILLA_CMAKE_PROJECT_TARGETS_FILE}
)
install(
TARGETS ${STRINGZILLA_TARGET_NAME}
EXPORT ${STRINGZILLA_TARGETS_EXPORT_NAME}
INCLUDES DESTINATION ${STRINGZILLA_INCLUDE_INSTALL_DIR}
)
install(
EXPORT ${STRINGZILLA_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${STRINGZILLA_CONFIG_INSTALL_DIR}
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION ${STRINGZILLA_PKGCONFIG_INSTALL_DIR}
)
install(DIRECTORY ${STRINGZILLA_INCLUDE_BUILD_DIR}
DESTINATION ${STRINGZILLA_INCLUDE_INSTALL_DIR})
install(FILES ${STRINGZILLA_CMAKE_PROJECT_CONFIG_FILE}
${STRINGZILLA_CMAKE_VERSION_CONFIG_FILE}
DESTINATION ${STRINGZILLA_CONFIG_INSTALL_DIR})
export(
TARGETS ${STRINGZILLA_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${STRINGZILLA_CMAKE_PROJECT_TARGETS_FILE})
install(
TARGETS ${STRINGZILLA_TARGET_NAME}
EXPORT ${STRINGZILLA_TARGETS_EXPORT_NAME}
INCLUDES
DESTINATION ${STRINGZILLA_INCLUDE_INSTALL_DIR})
install(
EXPORT ${STRINGZILLA_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${STRINGZILLA_CONFIG_INSTALL_DIR})
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION ${STRINGZILLA_PKGCONFIG_INSTALL_DIR})
endif()

if(${STRINGZILLA_BUILD_TEST} OR ${STRINGZILLA_BUILD_BENCHMARK})
add_executable(stringzilla_test scripts/test.cpp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -O3 -flto -march=native -finline-functions -funroll-loops"
)

target_include_directories(stringzilla_test PRIVATE stringzilla)
set_target_properties(stringzilla_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set_target_properties(stringzilla_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR})

if(${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)
include(CTest)
enable_testing()
add_test(NAME stringzilla_test COMMAND stringzilla_test)
if(${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER
3.13)
include(CTest)
enable_testing()
add_test(NAME stringzilla_test COMMAND stringzilla_test)
endif()
endif()

Loading