mirror of
https://github.com/Z3Prover/z3
synced 2025-08-08 12:11:23 +00:00
Add high level bindings for js (#6048)
* [Draft] Added unfinished code for high level bindings for js * * Rewrote structure of js api files * Added more high level apis * Minor fixes * Fixed wasm github action * Fix JS test * Removed ContextOptions type * * Added Ints to JS Api * Added tests to JS Api * Added run-time checks for contexts * Removed default contexts * Merged Context and createContext so that the api behaves the sames as in other constructors * Added a test for Solver * Added Reals * Added classes for IntVals and RealVals * Added abillity to specify logic for solver * Try to make CI tests not fail * Changed APIs after a round of review * Fix test * Added BitVectors * Made sort into getter * Added initial JS docs * Added more coercible types * Removed done TODOs
This commit is contained in:
parent
3d00d1d56b
commit
7fdcbbaee9
37 changed files with 15973 additions and 643 deletions
77
src/api/js/scripts/build-wasm.ts
Normal file
77
src/api/js/scripts/build-wasm.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import assert from 'assert';
|
||||
import { SpawnOptions, spawnSync as originalSpawnSync } from 'child_process';
|
||||
import fs, { existsSync } from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import process from 'process';
|
||||
import { asyncFuncs } from './async-fns';
|
||||
import { makeCCWrapper } from './make-cc-wrapper';
|
||||
import { functions } from './parse-api';
|
||||
|
||||
console.log('--- Building WASM');
|
||||
|
||||
const SWAP_OPTS: SpawnOptions = {
|
||||
shell: true,
|
||||
stdio: 'inherit',
|
||||
env: {
|
||||
...process.env,
|
||||
CXXFLAGS: '-pthread -s USE_PTHREADS=1 -s DISABLE_EXCEPTION_CATCHING=0',
|
||||
LDFLAGS: '-s WASM_BIGINT -s -pthread -s USE_PTHREADS=1',
|
||||
FPMATH_ENABLED: 'False', // Until Safari supports WASM SSE, we have to disable fast FP support
|
||||
// TODO(ritave): Setting EM_CACHE breaks compiling on M1 MacBook
|
||||
//EM_CACHE: path.join(os.homedir(), '.emscripten/'),
|
||||
},
|
||||
};
|
||||
|
||||
function spawnSync(command: string, opts: SpawnOptions = {}) {
|
||||
console.log(`- ${command}`);
|
||||
// TODO(ritave): Create a splitter that keeps track of quoted strings
|
||||
const [cmd, ...args] = command.split(' ');
|
||||
const { error, ...rest } = originalSpawnSync(cmd, args, { ...SWAP_OPTS, ...opts });
|
||||
if (error !== undefined || rest.status !== 0) {
|
||||
if (error !== undefined) {
|
||||
console.error(error.message);
|
||||
} else {
|
||||
console.error(`Process exited with status ${rest.status}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
return rest;
|
||||
}
|
||||
|
||||
function exportedFuncs(): string[] {
|
||||
const extras = ['_set_throwy_error_handler', '_set_noop_error_handler', ...asyncFuncs.map(f => '_async_' + f)];
|
||||
|
||||
// TODO(ritave): This variable is unused in original script, find out if it's important
|
||||
const fns: any[] = (functions as any[]).filter(f => !asyncFuncs.includes(f.name));
|
||||
|
||||
return [...extras, ...(functions as any[]).map(f => '_' + f.name)];
|
||||
}
|
||||
|
||||
assert(fs.existsSync('./package.json'), 'Not in the root directory of js api');
|
||||
const z3RootDir = path.join(process.cwd(), '../../../');
|
||||
|
||||
// TODO(ritave): Detect if it's in the configuration we need
|
||||
if (!existsSync(path.join(z3RootDir, 'build/Makefile'))) {
|
||||
spawnSync('emconfigure python scripts/mk_make.py --staticlib --single-threaded --arm64=false', {
|
||||
cwd: z3RootDir,
|
||||
});
|
||||
}
|
||||
|
||||
spawnSync(`emmake make -j${os.cpus().length} libz3.a`, { cwd: path.join(z3RootDir, 'build') });
|
||||
|
||||
const ccWrapperPath = 'build/async-fns.cc';
|
||||
console.log(`- Building ${ccWrapperPath}`);
|
||||
fs.mkdirSync(path.dirname(ccWrapperPath), { recursive: true });
|
||||
fs.writeFileSync(ccWrapperPath, makeCCWrapper());
|
||||
|
||||
const fns = JSON.stringify(exportedFuncs());
|
||||
const methods = '["ccall","FS","allocate","UTF8ToString","intArrayFromString","ALLOC_NORMAL"]';
|
||||
const libz3a = path.normalize('../../../build/libz3.a');
|
||||
spawnSync(
|
||||
`emcc build/async-fns.cc ${libz3a} --std=c++20 --pre-js src/low-level/async-wrapper.js -g2 -pthread -fexceptions -s WASM_BIGINT -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=0 -s PTHREAD_POOL_SIZE_STRICT=0 -s MODULARIZE=1 -s 'EXPORT_NAME="initZ3"' -s EXPORTED_RUNTIME_METHODS=${methods} -s EXPORTED_FUNCTIONS=${fns} -s DISABLE_EXCEPTION_CATCHING=0 -s SAFE_HEAP=0 -s DEMANGLE_SUPPORT=1 -s TOTAL_MEMORY=1GB -I z3/src/api/ -o build/z3-built.js`,
|
||||
);
|
||||
|
||||
fs.rmSync(ccWrapperPath);
|
||||
|
||||
console.log('--- WASM build finished');
|
Loading…
Add table
Add a link
Reference in a new issue