cpp.js 1.0.0-beta.25 → 1.0.0-beta.27

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cpp.js",
3
- "version": "1.0.0-beta.25",
3
+ "version": "1.0.0-beta.27",
4
4
  "license": "MIT",
5
5
  "homepage": "https://cpp.js.org",
6
6
  "repository": "https://github.com/bugra9/cpp.js.git",
@@ -1,6 +1,5 @@
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';
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
  import run from './run.js';
3
3
  import getDependLibs from './getDependLibs.js';
4
4
  import getData from './getData.js';
@@ -8,7 +8,7 @@ import state from '../state/index.js';
8
8
  export default async function buildWasm(type, isProd = false) {
9
9
  const buildType = isProd ? 'Release' : 'Debug';
10
10
  const libs = [
11
- getDependLibs(),
11
+ ...getDependLibs(),
12
12
  `${state.config.paths.build}/Source-${buildType}/Emscripten-x86_64/lib${state.config.general.name}.a`,
13
13
  `${state.config.paths.build}/Bridge-${buildType}/Emscripten-x86_64/lib${state.config.general.name}.a`,
14
14
  ];
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable prefer-destructuring */
2
- import fs from 'fs';
2
+ import fs from 'node:fs';
3
3
  import state, { saveCache } from '../state/index.js';
4
4
  import { getFileHash } from '../utils/hash.js';
5
5
  import run from './run.js';
@@ -36,8 +36,7 @@ function createInterfaceFile(headerOrModuleFilePath) {
36
36
  }
37
37
 
38
38
  const headerPaths = (state.config.dependencyParameters?.pathsOfCmakeDepends?.split(';') || [])
39
- .filter((d) => d.startsWith(state.config.paths.base))
40
- .map((d) => d.replace(`${state.config.paths.base}/`, ''));
39
+ .filter((d) => d.startsWith(state.config.paths.base));
41
40
 
42
41
  const temp2 = headerPaths
43
42
  .map((p) => headerOrModuleFilePath.match(new RegExp(`^${p}/.*?/include/(.*?)$`, 'i')))
@@ -47,10 +46,10 @@ function createInterfaceFile(headerOrModuleFilePath) {
47
46
  if (temp.length < 2) return null;
48
47
 
49
48
  const filePathWithoutExt = temp[1];
50
- const interfaceFile = `${state.config.paths.base}/${filePathWithoutExt}.i`;
49
+ const interfaceFile = `${filePathWithoutExt}.i`;
51
50
 
52
51
  if (fs.existsSync(interfaceFile)) {
53
- const newPath = `${state.config.paths.build}/interface/${filePathWithoutExt}.i`;
52
+ const newPath = `${state.config.paths.build}/interface/${interfaceFile.split('/').at(-1)}`;
54
53
  fs.copyFileSync(interfaceFile, newPath);
55
54
  state.cache.interfaces[headerOrModuleFilePath] = newPath;
56
55
  state.cache.hashes[headerOrModuleFilePath] = fileHash;
@@ -1,5 +1,5 @@
1
- import os from 'os';
2
- import fs from 'fs';
1
+ import os from 'node:os';
2
+ import fs from 'node:fs';
3
3
  import replace from 'replace';
4
4
  import run from './run.js';
5
5
  import getCmakeParameters from './getCmakeParameters.js';
@@ -32,7 +32,8 @@ export default function createLib(platform, fileType, options = {}) {
32
32
  const ext = sharedPlatforms.includes(basePlatform) ? 'so' : 'a';
33
33
  buildParams = getBuildParams ? getBuildParams(platform, depPaths, ext, buildPath) : [];
34
34
  if (state.config.build?.buildType !== 'configure') {
35
- buildParams.push(`-DCMAKE_PREFIX_PATH=${libdir}`, `-DCMAKE_FIND_ROOT_PATH=${libdir}`);
35
+ const cmakeBuildType = sharedPlatforms.includes(basePlatform) ? 'SHARED' : 'STATIC';
36
+ buildParams.push(`-DCMAKE_PREFIX_PATH=${libdir}`, `-DCMAKE_FIND_ROOT_PATH=${libdir}`, `-DBUILD_TYPE=${cmakeBuildType}`);
36
37
  }
37
38
 
38
39
  const cFlags = Object.values(depPaths).map((d) => `-I${d.header}`).join(' ');
@@ -1,40 +1,44 @@
1
- import fs from 'fs';
2
- import { execFileSync } from 'child_process';
1
+ import fs from 'node:fs';
2
+ import upath from 'upath';
3
+ import { execFileSync } from 'node:child_process';
3
4
  import state from '../state/index.js';
4
5
 
5
- export default function createXCFramework(createLink = true) {
6
+ export default function createXCFramework(overrideConfig = null) {
6
7
  if (process.platform !== 'darwin') {
7
8
  return;
8
9
  }
9
- const { output } = state.config.paths;
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
+
10
15
  if (
11
16
  !fs.existsSync(`${output}/prebuilt/iOS-iphoneos/lib`)
12
17
  || !fs.existsSync(`${output}/prebuilt/iOS-iphonesimulator/lib`)
13
18
  ) return;
14
19
 
15
20
  const options = {
16
- cwd: `${output}/prebuilt`,
21
+ cwd: projectPath,
17
22
  stdio: 'inherit',
18
23
  };
19
24
 
20
- state.config.export.libName.forEach((fileName) => {
21
- if (!fs.existsSync(`${options.cwd}/${fileName}.xcframework`)) {
25
+ const relativeOutput = upath.relative(projectPath, output);
26
+
27
+ libName.forEach((fileName) => {
28
+ if (!fs.existsSync(`${projectPath}/${fileName}.xcframework`)) {
22
29
  const params = [
23
30
  '-create-xcframework',
24
- '-library', `iOS-iphoneos/lib/lib${fileName}.a`,
25
- '-headers', 'iOS-iphoneos/include',
26
- '-library', `iOS-iphonesimulator/lib/lib${fileName}.a`,
27
- '-headers', 'iOS-iphonesimulator/include',
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`,
28
35
  '-output', `${fileName}.xcframework`,
29
36
  ];
30
37
  execFileSync('xcodebuild', params, options);
31
38
  }
32
39
 
33
- if (!fs.existsSync(`${options.cwd}/${fileName}.xcframework.zip`)) {
34
- execFileSync('zip', ['-y', '-r', `./${fileName}.xcframework.zip`, `${fileName}.xcframework`], options);
35
- }
36
- if (createLink && !fs.existsSync(`${state.config.paths.project}/${fileName}.xcframework`)) {
37
- fs.symlinkSync(`${options.cwd}/${fileName}.xcframework`, `${state.config.paths.project}/${fileName}.xcframework`);
40
+ if (!fs.existsSync(`${output}/prebuilt/${fileName}.xcframework.zip`)) {
41
+ execFileSync('zip', ['-y', '-r', `${relativeOutput}/prebuilt/${fileName}.xcframework.zip`, `${fileName}.xcframework`], options);
38
42
  }
39
43
  });
40
44
  }
@@ -12,7 +12,12 @@ export default function getCmakeParameters(platform, options = {}) {
12
12
  const externalNativeGlob = [
13
13
  ...(options.nativeGlob || []),
14
14
  ];
15
+ const externalBridgeGlob = [
16
+ `${state.config.paths.cli}/assets/bridge.cpp`,
17
+ ...(options.bridgeGlob || []),
18
+ ];
15
19
  const nativeGlob = [
20
+ `${state.config.paths.cli}/assets/cppjsemptysource.cpp`,
16
21
  ...(dependParams.nativeGlob || []),
17
22
  ];
18
23
  const headerGlob = [
@@ -34,6 +39,7 @@ export default function getCmakeParameters(platform, options = {}) {
34
39
  `-DPROJECT_NAME=${options.name || state.config.general.name}`,
35
40
  `-DBASE_DIR=${state.config.paths.project}`,
36
41
  `-DEXTERNAL_NATIVE_GLOB=${externalNativeGlob.join(';')}`,
42
+ `-DEXTERNAL_BRIDGE_GLOB=${externalBridgeGlob.join(';')}`,
37
43
  `-DNATIVE_GLOB=${nativeGlob.join(';')}`,
38
44
  `-DHEADER_GLOB=${headerGlob.join(';')}`,
39
45
  `-DHEADER_DIR=${headerDirs.join(';')}`,
@@ -1,7 +1,8 @@
1
- import { execFileSync } from 'child_process';
2
- import fs from 'fs';
1
+ import { execFileSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
3
  import pullDockerImage, { getDockerImage } from '../utils/pullDockerImage.js';
4
4
  import getOsUserAndGroupId from '../utils/getOsUserAndGroupId.js';
5
+ import { getContentHash } from '../utils/hash.js';
5
6
  import state from '../state/index.js';
6
7
 
7
8
  const CROSSCOMPILER = 'aarch64-linux-android33';
@@ -151,92 +152,94 @@ export default function run(program, params = [], platformPrefix = null, platfor
151
152
  default:
152
153
  }
153
154
  }
154
- if (basePlatform === 'iOS' && program === null) {
155
+
156
+ const env = {};
157
+ let runner = 'DOCKER';
158
+ if ((basePlatform === 'iOS' && program === null) || state.config.system.RUNNER === 'LOCAL') {
159
+ runner = 'LOCAL';
160
+ }
161
+
162
+ if (runner === 'LOCAL') {
155
163
  const allowedEnv = [
156
164
  '^PWD$', '^SHELL$', '^LC_CTYPE$', '^PATH$', '^HOME$', '^TMPDIR$', '^USER$',
157
165
  '^PODS_*', '^CONFIGURATION_BUILD_DIR$', '^UNLOCALIZED_RESOURCES_FOLDER_PATH$',
158
166
  ];
159
- const env = {};
160
167
  Object.entries(process.env).forEach(([key, value]) => {
161
168
  if (allowedEnv.some((e) => key.match(e))) {
162
169
  env[key] = value;
163
170
  }
164
171
  });
165
- const pParams = [...platformParams, ...(dockerOptions.params || [])];
166
- for (let i = 0; i < pParams.length; i += 2) {
167
- if (pParams[i] === '-e') {
168
- const [key, ...rest] = pParams[i + 1].split('=');
169
- const value = rest.join('=');
170
- if (['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS'].includes(key)) {
171
- let v = value;
172
- if (v.startsWith('\'') || v.startsWith('"')) {
173
- v = v.substring(1, v.length - 1);
174
- }
175
- if (env[key]) env[key] += ` ${v}`;
176
- else env[key] = v;
177
- } else {
178
- env[key] = value;
172
+ }
173
+
174
+ const pParams = [...platformParams, ...(dockerOptions.params || [])];
175
+ for (let i = 0; i < pParams.length; i += 2) {
176
+ if (pParams[i] === '-e') {
177
+ const [key, ...rest] = pParams[i + 1].split('=');
178
+ const value = rest.join('=');
179
+ if (['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS'].includes(key)) {
180
+ let v = value;
181
+ if (v.startsWith('\'') || v.startsWith('"')) {
182
+ v = v.substring(1, v.length - 1);
179
183
  }
184
+ if (env[key]) env[key] += ` ${v}`;
185
+ else env[key] = v;
186
+ } else {
187
+ env[key] = value;
180
188
  }
181
189
  }
190
+ }
182
191
 
192
+ let fileExecParams;
193
+ if (runner === 'LOCAL') {
183
194
  env.PATH = `/opt/homebrew/bin:${env.PATH}`;
184
195
 
185
196
  const options = {
186
197
  cwd: dockerOptions.workdir || buildPath,
187
- stdio: dockerOptions.console ? 'inherit' : 'ignore',
198
+ stdio: dockerOptions.console ? 'inherit' : ['ignore', 'pipe', 'pipe'],
188
199
  env,
189
200
  };
190
- execFileSync(dProgram, dParams, options);
191
- } else if (false) {
192
- const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : 'ignore' };
193
- const args = [
194
- 'exec',
195
- '--user', getOsUserAndGroupId(),
196
- '--workdir', dockerOptions.workdir || replaceBasePathForDocker(buildPath),
197
- 'cppjs-builder',
198
- dProgram,
199
- ...replaceBasePathForDocker(dParams),
200
- ];
201
- execFileSync('docker', args, options);
202
- } else {
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
-
201
+ fileExecParams = [dProgram, dParams, options];
202
+ } else if (runner === 'DOCKER') {
222
203
  const dockerEnv = [];
223
204
  Object.entries(env).forEach(([key, value]) => {
224
205
  dockerEnv.push('-e', `${key}=${value}`);
225
206
  });
226
- const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : 'ignore' };
207
+ const options = { cwd: buildPath, stdio: dockerOptions.console ? 'inherit' : ['ignore', 'pipe', 'pipe'] };
208
+
209
+ let runnerParams = [];
210
+ let imageOrContainer = null;
211
+ if (state.config.system.RUNNER === 'DOCKER_RUN') {
212
+ imageOrContainer = getDockerImage();
213
+ runnerParams = ['run', '--rm', '-v', `${state.config.paths.base}:/tmp/cppjs/live`];
214
+ } else if (state.config.system.RUNNER === 'DOCKER_EXEC') {
215
+ imageOrContainer = `${getDockerImage()}-${getContentHash(state.config.paths.base)}`.replace('/', '-').replace(':', '-');
216
+ runnerParams = ['exec'];
217
+ } else {
218
+ throw new Error(`The runner ${state.config.system.RUNNER} is invalid.`);
219
+ }
220
+
227
221
  const args = [
228
- 'run',
229
- '--rm',
222
+ ...runnerParams,
230
223
  '--user', getOsUserAndGroupId(),
231
- '-v', `${state.config.paths.base}:/tmp/cppjs/live`,
232
224
  '--workdir', replaceBasePathForDocker(dockerOptions.workdir || buildPath),
233
225
  ...replaceBasePathForDocker(dockerEnv),
234
226
  // '-e', replaceBasePathForDocker(`CCACHE_DIR=${state.config.paths.build}/ccache`),
235
- getDockerImage(),
227
+ imageOrContainer,
236
228
  replaceBasePathForDocker(dProgram),
237
229
  ...replaceBasePathForDocker(dParams),
238
230
  ];
239
- execFileSync('docker', args, options);
231
+ fileExecParams = ['docker', args, options];
232
+ } else {
233
+ throw new Error(`The runner ${state.config.system.RUNNER} or command is invalid.`);
234
+ }
235
+
236
+ try {
237
+ execFileSync(...fileExecParams);
238
+ } catch (e) {
239
+ console.log(e?.stdout?.toString() || 'stdout is empty');
240
+ console.error(e?.stderr?.toString() || 'stderr is empty');
241
+ console.error('An error occurred while running the application. Please check the logs for more details.');
242
+ process.exit();
240
243
  }
241
244
  }
242
245
 
@@ -26,7 +26,7 @@ if (BUILD_SOURCE)
26
26
  endif(BUILD_SOURCE)
27
27
 
28
28
  if (BUILD_BRIDGE)
29
- file(GLOB BRIDGE_SRC_FILES "${BRIDGE_DIR}/*.i.cpp")
29
+ file(GLOB BRIDGE_SRC_FILES "${BRIDGE_DIR}/*.i.cpp;${EXTERNAL_BRIDGE_GLOB}")
30
30
  endif(BUILD_BRIDGE)
31
31
 
32
32
  file(GLOB_RECURSE EXTERNAL_SRC_FILES ${EXTERNAL_NATIVE_GLOB})
@@ -0,0 +1,17 @@
1
+ #include <emscripten/bind.h>
2
+
3
+ EMSCRIPTEN_BINDINGS(stl_wrappers) {
4
+ emscripten::register_vector<bool>("VectorBool");
5
+ emscripten::register_vector<char>("VectorChar");
6
+ emscripten::register_vector<short>("VectorShort");
7
+ emscripten::register_vector<int>("VectorInt");
8
+ emscripten::register_vector<int64_t>("VectorInt64");
9
+ emscripten::register_vector<float>("VectorFloat");
10
+ emscripten::register_vector<double>("VectorDouble");
11
+ emscripten::register_vector<std::string>("VectorString");
12
+
13
+ emscripten::register_map<int,int>("MapIntInt");
14
+ emscripten::register_map<int,std::string>("MapIntString");
15
+ emscripten::register_map<std::string,std::string>("MapStringString");
16
+ emscripten::register_map<std::string,int>("MapStringInt");
17
+ }
File without changes
package/src/bin.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from 'fs';
3
+ import fs from 'node:fs';
4
+ import { execFileSync } from 'node:child_process';
4
5
  import { Command, Option } from 'commander';
5
6
  import glob from 'glob';
6
7
  import upath from 'upath';
@@ -14,6 +15,10 @@ import createXCFramework from './actions/createXCFramework.js';
14
15
  import runCppjsApp from './actions/run.js';
15
16
  import downloadAndExtractFile from './utils/downloadAndExtractFile.js';
16
17
  import writeJson from './utils/writeJson.js';
18
+ import systemKeys from './utils/systemKeys.js';
19
+
20
+ import { getDockerImage } from './utils/pullDockerImage.js';
21
+ import { getContentHash } from './utils/hash.js';
17
22
 
18
23
  const packageJSON = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url)));
19
24
 
@@ -29,20 +34,22 @@ const commandBuild = program.command('build')
29
34
  .description('compile the project that was set up using Cpp.js')
30
35
  .addOption(new Option('-p, --platform <platform>', 'target platform').default('All').choices(['All', 'WebAssembly', 'Android', 'iOS']));
31
36
 
32
- const commandRun = program.command('run')
33
- .description('run docker application');
37
+ const commandDocker = program.command('docker')
38
+ .description('manage docker');
39
+ const commandRun = commandDocker.command('run').description('run docker application');
40
+ commandDocker.command('create').description('create docker container');
41
+ commandDocker.command('start').description('start docker container');
42
+ commandDocker.command('stop').description('stop docker container');
43
+ commandDocker.command('delete').description('delete docker container');
34
44
 
35
45
  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
-
44
- const commandPostInstall = program.command('postinstall')
45
- .description('prepare the required packages for Cpp.js after installation');
46
+ .description('Manage the Cpp.js configuration files');
47
+ commandConfig.command('get').description('get the Cpp.js system configuration');
48
+ commandConfig.command('set').description('set the Cpp.js system configuration');
49
+ commandConfig.command('delete').description('delete the Cpp.js system configuration');
50
+ const commandConfigList = commandConfig.command('list').description('list the Cpp.js configurations')
51
+ .addOption(new Option('-t, --type <type>', 'config type').default('system').choices(['all', 'system', 'project']));
52
+ commandConfig.command('keys').description('list all available system configuration keys for Cpp.js');
46
53
 
47
54
  program.parse(process.argv);
48
55
 
@@ -56,9 +63,72 @@ switch (program.args[0]) {
56
63
  }
57
64
  break;
58
65
  }
59
- case 'run': {
60
- const [programName, ...params] = commandRun.args;
61
- run(programName, params);
66
+ case 'docker': {
67
+ switch (program.args[1]) {
68
+ case 'run': {
69
+ const [programName, ...params] = commandRun.args;
70
+ run(programName, params);
71
+ break;
72
+ }
73
+ case 'create': {
74
+ const args = [
75
+ 'run',
76
+ '-dit',
77
+ '--name',
78
+ `${getDockerImage()}-${getContentHash(state.config.paths.base)}`.replace('/', '-').replace(':', '-'),
79
+ '-v', `${state.config.paths.base}:/tmp/cppjs/live`,
80
+ getDockerImage(),
81
+ 'bash',
82
+ ];
83
+ try {
84
+ execFileSync('docker', args, { stdio: 'inherit' });
85
+ } catch (e) {
86
+ console.error('An error occurred while running the application. Please check the logs for more details.');
87
+ process.exit();
88
+ }
89
+ break;
90
+ }
91
+ case 'start': {
92
+ const args = [
93
+ 'start',
94
+ `${getDockerImage()}-${getContentHash(state.config.paths.base)}`.replace('/', '-').replace(':', '-'),
95
+ ];
96
+ try {
97
+ execFileSync('docker', args, { stdio: 'inherit' });
98
+ } catch (e) {
99
+ console.error('An error occurred while running the application. Please check the logs for more details.');
100
+ process.exit();
101
+ }
102
+ break;
103
+ }
104
+ case 'stop': {
105
+ const args = [
106
+ 'stop',
107
+ `${getDockerImage()}-${getContentHash(state.config.paths.base)}`.replace('/', '-').replace(':', '-'),
108
+ ];
109
+ try {
110
+ execFileSync('docker', args, { stdio: 'inherit' });
111
+ } catch (e) {
112
+ console.error('An error occurred while running the application. Please check the logs for more details.');
113
+ process.exit();
114
+ }
115
+ break;
116
+ }
117
+ case 'delete': {
118
+ const args = [
119
+ 'rm',
120
+ `${getDockerImage()}-${getContentHash(state.config.paths.base)}`.replace('/', '-').replace(':', '-'),
121
+ ];
122
+ try {
123
+ execFileSync('docker', args, { stdio: 'inherit' });
124
+ } catch (e) {
125
+ console.error('An error occurred while running the application. Please check the logs for more details.');
126
+ process.exit();
127
+ }
128
+ break;
129
+ }
130
+ default:
131
+ }
62
132
  break;
63
133
  }
64
134
  case 'config': {
@@ -75,29 +145,58 @@ switch (program.args[0]) {
75
145
  case 'list':
76
146
  listSystemConfig(commandConfigList.opts().type);
77
147
  break;
148
+ case 'keys':
149
+ listSystemKeys();
150
+ break;
78
151
  default:
79
152
  break;
80
153
  }
81
154
  break;
82
155
  }
83
- case 'postinstall': {
84
- postInstall();
85
- break;
86
- }
87
156
  default:
88
157
  break;
89
158
  }
90
159
 
91
- function getSystemConfig(key) {
92
- console.log(state.config.system[key]);
160
+ function listSystemKeys() {
161
+ console.info('Available configurations:');
162
+ console.table(systemKeys);
163
+ }
164
+
165
+ function getSystemConfig(systemKey) {
166
+ if (!systemKey) {
167
+ listSystemConfig('system');
168
+ return;
169
+ }
170
+ const key = systemKey.toUpperCase();
171
+ const output = {};
172
+ if (key in state.config.system) {
173
+ output[key] = { value: state.config.system[key] || 'undefined', default: systemKeys[key].default };
174
+ }
175
+ Object.keys(systemKeys).filter((k) => k.includes(key)).forEach((k) => {
176
+ if (k in state.config.system) {
177
+ output[k] = { value: state.config.system[k] || 'undefined', default: systemKeys[k].default };
178
+ }
179
+ });
180
+
181
+ console.table(output);
93
182
  }
94
183
 
95
184
  function setSystemConfig(key, value) {
185
+ if (!systemKeys[key]) {
186
+ throw new Error(`Configuration ${key} is not available. Please choose from the following available configurations: ${Object.keys(systemKeys).join(', ')}`);
187
+ }
188
+ if (systemKeys[key].options && !systemKeys[key].options.includes(value)) {
189
+ throw new Error(`Value ${value} is not available. Please choose from the following available values: ${systemKeys[key].options.join(', ')}`);
190
+ }
191
+
96
192
  state.config.system[key] = value;
97
193
  writeJson(state.config.paths.systemConfig, state.config.system);
98
194
  }
99
195
 
100
196
  function deleteSystemConfig(key) {
197
+ if (!systemKeys[key]) {
198
+ throw new Error(`Configuration ${key} is not available. Please choose from the following available configurations: ${Object.keys(systemKeys).join(', ')}`);
199
+ }
101
200
  delete state.config.system[key];
102
201
  writeJson(state.config.paths.systemConfig, state.config.system);
103
202
  }
@@ -106,7 +205,7 @@ function listSystemConfig(type) {
106
205
  const { system: systemConfig, ...projectConfig } = state.config;
107
206
  if (type === 'all' || type === 'system') {
108
207
  console.log('System Configuration');
109
- console.log(JSON.stringify(systemConfig, null, 2));
208
+ console.table(systemConfig);
110
209
  }
111
210
 
112
211
  if (type === 'all') {
@@ -115,38 +214,8 @@ function listSystemConfig(type) {
115
214
 
116
215
  if (type === 'all' || type === 'project') {
117
216
  console.log('Project Configuration');
118
- console.log(JSON.stringify(projectConfig, null, 2));
119
- }
120
- }
121
-
122
- function postInstall() {
123
- const projectPath = process.env.PWD;
124
- const isDarwin = process.platform === 'darwin';
125
- if (
126
- !isDarwin
127
- || (
128
- !fs.existsSync(`${projectPath}/cppjs.config.js`)
129
- && !fs.existsSync(`${projectPath}/cppjs.config.cjs`)
130
- && !fs.existsSync(`${projectPath}/cppjs.config.mjs`)
131
- )
132
- ) {
133
- return;
134
- }
135
-
136
- const name = state?.config?.general?.name;
137
- let dist = state?.config?.paths?.output;
138
- dist = dist ? upath.relative(projectPath, dist) : null;
139
-
140
- if (!name || !dist) {
141
- return;
217
+ console.table(projectConfig);
142
218
  }
143
-
144
- state?.config?.export?.libName?.forEach((fileName) => {
145
- if (fs.existsSync(`${projectPath}/${fileName}.xcframework`) || !fs.existsSync(`${dist}/prebuilt/${fileName}.xcframework`)) {
146
- return;
147
- }
148
- fs.symlinkSync(`${dist}/prebuilt/${fileName}.xcframework`, `${projectPath}/${fileName}.xcframework`);
149
- });
150
219
  }
151
220
 
152
221
  function run(programName, params) {
@@ -177,7 +246,7 @@ async function buildExternal(platform) {
177
246
  });
178
247
  }
179
248
 
180
- await buildLib(platform);
249
+ buildLib(platform);
181
250
  }
182
251
 
183
252
  async function build(platform) {
@@ -187,10 +256,23 @@ async function build(platform) {
187
256
  }
188
257
  }
189
258
 
190
- async function buildLib(platform) {
259
+ function buildLib(platform) {
191
260
  state.platforms[platform].forEach((p) => {
192
261
  if (!fs.existsSync(`${state.config.paths.output}/prebuilt/${p}/lib`)) {
193
262
  createLib(p, 'Source', { isProd: true, buildSource: true });
263
+
264
+ const modules = [];
265
+ state.config.paths.module.forEach((modulePath) => {
266
+ modules.push(...glob.sync('**/*.i', { absolute: true, cwd: modulePath }));
267
+ modules.push(...glob.sync('*.i', { absolute: true, cwd: modulePath }));
268
+ });
269
+ if (modules.length > 0) {
270
+ fs.mkdirSync(`${state.config.paths.output}/prebuilt/${p}/swig`, { recursive: true });
271
+ }
272
+ modules.forEach((modulePath) => {
273
+ const fileName = modulePath.split('/').at(-1);
274
+ fs.copyFileSync(modulePath, `${state.config.paths.output}/prebuilt/${p}/swig/${fileName}`);
275
+ });
194
276
  } else {
195
277
  console.log(`${state.config.general.name} is already compiled to ${p} architecture.`);
196
278
  }
@@ -79,7 +79,7 @@ function getWebScript(env, modulePrefix) {
79
79
  return `
80
80
  export function initCppJs(config = {}) {
81
81
  return new Promise((resolve, reject) => {
82
- import('/cpp.js').then(n => {
82
+ import(/* webpackIgnore: true */ '/cpp.js').then(n => {
83
83
  return window.CppJs.initCppJs(${params});
84
84
  }).then(m => {
85
85
  ${modulePrefix}
@@ -1,3 +1,4 @@
1
+ import fs from 'node:fs';
1
2
  import state from '../state/index.js';
2
3
 
3
4
  export default function getDependFilePath(source, platform) {
@@ -6,13 +7,24 @@ export default function getDependFilePath(source, platform) {
6
7
 
7
8
  const dependPackage = state.config.allDependencies.find((d) => source.startsWith(d.package.name));
8
9
  if (dependPackage) {
9
- const filePath = source.substring(dependPackage.package.name.length + 1);
10
+ const depName = dependPackage.package.name;
11
+ const filePath = source.substring(depName.length + 1);
10
12
 
11
- let path = `${dependPackage.paths.output}/prebuilt/${platform}/${filePath}`;
13
+ let path;
12
14
  if (headerRegex.test(source)) {
13
- path = `${dependPackage.paths.output}/prebuilt/${platform}/include/${filePath}`;
15
+ path = `${dependPackage.paths.output}/prebuilt/${platform}/include`;
14
16
  } else if (moduleRegex.test(source)) {
15
- path = `${dependPackage.paths.output}/prebuilt/${platform}/swig/${filePath}`;
17
+ path = `${dependPackage.paths.output}/prebuilt/${platform}/swig`;
18
+ } else {
19
+ path = `${dependPackage.paths.output}/prebuilt/${platform}`;
20
+ }
21
+
22
+ if (fs.existsSync(`${path}/${depName}/${filePath}`)) {
23
+ path = `${path}/${depName}/${filePath}`;
24
+ } else if (fs.existsSync(`${path}/${filePath}`)) {
25
+ path = `${path}/${filePath}`;
26
+ } else {
27
+ throw new Error(`${source} not found in ${depName} package.`);
16
28
  }
17
29
 
18
30
  return path;
@@ -55,9 +55,9 @@ function setAllDependecyPaths() {
55
55
  if (basePlatform === 'iOS') {
56
56
  let xcRoot;
57
57
  if (platform === 'iOS-iphoneos') {
58
- xcRoot = `${d.paths.output}/prebuilt/${name}.xcframework/ios-arm64_arm64e`;
58
+ xcRoot = `${d.paths.project}/${name}.xcframework/ios-arm64_arm64e`;
59
59
  } else if (platform === 'iOS-iphonesimulator') {
60
- xcRoot = `${d.paths.output}/prebuilt/${name}.xcframework/ios-arm64_arm64e_x86_64-simulator`;
60
+ xcRoot = `${d.paths.project}/${name}.xcframework/ios-arm64_arm64e_x86_64-simulator`;
61
61
  }
62
62
  dep.header = `${xcRoot}/Headers`;
63
63
  dep.libPath = xcRoot;
@@ -1,4 +1,5 @@
1
- import os from 'os';
1
+ import os from 'node:os';
2
+ import systemKeys from '../utils/systemKeys.js';
2
3
  import loadJs from '../utils/loadJs.js';
3
4
  import loadJson from '../utils/loadJson.js';
4
5
  import getParentPath from '../utils/getParentPath.js';
@@ -16,6 +17,12 @@ export default async function loadConfig(configDir = process.cwd(), configName =
16
17
  output.paths.systemConfig = `${os.homedir()}/.cppjs.json`;
17
18
  output.system = loadJson(output.paths.systemConfig) || {};
18
19
 
20
+ Object.entries(systemKeys).forEach(([key, value]) => {
21
+ if (!(key in output.system)) {
22
+ output.system[key] = value.default;
23
+ }
24
+ });
25
+
19
26
  return output;
20
27
  }
21
28
 
@@ -1,5 +1,5 @@
1
- import path from 'path';
2
- import fs, { mkdirSync } from 'fs';
1
+ import path from 'node:path';
2
+ import fs, { mkdirSync } from 'node:fs';
3
3
  import fr from 'follow-redirects';
4
4
  import decompress from 'decompress';
5
5
 
@@ -1,4 +1,4 @@
1
- import os from 'os';
1
+ import os from 'node:os';
2
2
 
3
3
  let osUserAndGroupId;
4
4
  export default function getOsUserAndGroupId() {
@@ -1,4 +1,4 @@
1
- import * as url from 'url';
1
+ import * as url from 'node:url';
2
2
  import upath from 'upath';
3
3
 
4
4
  export default function getParentPath(importUrl) {
package/src/utils/hash.js CHANGED
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import { createHash } from 'crypto';
1
+ import fs from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
3
 
4
4
  export function getFileHash(path) {
5
5
  const data = fs.readFileSync(path);
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
 
3
3
  export default async function loadJs(path, fileName, fileExt = ['json', 'js', 'mjs', 'cjs', 'ts']) {
4
4
  let filePath;
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
 
3
3
  export default function loadJson(filePath) {
4
4
  if (!fs.existsSync(filePath)) {
@@ -1,9 +1,9 @@
1
- import { execFileSync } from 'child_process';
1
+ import { execFileSync } from 'node:child_process';
2
2
 
3
3
  let isDockerImageAvailable = false;
4
4
 
5
5
  export function getDockerImage() {
6
- return 'bugra9/cpp.js:0.2.7';
6
+ return 'bugra9/cpp.js:0.2.8';
7
7
  }
8
8
 
9
9
  export default function pullDockerImage() {
@@ -0,0 +1,18 @@
1
+ const systemKeys = {
2
+ XCODE_DEVELOPMENT_TEAM: {
3
+ description: 'The unique identifier of the development team used for code signing and app distribution in Xcode.',
4
+ default: '',
5
+ },
6
+ RUNNER: {
7
+ description: 'The execution environment for running the application.',
8
+ options: ['DOCKER_RUN', 'DOCKER_EXEC', 'LOCAL'],
9
+ default: 'DOCKER_RUN',
10
+ },
11
+ LOG_LEVEL: {
12
+ description: 'The verbosity of log output.',
13
+ options: ['DEBUG', 'INFO', 'WARN', 'ERROR'],
14
+ default: 'INFO',
15
+ },
16
+ };
17
+
18
+ export default systemKeys;
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
 
3
3
  export default function writeJson(filePath, data) {
4
4
  try {