/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import { argv, cleanTask, copyTask, eslintTask, logger, jestTask, option, parallel, series, spawn, task, tscTask, } from 'just-scripts'; import glob from 'glob'; import path from 'path'; import which from 'which'; const node = process.execPath; option('fix'); task('clean', cleanTask({paths: ['build', 'dist']})); task( 'prepare-for-build', parallel( babelTransformTask({paths: ['src_js'], dest: 'dist'}), copyTask({paths: ['src_js/**/*.d.ts'], dest: 'dist'}), emcmakeGenerateTask(), ), ); function defineFlavor(flavor: string, env: NodeJS.ProcessEnv) { task(`cmake-build:${flavor}`, cmakeBuildTask({targets: [flavor]})); task( `jest:${flavor}`, jestTask({config: path.join(__dirname, 'jest.config.ts'), env}), ); task( `test:${flavor}`, series('prepare-for-build', `cmake-build:${flavor}`, `jest:${flavor}`), ); } defineFlavor('asmjs-async', {WASM: '0', SYNC: '0'}); defineFlavor('asmjs-sync', {WASM: '0', SYNC: '1'}); defineFlavor('wasm-async', {WASM: '1', SYNC: '0'}); defineFlavor('wasm-sync', {WASM: '1', SYNC: '1'}); task('cmake-build:all', cmakeBuildTask()); task( 'cmake-build:async', cmakeBuildTask({targets: ['asmjs-async', 'wasm-async']}), ); task( 'cmake-build:sync', cmakeBuildTask({targets: ['asmjs-sync', 'wasm-sync']}), ); task('build', series('prepare-for-build', 'cmake-build:all')); task( 'test', series( 'prepare-for-build', series('cmake-build:asmjs-async', 'jest:asmjs-async'), series('cmake-build:asmjs-sync', 'jest:asmjs-sync'), series('cmake-build:wasm-async', 'jest:wasm-async'), series('cmake-build:wasm-sync', 'jest:wasm-sync'), ), ); task( 'benchmark', series('prepare-for-build', 'cmake-build:sync', runBenchTask()), ); task( 'lint', parallel( tscTask(), series(eslintTask({fix: argv().fix}), clangFormatTask({fix: argv().fix})), ), ); function babelTransformTask(opts: { paths: ReadonlyArray; dest: string; }) { return () => { const args = [...opts.paths, '--source-maps', '--out-dir', opts.dest]; logger.info(`Transforming [${opts.paths.join(',')}] to '${opts.dest}'`); return spawn(node, [require.resolve('@babel/cli/bin/babel'), ...args]); }; } function runBenchTask() { return () => { const files = glob.sync('./tests/Benchmarks/**/*'); const args = ['./tests/bin/run-bench.ts', ...files]; logger.info(args.join(' ')); return spawn(node, args, { stdio: 'inherit', env: {NODE_OPTIONS: '-r ts-node/register'}, }); }; } function emcmakeGenerateTask() { return () => { const emcmake = which.sync('emcmake'); const ninja = which.sync('ninja', {nothrow: true}); const args = [ 'cmake', '-S', '.', '-B', 'build', ...(ninja ? ['-G', 'Ninja'] : []), ]; logger.info(['emcmake', ...args].join(' ')); return spawn(emcmake, args); }; } function cmakeBuildTask(opts?: {targets?: ReadonlyArray}) { return () => { const cmake = which.sync('cmake'); const args = [ '--build', 'build', ...(opts?.targets ? ['--target', ...opts.targets] : []), ]; logger.info(['cmake', ...args].join(' ')); return spawn(cmake, args, {stdio: 'inherit'}); }; } function clangFormatTask(opts?: {fix?: boolean}) { return () => { const args = [ ...(opts?.fix ? ['-i'] : ['--dry-run', '--Werror']), ...glob.sync('**/*.{h,hh,hpp,c,cpp,cc,m,mm}'), ]; logger.info(['clang-format', ...args].join(' ')); return spawn(node, [require.resolve('clang-format'), ...args], { stdio: 'inherit', }); }; }