cpp.js 1.0.0-beta.20 → 1.0.0-beta.21

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 CHANGED
@@ -14,6 +14,9 @@
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="Linux Build" src="https://img.shields.io/github/actions/workflow/status/bugra9/cpp.js/linux_build.yml?branch=main&style=for-the-badge&label=Linux%20Build">
19
+ <img alt="Macos Build" src="https://img.shields.io/github/actions/workflow/status/bugra9/cpp.js/macos_build.yml?branch=main&style=for-the-badge&label=Macos%20Build">
17
20
  </div>
18
21
 
19
22
  <h3 align="center">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cpp.js",
3
- "version": "1.0.0-beta.20",
3
+ "version": "1.0.0-beta.21",
4
4
  "license": "MIT",
5
5
  "homepage": "https://cpp.js.org",
6
6
  "repository": "https://github.com/bugra9/cpp.js.git",
@@ -20,7 +20,10 @@
20
20
  "glob": "^8.0.3",
21
21
  "rollup": "^4.18.0",
22
22
  "rollup-plugin-uglify": "^6.0.4",
23
- "upath": "^2.0.1"
23
+ "upath": "^2.0.1",
24
+ "decompress": "4.2.1",
25
+ "follow-redirects": "1.15.9",
26
+ "replace": "1.2.2"
24
27
  },
