cpp.js 1.0.0-beta.7 → 1.0.0

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +1 -1
  3. package/README.md +9 -26
  4. package/package.json +23 -23
  5. package/src/{functions/buildJS.js → actions/buildJs.js} +7 -6
  6. package/src/actions/buildWasm.js +68 -0
  7. package/src/actions/createInterface.js +128 -0
  8. package/src/actions/createLib.js +104 -0
  9. package/src/actions/createXCFramework.js +44 -0
  10. package/src/actions/getAllBridges.js +8 -0
  11. package/src/actions/getCmakeParameters.js +56 -0
  12. package/src/actions/getData.js +28 -0
  13. package/src/actions/getDependLibs.js +19 -0
  14. package/src/{functions → actions}/run.js +118 -64
  15. package/src/assets/CMakeLists.txt +14 -10
  16. package/src/assets/commonBridges.cpp +16 -0
  17. package/src/assets/dist.cmake +1 -1
  18. package/src/assets/ios.toolchain.cmake +4 -4
  19. package/src/bin.js +255 -96
  20. package/src/index.js +13 -63
  21. package/src/integration/getCppJsScript.js +91 -0
  22. package/src/integration/getDependFilePath.js +34 -0
  23. package/src/state/calculateDependencyParameters.js +64 -0
  24. package/src/state/index.js +81 -0
  25. package/src/state/loadConfig.js +104 -0
  26. package/src/utils/downloadAndExtractFile.js +36 -0
  27. package/src/utils/findFiles.js +5 -0
  28. package/src/utils/fixPackageName.js +7 -0
  29. package/src/utils/getAbsolutePath.js +14 -0
  30. package/src/utils/getCMakeListsFilePath.js +17 -0
  31. package/src/utils/getOsUserAndGroupId.js +1 -1
  32. package/src/utils/getParentPath.js +12 -0
  33. package/src/utils/hash.js +20 -0
  34. package/src/utils/loadJs.js +32 -0
  35. package/src/utils/loadJson.js +16 -0
  36. package/src/utils/pullDockerImage.js +2 -2
  37. package/src/utils/systemKeys.js +18 -0
  38. package/src/utils/writeJson.js +9 -0
  39. package/.mocharc.yaml +0 -3
  40. package/src/functions/createBridge.js +0 -37
  41. package/src/functions/createLib.js +0 -44
  42. package/src/functions/createWasm.js +0 -67
  43. package/src/functions/findOrCreateInterfaceFile.js +0 -68
  44. package/src/functions/finishBuild.js +0 -43
  45. package/src/functions/getCmakeParams.js +0 -106
  46. package/src/functions/getData.js +0 -36
  47. package/src/functions/getLibs.js +0 -33
  48. package/src/functions/specs/createBridge.spec.js +0 -51
  49. package/src/functions/specs/findOrCreateInterfaceFile.spec.js +0 -49
  50. package/src/utils/createTempDir.js +0 -15
  51. package/src/utils/findCMakeListsFile.js +0 -16
  52. package/src/utils/getBaseInfo.js +0 -15
  53. package/src/utils/getCliPath.js +0 -12
  54. package/src/utils/getConfig.js +0 -170
  55. package/src/utils/getDirName.js +0 -8
  56. package/src/utils/getPathInfo.js +0 -10
  57. package/src/utils/specs/findCMakeListsFile.spec.js +0 -34
  58. package/src/utils/specs/utils.spec.js +0 -81
  59. package/test/data/sample.cpp +0 -1
  60. package/test/data/sample.h +0 -10
  61. package/test/data/sample.i +0 -12
  62. package/test/data/sample2.ei +0 -12
  63. package/test/data/sample2.h +0 -10
  64. /package/{test/data/sample2.cpp → src/assets/cppjsEmptySource.cpp} +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # cpp.js
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 🚀 first stable release
8
+
9
+ ## 1.0.0-beta.33
10
+
11
+ ### Patch Changes
12
+
13
+ - chore: add initial version of CHANGELOGS files
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Buğra Sarı
3
+ Copyright (c) 2025 Buğra Sarı
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -14,6 +14,11 @@
14
14
  <a href="https://github.com/bugra9/cpp.js/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/bugra9/cpp.js?style=for-the-badge" /></a>
15
15
  <a href="https://github.com/bugra9/cpp.js/discussions"><img alt="Discussions" src="https://img.shields.io/github/discussions/bugra9/cpp.js?style=for-the-badge" /></a>
16
16
  <a href="https://github.com/bugra9/cpp.js/issues"><img alt="Issues" src="https://img.shields.io/github/issues/bugra9/cpp.js?style=for-the-badge" /></a>
