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 +3 -0
- package/package.json +5 -2
- package/src/actions/createLib.js +73 -10
- package/src/actions/getCmakeParameters.js +2 -0
- package/src/actions/run.js +32 -17
- package/src/bin.js +114 -8
- package/src/export/react-native.js +51 -0
- package/src/export/web.js +42 -0
- package/src/index.js +3 -0
- package/src/state/index.js +37 -0
- package/src/state/loadConfig.js +8 -1
- package/src/utils/downloadAndExtractFile.js +36 -0
- package/src/utils/pullDockerImage.js +1 -1
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.
|
|
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"
|
package/src/actions/createLib.js
CHANGED
|
@@ -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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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
|
]);
|
package/src/actions/run.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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' : '
|
|
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' : '
|
|
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
|
|
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 ||
|
|
217
|
-
...replaceBasePathForDocker(
|
|
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
|
|
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
|
-
|
|
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';
|
package/src/state/index.js
CHANGED
|
@@ -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
|
}
|
package/src/state/loadConfig.js
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|