@datagrok/eda 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/detectors.js +9 -0
- package/dist/111.js +2 -0
- package/dist/146.js +2 -0
- package/dist/155.js +2 -0
- package/dist/355.js +2 -0
- package/dist/584.js +2 -0
- package/dist/604.js +2 -0
- package/dist/632.js +2 -0
- package/dist/645.js +2 -0
- package/dist/93.js +2 -0
- package/dist/d711f70338306e5bddc4.wasm +0 -0
- package/dist/package-test.js +2 -0
- package/dist/package.js +2 -0
- package/package.json +49 -0
- package/package.png +0 -0
- package/scripts/command.txt +1 -0
- package/scripts/exportForTS.py +862 -0
- package/scripts/exportForTSConstants.py +93 -0
- package/scripts/func.json +1 -0
- package/scripts/module.json +11 -0
- package/src/EDAtools.ts +46 -0
- package/src/EDAui.ts +118 -0
- package/src/dataGenerators.ts +74 -0
- package/src/demos.ts +38 -0
- package/src/package-test.ts +12 -0
- package/src/package.ts +248 -0
- package/src/svm.ts +485 -0
- package/src/utils.ts +51 -0
- package/tsconfig.json +71 -0
- package/wasm/EDA.js +443 -0
- package/wasm/EDA.wasm +0 -0
- package/wasm/EDAAPI.js +131 -0
- package/wasm/EDAForWebWorker.js +21 -0
- package/wasm/PCA/PCA.cpp +151 -0
- package/wasm/PCA/PCA.h +48 -0
- package/wasm/PLS/PLS.h +64 -0
- package/wasm/PLS/pls.cpp +393 -0
- package/wasm/callWasm.js +475 -0
- package/wasm/callWasmForWebWorker.js +706 -0
- package/wasm/dataGenerators.h +169 -0
- package/wasm/dataMining.h +116 -0
- package/wasm/pcaExport.cpp +64 -0
- package/wasm/plsExport.cpp +75 -0
- package/wasm/svm.h +608 -0
- package/wasm/svmApi.cpp +323 -0
- package/wasm/workers/errorWorker.js +13 -0
- package/wasm/workers/generateDatasetWorker.js +13 -0
- package/wasm/workers/normalizeDatasetWorker.js +13 -0
- package/wasm/workers/partialLeastSquareRegressionWorker.js +13 -0
- package/wasm/workers/predictByLSSVMWorker.js +13 -0
- package/wasm/workers/principalComponentAnalysisWorker.js +13 -0
- package/wasm/workers/trainAndAnalyzeLSSVMWorker.js +13 -0
- package/wasm/workers/trainLSSVMWorker.js +13 -0
- package/webpack.config.js +37 -0
|
@@ -0,0 +1,862 @@
|
|
|
1
|
+
""" export.py March 02, 2023.
|
|
2
|
+
This script exports C/C++-functions to Datagrok package.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
import shutil
|
|
8
|
+
|
|
9
|
+
from exportForTSConstants import *
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def getSettings(nameOfFile):
|
|
13
|
+
"""
|
|
14
|
+
Return dictionary with settings of C/C++-functions export from json-file with settings.
|
|
15
|
+
"""
|
|
16
|
+
with open(nameOfFile, READ_MODE) as file:
|
|
17
|
+
return json.load(file)
|
|
18
|
+
|
|
19
|
+
class Function:
|
|
20
|
+
""" Exported C/C++-function specification class.
|
|
21
|
+
"""
|
|
22
|
+
def __init__(self, cFuncAnnotationLines, typeList):
|
|
23
|
+
self.annotation = []
|
|
24
|
+
self.arguments = {}
|
|
25
|
+
self.prototype = ''
|
|
26
|
+
self.prototypeForWebWorker = ''
|
|
27
|
+
self.callArgs = '['
|
|
28
|
+
self.typeList = typeList
|
|
29
|
+
self.cFuncTypeIndex = 0
|
|
30
|
+
self.output = {}
|
|
31
|
+
self.paramsWithNewSpecifier = {}
|
|
32
|
+
|
|
33
|
+
# process each line of annotation
|
|
34
|
+
for line in cFuncAnnotationLines:
|
|
35
|
+
self.processAnnotationLine(line)
|
|
36
|
+
|
|
37
|
+
# complete output of specification
|
|
38
|
+
self.finalizeOutput()
|
|
39
|
+
|
|
40
|
+
# final preparation of prototypes
|
|
41
|
+
self.prototype = self.prototype.rstrip(', ')
|
|
42
|
+
self.prototype += ')'
|
|
43
|
+
self.prototypeForWebWorker = self.prototypeForWebWorker.rstrip(', ')
|
|
44
|
+
self.prototypeForWebWorker += ')'
|
|
45
|
+
|
|
46
|
+
# final preparation of call args string
|
|
47
|
+
self.callArgs = self.callArgs.rstrip(', ')
|
|
48
|
+
self.callArgs += ']'
|
|
49
|
+
|
|
50
|
+
# create specification dict
|
|
51
|
+
self.specification = {ARGUMENTS: self.arguments,
|
|
52
|
+
OUTPUT: self.output,
|
|
53
|
+
ANNOTATION: self.annotation,
|
|
54
|
+
PROTOTYPE: self.prototype,
|
|
55
|
+
WW_PROTOTYPE: self.prototypeForWebWorker,
|
|
56
|
+
CALL_ARGS: self.callArgs}
|
|
57
|
+
|
|
58
|
+
def processAnnotationLine(self, line):
|
|
59
|
+
""" Process one line of annotation before exported C/C++-function.
|
|
60
|
+
"""
|
|
61
|
+
if line.startswith(ANNOT_INPUT):
|
|
62
|
+
self.processInputLine(line)
|
|
63
|
+
elif line.startswith(ANNOT_OUTPUT):
|
|
64
|
+
self.processOutputLine(line)
|
|
65
|
+
elif line.startswith(ANNOT_NAME):
|
|
66
|
+
self.processNameLine(line)
|
|
67
|
+
else:
|
|
68
|
+
self.annotation.append(line)
|
|
69
|
+
|
|
70
|
+
def processNameLine(self, line):
|
|
71
|
+
""" Process line containing '//name:'.
|
|
72
|
+
"""
|
|
73
|
+
ignore1, ignore2, name = line.partition(' ')
|
|
74
|
+
self.prototype += f'{name}('
|
|
75
|
+
self.prototypeForWebWorker += f'{name}{IN_WEBWORKER_SUFFIX}('
|
|
76
|
+
self.annotation.append(line)
|
|
77
|
+
|
|
78
|
+
def processOutputLine(self, line):
|
|
79
|
+
""" Process line containing '//output:'.
|
|
80
|
+
"""
|
|
81
|
+
if ANNOT_NEW in line:
|
|
82
|
+
self.processOutputLineWithNew(line)
|
|
83
|
+
else:
|
|
84
|
+
self.processOutputLineWithoutNew(line)
|
|
85
|
+
|
|
86
|
+
def processInputLine(self, line):
|
|
87
|
+
""" Process '//input'-line with arguments that are passed.
|
|
88
|
+
"""
|
|
89
|
+
self.annotation.append(line)
|
|
90
|
+
|
|
91
|
+
# get type and name part of line
|
|
92
|
+
ignore1, ignore2, rest = line.partition(': ')
|
|
93
|
+
|
|
94
|
+
# get type and name of the argument
|
|
95
|
+
argType, ignore, argName = rest.partition(' ')
|
|
96
|
+
|
|
97
|
+
self.prototype += argName + ', '
|
|
98
|
+
self.prototypeForWebWorker += argName + ', '
|
|
99
|
+
|
|
100
|
+
if argType == ANNOT_DATAFRAME:
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
self.callArgs += argName + ', '
|
|
104
|
+
|
|
105
|
+
currentType = self.typeList[self.cFuncTypeIndex]
|
|
106
|
+
|
|
107
|
+
if argType == ANNOT_COLUMN:
|
|
108
|
+
self.arguments[argName] = {TYPE: currentType + COLUMN}
|
|
109
|
+
self.cFuncTypeIndex += 2
|
|
110
|
+
|
|
111
|
+
elif argType == ANNOT_COLUMN_LIST:
|
|
112
|
+
self.arguments[argName] = {TYPE: currentType + COLUMNS}
|
|
113
|
+
self.cFuncTypeIndex += 3
|
|
114
|
+
|
|
115
|
+
else:
|
|
116
|
+
self.arguments[argName] = {TYPE: NUM}
|
|
117
|
+
self.cFuncTypeIndex += 1
|
|
118
|
+
|
|
119
|
+
def processOutputLineWithNew(self, line):
|
|
120
|
+
""" Process '//output'-line with arguments that are newly created.
|
|
121
|
+
"""
|
|
122
|
+
# get type and name part of line
|
|
123
|
+
ignore1, ignore2, rest = line.partition(': ')
|
|
124
|
+
|
|
125
|
+
# get type and name of the argument
|
|
126
|
+
argType, ignore, rest = rest.partition(' ')
|
|
127
|
+
|
|
128
|
+
if argType == ANNOT_DATAFRAME:
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
# extract name & specification
|
|
132
|
+
argName, ignore, specification = rest.partition(' ')
|
|
133
|
+
|
|
134
|
+
# store argument info in dictionary
|
|
135
|
+
self.paramsWithNewSpecifier[argName] = argType
|
|
136
|
+
|
|
137
|
+
# extract the main data
|
|
138
|
+
specification = specification.lstrip(f'[{ANNOT_NEW}(').rstrip(')]')
|
|
139
|
+
|
|
140
|
+
currentType = self.typeList[self.cFuncTypeIndex]
|
|
141
|
+
|
|
142
|
+
if argType == ANNOT_COLUMN:
|
|
143
|
+
specification = specification.strip()
|
|
144
|
+
|
|
145
|
+
ref = None
|
|
146
|
+
value = None
|
|
147
|
+
|
|
148
|
+
if ANNOT_DOT not in specification:
|
|
149
|
+
ref = specification
|
|
150
|
+
value = DATA
|
|
151
|
+
else:
|
|
152
|
+
ref, ignore, value = specification.partition(ANNOT_DOT)
|
|
153
|
+
|
|
154
|
+
self.arguments[argName] = {TYPE: NEW + currentType.capitalize() + COLUMN}
|
|
155
|
+
self.arguments[argName][NUM_OF_ROWS] = {REF: ref, VALUE: sizesMap[value]}
|
|
156
|
+
self.cFuncTypeIndex += 2
|
|
157
|
+
|
|
158
|
+
elif argType == ANNOT_COLUMN_LIST:
|
|
159
|
+
|
|
160
|
+
first, ignore, last = specification.partition(',')
|
|
161
|
+
first = first.strip()
|
|
162
|
+
last = last.strip()
|
|
163
|
+
|
|
164
|
+
self.arguments[argName] = {TYPE: NEW + currentType.capitalize() + COLUMNS}
|
|
165
|
+
|
|
166
|
+
ref = None
|
|
167
|
+
value = None
|
|
168
|
+
|
|
169
|
+
if ANNOT_DOT not in first:
|
|
170
|
+
ref = first
|
|
171
|
+
value = DATA
|
|
172
|
+
else:
|
|
173
|
+
ref, ignore, value = first.partition(ANNOT_DOT)
|
|
174
|
+
|
|
175
|
+
self.arguments[argName][NUM_OF_ROWS] = {REF: ref, VALUE: sizesMap[value]}
|
|
176
|
+
|
|
177
|
+
if ANNOT_DOT not in last:
|
|
178
|
+
ref = last
|
|
179
|
+
value = DATA
|
|
180
|
+
else:
|
|
181
|
+
ref, ignore, value = last.partition(ANNOT_DOT)
|
|
182
|
+
|
|
183
|
+
self.arguments[argName][NUM_OF_COLUMNS] = {REF: ref, VALUE: sizesMap[value]}
|
|
184
|
+
|
|
185
|
+
self.cFuncTypeIndex += 3
|
|
186
|
+
|
|
187
|
+
else:
|
|
188
|
+
self.arguments[argName] = {TYPE: NUM}
|
|
189
|
+
self.cFuncTypeIndex += 1
|
|
190
|
+
|
|
191
|
+
def processOutputLineWithoutNew(self, line):
|
|
192
|
+
""" Process '//output'-line.
|
|
193
|
+
"""
|
|
194
|
+
ignore1, ignore2, specification = line.partition(':')
|
|
195
|
+
|
|
196
|
+
outputType, ignore, outputSource = specification.strip().partition(' ')
|
|
197
|
+
|
|
198
|
+
outputType = outputType.strip()
|
|
199
|
+
|
|
200
|
+
ignore1, ignore2, outputSource = outputSource.partition(' ')
|
|
201
|
+
|
|
202
|
+
outputSource = outputSource.strip().strip('[]')
|
|
203
|
+
|
|
204
|
+
if outputType == ANNOT_OBJECTS:
|
|
205
|
+
self.output[TYPE] = outputType
|
|
206
|
+
args = outputSource.split(',')
|
|
207
|
+
sourceString = ''
|
|
208
|
+
|
|
209
|
+
for arg in args:
|
|
210
|
+
sourceString += f"'{arg.strip()}', "
|
|
211
|
+
|
|
212
|
+
self.output[SOURCE] = f"[{sourceString.rstrip(', ')}]"
|
|
213
|
+
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
elif outputType == ANNOT_DATAFRAME:
|
|
217
|
+
self.output[TYPE] = TABLE_FROM_COLUMNS
|
|
218
|
+
self.output[SOURCE] = f'{outputSource}'
|
|
219
|
+
|
|
220
|
+
else:
|
|
221
|
+
self.output[TYPE] = f'{outputType}'
|
|
222
|
+
self.output[SOURCE] = f'{outputSource}'
|
|
223
|
+
|
|
224
|
+
stringToAnnotation, ignore1, ignore2 = line.partition('[')
|
|
225
|
+
self.annotation.append(stringToAnnotation)
|
|
226
|
+
|
|
227
|
+
def finalizeOutput(self):
|
|
228
|
+
""" Complete output part of the function specification.
|
|
229
|
+
"""
|
|
230
|
+
if len(self.output) == 0:
|
|
231
|
+
if len(self.paramsWithNewSpecifier) == 0:
|
|
232
|
+
raise Warning
|
|
233
|
+
elif len(self.paramsWithNewSpecifier) == 1:
|
|
234
|
+
argName = list(self.paramsWithNewSpecifier.keys())[0]
|
|
235
|
+
self.output[TYPE] = self.paramsWithNewSpecifier[argName]
|
|
236
|
+
self.output[SOURCE] = argName
|
|
237
|
+
self.annotation.append(f'{ANNOT_OUTPUT} {self.output[TYPE]} {argName}')
|
|
238
|
+
else:
|
|
239
|
+
self.output[TYPE] = OBJECTS
|
|
240
|
+
sourceString = '['
|
|
241
|
+
|
|
242
|
+
for name in self.paramsWithNewSpecifier.keys():
|
|
243
|
+
sourceString += f"'{name}'" + ', '
|
|
244
|
+
|
|
245
|
+
sourceString = sourceString.rstrip(', ')
|
|
246
|
+
sourceString += ']'
|
|
247
|
+
self.output[SOURCE] = sourceString
|
|
248
|
+
|
|
249
|
+
def getSpecification(self):
|
|
250
|
+
return self.specification
|
|
251
|
+
|
|
252
|
+
def getFunctionsFromFile(nameOfFile):
|
|
253
|
+
"""
|
|
254
|
+
Parse C/C++-file and return specification of exported functions.
|
|
255
|
+
"""
|
|
256
|
+
with open(nameOfFile, READ_MODE) as file:
|
|
257
|
+
listOfLines = file.readlines()
|
|
258
|
+
dictionaryOfFunctions = {}
|
|
259
|
+
|
|
260
|
+
for lineIndex in range(len(listOfLines)):
|
|
261
|
+
# the next line is function's prototype
|
|
262
|
+
if listOfLines[lineIndex].startswith(EM_MACROS):
|
|
263
|
+
|
|
264
|
+
# 1. Analyze function description
|
|
265
|
+
j = lineIndex + 1
|
|
266
|
+
funcLine = ''
|
|
267
|
+
|
|
268
|
+
# 1.1) get one line prototype of exported function
|
|
269
|
+
while True:
|
|
270
|
+
funcLine += listOfLines[j].strip().rstrip('\n')
|
|
271
|
+
if ')' in listOfLines[j]:
|
|
272
|
+
break
|
|
273
|
+
j += 1
|
|
274
|
+
|
|
275
|
+
# 1.2) get name of function & a string of its arguments
|
|
276
|
+
ignore1, ignore2, nameAndArgs = funcLine.partition(' ')
|
|
277
|
+
functionName, ignore, argsLine = nameAndArgs.partition('(')
|
|
278
|
+
|
|
279
|
+
# 1.3) get types of arguments
|
|
280
|
+
cFuncArgs = argsLine.split(',')
|
|
281
|
+
typeList = [] # list of argument's type
|
|
282
|
+
|
|
283
|
+
for s in cFuncArgs:
|
|
284
|
+
argType, ignore1, ignore2 = s.strip().partition(' ')
|
|
285
|
+
typeList.append(argType)
|
|
286
|
+
|
|
287
|
+
# 1.4) get annotation lines
|
|
288
|
+
j = lineIndex - 1
|
|
289
|
+
annotationLines = []
|
|
290
|
+
|
|
291
|
+
while listOfLines[j].startswith('//'):
|
|
292
|
+
annotationLines.append(listOfLines[j].strip())
|
|
293
|
+
j -= 1
|
|
294
|
+
|
|
295
|
+
annotationLines.reverse()
|
|
296
|
+
function = Function(annotationLines, typeList)
|
|
297
|
+
dictionaryOfFunctions[functionName] = function.getSpecification()
|
|
298
|
+
|
|
299
|
+
return dictionaryOfFunctions
|
|
300
|
+
|
|
301
|
+
def getFunctionsFromListOfFiles(settings):
|
|
302
|
+
""" Loads a list of C-file names and gets functions from each of these files
|
|
303
|
+
"""
|
|
304
|
+
functions = {} # dictionary: key - name of file; value - functions data
|
|
305
|
+
|
|
306
|
+
for name in settings[SOURCE]:
|
|
307
|
+
functions[name] = getFunctionsFromFile(settings[FOLDER] + '/' + name)
|
|
308
|
+
|
|
309
|
+
return functions
|
|
310
|
+
|
|
311
|
+
def saveFunctionsDataToFile(functionsData, nameOfFile):
|
|
312
|
+
"""
|
|
313
|
+
Save C-functions descriptors to json-file.
|
|
314
|
+
"""
|
|
315
|
+
with open(nameOfFile, WRITE_MODE) as file:
|
|
316
|
+
json.dump(functionsData, file)
|
|
317
|
+
|
|
318
|
+
def getCommand(settings, functionsData):
|
|
319
|
+
"""
|
|
320
|
+
Return Emscripten command based on settings and functions data.
|
|
321
|
+
"""
|
|
322
|
+
command = 'em++' # Emscripten command, starts with "emcc"
|
|
323
|
+
|
|
324
|
+
# set optimization mode
|
|
325
|
+
command += ' ' + settings[OPTIMIZATION_MODE]
|
|
326
|
+
|
|
327
|
+
# add names of C-files
|
|
328
|
+
for nameOfFile in settings[SOURCE]:
|
|
329
|
+
command += f' {settings[FOLDER]}/{nameOfFile}'
|
|
330
|
+
|
|
331
|
+
# add name of JS-library that is created by Emscripten
|
|
332
|
+
command += f' -o {settings[FOLDER]}/{settings[NAME]}.js'
|
|
333
|
+
|
|
334
|
+
# specify memory restrictions
|
|
335
|
+
command += ' -s TOTAL_MEMORY=' + settings[TOTAL_MEMORY]
|
|
336
|
+
|
|
337
|
+
# set that wasm-file must be created
|
|
338
|
+
command += ' -s WASM=1'
|
|
339
|
+
|
|
340
|
+
# allow memory growth
|
|
341
|
+
command += ' -s ALLOW_MEMORY_GROWTH=1'
|
|
342
|
+
|
|
343
|
+
# create module (? should be checked!)
|
|
344
|
+
command += ' -s MODULARIZE=1'
|
|
345
|
+
|
|
346
|
+
# set export name
|
|
347
|
+
command += ' -s EXPORT_NAME="export' + settings[NAME] + '"'
|
|
348
|
+
|
|
349
|
+
# set a list of exported functions
|
|
350
|
+
command += ' -s EXPORTED_FUNCTIONS=['
|
|
351
|
+
|
|
352
|
+
# add names of functions
|
|
353
|
+
for nameOfFile in functionsData.keys():
|
|
354
|
+
for nameOfFunction in functionsData[nameOfFile].keys():
|
|
355
|
+
command += '"_' + nameOfFunction + '",'
|
|
356
|
+
|
|
357
|
+
# add malloc and free - they are used for memory operating
|
|
358
|
+
command += '"_malloc","_free"]'
|
|
359
|
+
|
|
360
|
+
# add exported runtime methods
|
|
361
|
+
command += ' -s EXPORTED_RUNTIME_METHODS=["cwrap","ccall"]' # also, "ccall" can be added
|
|
362
|
+
|
|
363
|
+
# the following is required when running in webworker
|
|
364
|
+
command += ' -sENVIRONMENT=web,worker'
|
|
365
|
+
|
|
366
|
+
return command
|
|
367
|
+
|
|
368
|
+
def saveCommand(command, nameOfFile):
|
|
369
|
+
"""
|
|
370
|
+
Save Emscripten command to txt-file.
|
|
371
|
+
"""
|
|
372
|
+
with open(nameOfFile, WRITE_MODE) as file:
|
|
373
|
+
file.write(command)
|
|
374
|
+
|
|
375
|
+
def createJSwrapperForWasmInWebWorkerRun(settings):
|
|
376
|
+
"""
|
|
377
|
+
Create JS-wrapper for wasm-functions run in webworkers.
|
|
378
|
+
"""
|
|
379
|
+
folder = settings[FOLDER]
|
|
380
|
+
name = settings[NAME]
|
|
381
|
+
|
|
382
|
+
# open JS-file generated by Emscripten
|
|
383
|
+
with open(f'{folder}/{name}{EM_LIB_EXTENSION}', READ_MODE) as emFile:
|
|
384
|
+
listOfLines = emFile.readlines()
|
|
385
|
+
|
|
386
|
+
# this modification provides further usage of the module in webworker
|
|
387
|
+
listOfLines[NUM_OF_LINE_TO_MODIFY] = KEY_WORD_TO_ADD + listOfLines[NUM_OF_LINE_TO_MODIFY]
|
|
388
|
+
|
|
389
|
+
# create JS-wrapper for call wasm-functions in webworker
|
|
390
|
+
with open(f'{folder}/{name}{WW_FILE_SUFFIX}{EM_LIB_EXTENSION}',WRITE_MODE) as file:
|
|
391
|
+
|
|
392
|
+
replacement = f"fetch(new URL('{folder}/{name}.wasm', import.meta.url))"
|
|
393
|
+
|
|
394
|
+
# put lines (replacement is required for further usage in webworkers)
|
|
395
|
+
for line in listOfLines:
|
|
396
|
+
file.write(line.replace(LINE_TO_REPLACE, replacement))
|
|
397
|
+
|
|
398
|
+
def createWorkerFiles(settings, functionsData):
|
|
399
|
+
"""
|
|
400
|
+
Create worker files corresponding to each exported function.
|
|
401
|
+
"""
|
|
402
|
+
folder = settings[FOLDER]
|
|
403
|
+
name = settings[NAME]
|
|
404
|
+
runtimeSystem = settings[RUNTIME_SYSTEM_FOR_WEBWORKER]
|
|
405
|
+
|
|
406
|
+
folderName = f'{folder}/{WORKERS_FOLDER}'
|
|
407
|
+
|
|
408
|
+
# check existnace of folder for workers
|
|
409
|
+
if not os.path.exists(folderName):
|
|
410
|
+
os.mkdir(folderName)
|
|
411
|
+
|
|
412
|
+
# generation of workers for each file and each exported function
|
|
413
|
+
for nameOfFile in functionsData.keys():
|
|
414
|
+
for funcName in functionsData[nameOfFile].keys():
|
|
415
|
+
|
|
416
|
+
# create name of worker
|
|
417
|
+
workerName = f'{folderName}/{funcName}{WORKER_SUFFIX}{WORKER_EXTENSION}'
|
|
418
|
+
|
|
419
|
+
# create file and generate code of the current worker
|
|
420
|
+
with open(workerName, WRITE_MODE) as file:
|
|
421
|
+
put = file.write
|
|
422
|
+
put(f'{AUTOMATIC_GENERATION_LINE}\n\n')
|
|
423
|
+
libFile = f'../{folder}/{name}{WW_FILE_SUFFIX}'
|
|
424
|
+
put('import {export' + name + '}' + f" from '{libFile}';\n")
|
|
425
|
+
put('import {' + CPP_WRAPPER_FUNCTION + '}')
|
|
426
|
+
put(f" from '../{runtimeSystem}';\n\n")
|
|
427
|
+
put('onmessage = async function (evt) {\n')
|
|
428
|
+
put(f'{WW_SPACE}export{name}().then(module => \n')
|
|
429
|
+
put(WW_SUBSPACE + '{\n')
|
|
430
|
+
put(f'{WW_SUBSUBSPACE}let args = evt.data;\n')
|
|
431
|
+
line = f"let result = cppWrapper(module, args, '{funcName}', 'number');"
|
|
432
|
+
put(f'{WW_SUBSUBSPACE}{line}\n')
|
|
433
|
+
put(WW_SUBSUBSPACE + "postMessage({'callResult': result, 'args': args});\n")
|
|
434
|
+
put(WW_SUBSPACE + '} )\n}')
|
|
435
|
+
|
|
436
|
+
def updatePackageJsonFile(settings):
|
|
437
|
+
""" Add JS-file with exported C/C++-functions to "sources" of package.json.
|
|
438
|
+
"""
|
|
439
|
+
# data from package.json
|
|
440
|
+
packageData = None
|
|
441
|
+
|
|
442
|
+
# get package data from package.json
|
|
443
|
+
with open(settings[PACKAGE_JSON_FILE], READ_MODE) as file:
|
|
444
|
+
packageData = json.load(file)
|
|
445
|
+
|
|
446
|
+
# create full name of JS-lib file that is added to package.json
|
|
447
|
+
fullNameOfLibFile = f"{settings[FOLDER].lstrip('../')}/{settings[NAME]}.js"
|
|
448
|
+
|
|
449
|
+
# add dependence to package data
|
|
450
|
+
if PJSN_SOURCES in packageData.keys():
|
|
451
|
+
# add JS-file if "source" does not contain it yet
|
|
452
|
+
if fullNameOfLibFile not in packageData[PJSN_SOURCES]:
|
|
453
|
+
packageData[PJSN_SOURCES].append(fullNameOfLibFile)
|
|
454
|
+
else:
|
|
455
|
+
packageData[PJSN_SOURCES] = [ fullNameOfLibFile ]
|
|
456
|
+
|
|
457
|
+
# update package.json
|
|
458
|
+
with open(settings[PACKAGE_JSON_FILE], WRITE_MODE) as file:
|
|
459
|
+
json.dump(packageData, file)
|
|
460
|
+
|
|
461
|
+
def completeJsWasmfile(settings, functionsData):
|
|
462
|
+
"""
|
|
463
|
+
Add exported C/C++-function specifications and the corresponding init-function
|
|
464
|
+
to JS-file created by Emscripten.
|
|
465
|
+
"""
|
|
466
|
+
with open(f'{settings[FOLDER]}/{settings[NAME]}.js', APPEND_MODE) as file:
|
|
467
|
+
put = file.write
|
|
468
|
+
put('\n\n')
|
|
469
|
+
|
|
470
|
+
exportedFuncsNames = []
|
|
471
|
+
|
|
472
|
+
for cppFile in functionsData.keys():
|
|
473
|
+
for funcName in functionsData[cppFile].keys():
|
|
474
|
+
exportedFuncsNames.append(funcName)
|
|
475
|
+
put(f'var {funcName} = ' + '{\n')
|
|
476
|
+
arguments = functionsData[cppFile][funcName][ARGUMENTS]
|
|
477
|
+
put(f'{SPACE}{ARGUMENTS}: ' + '{\n')
|
|
478
|
+
argCommasCount = len(arguments.keys()) - 1
|
|
479
|
+
|
|
480
|
+
for arg in arguments.keys():
|
|
481
|
+
put(f'{SUBSPACE}{arg}: ' + '{\n')
|
|
482
|
+
attrCommasCount = len(arguments[arg].keys()) - 1
|
|
483
|
+
|
|
484
|
+
for attribute in arguments[arg].keys():
|
|
485
|
+
|
|
486
|
+
if attribute == TYPE:
|
|
487
|
+
put(f"{SUBSUBSPACE}{attribute}: '{arguments[arg][attribute]}'")
|
|
488
|
+
|
|
489
|
+
if attrCommasCount > 0:
|
|
490
|
+
put(',')
|
|
491
|
+
attrCommasCount -= 1
|
|
492
|
+
|
|
493
|
+
put('\n')
|
|
494
|
+
|
|
495
|
+
else:
|
|
496
|
+
put(f'{SUBSUBSPACE}{attribute}: ' + '{\n')
|
|
497
|
+
ref = arguments[arg][attribute][REF]
|
|
498
|
+
put(f"{SUBSUBSUBSPACE}{REF}: '{ref}',\n")
|
|
499
|
+
value = arguments[arg][attribute][VALUE]
|
|
500
|
+
put(f"{SUBSUBSUBSPACE}{VALUE}: '{value}'\n")
|
|
501
|
+
put(SUBSUBSPACE + '}')
|
|
502
|
+
|
|
503
|
+
if attrCommasCount > 0:
|
|
504
|
+
put(',')
|
|
505
|
+
attrCommasCount -= 1
|
|
506
|
+
|
|
507
|
+
put('\n')
|
|
508
|
+
|
|
509
|
+
put(SUBSPACE + '}')
|
|
510
|
+
|
|
511
|
+
if argCommasCount > 0:
|
|
512
|
+
put(',')
|
|
513
|
+
argCommasCount -= 1
|
|
514
|
+
|
|
515
|
+
put('\n')
|
|
516
|
+
|
|
517
|
+
put(SPACE + '},\n')
|
|
518
|
+
put(f'{SPACE}{OUTPUT}: ' + '{\n')
|
|
519
|
+
outputType = functionsData[cppFile][funcName][OUTPUT][TYPE]
|
|
520
|
+
put(f"{SUBSPACE}{TYPE}: '{outputType}',\n")
|
|
521
|
+
outputSource = functionsData[cppFile][funcName][OUTPUT][SOURCE]
|
|
522
|
+
put(f'{SUBSPACE}{SOURCE}: ')
|
|
523
|
+
|
|
524
|
+
if outputType != OBJECTS:
|
|
525
|
+
put(f"'{outputSource}'")
|
|
526
|
+
else:
|
|
527
|
+
put(f'{outputSource}')
|
|
528
|
+
|
|
529
|
+
put(f'\n{SPACE}' + '}\n')
|
|
530
|
+
put('}; ' + f'// {funcName}\n\n')
|
|
531
|
+
|
|
532
|
+
# add init-function
|
|
533
|
+
put(f'var {settings[NAME]} = undefined;\n\n')
|
|
534
|
+
put(f'async function init{settings[NAME]}() ' + '{\n')
|
|
535
|
+
put(f'{SPACE}if ({settings[NAME]} === undefined) ' + '{\n')
|
|
536
|
+
put(f'{SUBSPACE}console.log("Wasm not Loaded, Loading");\n')
|
|
537
|
+
put(f'{SUBSPACE}{settings[NAME]} = await export{settings[NAME]}();\n')
|
|
538
|
+
|
|
539
|
+
for name in exportedFuncsNames:
|
|
540
|
+
put(f'{SUBSPACE}{settings[NAME]}.{name} = {name};\n')
|
|
541
|
+
|
|
542
|
+
put(SPACE + '} else {\n')
|
|
543
|
+
put(f'{SUBSPACE}console.log("Wasm Loaded, Passing");\n')
|
|
544
|
+
put(SPACE + '}\n')
|
|
545
|
+
put('}')
|
|
546
|
+
|
|
547
|
+
def generateApiFile(settings, functionsData):
|
|
548
|
+
""" Generate code in the package-file.
|
|
549
|
+
"""
|
|
550
|
+
def generateFuncsForMainStreamRun(put, funcName, funcData):
|
|
551
|
+
"""
|
|
552
|
+
Generate code of functions for run in the main stream.
|
|
553
|
+
"""
|
|
554
|
+
|
|
555
|
+
# put package function code
|
|
556
|
+
put(f'export function {SERVICE_PREFFIX}{funcData[PROTOTYPE]} ' + '{\n')
|
|
557
|
+
put(f"{SPACE}return callWasm({settings[NAME]}, '{funcName}', {funcData[CALL_ARGS]});\n")
|
|
558
|
+
put('}\n\n')
|
|
559
|
+
|
|
560
|
+
def generateFuncsForWebWorker(put, funcName, funcData):
|
|
561
|
+
"""
|
|
562
|
+
Generate code of functions for run in webworker.
|
|
563
|
+
"""
|
|
564
|
+
|
|
565
|
+
# put package function code
|
|
566
|
+
put(f'export async function {SERVICE_PREFFIX}{funcData[WW_PROTOTYPE]} ' + '{\n')
|
|
567
|
+
|
|
568
|
+
workerName = f'{settings[FOLDER]}/{WORKERS_FOLDER}/{funcName}{WORKER_SUFFIX}{WORKER_EXTENSION}'
|
|
569
|
+
|
|
570
|
+
put(f'{SPACE}return new Promise((resolve, reject) => ')
|
|
571
|
+
put('{\n')
|
|
572
|
+
put(f"{SUBSPACE}const worker = new Worker(new URL('{workerName}', import.meta.url));\n")
|
|
573
|
+
put(f"{SUBSPACE}worker.postMessage(getCppInput({settings[NAME]}['{funcName}'].arguments,")
|
|
574
|
+
put(f"{funcData[CALL_ARGS]}));\n{SUBSPACE}")
|
|
575
|
+
put('worker.onmessage = function(e) {\n')
|
|
576
|
+
put(f'{SUBSUBSPACE}worker.terminate();\n')
|
|
577
|
+
put(f'{SUBSUBSPACE}resolve(')
|
|
578
|
+
put(f"getResult({settings[NAME]}['{funcName}'], e.data));\n")
|
|
579
|
+
put(SUBSPACE)
|
|
580
|
+
put('}\n')
|
|
581
|
+
put(SPACE)
|
|
582
|
+
put('});\n')
|
|
583
|
+
put('}\n\n')
|
|
584
|
+
|
|
585
|
+
apiFile = f'../wasm/{settings[NAME]}{API_SUFFIX}.js'
|
|
586
|
+
|
|
587
|
+
with open(apiFile, WRITE_MODE) as file:
|
|
588
|
+
put = file.write
|
|
589
|
+
|
|
590
|
+
put(AUTOMATIC_GENERATION_LINE)
|
|
591
|
+
put(f'\n// JavaScript API for call wasm-functions from the module {settings[NAME]}\n')
|
|
592
|
+
put('\n// Imports for call wasm runtime-system: in the main stream and in webworkers\n')
|
|
593
|
+
|
|
594
|
+
# put import-line: wasm-computations in the main stream
|
|
595
|
+
put('import {' + CALL_WASM + '} from ')
|
|
596
|
+
callWasm = settings[RUNTIME_SYSTEM].rstrip('.js')
|
|
597
|
+
put(f"'{callWasm}';\n")
|
|
598
|
+
|
|
599
|
+
# put import-line: wasm-computations in webworkers
|
|
600
|
+
put('import {' + f'{GET_CPP_INPUT}, {GET_RESULT}' + '} from ')
|
|
601
|
+
callWasmWW = settings[RUNTIME_SYSTEM_FOR_WEBWORKER].rstrip('.js')
|
|
602
|
+
put(f"'{callWasmWW}';\n\n")
|
|
603
|
+
|
|
604
|
+
# put init-function
|
|
605
|
+
#put('//tags: init\n')
|
|
606
|
+
put(f'export async function _init{settings[NAME]}API() ' + '{\n')
|
|
607
|
+
put(f'{SPACE}await init{settings[NAME]}();\n')
|
|
608
|
+
put('}\n\n')
|
|
609
|
+
|
|
610
|
+
# put call of each exported C/C++-function
|
|
611
|
+
for cppFileName in functionsData.keys():
|
|
612
|
+
for funcName in functionsData[cppFileName].keys():
|
|
613
|
+
generateFuncsForMainStreamRun(put, funcName, functionsData[cppFileName][funcName])
|
|
614
|
+
generateFuncsForWebWorker(put, funcName, functionsData[cppFileName][funcName])
|
|
615
|
+
|
|
616
|
+
def generateCodeInPackageTsFile(settings, functionsData):
|
|
617
|
+
"""
|
|
618
|
+
Generate code of wasm-computations call in the file package.ts.
|
|
619
|
+
"""
|
|
620
|
+
def putImportLines(put, settings, functionsData):
|
|
621
|
+
"""
|
|
622
|
+
Generate import lines.
|
|
623
|
+
"""
|
|
624
|
+
put('\nimport {')
|
|
625
|
+
|
|
626
|
+
# init module function
|
|
627
|
+
put(f'_init{settings[NAME]}{API_SUFFIX}')
|
|
628
|
+
|
|
629
|
+
# put other import functions
|
|
630
|
+
for cppFileName in functionsData.keys():
|
|
631
|
+
for funcName in functionsData[cppFileName].keys():
|
|
632
|
+
put(f', {SERVICE_PREFFIX}{funcName},')
|
|
633
|
+
put(f' {SERVICE_PREFFIX}{funcName}{IN_WEBWORKER_SUFFIX}')
|
|
634
|
+
|
|
635
|
+
put('}')
|
|
636
|
+
put(f" from '../wasm/{settings[NAME]}{API_SUFFIX}';\n\n")
|
|
637
|
+
|
|
638
|
+
def putInitFunction(put, settings):
|
|
639
|
+
"""
|
|
640
|
+
Generate code of init-function.
|
|
641
|
+
"""
|
|
642
|
+
put('//tags: init\n')
|
|
643
|
+
put('export async function init(): Promise<void> {\n')
|
|
644
|
+
put(f'{SPACE}await _init{settings[NAME]}{API_SUFFIX}();\n')
|
|
645
|
+
put('}\n\n')
|
|
646
|
+
|
|
647
|
+
def getTStype(argType):
|
|
648
|
+
"""
|
|
649
|
+
Returns TypeScript type.
|
|
650
|
+
"""
|
|
651
|
+
if argType in typesMap.keys():
|
|
652
|
+
return typesMap[argType]
|
|
653
|
+
return ANY_TYPE
|
|
654
|
+
|
|
655
|
+
def getArgTypeAndArgName(annotationLine):
|
|
656
|
+
"""
|
|
657
|
+
Returns a tuple: (argType,argName)
|
|
658
|
+
"""
|
|
659
|
+
ignore1, ignore2, rest = annotationLine.partition(' ')
|
|
660
|
+
rest.strip(' ')
|
|
661
|
+
argType, ignore1, rest = rest.partition(' ')
|
|
662
|
+
rest.strip(' ')
|
|
663
|
+
argName, ignore1, ignore2 = rest.partition(' ')
|
|
664
|
+
return argType, argName
|
|
665
|
+
|
|
666
|
+
def putPrototype(put, funcName, funcData):
|
|
667
|
+
"""
|
|
668
|
+
Put prototype of the function for the main thread call.
|
|
669
|
+
"""
|
|
670
|
+
put(f'export function {funcName}(')
|
|
671
|
+
|
|
672
|
+
# default return type
|
|
673
|
+
returnType = 'void'
|
|
674
|
+
|
|
675
|
+
arguments = ''
|
|
676
|
+
|
|
677
|
+
# put arguments
|
|
678
|
+
for line in funcData[ANNOTATION]:
|
|
679
|
+
if line.startswith(ANNOT_INPUT):
|
|
680
|
+
argType, argName = getArgTypeAndArgName(line)
|
|
681
|
+
arguments += f'{argName}: {getTStype(argType)}, '
|
|
682
|
+
elif line.startswith(ANNOT_OUTPUT):
|
|
683
|
+
returnType, argName = getArgTypeAndArgName(line)
|
|
684
|
+
|
|
685
|
+
arguments.rstrip(', ')
|
|
686
|
+
put(arguments.rstrip(', '))
|
|
687
|
+
|
|
688
|
+
put(f'): {getTStype(returnType)}')
|
|
689
|
+
|
|
690
|
+
put(' {\n')
|
|
691
|
+
|
|
692
|
+
def putPrototypeForWebWorker(put, funcName, funcData):
|
|
693
|
+
"""
|
|
694
|
+
Put prototype of the function for call in webworker.
|
|
695
|
+
"""
|
|
696
|
+
put(f'export async function {funcName}{IN_WEBWORKER_SUFFIX}(')
|
|
697
|
+
|
|
698
|
+
# default return type
|
|
699
|
+
returnType = 'void'
|
|
700
|
+
|
|
701
|
+
arguments = ''
|
|
702
|
+
|
|
703
|
+
# put arguments
|
|
704
|
+
for line in funcData[ANNOTATION]:
|
|
705
|
+
if line.startswith(ANNOT_INPUT):
|
|
706
|
+
argType, argName = getArgTypeAndArgName(line)
|
|
707
|
+
arguments += f'{argName}: {getTStype(argType)}, '
|
|
708
|
+
elif line.startswith(ANNOT_OUTPUT):
|
|
709
|
+
returnType, argName = getArgTypeAndArgName(line)
|
|
710
|
+
|
|
711
|
+
arguments.rstrip(', ')
|
|
712
|
+
put(arguments.rstrip(', '))
|
|
713
|
+
|
|
714
|
+
put(f'): Promise<{getTStype(returnType)}>')
|
|
715
|
+
|
|
716
|
+
put(' {\n')
|
|
717
|
+
|
|
718
|
+
def generateWasmCall(put, funcName, funcData):
|
|
719
|
+
"""
|
|
720
|
+
Generate code for wasm function call in the main thread.
|
|
721
|
+
"""
|
|
722
|
+
# put annotation lines
|
|
723
|
+
for line in funcData[ANNOTATION]:
|
|
724
|
+
put(f'{line}\n')
|
|
725
|
+
|
|
726
|
+
# put function prototype
|
|
727
|
+
putPrototype(put, funcName, funcData)
|
|
728
|
+
|
|
729
|
+
# put main body
|
|
730
|
+
put(f'{SPACE}return {SERVICE_PREFFIX}{funcData[PROTOTYPE]};\n')
|
|
731
|
+
|
|
732
|
+
put('}\n\n')
|
|
733
|
+
|
|
734
|
+
def putMainBodyForWebWorker(put, funcName, funcData):
|
|
735
|
+
"""
|
|
736
|
+
Put main body for call wasm-computations in webworker.
|
|
737
|
+
"""
|
|
738
|
+
put(f'{SPACE}let {OUTPUT_VARIABLE}: any;\n')
|
|
739
|
+
put(f'{SPACE}let {PROMISE_VARIABLE} = ')
|
|
740
|
+
put(f'{SERVICE_PREFFIX}{funcName}{IN_WEBWORKER_SUFFIX}(')
|
|
741
|
+
|
|
742
|
+
ignore1, ignore2, arguments = funcData[PROTOTYPE].partition('(')
|
|
743
|
+
put(f'{arguments};\n\n')
|
|
744
|
+
|
|
745
|
+
put(f'{SPACE}await {PROMISE_VARIABLE}.then(\n')
|
|
746
|
+
put(f'{SUBSPACE}{RESULT_VARIBLABLE} => ')
|
|
747
|
+
put('{ ')
|
|
748
|
+
put(f' {OUTPUT_VARIABLE} = {RESULT_VARIBLABLE};')
|
|
749
|
+
put(' },\n')
|
|
750
|
+
put(f'{SUBSPACE}{ERROR_VARIABLE} => ')
|
|
751
|
+
put('{ ')
|
|
752
|
+
put(' throw new Error (`Error: ${')
|
|
753
|
+
put(ERROR_VARIABLE)
|
|
754
|
+
put('}`); }\n')
|
|
755
|
+
put(f'{SPACE});\n\n')
|
|
756
|
+
put(f'{SPACE}return {OUTPUT_VARIABLE};\n')
|
|
757
|
+
|
|
758
|
+
def generateWasmInWebWorkerCall(put, funcName, funcData):
|
|
759
|
+
"""
|
|
760
|
+
Generate code for wasm function call in the webworker.
|
|
761
|
+
"""
|
|
762
|
+
# put annotation lines
|
|
763
|
+
for line in funcData[ANNOTATION]:
|
|
764
|
+
if ANNOT_NAME in line:
|
|
765
|
+
put(f'{line.rstrip()}{IN_WEBWORKER_SUFFIX}\n')
|
|
766
|
+
else:
|
|
767
|
+
put(f'{line}\n')
|
|
768
|
+
|
|
769
|
+
# put function prototype
|
|
770
|
+
putPrototypeForWebWorker(put, funcName, funcData)
|
|
771
|
+
|
|
772
|
+
# put main body
|
|
773
|
+
putMainBodyForWebWorker(put, funcName, funcData)
|
|
774
|
+
|
|
775
|
+
put('}\n\n')
|
|
776
|
+
|
|
777
|
+
with open(settings[PACKAGE_FILE], APPEND_MODE) as file:
|
|
778
|
+
put = file.write
|
|
779
|
+
|
|
780
|
+
# put import lines
|
|
781
|
+
putImportLines(put, settings, functionsData)
|
|
782
|
+
|
|
783
|
+
# put init-function
|
|
784
|
+
putInitFunction(put, settings)
|
|
785
|
+
|
|
786
|
+
# generate code for wasm-computations call
|
|
787
|
+
for cppFileName in functionsData.keys():
|
|
788
|
+
for funcName, funcData in functionsData[cppFileName].items():
|
|
789
|
+
generateWasmCall(put, funcName, funcData)
|
|
790
|
+
generateWasmInWebWorkerCall(put, funcName, funcData)
|
|
791
|
+
|
|
792
|
+
put('\n')
|
|
793
|
+
|
|
794
|
+
def main(nameOfSettingsFile="module.json"):
|
|
795
|
+
"""
|
|
796
|
+
The main script:
|
|
797
|
+
1) load export settings from json-file;
|
|
798
|
+
2) parse C/C++-files and get C/C++-functions to be exported;
|
|
799
|
+
3) create Emscripten command;
|
|
800
|
+
4) execute Emscripten command;
|
|
801
|
+
5) create JS-wrapper for wasm-functions run in webworkers;
|
|
802
|
+
6) create worker files;
|
|
803
|
+
7) complete JS-file created by Emscripten;
|
|
804
|
+
8) create JS API file;
|
|
805
|
+
9) generate code of wasm-computations call in package.ts;
|
|
806
|
+
10) update the file package.json: add JS-file name created by Emscripten to 'sources'.
|
|
807
|
+
"""
|
|
808
|
+
try:
|
|
809
|
+
# 1) load settings
|
|
810
|
+
settings = getSettings(nameOfSettingsFile)
|
|
811
|
+
|
|
812
|
+
# 2) parse C-files and get exported functions data
|
|
813
|
+
functionsData = getFunctionsFromListOfFiles(settings)
|
|
814
|
+
|
|
815
|
+
# write functions descriptors to json-file
|
|
816
|
+
saveFunctionsDataToFile(functionsData, 'func.json')
|
|
817
|
+
|
|
818
|
+
# 3) get command for Emscripten tool
|
|
819
|
+
command = getCommand(settings, functionsData)
|
|
820
|
+
|
|
821
|
+
# save command to file
|
|
822
|
+
saveCommand(command, 'command.txt')
|
|
823
|
+
|
|
824
|
+
# 4) execute command by Emscripten
|
|
825
|
+
os.system(command)
|
|
826
|
+
|
|
827
|
+
# 5) create JS-wrapper for wasm-functions run in webworkers
|
|
828
|
+
createJSwrapperForWasmInWebWorkerRun(settings)
|
|
829
|
+
|
|
830
|
+
# 6) create worker files
|
|
831
|
+
createWorkerFiles(settings, functionsData)
|
|
832
|
+
|
|
833
|
+
# 7) complete JS-file created by Emscripten
|
|
834
|
+
completeJsWasmfile(settings, functionsData)
|
|
835
|
+
|
|
836
|
+
# 8) create JS API file
|
|
837
|
+
generateApiFile(settings, functionsData)
|
|
838
|
+
|
|
839
|
+
# 9) generate code of wasm-computations call in package.ts
|
|
840
|
+
generateCodeInPackageTsFile(settings, functionsData)
|
|
841
|
+
|
|
842
|
+
# 10) update the file package.json
|
|
843
|
+
updatePackageJsonFile(settings)
|
|
844
|
+
|
|
845
|
+
# 11)* delete of the __pycache__ folder, otherwise it must be done further manually
|
|
846
|
+
shutil.rmtree('__pycache__')
|
|
847
|
+
|
|
848
|
+
except OSError:
|
|
849
|
+
print("OS ERROR: check paths and file names!")
|
|
850
|
+
|
|
851
|
+
except KeyError:
|
|
852
|
+
print("PARSING ERROR: check C/C++-code!")
|
|
853
|
+
|
|
854
|
+
except IndexError:
|
|
855
|
+
print("PARSING ERROR: check C/C++-code!")
|
|
856
|
+
|
|
857
|
+
except Warning:
|
|
858
|
+
print("Check annotation of exported C/C++-function!")
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
if __name__ == '__main__':
|
|
862
|
+
main()
|