couchbase 4.4.3 → 4.4.4
Sign up to get free protection for your applications and to get access to all the features.
- package/BUILDING.md +182 -0
- package/CMakeLists.txt +11 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +4 -2
- package/deps/couchbase-cxx-cache/boringssl/e31ea00c1ea52052d2d78d44006cc88c80fa24a9/boringssl/src/BUILDING.md +206 -0
- package/deps/couchbase-cxx-client/CMakeLists.txt +3 -1
- package/deps/couchbase-cxx-client/README.md +2 -2
- package/deps/couchbase-cxx-client/cmake/APKBUILD.in +54 -0
- package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +0 -5
- package/deps/couchbase-cxx-client/cmake/Packaging.cmake +174 -11
- package/deps/couchbase-cxx-client/cmake/RPath.cmake +10 -0
- package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +4 -0
- package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
- package/deps/couchbase-cxx-client/cmake/couchbase-cxx-client.spec.in +2 -2
- package/deps/couchbase-cxx-client/cmake/couchbase_cxx_client.pc.in +2 -2
- package/deps/couchbase-cxx-client/cmake/debian/changelog.in +5 -0
- package/deps/couchbase-cxx-client/cmake/debian/compat +1 -0
- package/deps/couchbase-cxx-client/cmake/debian/control +40 -0
- package/deps/couchbase-cxx-client/cmake/debian/rules +41 -0
- package/deps/couchbase-cxx-client/cmake/debian/source/format +1 -0
- package/deps/couchbase-cxx-client/core/impl/analytics.cxx +1 -0
- package/deps/couchbase-cxx-client/core/impl/collection.cxx +27 -3
- package/deps/couchbase-cxx-client/core/impl/error.cxx +24 -3
- package/deps/couchbase-cxx-client/core/impl/get_replica.hxx +2 -0
- package/deps/couchbase-cxx-client/core/impl/lookup_in_replica.hxx +2 -0
- package/deps/couchbase-cxx-client/core/impl/observe_seqno.hxx +2 -0
- package/deps/couchbase-cxx-client/core/impl/query.cxx +1 -0
- package/deps/couchbase-cxx-client/core/impl/search.cxx +2 -0
- package/deps/couchbase-cxx-client/core/io/http_command.hxx +2 -2
- package/deps/couchbase-cxx-client/core/io/mcbp_command.hxx +1 -1
- package/deps/couchbase-cxx-client/core/meta/features.hxx +11 -0
- package/deps/couchbase-cxx-client/core/meta/version.cxx +47 -6
- package/deps/couchbase-cxx-client/core/operations/document_analytics.cxx +23 -17
- package/deps/couchbase-cxx-client/core/operations/document_analytics.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/document_append.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_decrement.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_exists.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_get.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_get_all_replicas.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_get_and_lock.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_get_and_touch.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_get_any_replica.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_get_projected.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_increment.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_insert.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in_all_replicas.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_lookup_in_any_replica.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_mutate_in.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_prepend.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/document_remove.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_replace.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_search.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/document_touch.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_unlock.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_upsert.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/document_view.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/http_noop.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_dataset_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_dataset_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_dataset_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_dataverse_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_dataverse_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_get_pending_mutations.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_index_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_index_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_index_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_connect.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_disconnect.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_get_all.cxx +23 -15
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_get_all.hxx +4 -3
- package/deps/couchbase-cxx-client/core/operations/management/analytics_link_replace.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_describe.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_flush.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_get.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/bucket_update.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/change_password.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/cluster_describe.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/cluster_developer_preview_enable.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/collection_create.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/collection_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/collection_update.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/collections_manifest_get.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/eventing_deploy_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_drop_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_get_all_functions.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_get_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_get_status.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_pause_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_resume_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_undeploy_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/eventing_upsert_function.hxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/management/freeform.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/group_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/group_get.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/group_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/group_upsert.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -0
- package/deps/couchbase-cxx-client/core/operations/management/role_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/scope_create.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/scope_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/scope_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_get_stats.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_get_stats.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/user_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/user_get.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/user_get_all.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/user_upsert.cxx +3 -3
- package/deps/couchbase-cxx-client/core/operations/management/user_upsert.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/view_index_drop.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/view_index_get.hxx +1 -0
- package/deps/couchbase-cxx-client/core/operations/management/view_index_get_all.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/view_index_upsert.hxx +1 -0
- package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +9 -21
- package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +6 -33
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +41 -41
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +15 -16
- package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +2 -2
- package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +0 -20
- package/deps/couchbase-cxx-client/couchbase/common_options.hxx +16 -1
- package/deps/couchbase-cxx-client/couchbase/metrics/otel_meter.hxx +16 -20
- package/dist/analyticsindexmanager.d.ts +98 -14
- package/dist/analyticsindexmanager.js +452 -411
- package/dist/binding.d.ts +53 -4
- package/dist/bindingutilities.d.ts +26 -1
- package/dist/bindingutilities.js +108 -1
- package/dist/couchbase.d.ts +3 -1
- package/dist/couchbase.js +2 -0
- package/dist/rangeScan.d.ts +1 -1
- package/dist/rangeScan.js +1 -1
- package/dist/transactions.d.ts +34 -3
- package/dist/transactions.js +25 -18
- package/dist/transcoders.d.ts +68 -0
- package/dist/transcoders.js +194 -1
- package/dist/usermanager.d.ts +14 -14
- package/dist/usermanager.js +178 -228
- package/dist/utilities.js +4 -6
- package/dist/utilities_internal.js +1 -2
- package/package.json +9 -8
- package/src/connection.cpp +22 -0
- package/src/connection.hpp +12 -0
- package/src/connection_autogen.cpp +100 -0
- package/src/jstocbpp_autogen.hpp +315 -8
- package/src/jstocbpp_transactions.hpp +1 -2
- package/tools/gen-bindings-js.js +38 -3
- package/tools/gen-bindings-json.py +575 -328
@@ -1,21 +1,36 @@
|
|
1
|
-
|
1
|
+
# Copyright 2016-2024. Couchbase, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
2
16
|
import json
|
17
|
+
import os
|
18
|
+
import pathlib
|
3
19
|
import re
|
4
|
-
import
|
20
|
+
import subprocess
|
21
|
+
import sys
|
5
22
|
|
6
23
|
from functools import reduce
|
24
|
+
from typing import (Dict, List, Optional, Tuple)
|
25
|
+
|
26
|
+
import clang.cindex
|
7
27
|
|
8
|
-
#
|
28
|
+
# START CONFIGURATION
|
9
29
|
|
10
|
-
|
11
|
-
|
12
|
-
# x64: /usr/local/opt/llvm/lib
|
13
|
-
# arm64: /opt/homebrew/opt/llvm/lib
|
14
|
-
llvmLibPath = "/usr/local/Cellar/llvm/13.0.1_1/lib/"
|
30
|
+
CXX_CLIENT_ROOT = os.path.join(pathlib.Path(__file__).parent.parent, 'deps', 'couchbase-cxx-client')
|
31
|
+
CXX_CLIENT_CACHE = os.path.join(pathlib.Path(__file__).parent.parent, 'deps', 'couchbase-cxx-cache')
|
15
32
|
|
16
|
-
|
17
|
-
cxx_client_cache = "../deps/couchbase-cxx-cache"
|
18
|
-
cxx_deps_include_paths = {
|
33
|
+
CXX_DEPS_INCLUDE_PATHS = {
|
19
34
|
'asio': ['-I{0}/asio/{1}/asio/asio/include'],
|
20
35
|
'fmt': ['-I{0}/fmt/{1}/fmt/include'],
|
21
36
|
'gsl': ['-I{0}/gsl/{1}/gsl/include'],
|
@@ -25,7 +40,7 @@ cxx_deps_include_paths = {
|
|
25
40
|
'spdlog': ['-I{0}/spdlog/{1}/spdlog/include'],
|
26
41
|
}
|
27
42
|
|
28
|
-
|
43
|
+
FILE_LIST = [
|
29
44
|
"core/management/analytics_dataset.hxx",
|
30
45
|
"core/management/analytics_index.hxx",
|
31
46
|
"core/management/analytics_link_azure_blob_external.hxx",
|
@@ -76,7 +91,7 @@ fileList = [
|
|
76
91
|
"core/vector_query_combination.hxx",
|
77
92
|
]
|
78
93
|
|
79
|
-
|
94
|
+
TYPE_LIST = [
|
80
95
|
"couchbase::core::management::analytics::dataset",
|
81
96
|
"couchbase::core::management::analytics::index",
|
82
97
|
"couchbase::core::management::analytics::azure_blob_external_link",
|
@@ -171,331 +186,563 @@ typeList = [
|
|
171
186
|
"couchbase::read_preference"
|
172
187
|
]
|
173
188
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
cpm_path = os.path.join(cxx_client_cache, dep)
|
180
|
-
dir_pattern = r'[0-9a-z]{40}'
|
181
|
-
cpm_hash_dir = next((d for d in os.listdir(cpm_path)
|
182
|
-
if os.path.isdir(os.path.join(cpm_path, d)) and re.match(dir_pattern, d)),
|
183
|
-
None)
|
184
|
-
if not cpm_hash_dir:
|
185
|
-
raise Exception(f'Unable to find CPM hash directory for path: {cpm_path}.')
|
186
|
-
return list(map(lambda p: p.format(cxx_client_cache, cpm_hash_dir), includes))
|
187
|
-
|
188
|
-
def list_headers_in_dir(path):
|
189
|
-
# enumerates a folder but keeps the full pathing for the files returned
|
190
|
-
# and removes certain files we don't want (like non-hxx, _json.hxx or _fmt.hxx)
|
191
|
-
|
192
|
-
# list all the files in the folder
|
193
|
-
files = os.listdir(path)
|
194
|
-
# only include .hxx files
|
195
|
-
files = list(filter(lambda x: x.endswith('.hxx'), files))
|
196
|
-
# add the folder path back on
|
197
|
-
files = list(map(lambda x: path + x, files))
|
198
|
-
return files
|
199
|
-
|
200
|
-
|
201
|
-
# parse through the list of files specified and expand wildcards
|
202
|
-
fullFileList = []
|
203
|
-
for filePath in fileList:
|
204
|
-
if "*" in filePath:
|
205
|
-
# wildcard path
|
206
|
-
basePath = filePath[:-1]
|
207
|
-
if "*" in basePath:
|
208
|
-
# if there is still a wildcard, we have an issue...
|
209
|
-
raise NotImplementedError(
|
210
|
-
"wildcard only supported at end of file path")
|
211
|
-
files = list_headers_in_dir(os.path.join(cxx_client_root, basePath))
|
212
|
-
fullFileList = fullFileList + files
|
213
|
-
else:
|
214
|
-
# normal path
|
215
|
-
fullFileList.append(os.path.join(cxx_client_root, filePath))
|
216
|
-
|
217
|
-
# exclude _json.hxx files
|
218
|
-
fullFileList = list(
|
219
|
-
filter(lambda x: not x.endswith('_json.hxx'), fullFileList))
|
220
|
-
# exclude _fmt.hxx files
|
221
|
-
fullFileList = list(
|
222
|
-
filter(lambda x: not x.endswith('_fmt.hxx'), fullFileList))
|
223
|
-
|
224
|
-
|
225
|
-
# generate a list of regexps from the type list (for handling wildcards)
|
226
|
-
typeListRe = list(map(lambda x: x.replace("*", "(.*)") + "(.*)", typeList))
|
227
|
-
|
228
|
-
|
229
|
-
def is_included_type(name, with_durability=False):
|
230
|
-
|
231
|
-
# TODO(brett19): This should be generalized somehow...
|
232
|
-
if "is_compound_operation" in name:
|
233
|
-
return False
|
234
|
-
|
235
|
-
if "replica_context" in name:
|
236
|
-
return False
|
237
|
-
|
238
|
-
if with_durability is True and '_with_legacy_durability' not in name:
|
239
|
-
return False
|
240
|
-
|
241
|
-
for x in typeListRe:
|
242
|
-
if re.fullmatch(x, name):
|
243
|
-
return True
|
244
|
-
return False
|
245
|
-
|
189
|
+
STD_COMPARATOR_TEMPLATES = ["std::less<{0}>", "std::greater<{0}>", "std::less_equal<{0}>", "std::greater_equal<{0}>"]
|
190
|
+
# flatten the list of lists
|
191
|
+
STD_COMPARATORS = list(reduce(lambda a, b: a + b,
|
192
|
+
list(map(lambda c: [c.format(s) for s in ['', 'void']], STD_COMPARATOR_TEMPLATES)),
|
193
|
+
[]))
|
246
194
|
|
247
|
-
|
248
|
-
|
195
|
+
INTERNAL_STRUCTS = []
|
196
|
+
UNNAMED_STRUCT_DELIM = '::(unnamed struct'
|
249
197
|
|
198
|
+
# IMPORTANT: the templates must exist in the TYPE_LIST
|
199
|
+
TEMPLATED_REQUESTS = {
|
200
|
+
'analytics_link_create_request': {
|
201
|
+
'template_name': 'analytics_link_type',
|
202
|
+
'templates': ['couchbase::core::management::analytics::azure_blob_external_link',
|
203
|
+
'couchbase::core::management::analytics::couchbase_remote_link',
|
204
|
+
'couchbase::core::management::analytics::s3_external_link']
|
205
|
+
},
|
206
|
+
'analytics_link_replace_request': {
|
207
|
+
'template_name': 'analytics_link_type',
|
208
|
+
'templates': ['couchbase::core::management::analytics::azure_blob_external_link',
|
209
|
+
'couchbase::core::management::analytics::couchbase_remote_link',
|
210
|
+
'couchbase::core::management::analytics::s3_external_link']
|
211
|
+
},
|
212
|
+
}
|
250
213
|
|
251
|
-
|
252
|
-
|
253
|
-
|
214
|
+
# END - CONFIGURATION
|
215
|
+
|
216
|
+
|
217
|
+
class BindingsGenerator:
|
218
|
+
|
219
|
+
def __init__(self,
|
220
|
+
llvm_clang_version: Optional[str] = None,
|
221
|
+
llvm_libdir: Optional[str] = None,
|
222
|
+
llvm_includedir: Optional[str] = None,
|
223
|
+
system_headers: Optional[str] = None,
|
224
|
+
verbose: Optional[bool] = False) -> None:
|
225
|
+
self._op_types = []
|
226
|
+
self._op_enums = []
|
227
|
+
self._full_file_list = []
|
228
|
+
# generate a list of regexps from the type list (for handling wildcards)
|
229
|
+
self._type_list_re = list(map(lambda x: x.replace("*", "(.*)") + "(.*)", TYPE_LIST))
|
230
|
+
self._verbose = verbose
|
231
|
+
self.configure_generator(llvm_clang_version, llvm_libdir, llvm_includedir, system_headers)
|
232
|
+
|
233
|
+
def configure_generator(self,
|
234
|
+
version: Optional[str] = None,
|
235
|
+
libdir: Optional[str] = None,
|
236
|
+
includedir: Optional[str] = None,
|
237
|
+
system_headers: Optional[str] = None) -> None:
|
238
|
+
if version is None:
|
239
|
+
version = os.environ.get('CN_LLVM_VERSION')
|
240
|
+
if version is None:
|
241
|
+
BindingsGenerator.find_llvm()
|
242
|
+
version = BindingsGenerator.get_llvm_version()
|
243
|
+
if version is None:
|
244
|
+
raise ValueError('Missing LLVM version.')
|
245
|
+
|
246
|
+
if includedir is None:
|
247
|
+
includedir = os.environ.get('CN_LLVM_INCLUDE')
|
248
|
+
if includedir is None:
|
249
|
+
includedir = BindingsGenerator.get_llvm_includedir()
|
250
|
+
if includedir is None:
|
251
|
+
raise ValueError('Missing LLVM include directory.')
|
252
|
+
|
253
|
+
if libdir is None:
|
254
|
+
libdir = os.environ.get('CN_LLVM_LIB')
|
255
|
+
if libdir is None:
|
256
|
+
libdir = BindingsGenerator.get_llvm_libdir()
|
257
|
+
if libdir is None:
|
258
|
+
raise ValueError('Missing LLVM lib directory.')
|
259
|
+
|
260
|
+
if system_headers is None:
|
261
|
+
system_headers = os.environ.get('CN_SYS_HEADERS')
|
262
|
+
if system_headers is None:
|
263
|
+
system_headers = BindingsGenerator.get_system_headers()
|
264
|
+
if system_headers is None:
|
265
|
+
raise ValueError('Missing system headers path.')
|
266
|
+
|
267
|
+
if self._verbose:
|
268
|
+
print(f'Using libdir={libdir}')
|
269
|
+
clang.cindex.Config.set_library_path(libdir)
|
270
|
+
|
271
|
+
self._include_paths = [
|
272
|
+
'-I/opt/homebrew/opt/llvm/include/c++/v1',
|
273
|
+
f'-I{CXX_CLIENT_ROOT}/',
|
274
|
+
f'-I/opt/homebrew/Cellar/llvm/{version}/lib/clang/{version[:2]}/include',
|
275
|
+
f'-I{system_headers}/usr/include'
|
276
|
+
]
|
277
|
+
|
278
|
+
for dep, inc in CXX_DEPS_INCLUDE_PATHS.items():
|
279
|
+
self._include_paths.extend(BindingsGenerator.set_cxx_deps_include_paths(dep, inc))
|
280
|
+
|
281
|
+
if self._verbose:
|
282
|
+
print(f'Include paths={self._include_paths}')
|
283
|
+
|
284
|
+
self.set_file_list()
|
285
|
+
|
286
|
+
def gen_bindings(self) -> None:
|
287
|
+
|
288
|
+
for headerPath in self._full_file_list:
|
289
|
+
print("processing " + headerPath)
|
290
|
+
index = clang.cindex.Index.create()
|
291
|
+
if self._verbose is True:
|
292
|
+
args = ['-std=c++17', '-v', f'-isysroot{os.getcwd()}'] + self._include_paths
|
293
|
+
else:
|
294
|
+
args = ['-std=c++17', f'-isysroot{os.getcwd()}'] + self._include_paths
|
295
|
+
translation_unit = index.parse(headerPath, args=args)
|
296
|
+
|
297
|
+
# output clang compiler diagnostics information (for debugging)
|
298
|
+
if 1:
|
299
|
+
for diagnostic in translation_unit.diagnostics:
|
300
|
+
diagnosticMsg = diagnostic.format()
|
301
|
+
print(diagnostic)
|
302
|
+
|
303
|
+
self.traverse(translation_unit.cursor, [], headerPath)
|
304
|
+
|
305
|
+
jsonData = json.dumps({
|
306
|
+
'op_structs': self._op_types,
|
307
|
+
'op_enums': self._op_enums
|
308
|
+
})
|
309
|
+
|
310
|
+
f = open("bindings.json", "w")
|
311
|
+
f.write(jsonData)
|
312
|
+
f.close()
|
313
|
+
|
314
|
+
def set_file_list(self) -> None:
|
315
|
+
for file_path in FILE_LIST:
|
316
|
+
if "*" in file_path:
|
317
|
+
# wildcard path
|
318
|
+
basePath = file_path[:-1]
|
319
|
+
if "*" in basePath:
|
320
|
+
# if there is still a wildcard, we have an issue...
|
321
|
+
raise NotImplementedError(
|
322
|
+
"wildcard only supported at end of file path")
|
323
|
+
if basePath[-1] != os.path.sep:
|
324
|
+
tokens = basePath.split(os.path.sep)
|
325
|
+
# filter = tokens[-1]
|
326
|
+
files = BindingsGenerator.list_headers_in_dir(os.path.join(CXX_CLIENT_ROOT, *tokens[:-1]),
|
327
|
+
tokens[-1])
|
328
|
+
else:
|
329
|
+
files = BindingsGenerator.list_headers_in_dir(os.path.join(CXX_CLIENT_ROOT, basePath))
|
330
|
+
self._full_file_list = self._full_file_list + files
|
331
|
+
else:
|
332
|
+
# normal path
|
333
|
+
self._full_file_list.append(os.path.join(CXX_CLIENT_ROOT, file_path))
|
334
|
+
|
335
|
+
# exclude _json.hxx files
|
336
|
+
self._full_file_list = list(filter(lambda x: not x.endswith('_json.hxx'), self._full_file_list))
|
337
|
+
# exclude _fmt.hxx files
|
338
|
+
self._full_file_list = list(filter(lambda x: not x.endswith('_fmt.hxx'), self._full_file_list))
|
339
|
+
|
340
|
+
def traverse(self, node, namespace, main_file) -> None:
|
341
|
+
# only scan the elements of the file we parsed
|
342
|
+
if node.location.file is not None and node.location.file.name != main_file:
|
343
|
+
return
|
344
|
+
|
345
|
+
if node.kind == clang.cindex.CursorKind.STRUCT_DECL or node.kind == clang.cindex.CursorKind.CLASS_DECL:
|
346
|
+
full_struct_name = "::".join([*namespace, node.displayname])
|
347
|
+
if full_struct_name.endswith('::') or UNNAMED_STRUCT_DELIM in full_struct_name:
|
348
|
+
if full_struct_name.endswith('::'):
|
349
|
+
struct_name = full_struct_name
|
350
|
+
else:
|
351
|
+
struct_name = full_struct_name.split(UNNAMED_STRUCT_DELIM)[0]
|
352
|
+
match = next((s for s in INTERNAL_STRUCTS if struct_name in s), None)
|
353
|
+
if match:
|
354
|
+
full_struct_name = match
|
355
|
+
|
356
|
+
if (BindingsGenerator.is_included_type(full_struct_name, self._type_list_re)
|
357
|
+
or full_struct_name in INTERNAL_STRUCTS):
|
358
|
+
struct_fields = []
|
359
|
+
parents = []
|
360
|
+
for child in node.get_children():
|
361
|
+
if child.kind == clang.cindex.CursorKind.FIELD_DECL:
|
362
|
+
struct_type = BindingsGenerator.parse_type(child.type)
|
363
|
+
type_str = child.type.get_canonical().spelling
|
364
|
+
if 'unnamed' in type_str:
|
365
|
+
name_tokens = type_str.split('::')
|
366
|
+
name_override = '::'.join(name_tokens[:-1] + [child.displayname])
|
367
|
+
struct_type['name'] = name_override
|
368
|
+
INTERNAL_STRUCTS.append(name_override)
|
369
|
+
|
370
|
+
struct_fields.append({
|
371
|
+
"name": child.displayname,
|
372
|
+
"type": struct_type,
|
373
|
+
})
|
374
|
+
elif child.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER:
|
375
|
+
parents.append("::".join([*namespace, child.displayname]))
|
376
|
+
|
377
|
+
if len(parents) > 0:
|
378
|
+
part_op_types = [ot for ot in self._op_types if ot['name'] in parents]
|
379
|
+
print(f'{part_op_types=}')
|
380
|
+
for sot in part_op_types:
|
381
|
+
struct_fields.extend(sot['fields'])
|
382
|
+
|
383
|
+
# replica read changes introduced duplicate get requests
|
384
|
+
if any(map(lambda op: op['name'] == full_struct_name, self._op_types)):
|
385
|
+
return
|
386
|
+
|
387
|
+
self._op_types.append({
|
388
|
+
"name": full_struct_name,
|
389
|
+
"fields": struct_fields,
|
390
|
+
})
|
391
|
+
if node.kind == clang.cindex.CursorKind.TYPE_ALIAS_DECL:
|
392
|
+
full_struct_name = "::".join([*namespace, node.displayname])
|
393
|
+
if BindingsGenerator.is_included_type(full_struct_name, self._type_list_re, with_durability=True):
|
394
|
+
type_ref = next((c for c in node.get_children() if c.kind == clang.cindex.CursorKind.TYPE_REF), None)
|
395
|
+
if type_ref:
|
396
|
+
base_request_name = type_ref.displayname.replace('struct', '').strip()
|
397
|
+
base_request = next((op for op in self._op_types if op['name'] == base_request_name), None)
|
398
|
+
if base_request:
|
399
|
+
new_fields = [f for f in base_request['fields'] if f['name'] != 'durability_level']
|
400
|
+
new_fields.extend([
|
401
|
+
{"name": "persist_to", "type": {"name": "couchbase::persist_to"}},
|
402
|
+
{"name": "replicate_to", "type": {"name": "couchbase::replicate_to"}}
|
403
|
+
])
|
254
404
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
405
|
+
self._op_types.append({
|
406
|
+
"name": full_struct_name,
|
407
|
+
"fields": new_fields
|
408
|
+
})
|
409
|
+
if node.kind == clang.cindex.CursorKind.ENUM_DECL:
|
410
|
+
full_enum_name = "::".join([*namespace, node.displayname])
|
411
|
+
if BindingsGenerator.is_included_type(full_enum_name, self._type_list_re):
|
412
|
+
enumValues = []
|
413
|
+
|
414
|
+
for child in node.get_children():
|
415
|
+
if child.kind == clang.cindex.CursorKind.ENUM_CONSTANT_DECL:
|
416
|
+
enumValues.append({
|
417
|
+
"name": child.displayname,
|
418
|
+
"value": child.enum_value,
|
419
|
+
})
|
420
|
+
self._op_enums.append({
|
421
|
+
"name": full_enum_name,
|
422
|
+
"type": BindingsGenerator.parse_type(node.enum_type),
|
423
|
+
"values": enumValues,
|
424
|
+
})
|
425
|
+
|
426
|
+
if node.kind == clang.cindex.CursorKind.NAMESPACE:
|
427
|
+
namespace = [*namespace, node.displayname]
|
428
|
+
if node.kind == clang.cindex.CursorKind.CLASS_DECL:
|
429
|
+
namespace = [*namespace, node.displayname]
|
430
|
+
if node.kind == clang.cindex.CursorKind.STRUCT_DECL:
|
431
|
+
namespace = [*namespace, node.displayname]
|
432
|
+
if node.kind == clang.cindex.CursorKind.CLASS_TEMPLATE:
|
433
|
+
name_tokens = node.displayname.split('<')
|
434
|
+
if len(name_tokens) == 2 and name_tokens[0] in TEMPLATED_REQUESTS:
|
435
|
+
req = TEMPLATED_REQUESTS.get(name_tokens[0])
|
436
|
+
full_struct_name = "::".join([*namespace, node.displayname])
|
437
|
+
for template in req['templates']:
|
438
|
+
struct_fields = []
|
439
|
+
for child in node.get_children():
|
440
|
+
if child.kind == clang.cindex.CursorKind.FIELD_DECL:
|
441
|
+
type_str = child.type.get_canonical().spelling
|
442
|
+
if 'type-parameter' in type_str:
|
443
|
+
struct_type = {
|
444
|
+
'name': 'template',
|
445
|
+
'of': {'name': template}}
|
446
|
+
else:
|
447
|
+
struct_type = BindingsGenerator.parse_type(child.type)
|
448
|
+
# print(f'struct_type={child.type}; type.kind={child.type.kind}; {type_str=}, displayname={child.displayname}')
|
449
|
+
struct_fields.append({
|
450
|
+
"name": child.displayname,
|
451
|
+
"type": struct_type,
|
452
|
+
})
|
453
|
+
self._op_types.append({
|
454
|
+
"name": full_struct_name.replace(req['template_name'], template),
|
455
|
+
"fields": struct_fields,
|
456
|
+
})
|
457
|
+
# return
|
458
|
+
|
459
|
+
for child in node.get_children():
|
460
|
+
self.traverse(child, namespace, main_file)
|
461
|
+
|
462
|
+
@staticmethod
|
463
|
+
def set_cxx_deps_include_paths(dep, includes):
|
464
|
+
cpm_path = os.path.join(CXX_CLIENT_CACHE, dep)
|
465
|
+
dir_pattern = r'[0-9a-z]{40}'
|
466
|
+
cpm_hash_dir = next((d for d in os.listdir(cpm_path)
|
467
|
+
if os.path.isdir(os.path.join(cpm_path, d)) and re.match(dir_pattern, d)),
|
468
|
+
None)
|
469
|
+
if not cpm_hash_dir:
|
470
|
+
raise Exception(f'Unable to find CPM hash directory for path: {cpm_path}.')
|
471
|
+
return list(map(lambda p: p.format(CXX_CLIENT_CACHE, cpm_hash_dir), includes))
|
472
|
+
|
473
|
+
@staticmethod
|
474
|
+
def list_headers_in_dir(path: str, file_startswith: Optional[str] = None) -> List[str]:
|
475
|
+
# enumerates a folder but keeps the full pathing for the files returned
|
476
|
+
# and removes certain files we don't want (like non-hxx, _json.hxx or _fmt.hxx)
|
477
|
+
|
478
|
+
# list all the files in the folder
|
479
|
+
files = os.listdir(path)
|
480
|
+
|
481
|
+
if file_startswith is not None:
|
482
|
+
files = list(filter(lambda f: f.endswith('.hxx') and f.startswith(file_startswith), files))
|
483
|
+
# add the folder path back on
|
484
|
+
files = list(map(lambda f: os.path.join(path, f), files))
|
485
|
+
else:
|
486
|
+
# only include .hxx files
|
487
|
+
files = list(filter(lambda f: f.endswith('.hxx'), files))
|
488
|
+
# add the folder path back on
|
489
|
+
files = list(map(lambda f: path + f, files))
|
490
|
+
return files
|
491
|
+
|
492
|
+
@staticmethod
|
493
|
+
def is_included_type(name: str, type_list_re: List[str], with_durability: Optional[bool] = False) -> bool:
|
494
|
+
|
495
|
+
# TODO(brett19): This should be generalized somehow...
|
496
|
+
if "is_compound_operation" in name:
|
497
|
+
return False
|
498
|
+
|
499
|
+
if "replica_context" in name:
|
500
|
+
return False
|
501
|
+
|
502
|
+
if with_durability is True and '_with_legacy_durability' not in name:
|
503
|
+
return False
|
504
|
+
|
505
|
+
for x in type_list_re:
|
506
|
+
if re.fullmatch(x, name):
|
507
|
+
return True
|
508
|
+
return False
|
260
509
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
"of": parse_type_str(tplParams)
|
323
|
-
}
|
324
|
-
if tplClassName == "std::vector":
|
325
|
-
return {
|
326
|
-
"name": "std::vector",
|
327
|
-
"of": parse_type_str(tplParams)
|
328
|
-
}
|
329
|
-
if tplClassName == "std::set":
|
330
|
-
return {
|
331
|
-
"name": "std::set",
|
332
|
-
"of": parse_type_str(tplParams)
|
333
|
-
}
|
334
|
-
if tplClassName == "std::variant":
|
335
|
-
variantParts = tplParams.split(", ")
|
336
|
-
variantTypes = []
|
337
|
-
for variantPart in variantParts:
|
338
|
-
variantTypes.append(parse_type_str(variantPart))
|
339
|
-
return {
|
340
|
-
"name": "std::variant",
|
341
|
-
"of": variantTypes
|
342
|
-
}
|
343
|
-
if tplClassName == "std::array":
|
344
|
-
variantParts = tplParams.split(", ")
|
345
|
-
if len(variantParts) != 2:
|
346
|
-
print("FAILED TO PARSE ARRAY TYPES: " + typeStr)
|
347
|
-
return {"name": "unknown", "str": typeStr}
|
348
|
-
return {
|
349
|
-
"name": "std::array",
|
350
|
-
"of": parse_type_str(variantParts[0]),
|
351
|
-
"size": int(variantParts[1])
|
352
|
-
}
|
353
|
-
if tplClassName == "std::map":
|
354
|
-
variantParts = tplParams.split(", ")
|
355
|
-
if len(variantParts) < 2 or len(variantParts) > 3:
|
356
|
-
print("FAILED TO PARSE MAP TYPES: " + typeStr)
|
357
|
-
return {"name": "unknown", "str": typeStr}
|
358
|
-
|
359
|
-
if len(variantParts) == 2:
|
510
|
+
@staticmethod
|
511
|
+
def parse_type(type_: str) -> Dict[str, str]:
|
512
|
+
type_str = type_.get_canonical().spelling
|
513
|
+
return BindingsGenerator.parse_type_str(type_str)
|
514
|
+
|
515
|
+
@staticmethod
|
516
|
+
def parse_type_str(type_str: str) -> Dict[str, str]:
|
517
|
+
if type_str == "std::mutex":
|
518
|
+
return {"name": "std::mutex"}
|
519
|
+
if type_str == "std::string":
|
520
|
+
return {"name": "std::string"}
|
521
|
+
if type_str == "std::chrono::duration<long long>":
|
522
|
+
return {"name": "std::chrono::seconds"}
|
523
|
+
if type_str == "std::chrono::duration<long long, std::ratio<1, 1000>>":
|
524
|
+
return {"name": "std::chrono::milliseconds"}
|
525
|
+
if type_str == "std::chrono::duration<long long, std::ratio<1, 1000000>>":
|
526
|
+
return {"name": "std::chrono::microseconds"}
|
527
|
+
if type_str == "std::chrono::duration<long long, std::ratio<1, 1000000000>>":
|
528
|
+
return {"name": "std::chrono::nanoseconds"}
|
529
|
+
if type_str == "std::error_code":
|
530
|
+
return {"name": "std::error_code"}
|
531
|
+
if type_str == "std::monostate":
|
532
|
+
return {"name": "std::monostate"}
|
533
|
+
if type_str == "std::byte":
|
534
|
+
return {"name": "std::byte"}
|
535
|
+
if type_str == "unsigned long":
|
536
|
+
return {"name": "std::size_t"}
|
537
|
+
if type_str == "char":
|
538
|
+
return {"name": "std::int8_t"}
|
539
|
+
if type_str == "unsigned char":
|
540
|
+
return {"name": "std::uint8_t"}
|
541
|
+
if type_str == "short":
|
542
|
+
return {"name": "std::int16_t"}
|
543
|
+
if type_str == "unsigned short":
|
544
|
+
return {"name": "std::uint16_t"}
|
545
|
+
if type_str == "int":
|
546
|
+
return {"name": "std::int32_t"}
|
547
|
+
if type_str == "unsigned int":
|
548
|
+
return {"name": "std::uint32_t"}
|
549
|
+
if type_str == "long long":
|
550
|
+
return {"name": "std::int64_t"}
|
551
|
+
if type_str == "unsigned long long":
|
552
|
+
return {"name": "std::uint64_t"}
|
553
|
+
if type_str == "bool":
|
554
|
+
return {"name": "std::bool"}
|
555
|
+
if type_str == "float":
|
556
|
+
return {"name": "std::float"}
|
557
|
+
if type_str == "double":
|
558
|
+
return {"name": "std::double"}
|
559
|
+
if type_str == "std::nullptr_t":
|
560
|
+
return {"name": "std::nullptr_t"}
|
561
|
+
if type_str in STD_COMPARATORS:
|
562
|
+
if 'void' in type_str:
|
563
|
+
return {"name": type_str.replace("void", "")}
|
564
|
+
return {"name": type_str}
|
565
|
+
|
566
|
+
tplParts = type_str.split("<", 1)
|
567
|
+
if len(tplParts) > 1:
|
568
|
+
tplClassName = tplParts[0]
|
569
|
+
tplParams = tplParts[1][:-1]
|
570
|
+
if tplClassName == "std::function":
|
360
571
|
return {
|
361
|
-
"name": "std::
|
362
|
-
"of": parse_type_str(variantParts[0]),
|
363
|
-
"to": parse_type_str(variantParts[1])
|
572
|
+
"name": "std::function"
|
364
573
|
}
|
365
|
-
|
574
|
+
if tplClassName == "std::optional":
|
366
575
|
return {
|
367
|
-
"name": "std::
|
368
|
-
"of": parse_type_str(
|
369
|
-
|
370
|
-
|
576
|
+
"name": "std::optional",
|
577
|
+
"of": BindingsGenerator.parse_type_str(tplParams)
|
578
|
+
}
|
579
|
+
if tplClassName == "std::vector":
|
580
|
+
return {
|
581
|
+
"name": "std::vector",
|
582
|
+
"of": BindingsGenerator.parse_type_str(tplParams)
|
583
|
+
}
|
584
|
+
if tplClassName == "std::set":
|
585
|
+
return {
|
586
|
+
"name": "std::set",
|
587
|
+
"of": BindingsGenerator. parse_type_str(tplParams)
|
588
|
+
}
|
589
|
+
if tplClassName == "std::variant":
|
590
|
+
variantParts = tplParams.split(", ")
|
591
|
+
variantTypes = []
|
592
|
+
for variantPart in variantParts:
|
593
|
+
variantTypes.append(BindingsGenerator.parse_type_str(variantPart))
|
594
|
+
return {
|
595
|
+
"name": "std::variant",
|
596
|
+
"of": variantTypes
|
597
|
+
}
|
598
|
+
if tplClassName == "std::array":
|
599
|
+
variantParts = tplParams.split(", ")
|
600
|
+
if len(variantParts) != 2:
|
601
|
+
print("FAILED TO PARSE ARRAY TYPES: " + type_str)
|
602
|
+
return {"name": "unknown", "str": type_str}
|
603
|
+
return {
|
604
|
+
"name": "std::array",
|
605
|
+
"of": BindingsGenerator.parse_type_str(variantParts[0]),
|
606
|
+
"size": int(variantParts[1])
|
607
|
+
}
|
608
|
+
if tplClassName == "std::map":
|
609
|
+
variantParts = tplParams.split(", ")
|
610
|
+
if len(variantParts) < 2 or len(variantParts) > 3:
|
611
|
+
print("FAILED TO PARSE MAP TYPES: " + type_str)
|
612
|
+
return {"name": "unknown", "str": type_str}
|
613
|
+
|
614
|
+
if len(variantParts) == 2:
|
615
|
+
return {
|
616
|
+
"name": "std::map",
|
617
|
+
"of": BindingsGenerator.parse_type_str(variantParts[0]),
|
618
|
+
"to": BindingsGenerator.parse_type_str(variantParts[1])
|
619
|
+
}
|
620
|
+
else:
|
621
|
+
return {
|
622
|
+
"name": "std::map",
|
623
|
+
"of": BindingsGenerator.parse_type_str(variantParts[0]),
|
624
|
+
"to": BindingsGenerator.parse_type_str(variantParts[1]),
|
625
|
+
"comparator": BindingsGenerator.parse_type_str(variantParts[2])
|
626
|
+
}
|
627
|
+
|
628
|
+
if tplClassName == "std::shared_ptr":
|
629
|
+
return {
|
630
|
+
"name": "std::shared_ptr",
|
631
|
+
"of": BindingsGenerator.parse_type_str(tplParams)
|
371
632
|
}
|
372
633
|
|
373
|
-
if
|
374
|
-
|
375
|
-
|
376
|
-
"of": parse_type_str(tplParams)
|
377
|
-
}
|
378
|
-
|
379
|
-
if not typeStr.startswith("couchbase::"):
|
380
|
-
print("FAILED TO PARSE STRING TYPE: " + typeStr)
|
381
|
-
return {"name": "unknown", "str": typeStr}
|
382
|
-
|
383
|
-
if 'unnamed struct' in typeStr:
|
384
|
-
print("WARNING: Found unnamed struct: " + typeStr)
|
385
|
-
|
386
|
-
return {"name": typeStr}
|
634
|
+
if not type_str.startswith("couchbase::"):
|
635
|
+
print("FAILED TO PARSE STRING TYPE: " + type_str)
|
636
|
+
return {"name": "unknown", "str": type_str}
|
387
637
|
|
388
|
-
|
389
|
-
|
638
|
+
if 'unnamed struct' in type_str:
|
639
|
+
print("WARNING: Found unnamed struct: " + type_str)
|
390
640
|
|
391
|
-
|
392
|
-
# only scan the elements of the file we parsed
|
393
|
-
if node.location.file != None and node.location.file.name != main_file:
|
394
|
-
return
|
395
|
-
|
396
|
-
if node.kind == clang.cindex.CursorKind.STRUCT_DECL or node.kind == clang.cindex.CursorKind.CLASS_DECL:
|
397
|
-
fullStructName = "::".join([*namespace, node.displayname])
|
398
|
-
if fullStructName.endswith('::') or UNNAMED_STRUCT_DELIM in fullStructName:
|
399
|
-
struct_name = fullStructName if fullStructName.endswith('::') else fullStructName.split(UNNAMED_STRUCT_DELIM)[0]
|
400
|
-
match = next((s for s in internal_structs if struct_name in s), None)
|
401
|
-
if match:
|
402
|
-
fullStructName = match
|
403
|
-
|
404
|
-
if is_included_type(fullStructName) or fullStructName in internal_structs:
|
405
|
-
structFields = []
|
406
|
-
for child in node.get_children():
|
407
|
-
if child.kind == clang.cindex.CursorKind.FIELD_DECL:
|
408
|
-
struct_type = parse_type(child.type)
|
409
|
-
type_str = child.type.get_canonical().spelling
|
410
|
-
if 'unnamed' in type_str:
|
411
|
-
name_tokens = type_str.split('::')
|
412
|
-
name_override = '::'.join(name_tokens[:-1] + [child.displayname])
|
413
|
-
struct_type['name'] = name_override
|
414
|
-
internal_structs.append(name_override)
|
415
|
-
|
416
|
-
structFields.append({
|
417
|
-
"name": child.displayname,
|
418
|
-
"type": struct_type,
|
419
|
-
})
|
420
|
-
# replica read changes introduced duplicate get requests
|
421
|
-
if any(map(lambda op: op['name'] == fullStructName, opTypes)):
|
422
|
-
return
|
423
|
-
|
424
|
-
opTypes.append({
|
425
|
-
"name": fullStructName,
|
426
|
-
"fields": structFields,
|
427
|
-
})
|
428
|
-
if node.kind == clang.cindex.CursorKind.TYPE_ALIAS_DECL:
|
429
|
-
fullStructName = "::".join([*namespace, node.displayname])
|
430
|
-
if is_included_type(fullStructName, with_durability=True):
|
431
|
-
type_ref = next((c for c in node.get_children() if c.kind == clang.cindex.CursorKind.TYPE_REF), None)
|
432
|
-
if type_ref:
|
433
|
-
base_request_name = type_ref.displayname.replace('struct', '').strip()
|
434
|
-
base_request = next((op for op in opTypes if op['name'] == base_request_name), None)
|
435
|
-
if base_request:
|
436
|
-
new_fields = [f for f in base_request['fields'] if f['name'] != 'durability_level']
|
437
|
-
new_fields.extend([
|
438
|
-
{"name":"persist_to", "type":{"name":"couchbase::persist_to"}},
|
439
|
-
{"name":"replicate_to", "type":{"name":"couchbase::replicate_to"}}
|
440
|
-
])
|
641
|
+
return {"name": type_str}
|
441
642
|
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
643
|
+
@staticmethod
|
644
|
+
def sh(command: str, piped: Optional[bool] = False) -> Tuple[str, int]:
|
645
|
+
try:
|
646
|
+
if piped is True:
|
647
|
+
proc = subprocess.Popen(command,
|
648
|
+
stdin=subprocess.PIPE,
|
649
|
+
stdout=subprocess.PIPE,
|
650
|
+
stderr=subprocess.PIPE,
|
651
|
+
shell=True)
|
652
|
+
else:
|
653
|
+
proc = subprocess.Popen(command,
|
654
|
+
stdout=subprocess.PIPE,
|
655
|
+
stderr=subprocess.PIPE,
|
656
|
+
shell=True)
|
657
|
+
stdout, stderr = proc.communicate()
|
658
|
+
stderr = stderr.decode('utf-8')
|
659
|
+
if stderr != '':
|
660
|
+
return stderr, 1
|
661
|
+
return stdout.decode('utf-8'), 0
|
662
|
+
except FileNotFoundError:
|
663
|
+
return "Error: Command not found.", 1
|
664
|
+
|
665
|
+
@staticmethod
|
666
|
+
def find_llvm() -> None:
|
667
|
+
if sys.platform == 'darwin':
|
668
|
+
output, err = BindingsGenerator.sh('which clang')
|
669
|
+
if err:
|
670
|
+
raise Exception(f'Unable to determine clang binary. Error code: {err}.')
|
671
|
+
if 'llvm' not in output.strip():
|
672
|
+
# TODO: aarch64 v. x86_64
|
673
|
+
os_path = os.environ.get('PATH').split(':')
|
674
|
+
os_path = ['/opt/homebrew/opt/llvm/bin'] + os_path
|
675
|
+
os.environ.update(**{'PATH': ':'.join(os_path)})
|
676
|
+
output, err = BindingsGenerator.sh('which clang')
|
677
|
+
if err:
|
678
|
+
raise Exception(f'Unable to determine clang binary. Error code: {err}.')
|
679
|
+
if 'llvm' not in output.strip():
|
680
|
+
raise Exception('Unable to set LLVM as default.')
|
681
|
+
elif sys.platform == 'linux':
|
682
|
+
print('Under construction')
|
683
|
+
else:
|
684
|
+
raise ValueError('Unsupported platform')
|
685
|
+
|
686
|
+
@staticmethod
|
687
|
+
def get_llvm_version() -> str:
|
688
|
+
output, err = BindingsGenerator.sh('llvm-config --version')
|
689
|
+
if err:
|
690
|
+
raise Exception(f'Unable to determine LLVM version. Error code: {err}')
|
691
|
+
return output.strip()
|
692
|
+
|
693
|
+
@staticmethod
|
694
|
+
def get_llvm_includedir() -> str:
|
695
|
+
output, err = BindingsGenerator.sh('llvm-config --includedir')
|
696
|
+
if err:
|
697
|
+
raise Exception(f'Unable to determine LLVM includedir. Error code: {err}')
|
698
|
+
return output.strip()
|
699
|
+
|
700
|
+
@staticmethod
|
701
|
+
def get_llvm_libdir() -> str:
|
702
|
+
output, err = BindingsGenerator.sh('llvm-config --libdir')
|
703
|
+
if err:
|
704
|
+
raise Exception(f'Unable to determine LLVM libdir. Error code: {err}')
|
705
|
+
return output.strip()
|
706
|
+
|
707
|
+
@staticmethod
|
708
|
+
def get_system_headers() -> str:
|
709
|
+
if sys.platform == 'darwin':
|
710
|
+
output, err = BindingsGenerator.sh('xcrun --show-sdk-path')
|
711
|
+
if err:
|
712
|
+
raise Exception(f'Unable to determine system header path. Error code: {err}.')
|
713
|
+
return output.strip()
|
714
|
+
elif sys.platform == 'linux':
|
715
|
+
print('Under construction')
|
716
|
+
else:
|
717
|
+
raise ValueError('Unsupported platform')
|
718
|
+
|
719
|
+
|
720
|
+
if __name__ == '__main__':
|
721
|
+
from argparse import ArgumentParser
|
722
|
+
ap = ArgumentParser(description='Parse git version to PEP-440 version')
|
723
|
+
ap.add_argument('-v',
|
724
|
+
'--version',
|
725
|
+
help='Set CN_LLVM_VERSION, or use command: llvm-config --version')
|
726
|
+
ap.add_argument('-i',
|
727
|
+
'--includedir',
|
728
|
+
help='Set CN_LLVM_INCLUDE, or use command: llvm-config --includedir')
|
729
|
+
ap.add_argument('-l',
|
730
|
+
'--libdir',
|
731
|
+
help='Set CN_LLVM_LIB, or use command: llvm-config --libdir')
|
732
|
+
ap.add_argument('-s',
|
733
|
+
'--system-headers',
|
734
|
+
help='SET CN_SYS_HEADERS, or use command: xcrun --show-sdk-path')
|
735
|
+
options = ap.parse_args()
|
736
|
+
|
737
|
+
generator = BindingsGenerator(options.version,
|
738
|
+
options.libdir,
|
739
|
+
options.includedir,
|
740
|
+
options.system_headers)
|
741
|
+
generator.gen_bindings()
|
742
|
+
|
743
|
+
|
744
|
+
"""
|
745
|
+
|
746
|
+
https://github.com/llvm/llvm-project/issues/86009
|
747
|
+
|
748
|
+
"""
|