cpp.js 1.0.0-beta.2 → 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 +104 -0
- package/package.json +25 -6
- package/src/{functions/buildJS.js → actions/buildJs.js} +7 -5
- package/src/actions/buildWasm.js +68 -0
- package/src/actions/createInterface.js +127 -0
- package/src/actions/createLib.js +103 -0
- package/src/actions/createXCFramework.js +40 -0
- package/src/actions/getAllBridges.js +8 -0
- package/src/actions/getCmakeParameters.js +50 -0
- package/src/actions/getData.js +28 -0
- package/src/actions/getDependLibs.js +19 -0
- package/src/{functions → actions}/run.js +77 -40
- package/src/assets/CMakeLists.txt +13 -9
- package/src/assets/ios.toolchain.cmake +4 -4
- package/src/bin.js +147 -72
- package/src/export/react-native.js +51 -0
- package/src/export/web.js +42 -0
- package/src/index.js +13 -63
- package/src/state/calculateDependencyParameters.js +64 -0
- package/src/state/index.js +81 -0
- package/src/state/loadConfig.js +96 -0
- package/src/utils/downloadAndExtractFile.js +36 -0
- package/src/utils/fixPackageName.js +7 -0
- package/src/utils/getAbsolutePath.js +14 -0
- package/src/utils/{findCMakeListsFile.js → getCMakeListsFilePath.js} +4 -3
- package/src/utils/getOsUserAndGroupId.js +2 -1
- package/src/utils/getParentPath.js +12 -0
- package/src/utils/hash.js +20 -0
- package/src/utils/loadJs.js +32 -0
- package/src/utils/loadJson.js +16 -0
- package/src/utils/writeJson.js +9 -0
- package/.mocharc.yaml +0 -3
- package/src/functions/createBridge.js +0 -37
- package/src/functions/createLib.js +0 -44
- package/src/functions/createWasm.js +0 -71
- package/src/functions/findOrCreateInterfaceFile.js +0 -68
- package/src/functions/finishBuild.js +0 -43
- package/src/functions/getCmakeParams.js +0 -106
- package/src/functions/getData.js +0 -36
- package/src/functions/getLibs.js +0 -33
- package/src/functions/specs/createBridge.spec.js +0 -51
- package/src/functions/specs/findOrCreateInterfaceFile.spec.js +0 -49
- package/src/utils/createTempDir.js +0 -15
- package/src/utils/getBaseInfo.js +0 -15
- package/src/utils/getCliPath.js +0 -11
- package/src/utils/getConfig.js +0 -170
- package/src/utils/getDirName.js +0 -7
- package/src/utils/getPathInfo.js +0 -10
- package/src/utils/specs/findCMakeListsFile.spec.js +0 -34
- package/src/utils/specs/utils.spec.js +0 -81
- package/test/data/sample.cpp +0 -1
- package/test/data/sample.h +0 -10
- package/test/data/sample.i +0 -12
- package/test/data/sample2.cpp +0 -0
- package/test/data/sample2.ei +0 -12
- package/test/data/sample2.h +0 -10
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
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
|
|
6
|
-
import getPathInfo from '../utils/getPathInfo.js';
|
|
5
|
+
import state from '../state/index.js';
|
|
7
6
|
|
|
8
7
|
const CROSSCOMPILER = 'aarch64-linux-android33';
|
|
9
8
|
const ANDROID_NDK = '/opt/android-sdk/ndk/25.2.9519653';
|
|
@@ -66,22 +65,17 @@ const iosParams = [
|
|
|
66
65
|
'-e', `LDFLAGS="${IOS_HOST_FLAGS}"`,
|
|
67
66
|
]; */
|
|
68
67
|
|
|
69
|
-
function
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
68
|
+
export default function run(program, params = [], platformPrefix = null, platform = null, dockerOptions = {}) {
|
|
69
|
+
const buildPath = platformPrefix ? `${state.config.paths.build}/${platformPrefix}/${platform}` : state.config.paths.build;
|
|
70
|
+
if (!fs.existsSync(buildPath)) {
|
|
71
|
+
fs.mkdirSync(buildPath, { recursive: true });
|
|
72
|
+
}
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
const [basePlatform, ...arch] = (compiler.platform || 'unknown-unknown').split('-'); // Emscripten-x86_64, Android-arm64-v8a, iOS-iphoneos, iOS-iphonesimulator
|
|
74
|
+
const [basePlatform, ...arch] = (platform || 'unknown-unknown').split('-'); // Emscripten-x86_64, Android-arm64-v8a, iOS-iphoneos, iOS-iphonesimulator
|
|
77
75
|
if (basePlatform !== 'iOS' || program !== null) {
|
|
78
76
|
pullDockerImage();
|
|
79
77
|
}
|
|
80
78
|
|
|
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
79
|
let dProgram = program;
|
|
86
80
|
let dParams = params;
|
|
87
81
|
let platformParams = [];
|
|
@@ -118,14 +112,14 @@ export default function run(compiler, program, params = [], dockerOptions = {})
|
|
|
118
112
|
'-DFRAMEWORK=TRUE',
|
|
119
113
|
'-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0',
|
|
120
114
|
'-DCMAKE_SYSTEM_NAME=iOS',
|
|
121
|
-
`-DMACOSX_FRAMEWORK_IDENTIFIER=org.js.cpp.${
|
|
122
|
-
`-DCMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER=org.js.cpp.${
|
|
115
|
+
`-DMACOSX_FRAMEWORK_IDENTIFIER=org.js.cpp.${state.config.general.name}`,
|
|
116
|
+
`-DCMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER=org.js.cpp.${state.config.general.name}`,
|
|
123
117
|
`-DCMAKE_OSX_SYSROOT='${arch[0] === 'iphoneos' ? iosSdkPath : iosSimSdkPath}'`,
|
|
124
118
|
`-DCMAKE_OSX_ARCHITECTURES=${arch[0] === 'iphoneos' ? 'arm64;arm64e' : 'arm64;arm64e;x86_64'}`,
|
|
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') {
|
|
@@ -134,7 +128,7 @@ export default function run(compiler, program, params = [], dockerOptions = {})
|
|
|
134
128
|
if (dParams[0] !== '--build' && dParams[0] !== '--install') {
|
|
135
129
|
dParams = [
|
|
136
130
|
...dParams,
|
|
137
|
-
`-DCMAKE_TOOLCHAIN_FILE='${
|
|
131
|
+
`-DCMAKE_TOOLCHAIN_FILE='${state.config.paths.cli}/assets/ios.toolchain.cmake'`,
|
|
138
132
|
`-DPLATFORM=${arch[0] === 'iphoneos' ? 'OS64' : 'SIMULATORARM64'}`,
|
|
139
133
|
`-DARCHS=${arch[0] === 'iphoneos' ? 'arm64;arm64e' : 'arm64;arm64e;x86_64'}`,
|
|
140
134
|
'-DENABLE_BITCODE=TRUE',
|
|
@@ -142,14 +136,14 @@ export default function run(compiler, program, params = [], dockerOptions = {})
|
|
|
142
136
|
'-DFRAMEWORK=TRUE',
|
|
143
137
|
'-DCMAKE_OSX_DEPLOYMENT_TARGET=13.0',
|
|
144
138
|
'-DCMAKE_SYSTEM_NAME=iOS',
|
|
145
|
-
`-DMACOSX_FRAMEWORK_IDENTIFIER=org.js.cpp.${
|
|
146
|
-
`-DCMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER=org.js.cpp.${
|
|
139
|
+
`-DMACOSX_FRAMEWORK_IDENTIFIER=org.js.cpp.${state.config.general.name}`,
|
|
140
|
+
`-DCMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER=org.js.cpp.${state.config.general.name}`,
|
|
147
141
|
`-DCMAKE_OSX_SYSROOT='${arch[0] === 'iphoneos' ? iosSdkPath : iosSimSdkPath}'`,
|
|
148
142
|
`-DCMAKE_OSX_ARCHITECTURES=${arch[0] === 'iphoneos' ? 'arm64;arm64e' : 'arm64;arm64e;x86_64'}`,
|
|
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(compiler, program, params = [], dockerOptions = {})
|
|
|
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);
|
|
@@ -189,32 +183,75 @@ export default function run(compiler, program, params = [], dockerOptions = {})
|
|
|
189
183
|
env.PATH = `/opt/homebrew/bin:${env.PATH}`;
|
|
190
184
|
|
|
191
185
|
const options = {
|
|
192
|
-
cwd: dockerOptions.workdir ||
|
|
193
|
-
stdio: dockerOptions.console ? 'inherit' : '
|
|
186
|
+
cwd: dockerOptions.workdir || buildPath,
|
|
187
|
+
stdio: dockerOptions.console ? 'inherit' : 'ignore',
|
|
194
188
|
env,
|
|
195
189
|
};
|
|
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
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);
|
|
204
202
|
} else {
|
|
205
|
-
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' };
|
|
206
227
|
const args = [
|
|
207
228
|
'run',
|
|
229
|
+
'--rm',
|
|
208
230
|
'--user', getOsUserAndGroupId(),
|
|
209
|
-
'-v', `${base
|
|
210
|
-
'
|
|
211
|
-
|
|
212
|
-
'
|
|
213
|
-
...platformParams,
|
|
214
|
-
...(dockerOptions.params || []),
|
|
231
|
+
'-v', `${state.config.paths.base}:/tmp/cppjs/live`,
|
|
232
|
+
'--workdir', replaceBasePathForDocker(dockerOptions.workdir || buildPath),
|
|
233
|
+
...replaceBasePathForDocker(dockerEnv),
|
|
234
|
+
// '-e', replaceBasePathForDocker(`CCACHE_DIR=${state.config.paths.build}/ccache`),
|
|
215
235
|
getDockerImage(),
|
|
216
|
-
dProgram,
|
|
236
|
+
replaceBasePathForDocker(dProgram),
|
|
237
|
+
...replaceBasePathForDocker(dParams),
|
|
217
238
|
];
|
|
218
239
|
execFileSync('docker', args, options);
|
|
219
240
|
}
|
|
220
241
|
}
|
|
242
|
+
|
|
243
|
+
function replaceBasePathForDocker(data) {
|
|
244
|
+
if (typeof data === 'string' || data instanceof String) {
|
|
245
|
+
return data.replaceAll(state.config.paths.base, '/tmp/cppjs/live');
|
|
246
|
+
}
|
|
247
|
+
if (Array.isArray(data)) {
|
|
248
|
+
return data.map((d) => replaceBasePathForDocker(d));
|
|
249
|
+
}
|
|
250
|
+
if (typeof value === 'object' && data !== null) {
|
|
251
|
+
const newData = {};
|
|
252
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
253
|
+
newData[key] = replaceBasePathForDocker(value);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return data;
|
|
257
|
+
}
|
|
@@ -29,7 +29,9 @@ if (BUILD_BRIDGE)
|
|
|
29
29
|
file(GLOB BRIDGE_SRC_FILES "${BRIDGE_DIR}/*.i.cpp")
|
|
30
30
|
endif(BUILD_BRIDGE)
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
file(GLOB_RECURSE EXTERNAL_SRC_FILES ${EXTERNAL_NATIVE_GLOB})
|
|
33
|
+
|
|
34
|
+
set(SRC_FILES "${BUILD_SRC_FILES}" "${BRIDGE_SRC_FILES}" "${EXTERNAL_SRC_FILES}")
|
|
33
35
|
add_library("${PROJECT_NAME}" "${BUILD_TYPE}" ${SRC_FILES})
|
|
34
36
|
|
|
35
37
|
set(EXTRA_LINK_LIBRARIES "")
|
|
@@ -44,15 +46,17 @@ endif()
|
|
|
44
46
|
file(GLOB_RECURSE HEADER_FILES ${HEADER_GLOB})
|
|
45
47
|
target_include_directories("${PROJECT_NAME}" PUBLIC "${HEADER_DIR}")
|
|
46
48
|
|
|
49
|
+
install(TARGETS "${PROJECT_NAME}" DESTINATION "lib")
|
|
50
|
+
if(NOT "${HEADER_FILES}" STREQUAL "")
|
|
51
|
+
target_sources("${PROJECT_NAME}"
|
|
52
|
+
PUBLIC FILE_SET HEADERS
|
|
53
|
+
BASE_DIRS "${HEADER_DIR}"
|
|
54
|
+
FILES "${HEADER_FILES}")
|
|
55
|
+
install(TARGETS "${PROJECT_NAME}" FILE_SET HEADERS DESTINATION "include")
|
|
56
|
+
endif()
|
|
57
|
+
|
|
47
58
|
if (BUILD_SOURCE)
|
|
48
|
-
|
|
49
|
-
if(NOT "${HEADER_FILES}" STREQUAL "")
|
|
50
|
-
target_sources("${PROJECT_NAME}"
|
|
51
|
-
PUBLIC FILE_SET HEADERS
|
|
52
|
-
BASE_DIRS "${HEADER_DIR}"
|
|
53
|
-
FILES "${HEADER_FILES}")
|
|
54
|
-
install(TARGETS "${PROJECT_NAME}" FILE_SET HEADERS DESTINATION "include")
|
|
55
|
-
endif()
|
|
59
|
+
|
|
56
60
|
endif(BUILD_SOURCE)
|
|
57
61
|
unset(BUILD_SOURCE CACHE)
|
|
58
62
|
|
|
@@ -168,7 +168,7 @@ list(APPEND _supported_platforms
|
|
|
168
168
|
"TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" "SIMULATORARM64_TVOS"
|
|
169
169
|
"WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" "SIMULATORARM64_WATCHOS"
|
|
170
170
|
"MAC" "MAC_ARM64" "MAC_UNIVERSAL"
|
|
171
|
-
"VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED"
|
|
171
|
+
"VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED"
|
|
172
172
|
"MAC_CATALYST" "MAC_CATALYST_ARM64" "MAC_CATALYST_UNIVERSAL")
|
|
173
173
|
|
|
174
174
|
# Cache what generator is used
|
|
@@ -316,7 +316,7 @@ if(PLATFORM_INT STREQUAL "OS")
|
|
|
316
316
|
set(ARCHS armv7 armv7s arm64)
|
|
317
317
|
set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET})
|
|
318
318
|
else()
|
|
319
|
-
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})
|
|
319
|
+
set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET})
|
|
320
320
|
endif()
|
|
321
321
|
elseif(PLATFORM_INT STREQUAL "OS64")
|
|
322
322
|
set(SDK_NAME iphoneos)
|
|
@@ -1049,7 +1049,7 @@ set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
|
|
1049
1049
|
)
|
|
1050
1050
|
|
|
1051
1051
|
if(NAMED_LANGUAGE_SUPPORT_INT)
|
|
1052
|
-
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
|
1052
|
+
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
|
1053
1053
|
CMAKE_OBJC_FLAGS
|
|
1054
1054
|
CMAKE_OBJC_DEBUG
|
|
1055
1055
|
CMAKE_OBJC_MINSIZEREL
|
|
@@ -1087,7 +1087,7 @@ IF(NOT DEFINED CMAKE_FIND_FRAMEWORK)
|
|
|
1087
1087
|
ENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK)
|
|
1088
1088
|
|
|
1089
1089
|
# Set up the default search directories for frameworks.
|
|
1090
|
-
if(PLATFORM_INT MATCHES "^MAC_CATALYST")
|
|
1090
|
+
if(PLATFORM_INT MATCHES "^MAC_CATALYST")
|
|
1091
1091
|
set(CMAKE_FRAMEWORK_PATH
|
|
1092
1092
|
${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks
|
|
1093
1093
|
${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks
|
package/src/bin.js
CHANGED
|
@@ -1,30 +1,46 @@
|
|
|
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
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import
|
|
6
|
+
import upath from 'upath';
|
|
7
|
+
import replace from 'replace';
|
|
8
|
+
|
|
9
|
+
import { state } from './index.js';
|
|
10
|
+
import createBridgeFile from './actions/createInterface.js';
|
|
11
|
+
import createLib from './actions/createLib.js';
|
|
12
|
+
import buildWasm from './actions/buildWasm.js';
|
|
13
|
+
import createXCFramework from './actions/createXCFramework.js';
|
|
14
|
+
import runCppjsApp from './actions/run.js';
|
|
15
|
+
import downloadAndExtractFile from './utils/downloadAndExtractFile.js';
|
|
16
|
+
import writeJson from './utils/writeJson.js';
|
|
10
17
|
|
|
11
18
|
const packageJSON = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url)));
|
|
12
19
|
|
|
13
20
|
const program = new Command();
|
|
14
21
|
|
|
15
22
|
program
|
|
16
|
-
.name('
|
|
23
|
+
.name('cppjs')
|
|
17
24
|
.description('Compile C++ files to WebAssembly and native platforms.')
|
|
18
25
|
.version(packageJSON.version)
|
|
19
26
|
.showHelpAfterError();
|
|
20
27
|
|
|
21
28
|
const commandBuild = program.command('build')
|
|
22
29
|
.description('compile the project that was set up using Cpp.js')
|
|
23
|
-
.addOption(new Option('-p, --platform <platform>', 'target platform').default('
|
|
30
|
+
.addOption(new Option('-p, --platform <platform>', 'target platform').default('All').choices(['All', 'WebAssembly', 'Android', 'iOS']));
|
|
24
31
|
|
|
25
32
|
const commandRun = program.command('run')
|
|
26
33
|
.description('run docker application');
|
|
27
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
|
+
|
|
28
44
|
const commandPostInstall = program.command('postinstall')
|
|
29
45
|
.description('prepare the required packages for Cpp.js after installation');
|
|
30
46
|
|
|
@@ -33,7 +49,11 @@ program.parse(process.argv);
|
|
|
33
49
|
switch (program.args[0]) {
|
|
34
50
|
case 'build': {
|
|
35
51
|
const { platform } = commandBuild.opts();
|
|
36
|
-
build
|
|
52
|
+
if (state.config.build) {
|
|
53
|
+
buildExternal(platform);
|
|
54
|
+
} else {
|
|
55
|
+
build(platform);
|
|
56
|
+
}
|
|
37
57
|
break;
|
|
38
58
|
}
|
|
39
59
|
case 'run': {
|
|
@@ -41,6 +61,25 @@ switch (program.args[0]) {
|
|
|
41
61
|
run(programName, params);
|
|
42
62
|
break;
|
|
43
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
|
+
}
|
|
44
83
|
case 'postinstall': {
|
|
45
84
|
postInstall();
|
|
46
85
|
break;
|
|
@@ -49,6 +88,37 @@ switch (program.args[0]) {
|
|
|
49
88
|
break;
|
|
50
89
|
}
|
|
51
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
|
+
|
|
52
122
|
function postInstall() {
|
|
53
123
|
const projectPath = process.env.PWD;
|
|
54
124
|
const isDarwin = process.platform === 'darwin';
|
|
@@ -63,16 +133,15 @@ function postInstall() {
|
|
|
63
133
|
return;
|
|
64
134
|
}
|
|
65
135
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
dist = dist ? getPathInfo(dist, projectPath).relative : null;
|
|
136
|
+
const name = state?.config?.general?.name;
|
|
137
|
+
let dist = state?.config?.paths?.output;
|
|
138
|
+
dist = dist ? upath.relative(projectPath, dist) : null;
|
|
70
139
|
|
|
71
140
|
if (!name || !dist) {
|
|
72
141
|
return;
|
|
73
142
|
}
|
|
74
143
|
|
|
75
|
-
|
|
144
|
+
state?.config?.export?.libName?.forEach((fileName) => {
|
|
76
145
|
if (fs.existsSync(`${projectPath}/${fileName}.xcframework`) || !fs.existsSync(`${dist}/prebuilt/${fileName}.xcframework`)) {
|
|
77
146
|
return;
|
|
78
147
|
}
|
|
@@ -81,87 +150,93 @@ function postInstall() {
|
|
|
81
150
|
}
|
|
82
151
|
|
|
83
152
|
function run(programName, params) {
|
|
84
|
-
|
|
85
|
-
compiler.run(programName, params, { console: true });
|
|
153
|
+
runCppjsApp(programName, params, null, null, { console: true });
|
|
86
154
|
}
|
|
87
155
|
|
|
88
|
-
function
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
modules.push(...glob.sync('*.i', { absolute: true, cwd: modulePath }));
|
|
95
|
-
});
|
|
156
|
+
async function buildExternal(platform) {
|
|
157
|
+
const version = state.config.package.nativeVersion;
|
|
158
|
+
if (!version) {
|
|
159
|
+
console.error('no version found!');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
96
162
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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,
|
|
104
170
|
});
|
|
105
|
-
}
|
|
171
|
+
});
|
|
106
172
|
}
|
|
107
173
|
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
+
|
|
183
|
+
async function build(platform) {
|
|
184
|
+
buildLib(platform);
|
|
185
|
+
if (platform === 'WebAssembly' || platform === 'All') {
|
|
186
|
+
createWasmJs();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function buildLib(platform) {
|
|
191
|
+
state.platforms[platform].forEach((p) => {
|
|
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.`);
|
|
123
196
|
}
|
|
124
197
|
});
|
|
125
|
-
if (platform === 'all' || platform === 'ios') {
|
|
126
|
-
compiler2.finishBuild();
|
|
127
|
-
}
|
|
128
198
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
199
|
+
fs.cpSync(`${state.config.paths.build}/Source-Release/prebuilt`, `${state.config.paths.output}/prebuilt`, { recursive: true, dereference: true });
|
|
200
|
+
|
|
201
|
+
createXCFramework();
|
|
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);
|
|
132
206
|
}
|
|
133
207
|
|
|
134
|
-
async function
|
|
208
|
+
async function createWasmJs() {
|
|
135
209
|
let headers = [];
|
|
136
|
-
|
|
137
|
-
const compiler = new CppjsCompiler();
|
|
138
|
-
compiler.config.paths.header.forEach((headerPath) => {
|
|
210
|
+
state.config.paths.header.forEach((headerPath) => {
|
|
139
211
|
headers.push(glob.sync('**/*.h', { absolute: true, cwd: headerPath }));
|
|
140
212
|
});
|
|
141
213
|
headers = headers.filter((path) => !!path.toString()).flat();
|
|
142
214
|
|
|
215
|
+
const bridges = [];
|
|
143
216
|
headers.forEach((header) => {
|
|
144
|
-
|
|
217
|
+
const bridgePath = createBridgeFile(header);
|
|
218
|
+
bridges.push(bridgePath);
|
|
145
219
|
});
|
|
146
220
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
221
|
+
const opt = {
|
|
222
|
+
isProd: true,
|
|
223
|
+
buildSource: false,
|
|
224
|
+
nativeGlob: bridges,
|
|
225
|
+
};
|
|
226
|
+
createLib('Emscripten-x86_64', 'Bridge', opt);
|
|
150
227
|
|
|
151
|
-
|
|
152
|
-
|
|
228
|
+
await buildWasm('browser', true);
|
|
229
|
+
await buildWasm('node', true);
|
|
153
230
|
|
|
154
|
-
fs.rmSync(`${
|
|
155
|
-
if (fs.existsSync(`${
|
|
156
|
-
fs.renameSync(`${
|
|
231
|
+
fs.rmSync(`${state.config.paths.output}/data`, { recursive: true, force: true });
|
|
232
|
+
if (fs.existsSync(`${state.config.paths.build}/data`)) {
|
|
233
|
+
fs.renameSync(`${state.config.paths.build}/data`, `${state.config.paths.output}/data`);
|
|
157
234
|
}
|
|
158
235
|
|
|
159
|
-
fs.copyFileSync(`${
|
|
160
|
-
fs.copyFileSync(`${
|
|
161
|
-
fs.copyFileSync(`${
|
|
162
|
-
if (fs.existsSync(`${
|
|
163
|
-
fs.copyFileSync(`${
|
|
236
|
+
fs.copyFileSync(`${state.config.paths.build}/${state.config.general.name}.node.js`, `${state.config.paths.output}/${state.config.general.name}.node.js`);
|
|
237
|
+
fs.copyFileSync(`${state.config.paths.build}/${state.config.general.name}.browser.js`, `${state.config.paths.output}/${state.config.general.name}.browser.js`);
|
|
238
|
+
fs.copyFileSync(`${state.config.paths.build}/${state.config.general.name}.wasm`, `${state.config.paths.output}/${state.config.general.name}.wasm`);
|
|
239
|
+
if (fs.existsSync(`${state.config.paths.build}/${state.config.general.name}.data.txt`)) {
|
|
240
|
+
fs.copyFileSync(`${state.config.paths.build}/${state.config.general.name}.data.txt`, `${state.config.paths.output}/${state.config.general.name}.data.txt`);
|
|
164
241
|
}
|
|
165
|
-
|
|
166
|
-
fs.rmSync(compiler.config.paths.temp, { recursive: true, force: true });
|
|
167
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
|
+
}
|