25
28
  "devDependencies": {
26
29
  "mocha": "^10.2.0"
@@ -1,9 +1,12 @@
1
1
  import os from 'node:os';
2
+ import fs from 'node:fs';
3
+ import replace from 'replace';
2
4
  import run from './run.js';
3
5
  import getCmakeParameters from './getCmakeParameters.js';
4
6
  import state from '../state/index.js';
5
7
 
6
8
  const cpuCount = os.cpus().length - 1;
9
+ const sharedPlatforms = ['Android'];
7
10
 
8
11
  export default function createLib(platform, fileType, options = {}) {
9
12
  if (!platform || !options || typeof options !== 'object' || Array.isArray(options)) {
@@ -15,25 +18,85 @@ export default function createLib(platform, fileType, options = {}) {
15
18
  return;
16
19
  }
17
20
 
18
- const cmakeParams = getCmakeParameters(platform, options);
19
21
  const buildType = options.isProd ? 'Release' : 'Debug';
20
22
  const platformPrefix = `${fileType ? `${fileType}-` : ''}${buildType}`;
21
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
+ buildParams.push(`-DCMAKE_PREFIX_PATH=${libdir}`, `-DCMAKE_FIND_ROOT_PATH=${libdir}`);
36
+ }
37
+
38
+ const cFlags = Object.values(depPaths).map((d) => `-I${d.header}`).join(' ');
39
+ const ldFlags = Object.values(depPaths).map((d) => `-L${d.libPath}`).join(' ');
40
+ let dependLibs = '';
41
+ if (state.config.build?.buildType === 'configure') {
42
+ dependLibs = Object.keys(depPaths).map((d) => `-l${d}`).join(' ');
43
+ }
44
+
45
+ const extraLibs = getExtraLibs ? getExtraLibs(platform) : [];
46
+
47
+ buildEnv.params.push('-e', `CFLAGS=${cFlags}`);
48
+ buildEnv.params.push('-e', `CPPFLAGS=${cFlags}`);
49
+ buildEnv.params.push('-e', `LDFLAGS=${ldFlags} ${extraLibs.join(' ')}`);
50
+ // buildEnv.params.push('-e', `LIBS=${dependLibs} ${extraLibs.join(' ')}`);
51
+
52
+ state.config.build.env?.forEach((e) => {
53
+ buildEnv.params.push('-e', e);
54
+ });
55
+ } else {
56
+ buildParams = getCmakeParameters(platform, options);
57
+ }
58
+
22
59
  console.log(`${platform} is compiling...`);
23
60
  const t0 = performance.now();
61
+ const cmakeDir = state.config.build ? `${state.config.paths.build}/source` : state.config.paths.cmakeDir;
62
+
63
+ if (state.config.build?.beforeRun) {
64
+ const dataList = state.config.build?.beforeRun(cmakeDir);
65
+ dataList.forEach((data) => {
66
+ run(data.program, data.parameters || [], platformPrefix, platform, buildEnv);
67
+ });
68
+ }
69
+
24
70
  if (!options.bypassCmake) {
25
- run(null, [
26
- basePlatform === 'iOS' ? 'ios-cmake' : 'cmake', state.config.paths.cmakeDir,
27
- `-DCMAKE_BUILD_TYPE=${buildType}`,
28
- `-DCMAKE_INSTALL_PREFIX=${libdir}`,
29
- ...cmakeParams,
30
- ], platformPrefix, platform);
71
+ if (state.config.build?.buildType === 'configure') {
72
+ fs.cpSync(cmakeDir, buildPath, { recursive: true });
73
+ if (state.config.build?.sourceReplaceList) {
74
+ state.config.build.sourceReplaceList(platform, depPaths)?.forEach(({ regex, replacement, paths }) => {
75
+ replace({
76
+ regex, replacement, paths: paths.map((p) => `${buildPath}/${p}`), recursive: false, silent: true,
77
+ });
78
+ });
79
+ }
80
+ run(null, [
81
+ './configure',
82
+ ...buildParams,
83
+ `--prefix=${libdir}`,
84
+ ], platformPrefix, platform, buildEnv);
85
+ } else {
86
+ run(null, [
87
+ basePlatform === 'iOS' && state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake', cmakeDir,
88
+ `-DCMAKE_BUILD_TYPE=${buildType}`,
89
+ `-DCMAKE_INSTALL_PREFIX=${libdir}`,
90
+ ...buildParams,
91
+ ], platformPrefix, platform, buildEnv);
92
+ }
31
93
  }
32
94
  const t1 = performance.now();
33
- if (basePlatform === 'iOS') {
34
- run(null, ['ios-cmake', '--build', '.', '--config', buildType, '--target', 'install'], platformPrefix, platform);
95
+ if (basePlatform === 'iOS' && state.config.build?.buildType !== 'configure') {
96
+ const iOSCMakeBuilder = state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake';
97
+ run(null, [iOSCMakeBuilder, '--build', '.', '-j', cpuCount, '--config', buildType, '--target', 'install'], platformPrefix, platform, { console: buildEnv.console });
35
98
  } else {
36
- run(null, ['make', `-j${cpuCount}`, 'install'], platformPrefix, platform);
99
+ run(null, ['make', `-j${cpuCount}`, 'install'], platformPrefix, platform, { console: buildEnv.console });
37
100
  }
38
101
  const t2 = performance.now();
39
102
  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}`);
@@ -28,6 +28,7 @@ export default function getCmakeParameters(platform, options = {}) {
28
28
  const basePlatform = platform.split('-', 1)[0];
29
29
  const sharedPlatforms = ['Android'];
30
30
  const buildType = sharedPlatforms.includes(basePlatform) ? 'SHARED' : 'STATIC';
31
+ const otherBuildType = buildType === 'STATIC' ? 'SHARED' : 'STATIC';
31
32
 
32
33
  params.push(...[
33
34
  `-DPROJECT_NAME=${options.name || state.config.general.name}`,
@@ -40,6 +41,7 @@ export default function getCmakeParameters(platform, options = {}) {
40
41
  `-DDEPENDS_CMAKE_NAMES=${dependParams.nameOfCmakeDepends}`,
41
42
  `-DBRIDGE_DIR=${state.config.paths.build}/bridge`,
42
43
  `-DBUILD_TYPE=${buildType}`,
44
+ `-DBUILD_${otherBuildType}_LIBS=OFF`,
43
45
  // '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache',
44
46
  ...(options.buildSource !== false ? ['-DBUILD_SOURCE=TRUE'] : []),
45
47
  ]);
@@ -65,12 +65,6 @@ const iosParams = [
65
65
  '-e', `LDFLAGS="${IOS_HOST_FLAGS}"`,
66
66
  ]; */
67
67
 
68
- function getParentPath(path) {
69
- const pathArray = path.split('/');
70
- pathArray.pop();
71
- return pathArray.join('/');
72
- }
73
-
74
68
  export default function run(program, params = [], platformPrefix = null, platform = null, dockerOptions = {}) {
75
69
  const buildPath = platformPrefix ? `${state.config.paths.build}/${platformPrefix}/${platform}` : state.config.paths.build;
76
70
  if (!fs.existsSync(buildPath)) {
@@ -125,7 +119,7 @@ export default function run(program, params = [], platformPrefix = null, platfor
125
119
  `-DCMAKE_C_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
126
120
  `-DCMAKE_CXX_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
127
121
  '-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=\'iPhone Developer\'',
128
- '-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=7ZZLDWBUVT',
122
+ `-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=${state.config.system.XCODE_DEVELOPMENT_TEAM}`,
129
123
  ];
130
124
  }
131
125
  } else if (dProgram === 'ios-cmake') {
@@ -149,7 +143,7 @@ export default function run(program, params = [], platformPrefix = null, platfor
149
143
  `-DCMAKE_C_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
150
144
  `-DCMAKE_CXX_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
151
145
  '-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=\'iPhone Developer\'',
152
- '-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=7ZZLDWBUVT',
146
+ `-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=${state.config.system.XCODE_DEVELOPMENT_TEAM}`,
153
147
  ];
154
148
  }
155
149
  }
@@ -173,7 +167,7 @@ export default function run(program, params = [], platformPrefix = null, platfor
173
167
  if (pParams[i] === '-e') {
174
168
  const [key, ...rest] = pParams[i + 1].split('=');
175
169
  const value = rest.join('=');
176
- if (['CFLAGS', 'CXXFLAGS', 'LDFLAGS'].includes(key)) {
170
+ if (['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS'].includes(key)) {
177
171
  let v = value;
178
172
  if (v.startsWith('\'') || v.startsWith('"')) {
179
173
  v = v.substring(1, v.length - 1);
@@ -190,13 +184,12 @@ export default function run(program, params = [], platformPrefix = null, platfor
190
184
 
191
185
  const options = {
192
186
  cwd: dockerOptions.workdir || buildPath,
193
- stdio: dockerOptions.console ? 'inherit' : 'pipe',
187
+ stdio: dockerOptions.console ? 'inherit' : 'ignore',
194
188
  env,
195
189
  };
196
-
197
190
  execFileSync(dProgram, dParams, options);
198
191
  } else if (false) {
199
- const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : 'pipe' };
192
+ const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : 'ignore' };
200
193
  const args = [
201
194
  'exec',
202
195
  '--user', getOsUserAndGroupId(),
@@ -207,18 +200,40 @@ export default function run(program, params = [], platformPrefix = null, platfor
207
200
  ];
208
201
  execFileSync('docker', args, options);
209
202
  } else {
210
- const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : 'pipe' };
203
+ const env = {};
204
+ const pParams = [...platformParams, ...(dockerOptions.params || [])];
205
+ for (let i = 0; i < pParams.length; i += 2) {
206
+ if (pParams[i] === '-e') {
207
+ const [key, ...rest] = pParams[i + 1].split('=');
208
+ const value = rest.join('=');
209
+ if (['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS'].includes(key)) {
210
+ let v = value;
211
+ if (v.startsWith('\'') || v.startsWith('"')) {
212
+ v = v.substring(1, v.length - 1);
213
+ }
214
+ if (env[key]) env[key] += ` ${v}`;
215
+ else env[key] = v;
216
+ } else {
217
+ env[key] = value;
218
+ }
219
+ }
220
+ }
221
+
222
+ const dockerEnv = [];
223
+ Object.entries(env).forEach(([key, value]) => {
224
+ dockerEnv.push('-e', `${key}=${value}`);
225
+ });
226
+ const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : 'ignore' };
211
227
  const args = [
212
228
  'run',
213
229
  '--rm',
214
230
  '--user', getOsUserAndGroupId(),
215
231
  '-v', `${state.config.paths.base}:/tmp/cppjs/live`,
216
- '--workdir', dockerOptions.workdir || replaceBasePathForDocker(buildPath),
217
- ...replaceBasePathForDocker(platformParams),
218
- ...replaceBasePathForDocker(dockerOptions.params || []),
232
+ '--workdir', replaceBasePathForDocker(dockerOptions.workdir || buildPath),
233
+ ...replaceBasePathForDocker(dockerEnv),
219
234
  // '-e', replaceBasePathForDocker(`CCACHE_DIR=${state.config.paths.build}/ccache`),
220
235
  getDockerImage(),
221
- dProgram,
236
+ replaceBasePathForDocker(dProgram),
222
237
  ...replaceBasePathForDocker(dParams),
223
238
  ];
224
239
  execFileSync('docker', args, options);
package/src/bin.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import fs, { mkdirSync } from 'node:fs';
3
4
  import { Command, Option } from 'commander';
4
- import fs from 'fs';
5
5
  import glob from 'glob';
6
6
  import upath from 'upath';
7
+ import replace from 'replace';
7
8
 
8
9
  import { state } from './index.js';
9
10
  import createBridgeFile from './actions/createInterface.js';
@@ -11,6 +12,8 @@ import createLib from './actions/createLib.js';
11
12
  import buildWasm from './actions/buildWasm.js';
12
13
  import createXCFramework from './actions/createXCFramework.js';
13
14
  import runCppjsApp from './actions/run.js';
15
+ import downloadAndExtractFile from './utils/downloadAndExtractFile.js';
16
+ import writeJson from './utils/writeJson.js';
14
17
 
15
18
  const packageJSON = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url)));
16
19
 
@@ -29,6 +32,15 @@ const commandBuild = program.command('build')
29
32
  const commandRun = program.command('run')
30
33
  .description('run docker application');
31
34
 
35
+ const commandConfig = program.command('config')
36
+ .description('Manage the cpp.js configuration files');
37
+
38
+ commandConfig.command('get').description('get cpp.js system configuration');
39
+ commandConfig.command('set').description('set cpp.js system configuration');
40
+ commandConfig.command('delete').description('delete cpp.js system configuration');
41
+ const commandConfigList = commandConfig.command('list').description('list cpp.js configuration')
42
+ .addOption(new Option('-t, --type <type>', 'config type').default('all').choices(['all', 'system', 'project']));
43
+
32
44
  const commandPostInstall = program.command('postinstall')
33
45
  .description('prepare the required packages for Cpp.js after installation');
34
46
 
@@ -37,7 +49,11 @@ program.parse(process.argv);
37
49
  switch (program.args[0]) {
38
50
  case 'build': {
39
51
  const { platform } = commandBuild.opts();
40
- build(platform);
52
+ if (state.config.build) {
53
+ buildExternal(platform);
54
+ } else {
55
+ build(platform);
56
+ }
41
57
  break;
42
58
  }
43
59
  case 'run': {
@@ -45,6 +61,25 @@ switch (program.args[0]) {
45
61
  run(programName, params);
46
62
  break;
47
63
  }
64
+ case 'config': {
65
+ switch (program.args[1]) {
66
+ case 'get':
67
+ getSystemConfig(program.args[2]);
68
+ break;
69
+ case 'set':
70
+ setSystemConfig(program.args[2], program.args[3]);
71
+ break;
72
+ case 'delete':
73
+ deleteSystemConfig(program.args[2]);
74
+ break;
75
+ case 'list':
76
+ listSystemConfig(commandConfigList.opts().type);
77
+ break;
78
+ default:
79
+ break;
80
+ }
81
+ break;
82
+ }
48
83
  case 'postinstall': {
49
84
  postInstall();
50
85
  break;
@@ -53,6 +88,37 @@ switch (program.args[0]) {
53
88
  break;
54
89
  }
55
90
 
91
+ function getSystemConfig(key) {
92
+ console.log(state.config.system[key]);
93
+ }
94
+
95
+ function setSystemConfig(key, value) {
96
+ state.config.system[key] = value;
97
+ writeJson(state.config.paths.systemConfig, state.config.system);
98
+ }
99
+
100
+ function deleteSystemConfig(key) {
101
+ delete state.config.system[key];
102
+ writeJson(state.config.paths.systemConfig, state.config.system);
103
+ }
104
+
105
+ function listSystemConfig(type) {
106
+ const { system: systemConfig, ...projectConfig } = state.config;
107
+ if (type === 'all' || type === 'system') {
108
+ console.log('System Configuration');
109
+ console.log(JSON.stringify(systemConfig, null, 2));
110
+ }
111
+
112
+ if (type === 'all') {
113
+ console.log('');
114
+ }
115
+
116
+ if (type === 'all' || type === 'project') {
117
+ console.log('Project Configuration');
118
+ console.log(JSON.stringify(projectConfig, null, 2));
119
+ }
120
+ }
121
+
56
122
  function postInstall() {
57
123
  const projectPath = process.env.PWD;
58
124
  const isDarwin = process.platform === 'darwin';
@@ -87,15 +153,59 @@ function run(programName, params) {
87
153
  runCppjsApp(programName, params, null, null, { console: true });
88
154
  }
89
155
 
156
+ async function buildExternal(platform) {
157
+ const version = state.config.package.nativeVersion;
158
+ if (!version) {
159
+ console.error('no version found!');
160
+ return;
161
+ }
162
+
163
+ const { getURL, replaceList, copyToSource } = state.config.build;
164
+ const isNewlyCreated = await downloadAndExtractFile(getURL(version), state.config.paths.build);
165
+ const sourcePath = `${state.config.paths.build}/source`;
166
+ if (isNewlyCreated && replaceList) {
167
+ replaceList.forEach(({ regex, replacement, paths }) => {
168
+ replace({
169
+ regex, replacement, paths: paths.map((p) => `${sourcePath}/${p}`), recursive: false, silent: true,
170
+ });
171
+ });
172
+ }
173
+
174
+ if (isNewlyCreated && copyToSource) {
175
+ Object.entries(copyToSource).forEach(([key, value]) => {
176
+ fs.copyFileSync(`${state.config.paths.project}/${key}`, `${sourcePath}/${value}`);
177
+ });
178
+ }
179
+
180
+ await buildLib(platform);
181
+ }
182
+
90
183
  async function build(platform) {
184
+ buildLib(platform);
185
+ if (platform === 'WebAssembly' || platform === 'All') {
186
+ createWasmJs();
187
+ }
188
+ }
189
+
190
+ async function buildLib(platform) {
91
191
  state.platforms[platform].forEach((p) => {
92
- createLib(p, 'Source', { isProd: true, buildSource: true });
192
+ if (!fs.existsSync(`${state.config.paths.output}/prebuilt/${p}/lib`)) {
193
+ createLib(p, 'Source', { isProd: true, buildSource: true });
194
+ } else {
195
+ console.log(`${state.config.general.name} is already compiled to ${p} architecture.`);
196
+ }
93
197
  });
94
198
 
95
- fs.cpSync(`${state.config.paths.build}/Source-Release/prebuilt`, `${state.config.paths.output}/prebuilt`, { recursive: true });
199
+ fs.cpSync(`${state.config.paths.build}/Source-Release/prebuilt`, `${state.config.paths.output}/prebuilt`, { recursive: true, dereference: true });
96
200
 
97
201
  createXCFramework();
98
202
 
203
+ const distCmakeContent = fs.readFileSync(`${state.config.paths.cli}/assets/dist.cmake`, { encoding: 'utf8', flag: 'r' })
204
+ .replace('___PROJECT_NAME___', state.config.general.name).replace('___PROJECT_LIBS___', state.config.export.libName.join(';'));
205
+ fs.writeFileSync(`${state.config.paths.output}/prebuilt/CMakeLists.txt`, distCmakeContent);
206
+ }
207
+
208
+ async function createWasmJs() {
99
209
  let headers = [];
100
210
  state.config.paths.header.forEach((headerPath) => {
101
211
  headers.push(glob.sync('**/*.h', { absolute: true, cwd: headerPath }));
@@ -129,8 +239,4 @@ async function build(platform) {
129
239
  if (fs.existsSync(`${state.config.paths.build}/${state.config.general.name}.data.txt`)) {
130
240
  fs.copyFileSync(`${state.config.paths.build}/${state.config.general.name}.data.txt`, `${state.config.paths.output}/${state.config.general.name}.data.txt`);
131
241
  }
132
-
133
- const distCmakeContent = fs.readFileSync(`${state.config.paths.cli}/assets/dist.cmake`, { encoding: 'utf8', flag: 'r' })
134
- .replace('___PROJECT_NAME___', state.config.general.name).replace('___PROJECT_LIBS___', state.config.export.libName.join(';'));
135
- fs.writeFileSync(`${state.config.paths.output}/prebuilt/CMakeLists.txt`, distCmakeContent);
136
242
  }
@@ -0,0 +1,51 @@
1
+ import getData from '../actions/getData.js';
2
+ import loadJson from '../utils/loadJson.js';
3
+
4
+ export default function exportReactNative(platform, bridgePath = null) {
5
+ const env = JSON.stringify(getData('env', platform));
6
+
7
+ const bridgeExportFile = `${bridgePath}.exports.json`;
8
+ let symbols = null;
9
+ if (bridgePath) {
10
+ symbols = loadJson(bridgeExportFile);
11
+ }
12
+
13
+ let symbolExportDefineString = '';
14
+ let symbolExportAssignString = '';
15
+ if (symbols && Array.isArray(symbols)) {
16
+ symbolExportDefineString = symbols.map((s) => `export let ${s} = null;`).join('\n');
17
+ symbolExportAssignString = symbols.map((s) => `${s} = Module.${s};`).join('\n');
18
+ }
19
+
20
+ return `
21
+ import { NativeModules } from 'react-native';
22
+ import Module from '@cpp.js/core-embind-jsi';
23
+
24
+ const { RNJsiLib } = NativeModules;
25
+
26
+ function setEnv() {
27
+ const env = JSON.parse('${env}');
28
+ const CPPJS_DATA_PATH = Module.CppJS.getEnv('CPPJS_DATA_PATH');
29
+
30
+ Object.entries(env).forEach(([key, value]) => {
31
+ Module.CppJS.setEnv(key, value.replace('_CPPJS_DATA_PATH_', CPPJS_DATA_PATH), true);
32
+ });
33
+ }
34
+
35
+ export let AllSymbols = {};
36
+ ${symbolExportDefineString}
37
+ export function initCppJs(config = {}) {
38
+ return new Promise((resolve, reject) => {
39
+ if (RNJsiLib && RNJsiLib.start) {
40
+ RNJsiLib.start();
41
+ setEnv();
42
+ AllSymbols = Module;
43
+ ${symbolExportAssignString}
44
+ resolve(Module);
45
+ } else {
46
+ reject('Module failed to initialise.');
47
+ }
48
+ });
49
+ }
50
+ `;
51
+ }
@@ -0,0 +1,42 @@
1
+ import getData from '../actions/getData.js';
2
+ import loadJson from '../utils/loadJson.js';
3
+
4
+ const env = JSON.stringify(getData('env'));
5
+
6
+ const params = `{
7
+ ...config,
8
+ env: {...${env}, ...config.env},
9
+ paths: {
10
+ wasm: 'cpp.wasm',
11
+ data: 'cpp.data.txt'
12
+ }
13
+ }`;
14
+
15
+ export default function exportWeb(bridgePath = null) {
16
+ const bridgeExportFile = `${bridgePath}.exports.json`;
17
+ let symbols = null;
18
+ if (bridgePath) {
19
+ symbols = loadJson(bridgeExportFile);
20
+ }
21
+
22
+ let symbolExportDefineString = '';
23
+ let symbolExportAssignString = '';
24
+ if (symbols && Array.isArray(symbols)) {
25
+ symbolExportDefineString = symbols.map((s) => `export let ${s} = null;`).join('\n');
26
+ symbolExportAssignString = symbols.map((s) => `${s} = m.${s};`).join('\n');
27
+ }
28
+
29
+ return `
30
+ export let AllSymbols = {};
31
+ ${symbolExportDefineString}
32
+ export function initCppJs(config = {}) {
33
+ return new Promise(
34
+ (resolve, reject) => import('/cpp.js').then(n => { return window.CppJs.initCppJs(${params})}).then(m => {
35
+ AllSymbols = m;
36
+ ${symbolExportAssignString}
37
+ resolve(m);
38
+ })
39
+ );
40
+ }
41
+ `;
42
+ }
package/src/index.js CHANGED
@@ -8,3 +8,6 @@ export { default as getData } from './actions/getData.js';
8
8
  export { default as getCmakeParameters } from './actions/getCmakeParameters.js';
9
9
  export { default as createXCFramework } from './actions/createXCFramework.js';
10
10
  export { default as getAllBridges } from './actions/getAllBridges.js';
11
+ export { default as run } from './actions/run.js';
12
+ export { default as exportWeb } from './export/web.js';
13
+ export { default as exportReactNative } from './export/react-native.js';
@@ -30,6 +30,10 @@ await initProcessState();
30
30
  async function initProcessState() {
31
31
  state.cache = loadCacheState();
32
32
  state.config = await loadConfig();
33
+ setAllDependecyPaths();
34
+ if (state.config.build?.setState) {
35
+ state.config.build.setState(state);
36
+ }
33
37
  }
34
38
 
35
39
  function loadCacheState() {
@@ -37,6 +41,39 @@ function loadCacheState() {
37
41
  return loadJson(stateFilePath) || state.cache;
38
42
  }
39
43
 
44
+ function setAllDependecyPaths() {
45
+ state.config.allDependencyPaths = {};
46
+ state.platforms.All.forEach((platform) => {
47
+ const basePlatform = platform.split('-', 1)[0];
48
+ state.config.allDependencyPaths[platform] = {};
49
+ state.config.allDependencies.forEach((d) => {
50
+ d.export.libName.forEach((name) => {
51
+ state.config.allDependencyPaths[platform][name] = {
52
+ root: `${d.paths.output}/prebuilt/${platform}`,
53
+ };
54
+ const dep = state.config.allDependencyPaths[platform][name];
55
+ if (basePlatform === 'iOS') {
56
+ let xcRoot;
57
+ if (platform === 'iOS-iphoneos') {
58
+ xcRoot = `${d.paths.output}/prebuilt/${name}.xcframework/ios-arm64_arm64e`;
59
+ } else if (platform === 'iOS-iphonesimulator') {
60
+ xcRoot = `${d.paths.output}/prebuilt/${name}.xcframework/ios-arm64_arm64e_x86_64-simulator`;
61
+ }
62
+ dep.header = `${xcRoot}/Headers`;
63
+ dep.libPath = xcRoot;
64
+ dep.lib = `${dep.libPath}/lib${name}.a`;
65
+ dep.bin = `${dep.root}/bin`;
66
+ } else {
67
+ dep.header = `${dep.root}/include`;
68
+ dep.libPath = `${dep.root}/lib`;
69
+ dep.lib = `${dep.libPath}/lib${name}.${basePlatform === 'Android' ? 'so' : 'a'}`;
70
+ dep.bin = `${dep.root}/bin`;
71
+ }
72
+ });
73
+ });
74
+ });
75
+ }
76
+
40
77
  export function saveCache() {
41
78
  writeJson(`${cacheDir}/cache.json`, state.cache);
42
79
  }
@@ -1,3 +1,4 @@
1
+ import os from 'node:os';
1
2
  import loadJs from '../utils/loadJs.js';
2
3
  import loadJson from '../utils/loadJson.js';
3
4
  import getParentPath from '../utils/getParentPath.js';
@@ -9,7 +10,13 @@ import calculateDependencyParameters from './calculateDependencyParameters.js';
9
10
 
10
11
  export default async function loadConfig(configDir = process.cwd(), configName = 'cppjs.config') {
11
12
  const config = await loadJs(configDir, configName) || {};
12
- return getFilledConfig(config);
13
+ const output = getFilledConfig(config);
14
+ output.build = await loadJs(configDir, 'cppjs.build');
15
+
16
+ output.paths.systemConfig = `${os.homedir()}/.cppjs.json`;
17
+ output.system = loadJson(output.paths.systemConfig) || {};
18
+
19
+ return output;
13
20
  }
14
21
 
15
22
  function getFilledConfig(config, options = { isDepend: false }) {
@@ -0,0 +1,36 @@
1
+ import path from 'node:path';
2
+ import fs, { mkdirSync } from 'node:fs';
3
+ import fr from 'follow-redirects';
4
+ import decompress from 'decompress';
5
+
6
+ export default async function downloadAndExtractFile(url, output) {
7
+ if (fs.existsSync(`${output}/source`)) {
8
+ return false;
9
+ }
10
+ const filePath = await downloadFile(url, output);
11
+ const a = await decompress(filePath, output);
12
+ const oldFolder = a[0].path.split('/')[0];
13
+ fs.renameSync(`${output}/${oldFolder}`, `${output}/source`);
14
+ return true;
15
+ }
16
+
17
+ function downloadFile(url, folder) {
18
+ mkdirSync(folder, { recursive: true });
19
+ return new Promise((resolve) => {
20
+ const filename = path.basename(url);
21
+ if (fs.existsSync(`${folder}/${filename}`)) {
22
+ resolve(`${folder}/${filename}`);
23
+ return;
24
+ }
25
+
26
+ fr.https.get(url, (res) => {
27
+ const fileStream = fs.createWriteStream(`${folder}/${filename}`);
28
+ res.pipe(fileStream);
29
+
30
+ fileStream.on('finish', () => {
31
+ fileStream.close();
32
+ resolve(`${folder}/${filename}`);
33
+ });
34
+ });
35
+ });
36
+ }
@@ -3,7 +3,7 @@ import { execFileSync } from 'child_process';
3
3
  let isDockerImageAvailable = false;
4
4
 
5
5
  export function getDockerImage() {
6
- return 'bugra9/cpp.js:0.2.8';
6
+ return 'bugra9/cpp.js:0.2.6';
7
7
  }
8
8
 
9
9
  export default function pullDockerImage() {