cpp.js 0.6.0 → 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.
@@ -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 "os";
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(), "cppjs-app-cli-test");
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', function () {
24
+ describe('createBridge', () => {
25
25
  let tempdir;
26
- before(async function () {
26
+ before(async () => {
27
27
  tempdir = createTempDir();
28
28
  });
29
29
 
30
- it('createBridge', async function () {
31
- const path = __dirname+'/test/data/sample.i';
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 "os";
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(), "cppjs-app-cli-test");
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', function () {
24
+ describe('findOrCreateInterfaceFile', () => {
25
25
  let tempdir;
26
- before(async function () {
26
+ before(async () => {
27
27
  tempdir = createTempDir();
28
28
  });
29
29
 
30
- it('find interface file', async function () {
31
- const path = __dirname+'/test/data/sample.h';
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 function () {
37
- const path = __dirname+'/test/data/sample2.h';
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+'/test/data/sample2.ei';
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 + '/test/data/', ''),
46
- interfaceFileData2.trim().replace(__dirname + '/test/data/', '')
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 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';
3
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) {
@@ -20,4 +27,37 @@ export default class CppjsCompiler {
20
27
  createWasm(options) {
21
28
  return createWasm(this, options);
22
29
  }
30
+
31
+ createLib() {
32
+ return createLib(this);
33
+ }
34
+
35
+ getCmakeParams() {
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;
54
+ }
23
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 = 'a'+Math.random(), base = process.cwd()) {
5
- const path = p.join(base, ".cppjs");
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("CMakeLists.txt", { absolute: true, cwd: basePath });
5
+ let temp = glob.sync('CMakeLists.txt', { absolute: true, cwd: basePath });
6
6
  if (temp.length === 0) {
7
- temp = glob.sync("*/CMakeLists.txt", { absolute: true, cwd: basePath, ignore: ['node_modules/*', 'dist/*', 'build/*'] });
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() + '/assets/CMakeLists.txt';
15
+ return `${getCliPath()}/assets/CMakeLists.txt`;
16
16
  }
@@ -1,12 +1,11 @@
1
- import {dirname} from 'path';
2
1
  import * as url from 'node:url';
3
2
 
4
- const __filename = url.fileURLToPath(import.meta.url);
5
- const temp = __filename.split('/');
3
+ const filename = url.fileURLToPath(import.meta.url);
4
+ const temp = filename.split('/');
6
5
  temp.pop();
7
6
  temp.pop();
8
- const __dirname = temp.join('/');
7
+ const dirname = temp.join('/');
9
8
 
10
9
  export default function getCliPath() {
11
- return __dirname;
10
+ return dirname;
12
11
  }
@@ -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 __filename = url.fileURLToPath(import.meta.url);
8
- const temp = __filename.split('/'); temp.pop(); temp.pop();
9
- const __dirname = temp.join('/');
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 tempConfig = { general: {}, dependencies: [], paths: {}, ext: {}, export: {} };
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)) filePath = null;
52
- else return true;
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') tempConfig = file();
60
- else if (typeof file === "object") tempConfig = 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(tempConfig));
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 (p.isAbsolute(path)) {
89
+ if (nodePath.isAbsolute(path)) {
84
90
  return path;
85
91
  }
86
92
  if (projectPath) {
87
- return p.resolve(p.join(p.resolve(projectPath), path));
93
+ return nodePath.resolve(nodePath.join(nodePath.resolve(projectPath), path));
88
94
  }
89
- return p.resolve(path);
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 ? tempConfig.dependencies.map(d => fillConfig(forceToConfigSchema(d), { depend: true })) : [],
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
- if (!config.general.name) {
104
- config.general.name = 'cppjssample';
105
- const packageJsonPath = `${config.paths.project}/package.json`;
106
- if (fs.existsSync(packageJsonPath)) {
107
- const file = JSON.parse(fs.readFileSync(packageJsonPath));
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) : getPath(tempConfig.paths.cmake || findCMakeListsFile(config.paths.project));
124
- config.paths.cli = __dirname;
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 || [`lib${config.general.name}.a`];
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
  }
@@ -1,7 +1,7 @@
1
1
  import * as url from 'node:url';
2
2
 
3
3
  export default function getDirName(importUrl) {
4
- const __filename = url.fileURLToPath(importUrl);
5
- const temp = __filename.split('/'); temp.pop();
4
+ const filename = url.fileURLToPath(importUrl);
5
+ const temp = filename.split('/'); temp.pop();
6
6
  return temp.join('/');
7
7
  }
@@ -1,4 +1,4 @@
1
- import os from "os";
1
+ import os from 'os';
2
2
 
3
3
  let osUserAndGroupId;
4
4
  export default function getOsUserAndGroupId() {
@@ -1,8 +1,6 @@
1
1
  import p from 'path';
2
2
 
3
3
  export default function getPathInfo(path, base) {
4
- let basePath = base;
5
-
6
4
  const output = {
7
5
  relative: p.relative(base, path),
8
6
  absolute: path,