cpp.js 2.0.0-beta.2 → 2.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cpp.js",
3
- "version": "2.0.0-beta.2",
3
+ "version": "2.0.0-beta.4",
4
4
  "license": "MIT",
5
5
  "homepage": "https://cpp.js.org",
6
6
  "repository": "https://github.com/bugra9/cpp.js.git",
@@ -1,5 +1,5 @@
1
- /* eslint-disable no-await-in-loop */
2
- /* eslint-disable no-restricted-syntax */
1
+
2
+
3
3
  import { rollup } from 'rollup';
4
4
  import { nodeResolve } from '@rollup/plugin-node-resolve';
5
5
  import commonjs from '@rollup/plugin-commonjs';
@@ -21,7 +21,6 @@ const options = {
21
21
  browser: {
22
22
  plugins: [virtual(nodeLibs), nodeResolve(), commonjs({ transformMixedEsModules: true, ignoreTryCatch: 'remove' })],
23
23
  output: {
24
- file: 'browser',
25
24
  format: 'umd',
26
25
  name: 'initCppJs',
27
26
  },
@@ -29,38 +28,33 @@ const options = {
29
28
  node: {
30
29
  plugins: [nodeResolve(), commonjs()],
31
30
  output: {
32
- file: 'node',
33
31
  format: 'umd',
34
32
  name: 'initCppJs',
35
33
  },
36
34
  },
37
35
  };
38
36
 
39
- export default async function buildJS(input, type) {
40
- const entryJS = `${state.config.paths.cli}/assets/${type}.js`;
41
- const env = JSON.stringify(getData('env', 'Emscripten-x86_64', type));
37
+ export default async function buildJS(target) {
38
+ const entryJS = `${state.config.paths.cli}/assets/${target.runtimeEnv}.js`;
39
+ const env = JSON.stringify(getData('env', target));
42
40
  const systemConfig = `export default {
43
41
  env: ${env},
44
42
  paths: {
45
- wasm: '${state.config.general.name}.wasm',
46
- data: '${state.config.general.name}.data.txt',
47
- worker: '${state.config.general.name}.js',
43
+ wasm: '${target.wasmName}',
44
+ data: '${target.dataTxtName}',
45
+ worker: '${target.rawJsName}',
48
46
  }
49
47
  }`;
50
- let file = input;
51
- if (input.endsWith('.js')) {
52
- file = input.substring(0, input.length - 3);
53
- }
48
+
54
49
  // fs.renameSync(input, `${input}.raw.js`);
55
- const option = options[type];
50
+ const option = options[target.runtimeEnv];
56
51
  option.plugins = [virtual({
57
52
  'cpp.js/systemConfig': systemConfig,
58
- 'cpp.js/module': `export { default } from '${input}';`,
53
+ 'cpp.js/module': `export { default } from '${state.config.paths.build}/${target.rawJsName}';`,
59
54
  }), ...option.plugins];
60
55
  option.input = entryJS;
61
- option.output.file = `${file}.${option.output.file}.js`;
56
+ option.output.file = `${state.config.paths.build}/${target.jsName}`;
62
57
  const bundle = await rollup(option);
63
58
  await bundle.write(option.output);
64
59
  // fs.rmSync(`${input}.raw.js`, { force: true });
65
60
  }
66
- //
@@ -7,32 +7,46 @@ import buildJs from './buildJs.js';
7
7
  import triggerExtensions from './extensions.js';
8
8
  import state from '../state/index.js';
9
9
 
10
- export default async function buildWasm(type, isProd = false) {
10
+ export default async function buildWasm(target) {
11
+ const isProd = target.buildType === 'release';
11
12
  const buildType = isProd ? 'Release' : 'Debug';
13
+
14
+ if (fs.existsSync(`${state.config.paths.build}/${target.jsName}`) && fs.existsSync(`${state.config.paths.build}/${target.wasmName}`)) {
15
+ console.log(`${target.path} ${target.runtimeEnv || ''} wasm is already built`);
16
+ return;
17
+ }
18
+
12
19
  const libs = [
13
- ...getDependLibs(),
14
- `${state.config.paths.build}/Source-${buildType}/Emscripten-x86_64/lib${state.config.general.name}.a`,
15
- `${state.config.paths.build}/Bridge-${buildType}/Emscripten-x86_64/lib${state.config.general.name}.a`,
20
+ ...getDependLibs(target),
21
+ `${state.config.paths.build}/Source-${buildType}/${target.path}/lib${state.config.general.name}.a`,
22
+ `${state.config.paths.build}/Bridge-${buildType}/${target.path}/lib${state.config.general.name}.a`,
16
23
  ];
17
24
 
18
- const binary = getData('binary', 'Emscripten-x86_64');
25
+ const binary = getData('binary', target);
26
+ const emccFlags = binary?.emccFlags || [];
27
+
28
+ triggerExtensions('buildWasm', 'beforeBuild', [emccFlags]);
29
+
30
+ if (target.runtime === 'mt' && !emccFlags.includes('-pthread')) {
31
+ emccFlags.push('-pthread');
32
+ emccFlags.push('-sPTHREAD_POOL_SIZE=4');
33
+ }
34
+
35
+ if (target.platform === 'wasm') {
36
+ emccFlags.push('-msimd128');
37
+ }
19
38
 
20
- if (type === 'browser') {
39
+ if (target.arch === 'wasm64') {
40
+ emccFlags.push('-sMEMORY64=1');
41
+ }
42
+
43
+ if (target.runtimeEnv === 'browser') {
21
44
  console.log('wasm compiling for browser...');
22
45
  const t0 = performance.now();
23
- const emccFlags = [
24
- ...(binary?.emccFlags || []),
25
- ...(getData('binary', 'Emscripten-x86_64', 'browser')?.emccFlags || []),
26
- ];
27
46
 
28
47
  triggerExtensions('buildWasm', 'beforeBuildBrowser', [emccFlags]);
29
48
 
30
- if (state.config.build.usePthread && !emccFlags.includes('-pthread')) {
31
- emccFlags.push('-pthread');
32
- emccFlags.push('-sPTHREAD_POOL_SIZE=4');
33
- }
34
-
35
- const data = Object.entries(getData('data', 'Emscripten-x86_64', 'browser')).map(([key, value]) => ['--preload-file', `${key.replaceAll('@', '@@')}@${value}`]).flat();
49
+ const data = Object.entries(getData('data', target)).map(([key, value]) => ['--preload-file', `${key.replaceAll('@', '@@')}@/cppjs/${value}`]).flat();
36
50
  run('emcc', [
37
51
  '-lembind', '-Wl,--whole-archive',
38
52
  ...emccFlags,
@@ -45,16 +59,16 @@ export default async function buildWasm(type, isProd = false) {
45
59
  // '-s', 'ALLOW_MEMORY_GROWTH=1',
46
60
  '-s', 'EXPORTED_RUNTIME_METHODS=["FS", "ENV"]',
47
61
  '-fwasm-exceptions',
48
- '-o', `${state.config.paths.build}/${state.config.general.name}.js`,
62
+ '-o', `${state.config.paths.build}/${target.rawJsName}`,
49
63
  ...data,
50
- ]);
64
+ ], null, target);
51
65
  const t1 = performance.now();
52
66
  console.log('wasm compiled for browser...', Math.round(t1 - t0));
53
67
  console.log('js compiling for browser...');
54
68
  replace({
55
69
  regex: 'var _scriptName = ',
56
70
  replacement: `var _scriptName = 'cpp.worker.js'; //`,
57
- paths: [`${state.config.paths.build}/${state.config.general.name}.js`],
71
+ paths: [`${state.config.paths.build}/${target.rawJsName}`],
58
72
  recursive: false,
59
73
  silent: true,
60
74
  });
@@ -65,7 +79,7 @@ export default async function buildWasm(type, isProd = false) {
65
79
  recursive: false,
66
80
  silent: true,
67
81
  }); */
68
- await buildJs(`${state.config.paths.build}/${state.config.general.name}.js`, 'browser');
82
+ await buildJs(target);
69
83
  // fs.rmSync(`${state.config.paths.build}/${state.config.general.name}.js`);
70
84
  // fs.copyFileSync(`${state.config.paths.build}/${state.config.general.name}.browser.js`, `${state.config.paths.build}/${state.config.general.name}.js`);
71
85
  // fs.renameSync(`${state.config.paths.build}/${state.config.general.name}.js`, `${state.config.paths.build}/${state.config.general.name}.worker.browser.js`);
@@ -73,20 +87,11 @@ export default async function buildWasm(type, isProd = false) {
73
87
  console.log('js compiled for browser...', Math.round(t2 - t1));
74
88
  }
75
89
 
76
- if (type === 'node') {
90
+ if (target.runtimeEnv === 'node') {
77
91
  console.log('wasm compiling for node...');
78
- const emccFlags = [
79
- ...(binary?.emccFlags || []),
80
- ...(getData('binary', 'Emscripten-x86_64', 'node')?.emccFlags || []),
81
- ];
82
92
 
83
93
  triggerExtensions('buildWasm', 'beforeBuildNodeJS', [emccFlags]);
84
94
 
85
- if (state.config.build.usePthread && !emccFlags.includes('-pthread')) {
86
- emccFlags.push('-pthread');
87
- emccFlags.push('-sPTHREAD_POOL_SIZE=4');
88
- }
89
-
90
95
  run('emcc', [
91
96
  '-lembind', '-Wl,--whole-archive', '-lnodefs.js',
92
97
  ...emccFlags,
@@ -99,18 +104,18 @@ export default async function buildWasm(type, isProd = false) {
99
104
  '-s', 'NODERAWFS',
100
105
  '-s', 'EXPORTED_RUNTIME_METHODS=["FS", "ENV", "NODEFS"]',
101
106
  '-fwasm-exceptions',
102
- '-o', `${state.config.paths.build}/${state.config.general.name}.js`,
103
- ]);
107
+ '-o', `${state.config.paths.build}/${target.rawJsName}`,
108
+ ], null, target);
104
109
  console.log('wasm compiled for node...');
105
110
  console.log('js compiling for node...');
106
- await buildJs(`${state.config.paths.build}/${state.config.general.name}.js`, 'node');
111
+ await buildJs(target);
107
112
  if (emccFlags.includes('FETCH')) {
108
- fs.appendFileSync(`${state.config.paths.build}/${state.config.general.name}.node.js`, 'var XMLHttpRequest = require(\'xhr2\');\n');
113
+ fs.appendFileSync(`${state.config.paths.build}/${target.jsName}`, 'var XMLHttpRequest = require(\'xhr2\');\n');
109
114
  }
110
115
  // fs.renameSync(`${state.config.paths.build}/${state.config.general.name}.js`, `${state.config.paths.build}/${state.config.general.name}.worker.node.js`);
111
116
  console.log('js compiled for node...');
112
117
 
113
- Object.entries(getData('data', 'Emscripten-x86_64', 'node')).forEach(([key, value]) => {
118
+ Object.entries(getData('data', target)).forEach(([key, value]) => {
114
119
  if (fs.existsSync(key)) {
115
120
  const dAssetPath = `${state.config.paths.build}/data/${value}`;
116
121
  if (!fs.existsSync(dAssetPath)) {
@@ -121,7 +126,7 @@ export default async function buildWasm(type, isProd = false) {
121
126
  });
122
127
  }
123
128
 
124
- if (fs.existsSync(`${state.config.paths.build}/${state.config.general.name}.data`)) {
125
- fs.renameSync(`${state.config.paths.build}/${state.config.general.name}.data`, `${state.config.paths.build}/${state.config.general.name}.data.txt`);
129
+ if (fs.existsSync(`${state.config.paths.build}/${target.dataName}`)) {
130
+ fs.renameSync(`${state.config.paths.build}/${target.dataName}`, `${state.config.paths.build}/${target.dataTxtName}`);
126
131
  }
127
132
  }
@@ -1,11 +1,11 @@
1
- /* eslint-disable prefer-destructuring */
1
+
2
2
  import fs from 'node:fs';
3
3
  import upath from 'upath';
4
4
  import state, { saveCache } from '../state/index.js';
5
5
  import { getFileHash } from '../utils/hash.js';
6
6
  import run from './run.js';
7
7
 
8
- export default function createBridgeFile(headerOrModuleFilePath) {
8
+ export default function createBridgeFile(headerOrModuleFilePath, target = state.targets.find((t) => t.platform === 'wasm')) {
9
9
  const interfaceFilePath = upath.resolve(headerOrModuleFilePath);
10
10
  if (!fs.existsSync(`${state.config.paths.build}/interface`)) {
11
11
  fs.mkdirSync(`${state.config.paths.build}/interface`, { recursive: true });
@@ -13,11 +13,11 @@ export default function createBridgeFile(headerOrModuleFilePath) {
13
13
  if (!fs.existsSync(`${state.config.paths.build}/bridge`)) {
14
14
  fs.mkdirSync(`${state.config.paths.build}/bridge`, { recursive: true });
15
15
  }
16
- const interfaceFile = createInterfaceFile(interfaceFilePath);
17
- return createBridgeFileFromInterfaceFile(interfaceFile);
16
+ const interfaceFile = createInterfaceFile(interfaceFilePath, target);
17
+ return createBridgeFileFromInterfaceFile(interfaceFile, target);
18
18
  }
19
19
 
20
- function createInterfaceFile(headerOrModuleFilePath) {
20
+ function createInterfaceFile(headerOrModuleFilePath, target) {
21
21
  if (!headerOrModuleFilePath) {
22
22
  return null;
23
23
  }
@@ -37,7 +37,7 @@ function createInterfaceFile(headerOrModuleFilePath) {
37
37
  return newPath;
38
38
  }
39
39
 
40
- const headerPaths = (state.config.dependencyParameters?.pathsOfCmakeDepends?.split(';') || [])
40
+ const headerPaths = (state.config.dependencyParameters?.getCmakeDependsPathAndName(target).pathsOfCmakeDepends || [])
41
41
  .filter((d) => d.startsWith(state.config.paths.base));
42
42
 
43
43
  const temp2 = headerPaths
@@ -92,7 +92,7 @@ function createInterfaceFile(headerOrModuleFilePath) {
92
92
  return outputFilePath;
93
93
  }
94
94
 
95
- function createBridgeFileFromInterfaceFile(interfaceFilePath) {
95
+ function createBridgeFileFromInterfaceFile(interfaceFilePath, target) {
96
96
  if (!interfaceFilePath) {
97
97
  return null;
98
98
  }
@@ -105,8 +105,8 @@ function createBridgeFileFromInterfaceFile(interfaceFilePath) {
105
105
  const allHeaders = state.config.dependencyParameters.headerPathWithDepends.split(';');
106
106
 
107
107
  let includePath = [
108
- ...state.config.allDependencies.map((d) => `${d.paths.output}/prebuilt/Emscripten-x86_64/include`),
109
- ...state.config.allDependencies.map((d) => `${d.paths.output}/prebuilt/Emscripten-x86_64/swig`),
108
+ ...state.config.allDependencies.map((d) => `${d.paths.output}/prebuilt/${target.path}/include`),
109
+ ...state.config.allDependencies.map((d) => `${d.paths.output}/prebuilt/${target.path}/swig`),
110
110
  ...state.config.paths.header,
111
111
  ...allHeaders,
112
112
  ].filter((path) => !!path.toString()).map((path) => `-I${path}`);
@@ -118,7 +118,7 @@ function createBridgeFileFromInterfaceFile(interfaceFilePath) {
118
118
  '-o', `${state.config.paths.build}/bridge/${interfaceFilePath.split('/').at(-1)}.cpp`,
119
119
  ...includePath,
120
120
  interfaceFilePath,
121
- ]);
121
+ ], null, target);
122
122
 
123
123
  state.cache.bridges[interfaceFilePath] = `${state.config.paths.build}/bridge/${interfaceFilePath.split('/').at(-1)}.cpp`;
124
124
  state.cache.hashes[interfaceFilePath] = fileHash;
@@ -8,33 +8,36 @@ import triggerExtensions from './extensions.js';
8
8
  import state from '../state/index.js';
9
9
 
10
10
  const cpuCount = os.cpus().length - 1;
11
- const sharedPlatforms = ['Android'];
11
+ const sharedPlatforms = ['android'];
12
12
 
13
- export default function createLib(platform, fileType, options = {}) {
14
- if (!platform || !options || typeof options !== 'object' || Array.isArray(options)) {
15
- throw new Error('invalid platform or options');
13
+ export default function createLib(target, fileType, options = {}) {
14
+ if (!target || !options || typeof options !== 'object' || Array.isArray(options)) {
15
+ throw new Error('invalid target or options');
16
16
  }
17
17
 
18
- const basePlatform = platform.split('-', 1)[0];
19
- if (basePlatform === 'iOS' && process.platform !== 'darwin') {
18
+ if (target.platform === 'ios' && process.platform !== 'darwin') {
20
19
  return;
21
20
  }
22
21
 
23
- const buildType = options.isProd ? 'Release' : 'Debug';
22
+ const buildType = target.buildType === 'release' ? 'Release' : 'Debug';
24
23
  const platformPrefix = `${fileType ? `${fileType}-` : ''}${buildType}`;
25
- const libdir = `${state.config.paths.build}/${platformPrefix}/prebuilt/${platform}`;
26
- const buildPath = `${state.config.paths.build}/${platformPrefix}/${platform}`;
24
+ const libdir = `${state.config.paths.build}/${platformPrefix}/prebuilt/${target.path}`;
25
+ const buildPath = `${state.config.paths.build}/${platformPrefix}/${target.path}`;
26
+ if (fs.existsSync(`${libdir}/lib`)) {
27
+ console.log(`${target.path} is already built`);
28
+ return;
29
+ }
27
30
 
28
31
  const buildEnv = { params: [] };
29
32
  let buildParams;
30
- const depPaths = state.config.allDependencyPaths[platform];
33
+ const depPaths = state.config.allDependencyPaths[target.path];
31
34
  if (state.config.build.withBuildConfig) {
32
- const { getBuildParams, getExtraLibs, usePthread } = state.config.build;
35
+ const { getBuildParams, getExtraLibs } = state.config.build;
33
36
  buildEnv.console = true;
34
- const ext = sharedPlatforms.includes(basePlatform) ? 'so' : 'a';
35
- buildParams = getBuildParams ? getBuildParams(platform, depPaths, ext, buildPath) : [];
37
+ const ext = sharedPlatforms.includes(target.platform) ? 'so' : 'a';
38
+ buildParams = getBuildParams ? getBuildParams(target, depPaths, ext, buildPath) : [];
36
39
  if (state.config.build?.buildType !== 'configure') {
37
- const cmakeBuildType = sharedPlatforms.includes(basePlatform) ? 'SHARED' : 'STATIC';
40
+ const cmakeBuildType = sharedPlatforms.includes(target.platform) ? 'SHARED' : 'STATIC';
38
41
  buildParams.push(`-DCMAKE_PREFIX_PATH=${libdir}`, `-DCMAKE_FIND_ROOT_PATH=${libdir}`, `-DBUILD_TYPE=${cmakeBuildType}`);
39
42
  }
40
43
 
@@ -42,50 +45,71 @@ export default function createLib(platform, fileType, options = {}) {
42
45
  const ldFlags = Object.values(depPaths).filter(d => d.libPath).map((d) => `-L${d.libPath}`);
43
46
  let dependLibs = '';
44
47
  if (state.config.build?.buildType === 'configure') {
45
- dependLibs = Object.keys(depPaths).filter(d => d).map((d) => `-l${d}`).join(' ');
48
+ dependLibs = Object.keys(depPaths).filter(d => d && d !== 'cmake').map((d) => `-l${d}`).join(' ');
46
49
  }
47
50
 
48
- const extraLibs = getExtraLibs ? getExtraLibs(platform) : [];
51
+ const extraLibs = getExtraLibs ? getExtraLibs(target) : [];
49
52
 
50
53
  triggerExtensions('createLib', 'setFlagWithBuildConfig', [buildEnv, cFlags, ldFlags]);
51
-
52
- if (usePthread) {
54
+ if (target.runtime === 'mt') {
53
55
  cFlags.push('-pthread');
54
56
  ldFlags.push('-pthread');
55
57
  }
56
58
 
59
+ if (target.platform === 'wasm') {
60
+ cFlags.push('-msimd128');
61
+ ldFlags.push('-msimd128');
62
+ }
63
+
64
+ if (target.platform === 'wasm' && target.arch === 'wasm64') {
65
+ cFlags.push('-sMEMORY64=1');
66
+ ldFlags.push('-sMEMORY64=1');
67
+ }
68
+
57
69
  buildEnv.params.push('-e', `CFLAGS=${cFlags.join(' ')}`);
58
70
  buildEnv.params.push('-e', `CXXFLAGS=${cFlags.join(' ')}`);
59
71
  buildEnv.params.push('-e', `LDFLAGS=${ldFlags.join(' ')} ${extraLibs.join(' ')}`);
60
- // buildEnv.params.push('-e', `LIBS=${dependLibs} ${extraLibs.join(' ')}`);
72
+ buildEnv.params.push('-e', `LIBS=${dependLibs} ${extraLibs.join(' ')}`);
61
73
 
62
74
  let configBuildEnv = state.config.build.env;
63
75
  if (configBuildEnv && typeof configBuildEnv === 'function') {
64
- configBuildEnv = configBuildEnv(platform);
76
+ configBuildEnv = configBuildEnv(target);
65
77
  }
66
78
  configBuildEnv?.forEach((e) => {
67
79
  buildEnv.params.push('-e', e);
68
80
  });
69
81
  } else {
70
- buildParams = getCmakeParameters(platform, options);
82
+ buildParams = getCmakeParameters(target, options);
71
83
 
72
84
  triggerExtensions('createLib', 'setFlagWithoutBuildConfig', [buildEnv]);
73
85
 
74
- if (state.config.build.usePthread) {
86
+ if (target.runtime === 'mt') {
75
87
  buildEnv.params.push('-e', `CFLAGS=-pthread`);
76
88
  buildEnv.params.push('-e', `CXXFLAGS=-pthread`);
77
89
  buildEnv.params.push('-e', `LDFLAGS=-pthread`);
78
90
  }
91
+
92
+ if (target.platform === 'wasm') {
93
+ buildEnv.params.push('-e', `CFLAGS=-msimd128`);
94
+ buildEnv.params.push('-e', `CXXFLAGS=-msimd128`);
95
+ buildEnv.params.push('-e', `LDFLAGS=-msimd128`);
96
+ }
97
+
98
+ if (target.platform === 'wasm' && target.arch === 'wasm64') {
99
+ buildEnv.params.push('-e', `CFLAGS=-sMEMORY64=1`);
100
+ buildEnv.params.push('-e', `CXXFLAGS=-sMEMORY64=1`);
101
+ buildEnv.params.push('-e', `LDFLAGS=-sMEMORY64=1`);
102
+ }
79
103
  }
80
104
 
81
- console.log(`${platform} is compiling...`);
105
+ console.log(`${target.path} ${target.runtimeEnv || ''} ${fileType} is compiling...`);
82
106
  const t0 = performance.now();
83
107
  const cmakeDir = state.config.build.withBuildConfig ? `${state.config.paths.build}/source` : state.config.paths.cmakeDir;
84
108
 
85
109
  if (state.config.build?.beforeRun) {
86
110
  const dataList = state.config.build?.beforeRun(cmakeDir);
87
111
  dataList.forEach((data) => {
88
- run(data.program, data.parameters || [], platformPrefix, platform, buildEnv);
112
+ run(data.program, data.parameters || [], platformPrefix, target, buildEnv);
89
113
  });
90
114
  }
91
115
 
@@ -93,7 +117,7 @@ export default function createLib(platform, fileType, options = {}) {
93
117
  if (state.config.build?.buildType === 'configure') {
94
118
  fs.cpSync(cmakeDir, buildPath, { recursive: true });
95
119
  if (state.config.build?.sourceReplaceList) {
96
- state.config.build.sourceReplaceList(platform, depPaths)?.forEach(({ regex, replacement, paths }) => {
120
+ state.config.build.sourceReplaceList(target, depPaths)?.forEach(({ regex, replacement, paths }) => {
97
121
  replace({
98
122
  regex, replacement, paths: paths.map((p) => `${buildPath}/${p}`), recursive: false, silent: true,
99
123
  });
@@ -103,23 +127,23 @@ export default function createLib(platform, fileType, options = {}) {
103
127
  './configure',
104
128
  ...buildParams,
105
129
  `--prefix=${libdir}`,
106
- ], platformPrefix, platform, buildEnv);
130
+ ], platformPrefix, target, buildEnv);
107
131
  } else {
108
132
  run(null, [
109
- basePlatform === 'iOS' && state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake', cmakeDir,
133
+ target.platform === 'ios' && state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake', cmakeDir,
110
134
  `-DCMAKE_BUILD_TYPE=${buildType}`,
111
135
  `-DCMAKE_INSTALL_PREFIX=${libdir}`,
112
136
  ...buildParams,
113
- ], platformPrefix, platform, buildEnv);
137
+ ], platformPrefix, target, buildEnv);
114
138
  }
115
139
  }
116
140
  const t1 = performance.now();
117
- if (basePlatform === 'iOS' && state.config.build?.buildType !== 'configure') {
141
+ if (target.platform === 'ios' && state.config.build?.buildType !== 'configure') {
118
142
  const iOSCMakeBuilder = state.config.build?.useIOSCMake ? 'ios-cmake' : 'cmake';
119
- run(null, [iOSCMakeBuilder, '--build', '.', '-j', cpuCount, '--config', buildType, '--target', 'install'], platformPrefix, platform, { console: buildEnv.console });
143
+ run(null, [iOSCMakeBuilder, '--build', '.', '-j', cpuCount, '--config', buildType, '--target', 'install'], platformPrefix, target, { console: buildEnv.console });
120
144
  } else {
121
- run(null, ['make', `-j${cpuCount}`, 'install'], platformPrefix, platform, { console: buildEnv.console });
145
+ run(null, ['make', `-j${cpuCount}`, 'install'], platformPrefix, target, { console: buildEnv.console });
122
146
  }
123
147
  const t2 = performance.now();
124
- 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}`);
148
+ console.log(`${target.path} ${target.runtimeEnv || ''} ${fileType} compiled`, platformPrefix, `full time: ${Math.round(t2 - t0)}ms`, `cmake: ${Math.round(t1 - t0)}ms`, `build: ${Math.round(t2 - t1)}ms`, `core: ${cpuCount}`);
125
149
  }
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import upath from 'upath';
3
3
  import { execFileSync } from 'node:child_process';
4
4
  import state from '../state/index.js';
5
+ import { getTargetParams, getFilteredBuildTargets } from './target.js';
5
6
 
6
7
  const iOSDevPath = '/Applications/Xcode.app/Contents/Developer';
7
8
  const iosBinPath = `${iOSDevPath}/Toolchains/XcodeDefault.xctoolchain/usr/bin`;
@@ -9,6 +10,7 @@ const iosRanLibBin = `${iosBinPath}/ranlib`;
9
10
 
10
11
  export default function createXCFramework(overrideConfig = null) {
11
12
  if (process.platform !== 'darwin') {
13
+ console.log('XCFramework not created because platform is not darwin.');
12
14
  return;
13
15
  }
14
16
 
@@ -16,11 +18,6 @@ export default function createXCFramework(overrideConfig = null) {
16
18
  const projectPath = overrideConfig?.paths?.project || state.config.paths.project;
17
19
  const libName = overrideConfig?.export?.libName || state.config.export.libName;
18
20
 
19
- if (
20
- !fs.existsSync(`${output}/prebuilt/iOS-iphoneos/lib`)
21
- || !fs.existsSync(`${output}/prebuilt/iOS-iphonesimulator/lib`)
22
- ) return;
23
-
24
21
  const options = {
25
22
  cwd: projectPath,
26
23
  stdio: 'inherit',
@@ -28,23 +25,44 @@ export default function createXCFramework(overrideConfig = null) {
28
25
 
29
26
  const relativeOutput = upath.relative(projectPath, output);
30
27
 
31
- libName.forEach((fileName) => {
32
- if (!fs.existsSync(`${projectPath}/${fileName}.xcframework`)) {
33
- execFileSync(iosRanLibBin, [`${relativeOutput}/prebuilt/iOS-iphoneos/lib/lib${fileName}.a`], options);
34
- execFileSync(iosRanLibBin, [`${relativeOutput}/prebuilt/iOS-iphonesimulator/lib/lib${fileName}.a`], options);
35
- const params = [
36
- '-create-xcframework',
37
- '-library', `${relativeOutput}/prebuilt/iOS-iphoneos/lib/lib${fileName}.a`,
38
- '-headers', `${relativeOutput}/prebuilt/iOS-iphoneos/include`,
39
- '-library', `${relativeOutput}/prebuilt/iOS-iphonesimulator/lib/lib${fileName}.a`,
40
- '-headers', `${relativeOutput}/prebuilt/iOS-iphonesimulator/include`,
41
- '-output', `${fileName}.xcframework`,
42
- ];
43
- execFileSync('xcodebuild', params, options);
44
- }
28
+ const targetParams = overrideConfig?.targetParams || getTargetParams();
29
+ const buildTargets = getFilteredBuildTargets(targetParams, { platform: 'ios', runtime: 'mt', buildType: (targetParams.buildType && targetParams.buildType !== 'all') ? targetParams.buildType : 'release' });
45
30
 
46
- if (!fs.existsSync(`${output}/prebuilt/${fileName}.xcframework.zip`)) {
47
- execFileSync('zip', ['-y', '-r', `${relativeOutput}/prebuilt/${fileName}.xcframework.zip`, `${fileName}.xcframework`], options);
31
+ if (buildTargets.some(t => !fs.existsSync(`${output}/prebuilt/${t.path}/lib`))) {
32
+ console.log('XCFramework not created because some of the build targets are not built.');
33
+ return;
34
+ }
35
+
36
+ const targets = {};
37
+ buildTargets.forEach((target) => {
38
+ const p = `${target.platform}-${target.runtime}-${target.buildType}`;
39
+ if (!targets[p]) {
40
+ targets[p] = {};
48
41
  }
42
+ targets[p][target.arch] = target;
43
+ });
44
+
45
+ libName.forEach((fileName) => {
46
+ Object.values(targets).forEach((a) => {
47
+ const targets = Object.values(a);
48
+ // const targetName = `${fileName}-${targets[0].runtime}-${targets[0].buildType}.xcframework`;
49
+ const targetName = `${fileName}.xcframework`;
50
+ if (!fs.existsSync(`${projectPath}/${targetName}`)) {
51
+ console.log(`Creating XCFramework ${targetName}`);
52
+ const params = ['-create-xcframework'];
53
+ targets.forEach((target) => {
54
+ execFileSync(iosRanLibBin, [`${relativeOutput}/prebuilt/${target.path}/lib/lib${fileName}.a`], options);
55
+ params.push(
56
+ '-library', `${relativeOutput}/prebuilt/${target.path}/lib/lib${fileName}.a`,
57
+ '-headers', `${relativeOutput}/prebuilt/${target.path}/include`,
58
+ );
59
+ });
60
+ params.push('-output', targetName);
61
+ execFileSync('xcodebuild', params, options);
62
+ console.log(`XCFramework ${targetName} created.`);
63
+ } else {
64
+ console.log(`XCFramework ${targetName} already exists.`);
65
+ }
66
+ });
49
67
  });
50
68
  }
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import state from '../state/index.js';
3
3
  import getData from './getData.js';
4
4
 
5
- export default function getCmakeParameters(platform, options = {}) {
5
+ export default function getCmakeParameters(target, options = {}) {
6
6
  if (!options || typeof options !== 'object' || Array.isArray(options)) {
7
7
  throw new Error('invalid options');
8
8
  }
@@ -32,34 +32,28 @@ export default function getCmakeParameters(platform, options = {}) {
32
32
  ...(options.headerDirs || []),
33
33
  ];
34
34
 
35
- const basePlatform = platform.split('-', 1)[0];
36
- const sharedPlatforms = ['Android'];
37
- const buildType = sharedPlatforms.includes(basePlatform) ? 'SHARED' : 'STATIC';
35
+ const sharedPlatforms = ['android'];
36
+ const buildType = sharedPlatforms.includes(target.platform) ? 'SHARED' : 'STATIC';
38
37
  const otherBuildType = buildType === 'STATIC' ? 'SHARED' : 'STATIC';
39
38
 
40
- const cmakeCompileOptions = [...new Set(getData('cmake', platform)?.compileOptions || [])];
41
-
42
- const pathsOfCmakeDepends = dependParams.pathsOfCmakeDepends.split(';');
43
- const nameOfCmakeDepends = dependParams.nameOfCmakeDepends.split(';');
44
- const pathsOfCmakeDependsFilteredByPlatform = [];
45
- const nameOfCmakeDependsFilteredByPlatform = [];
46
- pathsOfCmakeDepends.forEach((d, i) => {
47
- if (fs.existsSync(`${d}/${platform}`) || (basePlatform === 'iOS' && fs.existsSync(`${d}/../../${nameOfCmakeDepends[i]}.xcframework`))) {
48
- pathsOfCmakeDependsFilteredByPlatform.push(d);
49
- nameOfCmakeDependsFilteredByPlatform.push(nameOfCmakeDepends[i]);
50
- }
51
- });
39
+ const cmakeCompileOptions = [...new Set(getData('cmake', target)?.compileOptions || [])];
52
40
 
53
41
  params.push(...[
54
42
  `-DPROJECT_NAME=${options.name || state.config.general.name}`,
43
+ // `-DPACKAGE_NAME_SUFFIX=${target.platform === 'ios' ? `-${target.runtime}-${target.buildType}` : ''}`,
44
+ `-DPROJECT_TARGET_PLATFORM=${target.platform}`,
45
+ `-DPROJECT_TARGET_ARCH=${target.arch}`,
46
+ `-DPROJECT_TARGET_RUNTIME=${target.runtime}`,
47
+ `-DPROJECT_TARGET_HOST=${target.platform}-${target.arch}-${target.runtime}-${target.buildType}`,
48
+ `-DPROJECT_TARGET_HOST_RELEASE=${target.platform}-${target.arch}-${target.runtime}-release`,
55
49
  `-DBASE_DIR=${state.config.paths.project}`,
56
50
  `-DEXTERNAL_NATIVE_GLOB=${externalNativeGlob.join(';')}`,
57
51
  `-DEXTERNAL_BRIDGE_GLOB=${externalBridgeGlob.join(';')}`,
58
52
  `-DNATIVE_GLOB=${nativeGlob.join(';')}`,
59
53
  `-DHEADER_GLOB=${headerGlob.join(';')}`,
60
54
  `-DHEADER_DIR=${headerDirs.join(';')}`,
61
- `-DDEPENDS_CMAKE_PATHS=${pathsOfCmakeDependsFilteredByPlatform.join(';')}`,
62
- `-DDEPENDS_CMAKE_NAMES=${nameOfCmakeDependsFilteredByPlatform.join(';')}`,
55
+ `-DDEPENDS_CMAKE_PATHS=${dependParams.getCmakeDependsPathAndName(target).pathsOfCmakeDepends.join(';')}`,
56
+ `-DDEPENDS_CMAKE_NAMES=${dependParams.getCmakeDependsPathAndName(target).nameOfCmakeDepends.join(';')}`,
63
57
  `-DBRIDGE_DIR=${state.config.paths.build}/bridge`,
64
58
  `-DBUILD_TYPE=${buildType}`,
65
59
  `-DBUILD_${otherBuildType}_LIBS=OFF`,