cpp.js 0.6.1 → 1.0.0-alpha.2
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/LICENSE +1 -1
- package/cpp.js-1.0.0-alpha.2.tgz +0 -0
- package/package.json +10 -3
- package/src/assets/CMakeLists.txt +26 -10
- package/src/assets/browser.js +161 -0
- package/src/assets/dist.cmake +36 -11
- package/src/assets/ios.toolchain.cmake +1145 -0
- package/src/assets/node.js +130 -0
- package/src/bin.js +102 -27
- package/src/functions/buildJS.js +63 -0
- package/src/functions/createBridge.js +16 -17
- package/src/functions/createLib.js +44 -0
- package/src/functions/createWasm.js +61 -192
- package/src/functions/findOrCreateInterfaceFile.js +29 -8
- package/src/functions/finishBuild.js +43 -0
- package/src/functions/getCmakeParams.js +106 -0
- package/src/functions/getData.js +37 -0
- package/src/functions/getLibs.js +33 -0
- package/src/functions/run.js +220 -0
- package/src/functions/specs/createBridge.spec.js +8 -9
- package/src/functions/specs/findOrCreateInterfaceFile.spec.js +12 -12
- package/src/index.js +39 -3
- package/src/utils/createTempDir.js +2 -2
- package/src/utils/findCMakeListsFile.js +3 -3
- package/src/utils/getCliPath.js +4 -5
- package/src/utils/getConfig.js +63 -32
- package/src/utils/getDirName.js +2 -2
- package/src/utils/getOsUserAndGroupId.js +1 -1
- package/src/utils/getPathInfo.js +0 -2
- package/src/utils/pullDockerImage.js +11 -6
- package/src/assets/extern-post.js +0 -14
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { execFileSync } from 'child_process';
|
|
3
|
+
import pullDockerImage, { getDockerImage } from '../utils/pullDockerImage.js';
|
|
4
|
+
import getOsUserAndGroupId from '../utils/getOsUserAndGroupId.js';
|
|
5
|
+
import getBaseInfo from '../utils/getBaseInfo.js';
|
|
6
|
+
import getPathInfo from '../utils/getPathInfo.js';
|
|
7
|
+
|
|
8
|
+
const CROSSCOMPILER = 'aarch64-linux-android33';
|
|
9
|
+
const ANDROID_NDK = '/opt/android-sdk/ndk/25.2.9519653';
|
|
10
|
+
const t = `${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin`;
|
|
11
|
+
const t2 = `${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64`;
|
|
12
|
+
|
|
13
|
+
const iOSDevPath = '/Applications/Xcode.app/Contents/Developer';
|
|
14
|
+
const iosBinPath = `${iOSDevPath}/Toolchains/XcodeDefault.xctoolchain/usr/bin`;
|
|
15
|
+
const iosSdkPath = `${iOSDevPath}/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk`;
|
|
16
|
+
const iosSimSdkPath = `${iOSDevPath}/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk`;
|
|
17
|
+
|
|
18
|
+
const androidParams = [
|
|
19
|
+
'-e', `AR=${t}/llvm-ar`,
|
|
20
|
+
'-e', `AS=${t}/llvm-as`,
|
|
21
|
+
'-e', `CC=${t}/${CROSSCOMPILER}-clang`,
|
|
22
|
+
'-e', `CXX=${t}/${CROSSCOMPILER}-clang++`,
|
|
23
|
+
'-e', `LD=${t}/ld`,
|
|
24
|
+
'-e', `RANLIB=${t}/llvm-ranlib`,
|
|
25
|
+
'-e', `STRIP=${t}/llvm-strip`,
|
|
26
|
+
'-e', `NM=${t}/nm`,
|
|
27
|
+
'-e', `CFLAGS=--sysroot=${t2}/sysroot`,
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const IOS_HOST_FLAGS = `-arch arm64 -arch arm64e -isysroot ${iosSdkPath} -fembed-bitcode`;
|
|
31
|
+
const IOS_SIM_HOST_FLAGS = `-arch x86_64 -arch arm64 -arch arm64e -isysroot ${iosSimSdkPath} -fembed-bitcode`;
|
|
32
|
+
const IOS_IPHONE_PARAMS = [
|
|
33
|
+
'-e', `CFLAGS="${IOS_HOST_FLAGS}"`,
|
|
34
|
+
'-e', `CXXFLAGS="${IOS_HOST_FLAGS}"`,
|
|
35
|
+
'-e', `LDFLAGS="${IOS_HOST_FLAGS}"`,
|
|
36
|
+
];
|
|
37
|
+
const IOS_SIM_PARAMS = [
|
|
38
|
+
'-e', `CFLAGS="${IOS_SIM_HOST_FLAGS}"`,
|
|
39
|
+
'-e', `CXXFLAGS="${IOS_SIM_HOST_FLAGS}"`,
|
|
40
|
+
'-e', `LDFLAGS="${IOS_SIM_HOST_FLAGS}"`,
|
|
41
|
+
];
|
|
42
|
+
const iosParams = [
|
|
43
|
+
'-e', `AR=${iosBinPath}/ar`,
|
|
44
|
+
'-e', `AS=${iosBinPath}/as`,
|
|
45
|
+
'-e', `CC=${iosBinPath}/clang`,
|
|
46
|
+
'-e', `CXX=${iosBinPath}/clang++`,
|
|
47
|
+
'-e', `CPP=${iosBinPath}/cpp`,
|
|
48
|
+
'-e', `LD=${iosBinPath}/ld`,
|
|
49
|
+
'-e', `RANLIB=${iosBinPath}/ranlib`,
|
|
50
|
+
'-e', `STRIP=${iosBinPath}/strip`,
|
|
51
|
+
'-e', `NM=${iosBinPath}/llvm-nm`,
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/* const iosMetalParams = [
|
|
55
|
+
'-e', `AR=${iosBinPath}/metal-ar`,
|
|
56
|
+
'-e', `AS=${iosBinPath}/metal-as`,
|
|
57
|
+
'-e', `CC=${iosBinPath}/clang`,
|
|
58
|
+
'-e', `CXX=${iosBinPath}/clang++`,
|
|
59
|
+
'-e', `CPP=${iosBinPath}/cpp`,
|
|
60
|
+
'-e', `LD=${iosBinPath}/ld`,
|
|
61
|
+
'-e', `RANLIB=${iosBinPath}/metal-ranlib`,
|
|
62
|
+
'-e', `STRIP=${iosBinPath}/metal-strip`,
|
|
63
|
+
'-e', `NM=${iosBinPath}/metal-nm`,
|
|
64
|
+
'-e', `CFLAGS="${IOS_HOST_FLAGS}"`,
|
|
65
|
+
'-e', `CXXFLAGS="${IOS_HOST_FLAGS}"`,
|
|
66
|
+
'-e', `LDFLAGS="${IOS_HOST_FLAGS}"`,
|
|
67
|
+
]; */
|
|
68
|
+
|
|
69
|
+
function getParentPath(path) {
|
|
70
|
+
const pathArray = path.split('/');
|
|
71
|
+
pathArray.pop();
|
|
72
|
+
return pathArray.join('/');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default function run(compiler, program, params = [], dockerOptions = {}) {
|
|
76
|
+
const [basePlatform, ...arch] = (compiler.platform || 'unknown-unknown').split('-'); // Emscripten-x86_64, Android-arm64-v8a, iOS-iphoneos, iOS-iphonesimulator
|
|
77
|
+
if (basePlatform !== 'iOS' || program !== null) {
|
|
78
|
+
pullDockerImage();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const base = getBaseInfo(compiler.config.paths.base);
|
|
82
|
+
const temp = getPathInfo(compiler.config.paths.temp, compiler.config.paths.base);
|
|
83
|
+
|
|
84
|
+
const cMakeParentPath = getParentPath(compiler.config.paths.cmake);
|
|
85
|
+
let dProgram = program;
|
|
86
|
+
let dParams = params;
|
|
87
|
+
let platformParams = [];
|
|
88
|
+
if (program === null) {
|
|
89
|
+
switch (basePlatform) {
|
|
90
|
+
case 'Emscripten':
|
|
91
|
+
platformParams = ['-e', 'CXXFLAGS=-fexceptions', '-e', 'CFLAGS=-fexceptions'];
|
|
92
|
+
if (params[0].includes('configure')) dProgram = 'emconfigure';
|
|
93
|
+
else if (params[0] === 'make') dProgram = 'emmake';
|
|
94
|
+
else if (params[0] === 'cmake') dProgram = 'emcmake';
|
|
95
|
+
else if (params[0] === 'cc') dProgram = 'emcc';
|
|
96
|
+
break;
|
|
97
|
+
case 'Android':
|
|
98
|
+
[dProgram, ...dParams] = params;
|
|
99
|
+
platformParams = androidParams;
|
|
100
|
+
if (dProgram === 'cmake') {
|
|
101
|
+
dParams = [
|
|
102
|
+
...dParams,
|
|
103
|
+
'-DCMAKE_SYSTEM_NAME=Android', '-DCMAKE_SYSTEM_VERSION=33', '-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a',
|
|
104
|
+
`-DCMAKE_ANDROID_NDK=${ANDROID_NDK}`,
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case 'iOS':
|
|
109
|
+
[dProgram, ...dParams] = params;
|
|
110
|
+
platformParams = [...iosParams, ...(arch[0] === 'iphoneos' ? IOS_IPHONE_PARAMS : IOS_SIM_PARAMS)];
|
|
111
|
+
if (dProgram === 'cmake') {
|
|
112
|
+
platformParams = [];
|
|
113
|
+
if (dParams[0] !== '--build' && dParams[0] !== '--install') {
|
|
114
|
+
dParams = [
|
|
115
|
+
...dParams,
|
|
116
|
+
'-G', 'Xcode',
|
|
117
|
+
'-DBUILD_SHARED_LIBS=OFF',
|
|
118
|
+
'-DFRAMEWORK=TRUE',
|
|
119
|
+
'-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0',
|
|
120
|
+
'-DCMAKE_SYSTEM_NAME=iOS',
|
|
121
|
+
`-DMACOSX_FRAMEWORK_IDENTIFIER=org.js.cpp.${compiler.config.general.name}`,
|
|
122
|
+
`-DCMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER=org.js.cpp.${compiler.config.general.name}`,
|
|
123
|
+
`-DCMAKE_OSX_SYSROOT='${arch[0] === 'iphoneos' ? iosSdkPath : iosSimSdkPath}'`,
|
|
124
|
+
`-DCMAKE_OSX_ARCHITECTURES=${arch[0] === 'iphoneos' ? 'arm64;arm64e' : 'arm64;arm64e;x86_64'}`,
|
|
125
|
+
`-DCMAKE_C_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
|
|
126
|
+
`-DCMAKE_CXX_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
|
|
127
|
+
'-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=\'iPhone Developer\'',
|
|
128
|
+
'-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=7ZZLDWBUVT',
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
} else if (dProgram === 'ios-cmake') {
|
|
132
|
+
dProgram = 'cmake';
|
|
133
|
+
platformParams = [];
|
|
134
|
+
if (dParams[0] !== '--build' && dParams[0] !== '--install') {
|
|
135
|
+
dParams = [
|
|
136
|
+
...dParams,
|
|
137
|
+
`-DCMAKE_TOOLCHAIN_FILE='${compiler.config.paths.cli}/assets/ios.toolchain.cmake'`,
|
|
138
|
+
`-DPLATFORM=${arch[0] === 'iphoneos' ? 'OS64' : 'SIMULATORARM64'}`,
|
|
139
|
+
`-DARCHS=${arch[0] === 'iphoneos' ? 'arm64;arm64e' : 'arm64;arm64e;x86_64'}`,
|
|
140
|
+
'-DENABLE_BITCODE=TRUE',
|
|
141
|
+
'-DBUILD_SHARED_LIBS=OFF',
|
|
142
|
+
'-DFRAMEWORK=TRUE',
|
|
143
|
+
'-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0',
|
|
144
|
+
'-DCMAKE_SYSTEM_NAME=iOS',
|
|
145
|
+
`-DMACOSX_FRAMEWORK_IDENTIFIER=org.js.cpp.${compiler.config.general.name}`,
|
|
146
|
+
`-DCMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER=org.js.cpp.${compiler.config.general.name}`,
|
|
147
|
+
`-DCMAKE_OSX_SYSROOT='${arch[0] === 'iphoneos' ? iosSdkPath : iosSimSdkPath}'`,
|
|
148
|
+
`-DCMAKE_OSX_ARCHITECTURES=${arch[0] === 'iphoneos' ? 'arm64;arm64e' : 'arm64;arm64e;x86_64'}`,
|
|
149
|
+
`-DCMAKE_C_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
|
|
150
|
+
`-DCMAKE_CXX_FLAGS=${arch[0] === 'iphoneos' ? '-fembed-bitcode' : '-fembed-bitcode-marker'}`,
|
|
151
|
+
'-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=\'iPhone Developer\'',
|
|
152
|
+
'-DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=7ZZLDWBUVT',
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
default:
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (basePlatform === 'iOS' && program === null) {
|
|
161
|
+
const allowedEnv = [
|
|
162
|
+
'^PWD$', '^SHELL$', '^LC_CTYPE$', '^PATH$', '^HOME$', '^TMPDIR$', '^USER$',
|
|
163
|
+
'^PODS_*', '^CONFIGURATION_BUILD_DIR$', '^UNLOCALIZED_RESOURCES_FOLDER_PATH$',
|
|
164
|
+
];
|
|
165
|
+
const env = {};
|
|
166
|
+
Object.entries(process.env).forEach(([key, value]) => {
|
|
167
|
+
if (allowedEnv.some((e) => key.match(e))) {
|
|
168
|
+
env[key] = value;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
const pParams = [...platformParams, ...(dockerOptions.params || [])];
|
|
172
|
+
for (let i = 0; i < pParams.length; i += 2) {
|
|
173
|
+
if (pParams[i] === '-e') {
|
|
174
|
+
const [key, ...rest] = pParams[i + 1].split('=');
|
|
175
|
+
const value = rest.join('=');
|
|
176
|
+
if (['CFLAGS', 'CXXFLAGS', 'LDFLAGS'].includes(key)) {
|
|
177
|
+
let v = value;
|
|
178
|
+
if (v.startsWith('\'') || v.startsWith('"')) {
|
|
179
|
+
v = v.substring(1, v.length - 1);
|
|
180
|
+
}
|
|
181
|
+
if (env[key]) env[key] += ` ${v}`;
|
|
182
|
+
else env[key] = v;
|
|
183
|
+
} else {
|
|
184
|
+
env[key] = value;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
env.PATH = `/opt/homebrew/bin:${env.PATH}`;
|
|
190
|
+
|
|
191
|
+
const options = {
|
|
192
|
+
cwd: dockerOptions.workdir || `/tmp/cppjs/live/${temp.relative}`,
|
|
193
|
+
stdio: dockerOptions.console ? 'inherit' : 'pipe',
|
|
194
|
+
env,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
if (!fs.existsSync('/tmp/cppjs')) fs.mkdirSync('/tmp/cppjs');
|
|
198
|
+
if (fs.existsSync('/tmp/cppjs/live')) fs.unlinkSync('/tmp/cppjs/live');
|
|
199
|
+
fs.symlinkSync(base.withoutSlash, '/tmp/cppjs/live');
|
|
200
|
+
if (!fs.existsSync('/tmp/cppjs/cli')) fs.symlinkSync(compiler.config.paths.cli, '/tmp/cppjs/cli');
|
|
201
|
+
if (!fs.existsSync('/tmp/cppjs/cmake')) fs.symlinkSync(cMakeParentPath, '/tmp/cppjs/cmake');
|
|
202
|
+
|
|
203
|
+
execFileSync(dProgram, dParams, options);
|
|
204
|
+
} else {
|
|
205
|
+
const options = { cwd: temp.absolute, stdio: dockerOptions.console ? 'inherit' : 'pipe' };
|
|
206
|
+
const args = [
|
|
207
|
+
'run',
|
|
208
|
+
'--user', getOsUserAndGroupId(),
|
|
209
|
+
'-v', `${base.withoutSlash}:/tmp/cppjs/live`,
|
|
210
|
+
'-v', `${compiler.config.paths.cli}:/tmp/cppjs/cli`,
|
|
211
|
+
'-v', `${cMakeParentPath}:/tmp/cppjs/cmake`,
|
|
212
|
+
'--workdir', dockerOptions.workdir || `/tmp/cppjs/live/${temp.relative}`,
|
|
213
|
+
...platformParams,
|
|
214
|
+
...(dockerOptions.params || []),
|
|
215
|
+
getDockerImage(),
|
|
216
|
+
dProgram, ...dParams,
|
|
217
|
+
];
|
|
218
|
+
execFileSync('docker', args, options);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { assert } from 'chai';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
-
import p, {dirname} from 'path';
|
|
3
|
+
import p, { dirname } from 'path';
|
|
4
4
|
import * as url from 'node:url';
|
|
5
|
-
import { tmpdir } from
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
6
|
import createBridge from './createBridge.js';
|
|
7
7
|
|
|
8
8
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
@@ -12,7 +12,7 @@ temp.pop();
|
|
|
12
12
|
const __dirname = temp.join('/');
|
|
13
13
|
|
|
14
14
|
export function createTempDir(folder) {
|
|
15
|
-
let path = p.join(tmpdir(),
|
|
15
|
+
let path = p.join(tmpdir(), 'cppjs-app-cli-test');
|
|
16
16
|
if (folder) path = p.join(path, folder);
|
|
17
17
|
|
|
18
18
|
if (fs.existsSync(path)) fs.rmSync(path, { recursive: true, force: true });
|
|
@@ -21,22 +21,21 @@ export function createTempDir(folder) {
|
|
|
21
21
|
return path;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
describe('createBridge',
|
|
24
|
+
describe('createBridge', () => {
|
|
25
25
|
let tempdir;
|
|
26
|
-
before(async
|
|
26
|
+
before(async () => {
|
|
27
27
|
tempdir = createTempDir();
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
it('createBridge', async
|
|
31
|
-
const path = __dirname
|
|
30
|
+
it('createBridge', async () => {
|
|
31
|
+
const path = `${__dirname}/test/data/sample.i`;
|
|
32
32
|
const bridgeFilePath = createBridge(path, tempdir);
|
|
33
33
|
const bridgeFileData = fs.readFileSync(bridgeFilePath, 'utf8');
|
|
34
34
|
|
|
35
35
|
const startIndex = bridgeFileData.indexOf('#include <emscripten/bind.h>');
|
|
36
36
|
const bridgeFileDataTrim = bridgeFileData.substring(startIndex, bridgeFileData.length).trim();
|
|
37
37
|
|
|
38
|
-
const expectedContent =
|
|
39
|
-
`#include <emscripten/bind.h>
|
|
38
|
+
const expectedContent = `#include <emscripten/bind.h>
|
|
40
39
|
|
|
41
40
|
#include "sample.h"
|
|
42
41
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { assert } from 'chai';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
-
import p, {dirname} from 'path';
|
|
3
|
+
import p, { dirname } from 'path';
|
|
4
4
|
import * as url from 'node:url';
|
|
5
|
-
import { tmpdir } from
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
6
|
import findOrCreateInterfaceFile from './findOrCreateInterfaceFile.js';
|
|
7
7
|
|
|
8
8
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
@@ -12,7 +12,7 @@ temp.pop();
|
|
|
12
12
|
const __dirname = temp.join('/');
|
|
13
13
|
|
|
14
14
|
export function createTempDir(folder) {
|
|
15
|
-
let path = p.join(tmpdir(),
|
|
15
|
+
let path = p.join(tmpdir(), 'cppjs-app-cli-test');
|
|
16
16
|
if (folder) path = p.join(path, folder);
|
|
17
17
|
|
|
18
18
|
if (fs.existsSync(path)) fs.rmSync(path, { recursive: true, force: true });
|
|
@@ -21,29 +21,29 @@ export function createTempDir(folder) {
|
|
|
21
21
|
return path;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
describe('findOrCreateInterfaceFile',
|
|
24
|
+
describe('findOrCreateInterfaceFile', () => {
|
|
25
25
|
let tempdir;
|
|
26
|
-
before(async
|
|
26
|
+
before(async () => {
|
|
27
27
|
tempdir = createTempDir();
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
it('find interface file', async
|
|
31
|
-
const path = __dirname
|
|
30
|
+
it('find interface file', async () => {
|
|
31
|
+
const path = `${__dirname}/test/data/sample.h`;
|
|
32
32
|
const interfaceFile = findOrCreateInterfaceFile(path, tempdir);
|
|
33
33
|
assert.equal(interfaceFile, path.replace('.h', '.i'));
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it('create interface file', async
|
|
37
|
-
const path = __dirname
|
|
36
|
+
it('create interface file', async () => {
|
|
37
|
+
const path = `${__dirname}/test/data/sample2.h`;
|
|
38
38
|
const interfaceFile = findOrCreateInterfaceFile(path, tempdir);
|
|
39
39
|
const interfaceFileData = fs.readFileSync(interfaceFile, 'utf8');
|
|
40
40
|
|
|
41
|
-
const path2 = __dirname
|
|
41
|
+
const path2 = `${__dirname}/test/data/sample2.ei`;
|
|
42
42
|
const interfaceFileData2 = fs.readFileSync(path2, 'utf8');
|
|
43
43
|
|
|
44
44
|
assert.equal(
|
|
45
|
-
interfaceFileData.trim().replace(__dirname
|
|
46
|
-
interfaceFileData2.trim().replace(__dirname
|
|
45
|
+
interfaceFileData.trim().replace(`${__dirname}/test/data/`, ''),
|
|
46
|
+
interfaceFileData2.trim().replace(`${__dirname}/test/data/`, ''),
|
|
47
47
|
);
|
|
48
48
|
});
|
|
49
49
|
});
|
package/src/index.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import createBridge from './functions/createBridge.js';
|
|
2
2
|
import findOrCreateInterfaceFile from './functions/findOrCreateInterfaceFile.js';
|
|
3
|
-
import
|
|
3
|
+
import run from './functions/run.js';
|
|
4
|
+
import finishBuild from './functions/finishBuild.js';
|
|
5
|
+
import getCmakeParams from './functions/getCmakeParams.js';
|
|
6
|
+
import getData from './functions/getData.js';
|
|
7
|
+
import createWasm from './functions/createWasm.js';
|
|
8
|
+
import createLib from './functions/createLib.js';
|
|
4
9
|
import getConfig from './utils/getConfig.js';
|
|
5
10
|
|
|
11
|
+
const platforms = ['Emscripten-x86_64', 'Android-arm64-v8a', 'iOS-iphoneos', 'iOS-iphonesimulator'];
|
|
6
12
|
export default class CppjsCompiler {
|
|
7
|
-
constructor() {
|
|
13
|
+
constructor(platform) {
|
|
8
14
|
this.config = getConfig();
|
|
9
15
|
this.interfaces = [];
|
|
16
|
+
this.platform = platform;
|
|
10
17
|
}
|
|
11
18
|
|
|
12
19
|
findOrCreateInterfaceFile(path) {
|
|
@@ -21,7 +28,36 @@ export default class CppjsCompiler {
|
|
|
21
28
|
return createWasm(this, options);
|
|
22
29
|
}
|
|
23
30
|
|
|
31
|
+
createLib() {
|
|
32
|
+
return createLib(this);
|
|
33
|
+
}
|
|
34
|
+
|
|
24
35
|
getCmakeParams() {
|
|
25
|
-
return getCmakeParams(this);
|
|
36
|
+
return getCmakeParams(this.config, null, true, true);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getData(field, prefixPath, subPlatform) {
|
|
40
|
+
return getData(this.config, field, prefixPath, this.platform, subPlatform);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
run(program, params, dockerOptions) {
|
|
44
|
+
run(this, program, params, dockerOptions);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
finishBuild() {
|
|
48
|
+
finishBuild(this);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line class-methods-use-this
|
|
52
|
+
getAllPlatforms() {
|
|
53
|
+
return platforms;
|
|
26
54
|
}
|
|
27
55
|
}
|
|
56
|
+
|
|
57
|
+
export function initCppJs() {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
resolve();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const Native = {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import p from 'path';
|
|
3
3
|
|
|
4
|
-
export default function createTempDir(folder =
|
|
5
|
-
const path = p.join(base,
|
|
4
|
+
export default function createTempDir(folder = `a${Math.random()}`, base = process.cwd()) {
|
|
5
|
+
const path = p.join(base, '.cppjs');
|
|
6
6
|
return createDir(folder, path);
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -2,9 +2,9 @@ import glob from 'glob';
|
|
|
2
2
|
import getCliPath from './getCliPath.js';
|
|
3
3
|
|
|
4
4
|
export default function findCMakeListsFile(basePath = process.cwd()) {
|
|
5
|
-
let temp = glob.sync(
|
|
5
|
+
let temp = glob.sync('CMakeLists.txt', { absolute: true, cwd: basePath });
|
|
6
6
|
if (temp.length === 0) {
|
|
7
|
-
temp = glob.sync(
|
|
7
|
+
temp = glob.sync('*/CMakeLists.txt', { absolute: true, cwd: basePath, ignore: ['node_modules/*', 'dist/*', 'build/*'] });
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
if (temp.length > 0) return temp[0];
|
|
@@ -12,5 +12,5 @@ export default function findCMakeListsFile(basePath = process.cwd()) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function getCliCMakeListsFile() {
|
|
15
|
-
return getCliPath()
|
|
15
|
+
return `${getCliPath()}/assets/CMakeLists.txt`;
|
|
16
16
|
}
|
package/src/utils/getCliPath.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {dirname} from 'path';
|
|
2
1
|
import * as url from 'node:url';
|
|
3
2
|
|
|
4
|
-
const
|
|
5
|
-
const temp =
|
|
3
|
+
const filename = url.fileURLToPath(import.meta.url);
|
|
4
|
+
const temp = filename.split('/');
|
|
6
5
|
temp.pop();
|
|
7
6
|
temp.pop();
|
|
8
|
-
const
|
|
7
|
+
const dirname = temp.join('/');
|
|
9
8
|
|
|
10
9
|
export default function getCliPath() {
|
|
11
|
-
return
|
|
10
|
+
return dirname;
|
|
12
11
|
}
|
package/src/utils/getConfig.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import nodePath from 'path';
|
|
3
|
+
import * as url from 'node:url';
|
|
2
4
|
import createTempDir, { createDir } from './createTempDir.js';
|
|
3
5
|
import findCMakeListsFile from './findCMakeListsFile.js';
|
|
4
|
-
import p from 'path';
|
|
5
|
-
import * as url from 'node:url';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const temp =
|
|
9
|
-
const
|
|
7
|
+
const filename = url.fileURLToPath(import.meta.url);
|
|
8
|
+
const temp = filename.split('/'); temp.pop(); temp.pop();
|
|
9
|
+
const dirname = temp.join('/');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @typedef {Object} Config
|
|
@@ -41,28 +41,33 @@ const __dirname = temp.join('/');
|
|
|
41
41
|
* @property {string} name Project name
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
-
let
|
|
44
|
+
let tempConfigDefault = {
|
|
45
|
+
general: {}, dependencies: [], paths: {}, ext: {}, export: {}, platform: {},
|
|
46
|
+
};
|
|
45
47
|
await initDefaultConfigFile();
|
|
46
48
|
|
|
47
49
|
async function initDefaultConfigFile() {
|
|
48
50
|
let filePath;
|
|
49
|
-
['json', 'js', 'mjs', 'cjs', 'ts'].some(e => {
|
|
51
|
+
['json', 'js', 'mjs', 'cjs', 'ts'].some((e) => {
|
|
50
52
|
filePath = `${process.cwd()}/cppjs.config.${e}`;
|
|
51
|
-
if (!fs.existsSync(filePath))
|
|
52
|
-
|
|
53
|
+
if (!fs.existsSync(filePath)) {
|
|
54
|
+
filePath = null;
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
53
58
|
});
|
|
54
59
|
|
|
55
60
|
if (filePath) {
|
|
56
61
|
let file = await import(filePath);
|
|
57
62
|
if (file.default) file = file.default;
|
|
58
63
|
|
|
59
|
-
if (typeof file === 'function')
|
|
60
|
-
else if (typeof file ===
|
|
64
|
+
if (typeof file === 'function') tempConfigDefault = file();
|
|
65
|
+
else if (typeof file === 'object') tempConfigDefault = file;
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
export default function getConfig() {
|
|
65
|
-
return fillConfig(forceToConfigSchema(
|
|
70
|
+
return fillConfig(forceToConfigSchema(tempConfigDefault));
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
function forceToConfigSchema(tempConfig) {
|
|
@@ -72,6 +77,7 @@ function forceToConfigSchema(tempConfig) {
|
|
|
72
77
|
paths: tempConfig && tempConfig.paths ? tempConfig.paths : {},
|
|
73
78
|
ext: tempConfig && tempConfig.ext ? tempConfig.ext : {},
|
|
74
79
|
export: tempConfig && tempConfig.export ? tempConfig.export : {},
|
|
80
|
+
platform: tempConfig && tempConfig.platform ? tempConfig.platform : {},
|
|
75
81
|
};
|
|
76
82
|
return config;
|
|
77
83
|
}
|
|
@@ -80,48 +86,55 @@ function getAbsolutePath(projectPath, path) {
|
|
|
80
86
|
if (!path) {
|
|
81
87
|
return null;
|
|
82
88
|
}
|
|
83
|
-
if (
|
|
89
|
+
if (nodePath.isAbsolute(path)) {
|
|
84
90
|
return path;
|
|
85
91
|
}
|
|
86
92
|
if (projectPath) {
|
|
87
|
-
return
|
|
93
|
+
return nodePath.resolve(nodePath.join(nodePath.resolve(projectPath), path));
|
|
88
94
|
}
|
|
89
|
-
return
|
|
95
|
+
return nodePath.resolve(path);
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
function fillConfig(tempConfig, options = {}) {
|
|
93
99
|
const config = {
|
|
94
100
|
general: {},
|
|
95
|
-
dependencies: tempConfig.dependencies
|
|
101
|
+
dependencies: (tempConfig.dependencies || []).map((d) => fillConfig(forceToConfigSchema(d), { depend: true })),
|
|
96
102
|
paths: {
|
|
97
103
|
project: getAbsolutePath(null, tempConfig.paths.project) || process.cwd(),
|
|
98
104
|
},
|
|
99
105
|
ext: {},
|
|
100
106
|
export: {},
|
|
107
|
+
platform: {},
|
|
108
|
+
package: {},
|
|
101
109
|
};
|
|
102
110
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
if (file && typeof file === 'object' && file.name){
|
|
109
|
-
config.general.name = file.name;
|
|
110
|
-
}
|
|
111
|
+
const packageJsonPath = `${config.paths.project}/package.json`;
|
|
112
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
113
|
+
const file = JSON.parse(fs.readFileSync(packageJsonPath));
|
|
114
|
+
if (file && typeof file === 'object' && file.name) {
|
|
115
|
+
config.package = file;
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
118
|
|
|
119
|
+
if (tempConfig?.general?.name) {
|
|
120
|
+
config.general.name = tempConfig.general.name;
|
|
121
|
+
} else {
|
|
122
|
+
config.general.name = config.package.name || 'cppjssample';
|
|
123
|
+
}
|
|
124
|
+
|
|
114
125
|
const getPath = getAbsolutePath.bind(null, config.paths.project);
|
|
115
126
|
|
|
116
127
|
config.paths.base = getPath(tempConfig.paths.base) || config.paths.project;
|
|
117
|
-
config.paths.temp = getPath(tempConfig.paths.temp) || createTempDir(undefined, config.paths.project)
|
|
118
|
-
config.paths.native = (tempConfig.paths.native || ['src/native']).map(p => getPath(p));
|
|
119
|
-
config.paths.module = (tempConfig.paths.module || config.paths.native).map(p => getPath(p));
|
|
120
|
-
config.paths.header = (tempConfig.paths.header || config.paths.native).map(p => getPath(p));
|
|
121
|
-
config.paths.bridge = (tempConfig.paths.bridge || [...config.paths.native, config.paths.temp]).map(p => getPath(p));
|
|
128
|
+
config.paths.temp = getPath(tempConfig.paths.temp) || createTempDir(undefined, config.paths.project);
|
|
129
|
+
config.paths.native = (tempConfig.paths.native || ['src/native']).map((p) => getPath(p));
|
|
130
|
+
config.paths.module = (tempConfig.paths.module || config.paths.native).map((p) => getPath(p));
|
|
131
|
+
config.paths.header = (tempConfig.paths.header || config.paths.native).map((p) => getPath(p));
|
|
132
|
+
config.paths.bridge = (tempConfig.paths.bridge || [...config.paths.native, config.paths.temp]).map((p) => getPath(p));
|
|
122
133
|
config.paths.output = getPath(tempConfig.paths.output) || config.paths.temp;
|
|
123
|
-
config.paths.cmake = options.depend ? findCMakeListsFile(config.paths.output) :
|
|
124
|
-
|
|
134
|
+
config.paths.cmake = options.depend ? findCMakeListsFile(config.paths.output) : (
|
|
135
|
+
getPath(tempConfig.paths.cmake || findCMakeListsFile(config.paths.project))
|
|
136
|
+
);
|
|
137
|
+
config.paths.cli = dirname;
|
|
125
138
|
|
|
126
139
|
config.ext.header = tempConfig.ext.header || ['h', 'hpp', 'hxx', 'hh'];
|
|
127
140
|
config.ext.source = tempConfig.ext.source || ['c', 'cpp', 'cxx', 'cc'];
|
|
@@ -130,10 +143,28 @@ function fillConfig(tempConfig, options = {}) {
|
|
|
130
143
|
config.export.type = tempConfig.export.type || 'cmake';
|
|
131
144
|
config.export.header = tempConfig.export.header || 'include';
|
|
132
145
|
config.export.libPath = getPath(tempConfig.export.libPath || 'lib');
|
|
133
|
-
config.export.libName = tempConfig.export.libName || [
|
|
146
|
+
config.export.libName = tempConfig.export.libName || [config.general.name];
|
|
147
|
+
config.export.binHeaders = tempConfig.export.binHeaders || [];
|
|
148
|
+
config.export.entry = tempConfig.export.entry;
|
|
149
|
+
|
|
150
|
+
config.platform['Emscripten-x86_64'] = tempConfig.platform['Emscripten-x86_64'] || {};
|
|
151
|
+
config.platform['Emscripten-x86_64-browser'] = tempConfig.platform['Emscripten-x86_64-browser'] || {};
|
|
152
|
+
config.platform['Emscripten-x86_64-node'] = tempConfig.platform['Emscripten-x86_64-node'] || {};
|
|
153
|
+
config.platform['Android-arm64-v8a'] = tempConfig.platform['Android-arm64-v8a'] || {};
|
|
154
|
+
config.platform['iOS-iphoneos'] = tempConfig.platform['iOS-iphoneos'] || {};
|
|
155
|
+
config.platform['iOS-iphonesimulator'] = tempConfig.platform['iOS-iphonesimulator'] || {};
|
|
134
156
|
|
|
135
157
|
createDir('interface', config.paths.temp);
|
|
136
158
|
createDir('bridge', config.paths.temp);
|
|
137
159
|
|
|
160
|
+
// eslint-disable-next-line max-len
|
|
161
|
+
config.getAllDependencies = () => {
|
|
162
|
+
const output = {};
|
|
163
|
+
[...config.dependencies, ...config.dependencies.map((d) => d.getAllDependencies()).flat()].forEach((d) => {
|
|
164
|
+
output[d.paths.project] = d;
|
|
165
|
+
});
|
|
166
|
+
return Object.values(output);
|
|
167
|
+
};
|
|
168
|
+
|
|
138
169
|
return config;
|
|
139
170
|
}
|
package/src/utils/getDirName.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as url from 'node:url';
|
|
2
2
|
|
|
3
3
|
export default function getDirName(importUrl) {
|
|
4
|
-
const
|
|
5
|
-
const temp =
|
|
4
|
+
const filename = url.fileURLToPath(importUrl);
|
|
5
|
+
const temp = filename.split('/'); temp.pop();
|
|
6
6
|
return temp.join('/');
|
|
7
7
|
}
|