17
+ <br />
18
+ <img alt="CodeQL" src="https://img.shields.io/github/actions/workflow/status/bugra9/cpp.js/github-code-scanning/codeql?branch=main&style=for-the-badge&label=CodeQL">
19
+ <img alt="Linux Build" src="https://img.shields.io/github/actions/workflow/status/bugra9/cpp.js/build-linux.yml?branch=main&style=for-the-badge&label=Linux%20Build">
20
+ <img alt="Macos Build" src="https://img.shields.io/github/actions/workflow/status/bugra9/cpp.js/build-macos.yml?branch=main&style=for-the-badge&label=Macos%20Build">
21
+ <img alt="Windows Build" src="https://img.shields.io/github/actions/workflow/status/bugra9/cpp.js/build-windows.yml?branch=main&style=for-the-badge&label=Windows%20Build">
17
22
  </div>
18
23
 
19
24
  <h3 align="center">
@@ -23,15 +28,15 @@
23
28
  <span> · </span>
24
29
  <a href="https://cpp.js.org/docs/api/cpp-bindings/overview">C++ Bindings</a>
25
30
  <span> · </span>
26
- <a href="https://cpp.js.org/showcase">Showcase</a>
31
+ <a href="https://cpp.js.org/docs/package/package/showcase">Showcase</a>
27
32
  </h3>
28
33
 
29
34
  ## Basic Usage
30
35
  **src/index.js**
31
36
  ```js
32
- import { initCppJs } from './native/Factorial.h';
37
+ import { initCppJs, Factorial } from './native/Factorial.h';
33
38
 
34
- const { Factorial } = await initCppJs();
39
+ await initCppJs();
35
40
  const factorial = new Factorial(99999);
36
41
  const result = factorial.calculate();
37
42
  console.log(result);
@@ -72,30 +77,8 @@ To set up a new cpp.js project with a minimal starter structure, execute the fol
72
77
  ```sh
73
78
  npm create cpp.js@latest
74
79
  ```
75
- ## Integrate Into Existing Project
76
- Integrate cpp.js seamlessly into your existing projects using the appropriate packages for your development needs. Refer to the documentation links for detailed integration guides.
77
-
78
- | Platform | Package(s) | Documentation |
79
- | -------- | ---------- | ------------- |
80
- | Standalone | [cpp.js](https://www.npmjs.com/package/cpp.js) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/standalone) |
81
- | Webpack | [cppjs-webpack-plugin](https://www.npmjs.com/package/cppjs-webpack-plugin), [cppjs-loader](https://www.npmjs.com/package/cppjs-loader) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/webpack) |
82
- | Rollup | [rollup-plugin-cppjs](https://www.npmjs.com/package/rollup-plugin-cppjs) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/rollup) |
83
- | Vite | [vite-plugin-cppjs](https://www.npmjs.com/package/vite-plugin-cppjs) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/vite) |
84
- | Rspack | [cppjs-webpack-plugin](https://www.npmjs.com/package/cppjs-webpack-plugin), [cppjs-loader](https://www.npmjs.com/package/cppjs-loader) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/rspack) |
85
- | Create React App (CRA) | [cppjs-webpack-plugin](https://www.npmjs.com/package/cppjs-webpack-plugin), [cppjs-loader](https://www.npmjs.com/package/cppjs-loader) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/create-react-app) |
86
- | React Native | [cppjs-plugin-react-native](https://www.npmjs.com/package/cppjs-plugin-react-native), [cppjs-plugin-react-native-ios-helper](https://www.npmjs.com/package/cppjs-plugin-react-native-ios-helper), [cppjs-core-rn-embind](https://www.npmjs.com/package/cppjs-core-rn-embind) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/react-native) |
87
- | Expo | [cppjs-plugin-react-native](https://www.npmjs.com/package/cppjs-plugin-react-native), [cppjs-plugin-react-native-ios-helper](https://www.npmjs.com/package/cppjs-plugin-react-native-ios-helper), [cppjs-core-rn-embind](https://www.npmjs.com/package/cppjs-core-rn-embind) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/expo) |
88
- | Node.js | [cpp.js](https://www.npmjs.com/package/cpp.js) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/nodejs) |
89
- | Cloudflare Workers | [cpp.js](https://www.npmjs.com/package/cpp.js) | [Learn](https://cpp.js.org/docs/guide/integrate-into-existing-project/cloudflare-worker) |
90
-
91
- ## Features
92
- - [Calling C++ from JavaScript](https://cpp.js.org/docs/guide/features/calling-cpp-from-javascript)
93
- - [Packages](https://cpp.js.org/docs/guide/features/packages)
94
- - [Plugins](https://cpp.js.org/docs/guide/features/plugins)
95
- - [Assets](https://cpp.js.org/docs/guide/features/assets)
96
- - [Working with a Monorepo](https://cpp.js.org/docs/guide/features/monorepo)
97
80
 
98
81
  ## License
99
82
  [MIT](https://github.com/bugra9/cpp.js/blob/main/LICENSE)
100
83
 
101
- Copyright (c) 2024, Buğra Sarı
84
+ Copyright (c) 2025, Buğra Sarı
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
1
  {
2
2
  "name": "cpp.js",
3
- "version": "1.0.0-beta.7",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
- "type": "module",
6
5
  "homepage": "https://cpp.js.org",
7
6
  "repository": "https://github.com/bugra9/cpp.js.git",
8
7
  "description": "Bind C++ to JavaScript without extra code. Cpp.js supports WebAssembly and React Native for cross-platform compatibility.",
9
- "keywords": [
10
- "WebAssembly",
11
- "React Native",
12
- "bind",
13
- "c++",
14
- "emscripten",
15
- "embind",
16
- "swig"
17
- ],
8
+ "type": "module",
18
9
  "bin": {
19
10
  "cpp.js": "./src/bin.js",
20
11
  "cppjs": "./src/bin.js"
21
12
  },
22
13
  "main": "src/index.js",
23
14
  "dependencies": {
24
- "@rollup/plugin-commonjs": "^26.0.1",
25
- "@rollup/plugin-node-resolve": "^15.2.3",
15
+ "@rollup/plugin-commonjs": "^28.0.2",
16
+ "@rollup/plugin-json": "^6.1.0",
17
+ "@rollup/plugin-node-resolve": "^16.0.0",
26
18
  "@rollup/plugin-virtual": "^3.0.2",
27
19
  "commander": "^12.1.0",
28
- "glob": "^8.0.3",
29
- "rollup": "^4.18.0",
30
- "rollup-plugin-uglify": "^6.0.4",
31
- "upath": "^2.0.1"
20
+ "glob": "^11.0.0",
21
+ "rollup": "^4.29.1",
22
+ "upath": "^2.0.1",
23
+ "decompress": "^4.2.1",
24
+ "follow-redirects": "^1.15.9",
25
+ "replace": "^1.2.2"
32
26
  },
33
- "devDependencies": {
34
- "mocha": "^10.2.0"
35
- },
36
- "scripts": {
37
- "test": "mocha"
38
- }
27
+ "keywords": [
28
+ "webassembly",
29
+ "react-native",
30
+ "bind",
31
+ "c++",
32
+ "emscripten",
33
+ "embind",
34
+ "swig",
35
+ "android",
36
+ "ios",
37
+ "mobile"
38
+ ]
39
39
  }
@@ -1,10 +1,11 @@
1
1
  /* eslint-disable no-await-in-loop */
2
2
  /* eslint-disable no-restricted-syntax */
3
- import fs from 'fs';
4
3
  import { rollup } from 'rollup';
5
4
  import { nodeResolve } from '@rollup/plugin-node-resolve';
6
5
  import commonjs from '@rollup/plugin-commonjs';
7
6
  import virtual from '@rollup/plugin-virtual';
7
+ import state from '../state/index.js';
8
+ import getData from './getData.js';
8
9
 
9
10
  const nodeLibs = {
10
11
  fs: 'export default {};',
@@ -34,14 +35,14 @@ const options = {
34
35
  },
35
36
  };
36
37
 
37
- export default async function buildJS(compiler, input, type) {
38
- const entryJS = `${compiler.config.paths.cli}/assets/${type}.js`;
39
- const env = JSON.stringify(compiler.getData('env', null, type));
38
+ export default async function buildJS(input, type) {
39
+ const entryJS = `${state.config.paths.cli}/assets/${type}.js`;
40
+ const env = JSON.stringify(getData('env', 'Emscripten-x86_64', type));
40
41
  const systemConfig = `export default {
41
42
  env: ${env},
42
43
  paths: {
43
- wasm: '${compiler.config.general.name}.wasm',
44
- data: '${compiler.config.general.name}.data.txt'
44
+ wasm: '${state.config.general.name}.wasm',
45
+ data: '${state.config.general.name}.data.txt'
45
46
  }
46
47
  }`;
47
48
  let file = input;
@@ -0,0 +1,68 @@
1
+ import fs from 'node:fs';
2
+ import run from './run.js';
3
+ import getDependLibs from './getDependLibs.js';
4
+ import getData from './getData.js';
5
+ import buildJs from './buildJs.js';
6
+ import state from '../state/index.js';
7
+
8
+ export default async function buildWasm(type, isProd = false) {
9
+ const buildType = isProd ? 'Release' : 'Debug';
10
+ const libs = [
11
+ ...getDependLibs(),
12
+ `${state.config.paths.build}/Source-${buildType}/Emscripten-x86_64/lib${state.config.general.name}.a`,
13
+ `${state.config.paths.build}/Bridge-${buildType}/Emscripten-x86_64/lib${state.config.general.name}.a`,
14
+ ];
15
+
16
+ if (type === 'browser') {
17
+ console.log('wasm compiling for browser...');
18
+ const t0 = performance.now();
19
+ const data = Object.entries(getData('data', 'Emscripten-x86_64', 'browser')).map(([key, value]) => ['--preload-file', `${key.replaceAll('@', '@@')}@${value}`]).flat();
20
+ run('emcc', [
21
+ '-lembind', '-Wl,--whole-archive',
22
+ ...libs, ...(isProd ? ['-O3'] : []),
23
+ '-s', 'WASM=1', '-s', 'MODULARIZE=1', '-s', 'DYNAMIC_EXECUTION=0',
24
+ '-s', 'RESERVED_FUNCTION_POINTERS=200', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-s', 'FORCE_FILESYSTEM=1',
25
+ '-s', 'ALLOW_MEMORY_GROWTH=1',
26
+ '-s', 'EXPORTED_RUNTIME_METHODS=["FS", "ENV"]',
27
+ '-o', `${state.config.paths.build}/${state.config.general.name}.js`,
28
+ ...data,
29
+ ]);
30
+ const t1 = performance.now();
31
+ console.log('wasm compiled for browser...', Math.round(t1 - t0));
32
+ console.log('js compiling for browser...');
33
+ await buildJs(`${state.config.paths.build}/${state.config.general.name}.js`, 'browser');
34
+ const t2 = performance.now();
35
+ console.log('js compiled for browser...', Math.round(t2 - t1));
36
+ }
37
+
38
+ if (type === 'node') {
39
+ console.log('wasm compiling for node...');
40
+ run('emcc', [
41
+ '-lembind', '-Wl,--whole-archive', '-lnodefs.js',
42
+ ...libs, ...(isProd ? ['-O3'] : []),
43
+ '-s', 'WASM=1', '-s', 'MODULARIZE=1', '-s', 'DYNAMIC_EXECUTION=0',
44
+ '-s', 'RESERVED_FUNCTION_POINTERS=200', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-s', 'FORCE_FILESYSTEM=1', '-s', 'NODERAWFS',
45
+ '-s', 'ALLOW_MEMORY_GROWTH=1',
46
+ '-s', 'EXPORTED_RUNTIME_METHODS=["FS", "ENV", "NODEFS"]',
47
+ '-o', `${state.config.paths.build}/${state.config.general.name}.js`,
48
+ ]);
49
+ console.log('wasm compiled for node...');
50
+ console.log('js compiling for node...');
51
+ await buildJs(`${state.config.paths.build}/${state.config.general.name}.js`, 'node');
52
+ console.log('js compiled for node...');
53
+
54
+ Object.entries(getData('data', 'Emscripten-x86_64', 'node')).forEach(([key, value]) => {
55
+ if (fs.existsSync(key)) {
56
+ const dAssetPath = `${state.config.paths.build}/data/${value}`;
57
+ if (!fs.existsSync(dAssetPath)) {
58
+ fs.mkdirSync(dAssetPath, { recursive: true });
59
+ fs.cpSync(key, dAssetPath, { recursive: true });
60
+ }
61
+ }
62
+ });
63
+ }
64
+
65
+ if (fs.existsSync(`${state.config.paths.build}/${state.config.general.name}.data`)) {
66
+ fs.renameSync(`${state.config.paths.build}/${state.config.general.name}.data`, `${state.config.paths.build}/${state.config.general.name}.data.txt`);
67
+ }
68
+ }
@@ -0,0 +1,128 @@
1
+ /* eslint-disable prefer-destructuring */
2
+ import fs from 'node:fs';
3
+ import upath from 'upath';
4
+ import state, { saveCache } from '../state/index.js';
5
+ import { getFileHash } from '../utils/hash.js';
6
+ import run from './run.js';
7
+
8
+ export default function createBridgeFile(headerOrModuleFilePath) {
9
+ const interfaceFilePath = upath.resolve(headerOrModuleFilePath);
10
+ if (!fs.existsSync(`${state.config.paths.build}/interface`)) {
11
+ fs.mkdirSync(`${state.config.paths.build}/interface`, { recursive: true });
12
+ }
13
+ if (!fs.existsSync(`${state.config.paths.build}/bridge`)) {
14
+ fs.mkdirSync(`${state.config.paths.build}/bridge`, { recursive: true });
15
+ }
16
+ const interfaceFile = createInterfaceFile(interfaceFilePath);
17
+ return createBridgeFileFromInterfaceFile(interfaceFile);
18
+ }
19
+
20
+ function createInterfaceFile(headerOrModuleFilePath) {
21
+ if (!headerOrModuleFilePath) {
22
+ return null;
23
+ }
24
+ const fileHash = getFileHash(headerOrModuleFilePath);
25
+ if (state.cache.hashes[headerOrModuleFilePath] === fileHash) {
26
+ return state.cache.interfaces[headerOrModuleFilePath];
27
+ }
28
+
29
+ const moduleRegex = new RegExp(`.(${state.config.ext.module.join('|')})$`);
30
+ const isModule = moduleRegex.test(headerOrModuleFilePath);
31
+ if (isModule) {
32
+ const newPath = `${state.config.paths.build}/interface/${headerOrModuleFilePath.split('/').pop()}`;
33
+ fs.copyFileSync(headerOrModuleFilePath, newPath);
34
+ state.cache.interfaces[headerOrModuleFilePath] = newPath;
35
+ state.cache.hashes[headerOrModuleFilePath] = fileHash;
36
+ saveCache();
37
+ return newPath;
38
+ }
39
+
40
+ const headerPaths = (state.config.dependencyParameters?.pathsOfCmakeDepends?.split(';') || [])
41
+ .filter((d) => d.startsWith(state.config.paths.base));
42
+
43
+ const temp2 = headerPaths
44
+ .map((p) => headerOrModuleFilePath.match(new RegExp(`^${p}/.*?/include/(.*?)$`, 'i')))
45
+ .filter((p) => p && p.length === 2);
46
+
47
+ const temp = headerOrModuleFilePath.match(/^(.*)\..+?$/);
48
+ if (temp.length < 2) return null;
49
+
50
+ const filePathWithoutExt = temp[1];
51
+ const interfaceFile = `${filePathWithoutExt}.i`;
52
+
53
+ if (fs.existsSync(interfaceFile)) {
54
+ const newPath = `${state.config.paths.build}/interface/${interfaceFile.split('/').at(-1)}`;
55
+ fs.copyFileSync(interfaceFile, newPath);
56
+ state.cache.interfaces[headerOrModuleFilePath] = newPath;
57
+ state.cache.hashes[headerOrModuleFilePath] = fileHash;
58
+ saveCache();
59
+ return newPath;
60
+ }
61
+
62
+ const fileName = filePathWithoutExt.split('/').at(-1);
63
+
64
+ let headerPath = state.config.paths.header.find((path) => headerOrModuleFilePath.startsWith(path));
65
+ if (headerPath) headerPath = headerOrModuleFilePath.substr(headerPath.length + 1);
66
+ else if (temp2 && temp2.length > 0) headerPath = temp2[0][1];
67
+ else headerPath = headerOrModuleFilePath.split('/').at(-1);
68
+
69
+ const content = `#ifndef _${fileName.toUpperCase()}_I
70
+ #define _${fileName.toUpperCase()}_I
71
+
72
+ %module ${fileName.toUpperCase()}
73
+
74
+ %{
75
+ #include "${headerPath}"
76
+ %}
77
+
78
+ %feature("shared_ptr");
79
+ %feature("polymorphic_shared_ptr");
80
+
81
+ %include "${headerPath}"
82
+
83
+ #endif
84
+ `;
85
+ const outputFilePath = `${state.config.paths.build}/interface/${fileName}.i`;
86
+ fs.writeFileSync(outputFilePath, content);
87
+
88
+ state.cache.interfaces[headerOrModuleFilePath] = outputFilePath;
89
+ state.cache.hashes[headerOrModuleFilePath] = fileHash;
90
+ saveCache();
91
+
92
+ return outputFilePath;
93
+ }
94
+
95
+ function createBridgeFileFromInterfaceFile(interfaceFilePath) {
96
+ if (!interfaceFilePath) {
97
+ return null;
98
+ }
99
+
100
+ const fileHash = getFileHash(interfaceFilePath);
101
+ if (state.cache.hashes[interfaceFilePath] === fileHash) {
102
+ return state.cache.bridges[interfaceFilePath];
103
+ }
104
+
105
+ const allHeaders = state.config.dependencyParameters.headerPathWithDepends.split(';');
106
+
107
+ let includePath = [
108
+ ...state.config.allDependencies.map((d) => `${d.paths.output}/prebuilt/Emscripten-x86_64/include`),
109
+ ...state.config.allDependencies.map((d) => `${d.paths.output}/prebuilt/Emscripten-x86_64/swig`),
110
+ ...state.config.paths.header,
111
+ ...allHeaders,
112
+ ].filter((path) => !!path.toString()).map((path) => `-I${path}`);
113
+ includePath = [...new Set(includePath)];
114
+
115
+ run('swig', [
116
+ '-c++',
117
+ '-embind',
118
+ '-o', `${state.config.paths.build}/bridge/${interfaceFilePath.split('/').at(-1)}.cpp`,
119
+ ...includePath,
120
+ interfaceFilePath,
121
+ ]);
122
+
123
+ state.cache.bridges[interfaceFilePath] = `${state.config.paths.build}/bridge/${interfaceFilePath.split('/').at(-1)}.cpp`;
124
+ state.cache.hashes[interfaceFilePath] = fileHash;
125
+ saveCache();
126
+
127
+ return state.cache.bridges[interfaceFilePath];
128
+ }
@@ -0,0 +1,104 @@
1
+ import os from 'node:os';
2
+ import fs from 'node:fs';
3
+ import replace from 'replace';
4
+ import run from './run.js';
5
+ import getCmakeParameters from './getCmakeParameters.js';
6
+ import state from '../state/index.js';
7
+
8
+ const cpuCount = os.cpus().length - 1;
9
+ const sharedPlatforms = ['Android'];
10
+
11
+ export default function createLib(platform, fileType, options = {}) {
12
+ if (!platform || !options || typeof options !== 'object' || Array.isArray(options)) {
13
+ throw new Error('invalid platform or options');
14
+ }
15
+
16
+ const basePlatform = platform.split('-', 1)[0];
17
+ if (basePlatform === 'iOS' && process.platform !== 'darwin') {
18
+ return;
19
+ }
20
+
21
+ const buildType = options.isProd ? 'Release' : 'Debug';
22
+ const platformPrefix = `${fileType ? `${fileType}-` : ''}${buildType}`;
23
+ const libdir = `${state.config.paths.build}/${platformPrefix}/prebuilt/${platform}`;
24
+ const buildPath = `${state.config.paths.build}/${platformPrefix}/${platform}`;
25
+
26
+ const buildEnv = { params: [] };
27
+ let buildParams;
28
+ const depPaths = state.config.allDependencyPaths[platform];
29
+ if (state.config.build) {
30
+ const { getBuildParams, getExtraLibs } = state.config.build;
31
+ buildEnv.console = true;
32
+ const ext = sharedPlatforms.includes(basePlatform) ? 'so' : 'a';
33
+ buildParams = getBuildParams ? getBuildParams(platform, depPaths, ext, buildPath) : [];
34
+ if (state.config.build?.buildType !== 'configure') {
35
+ const cmakeBuildType = sharedPlatforms.includes(basePlatform) ? 'SHARED' : 'STATIC';
36
+ buildParams.push(`-DCMAKE_PREFIX_PATH=${libdir}`, `-DCMAKE_FIND_ROOT_PATH=${libdir}`, `-DBUILD_TYPE=${cmakeBuildType}`);
37
+ }
38
+
39
+ const cFlags = Object.values(depPaths).map((d) => `-I${d.header}`).join(' ');
40
+ const ldFlags = Object.values(depPaths).map((d) => `-L${d.libPath}`).join(' ');
41
+ let dependLibs = '';
42
+ if (state.config.build?.buildType === 'configure') {
43
+ dependLibs = Object.keys(depPaths).map((d) => `-l${d}`).join(' ');
44
+ }
45
+
46
+ const extraLibs = getExtraLibs ? getExtraLibs(platform) : [];
47
+
48
+ buildEnv.params.push('-e', `CFLAGS=${cFlags}`);
49
+ buildEnv.params.push('-e', `CPPFLAGS=${cFlags}`);
50
+ buildEnv.params.push('-e', `LDFLAGS=${ldFlags} ${extraLibs.join(' ')}`);
51
+ // buildEnv.params.push('-e', `LIBS=${dependLibs} ${extraLibs.join(' ')}`);
52
+
53
+ state.config.build.env?.forEach((e) => {
54
+ buildEnv.params.push('-e', e);
55
+ });
56
+ } else {
57
+ buildParams = getCmakeParameters(platform, options);
58
+ }
59
+
60
+ console.log(`${platform} is compiling...`);
61
+ const t0 = performance.now();
62
+ const cmakeDir = state.config.build ? `${state.config.paths.build}/source` : state.config.paths.cmakeDir;
63
+
64
+ if (state.config.build?.beforeRun) {
65
+ const dataList = state.config.build?.beforeRun(cmakeDir);
66
+ dataList.forEach((data) => {
67
+ run(data.program, data.parameters || [], platformPrefix, platform, buildEnv);
68
+ });
69
+ }
70
+
71
+ if (!options.bypassCmake) {
72
+ if (state.config.build?.buildType === 'configure') {
73
+ fs.cpSync(cmakeDir, buildPath, { recursive: true });
74
+ if (state.config.build?.sourceReplaceList) {
75
+ state.config.build.sourceReplaceList(platform, depPaths)?.forEach(({ regex, replacement, paths }) => {
76
+ replace({
77
+ regex, replacement, paths: paths.map((p) => `${buildPath}/${p}`), recursive: false, silent: true,
78
+ });
79
+ });
80
+ }
81
+ run(null, [
82
+ './configure',
83
+ ...buildParams,
84
+ `--prefix=${libdir}`,
85
+ ], platformPrefix, platform, buildEnv);
86
+ } else {
87
+ run(null, [
88
+ basePlatform === 'iOS' && state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake', cmakeDir,
89
+ `-DCMAKE_BUILD_TYPE=${buildType}`,
90
+ `-DCMAKE_INSTALL_PREFIX=${libdir}`,
91
+ ...buildParams,
92
+ ], platformPrefix, platform, buildEnv);
93
+ }
94
+ }
95
+ const t1 = performance.now();
96
+ if (basePlatform === 'iOS' && state.config.build?.buildType !== 'configure') {
97
+ const iOSCMakeBuilder = state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake';
98
+ run(null, [iOSCMakeBuilder, '--build', '.', '-j', cpuCount, '--config', buildType, '--target', 'install'], platformPrefix, platform, { console: buildEnv.console });
99
+ } else {
100
+ run(null, ['make', `-j${cpuCount}`, 'install'], platformPrefix, platform, { console: buildEnv.console });
101
+ }
102
+ const t2 = performance.now();
103
+ console.log(`${platform} compiled`, platformPrefix, `full time: ${Math.round(t2 - t0)}ms`, `cmake: ${Math.round(t1 - t0)}ms`, `build: ${Math.round(t2 - t1)}ms`, `core: ${cpuCount}`);
104
+ }
@@ -0,0 +1,44 @@
1
+ import fs from 'node:fs';
2
+ import upath from 'upath';
3
+ import { execFileSync } from 'node:child_process';
4
+ import state from '../state/index.js';
5
+
6
+ export default function createXCFramework(overrideConfig = null) {
7
+ if (process.platform !== 'darwin') {
8
+ return;
9
+ }
10
+
11
+ const output = overrideConfig?.paths?.output || state.config.paths.output;
12
+ const projectPath = overrideConfig?.paths?.project || state.config.paths.project;
13
+ const libName = overrideConfig?.export?.libName || state.config.export.libName;
14
+
15
+ if (
16
+ !fs.existsSync(`${output}/prebuilt/iOS-iphoneos/lib`)
17
+ || !fs.existsSync(`${output}/prebuilt/iOS-iphonesimulator/lib`)
18
+ ) return;
19
+
20
+ const options = {
21
+ cwd: projectPath,
22
+ stdio: 'inherit',
23
+ };
24
+
25
+ const relativeOutput = upath.relative(projectPath, output);
26
+
27
+ libName.forEach((fileName) => {
28
+ if (!fs.existsSync(`${projectPath}/${fileName}.xcframework`)) {
29
+ const params = [
30
+ '-create-xcframework',
31
+ '-library', `${relativeOutput}/prebuilt/iOS-iphoneos/lib/lib${fileName}.a`,
32
+ '-headers', `${relativeOutput}/prebuilt/iOS-iphoneos/include`,
33
+ '-library', `${relativeOutput}/prebuilt/iOS-iphonesimulator/lib/lib${fileName}.a`,
34
+ '-headers', `${relativeOutput}/prebuilt/iOS-iphonesimulator/include`,
35
+ '-output', `${fileName}.xcframework`,
36
+ ];
37
+ execFileSync('xcodebuild', params, options);
38
+ }
39
+
40
+ if (!fs.existsSync(`${output}/prebuilt/${fileName}.xcframework.zip`)) {
41
+ execFileSync('zip', ['-y', '-r', `${relativeOutput}/prebuilt/${fileName}.xcframework.zip`, `${fileName}.xcframework`], options);
42
+ }
43
+ });
44
+ }
@@ -0,0 +1,8 @@
1
+ import findFiles from '../utils/findFiles.js';
2
+ import state from '../state/index.js';
3
+
4
+ export default function getAllBridges() {
5
+ return [
6
+ ...findFiles(`${state.config.paths.build}/bridge/*.i.cpp`),
7
+ ];
8
+ }
@@ -0,0 +1,56 @@
1
+ import state from '../state/index.js';
2
+
3
+ export default function getCmakeParameters(platform, options = {}) {
4
+ if (!options || typeof options !== 'object' || Array.isArray(options)) {
5
+ throw new Error('invalid options');
6
+ }
7
+
8
+ const params = [];
9
+ // if (isBuildBridge) params.push('-DBUILD_BRIDGE=TRUE');
10
+
11
+ const dependParams = state.config.dependencyParameters;
12
+ const externalNativeGlob = [
13
+ ...(options.nativeGlob || []),
14
+ ];
15
+ const externalBridgeGlob = [
16
+ `${state.config.paths.cli}/assets/commonBridges.cpp`,
17
+ ...(options.bridgeGlob || []),
18
+ ];
19
+ const nativeGlob = [
20
+ `${state.config.paths.cli}/assets/cppjsEmptySource.cpp`,
21
+ ...(dependParams.nativeGlob || []),
22
+ ];
23
+ const headerGlob = [
24
+ ...(dependParams.headerGlob || []),
25
+ ...(options.headerGlob || []),
26
+ ];
27
+
28
+ const headerDirs = [
29
+ dependParams.headerPathWithDepends,
30
+ ...(options.headerDirs || []),
31
+ ];
32
+
33
+ const basePlatform = platform.split('-', 1)[0];
34
+ const sharedPlatforms = ['Android'];
35
+ const buildType = sharedPlatforms.includes(basePlatform) ? 'SHARED' : 'STATIC';
36
+ const otherBuildType = buildType === 'STATIC' ? 'SHARED' : 'STATIC';
37
+
38
+ params.push(...[
39
+ `-DPROJECT_NAME=${options.name || state.config.general.name}`,
40
+ `-DBASE_DIR=${state.config.paths.project}`,
41
+ `-DEXTERNAL_NATIVE_GLOB=${externalNativeGlob.join(';')}`,
42
+ `-DEXTERNAL_BRIDGE_GLOB=${externalBridgeGlob.join(';')}`,
43
+ `-DNATIVE_GLOB=${nativeGlob.join(';')}`,
44
+ `-DHEADER_GLOB=${headerGlob.join(';')}`,
45
+ `-DHEADER_DIR=${headerDirs.join(';')}`,
46
+ `-DDEPENDS_CMAKE_PATHS=${dependParams.pathsOfCmakeDepends}`,
47
+ `-DDEPENDS_CMAKE_NAMES=${dependParams.nameOfCmakeDepends}`,
48
+ `-DBRIDGE_DIR=${state.config.paths.build}/bridge`,
49
+ `-DBUILD_TYPE=${buildType}`,
50
+ `-DBUILD_${otherBuildType}_LIBS=OFF`,
51
+ // '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache',
52
+ ...(options.buildSource !== false ? ['-DBUILD_SOURCE=TRUE'] : []),
53
+ ]);
54
+
55
+ return params;
56
+ }
@@ -0,0 +1,28 @@
1
+ /* eslint-disable default-param-last */
2
+ /* eslint-disable no-param-reassign */
3
+ import state from '../state/index.js';
4
+
5
+ function getRecursiveData(obj, config, dependency, field, platform, subPlatform) {
6
+ const platformName = subPlatform ? `${platform}-${subPlatform}` : platform;
7
+ if (dependency?.platform?.[platformName]?.[field]) {
8
+ Object.entries(dependency.platform[platformName][field]).forEach(([dKey, value]) => {
9
+ if (field === 'data') {
10
+ const key = `${dependency.paths.project}/dist/prebuilt/${platform}/${dKey}`;
11
+ obj[key] = value;
12
+ } else {
13
+ obj[dKey] = value;
14
+ }
15
+ });
16
+ }
17
+
18
+ dependency.dependencies.forEach((dep) => {
19
+ getRecursiveData(obj, config, dep, field, platform, subPlatform);
20
+ });
21
+ }
22
+
23
+ export default function getData(field, platform = 'Emscripten-x86_64', subPlatform) {
24
+ const output = {};
25
+ getRecursiveData(output, state.config, state.config, field, platform, subPlatform);
26
+
27
+ return output;
28
+ }
@@ -0,0 +1,19 @@
1
+ import findFiles from '../utils/findFiles.js';
2
+ import state from '../state/index.js';
3
+
4
+ export default function getDependLibs() {
5
+ let dependLibs = [
6
+ ...findFiles(`${state.config.paths.build}/Source-Release/Emscripten-x86_64/dependencies/**/*.a`, { cwd: state.config.paths.project }),
7
+ ];
8
+ state.config.dependencyParameters.cmakeDepends.forEach((d) => {
9
+ if (d.export.libName) {
10
+ d.export.libName.forEach((fileName) => {
11
+ if (d.platform['Emscripten-x86_64'].ignoreLibName?.includes(fileName)) return;
12
+ dependLibs.push(...findFiles(`${d.paths.output}/prebuilt/Emscripten-x86_64/lib/lib${fileName}.a`, { cwd: d.paths.project }));
13
+ });
14
+ }
15
+ });
16
+
17
+ dependLibs = [...new Set(dependLibs)];
18
+ return dependLibs;
19
+ }