cpp.js 0.2.0 → 0.3.0

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": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,23 @@
1
+ cmake_minimum_required(VERSION 3.1)
2
+ project("${PROJECT_NAME}")
3
+
4
+ option(BUILD_BRIDGE "Build Bridge" OFF)
5
+ option(BUILD_SOURCE "Build Source" OFF)
6
+
7
+ if(BUILD_SOURCE)
8
+ file(GLOB BUILD_SRC_FILES "${BASE_DIR}/native/**/*.cpp" "${BASE_DIR}/native/*.cpp" "${BASE_DIR}/src/native/**/*.cpp" "${BASE_DIR}/src/native/*.cpp")
9
+ endif(BUILD_SOURCE)
10
+ unset(BUILD_SOURCE CACHE)
11
+
12
+ message("aa", BUILD_SRC_FILES)
13
+
14
+ if(BUILD_BRIDGE)
15
+ file(GLOB BRIDGE_SRC_FILES "${BRIDGE_DIR}/*.i.cpp")
16
+ endif(BUILD_BRIDGE)
17
+ unset(BUILD_BRIDGE CACHE)
18
+
19
+ set(SRC_FILES "${BUILD_SRC_FILES}" "${BRIDGE_SRC_FILES}")
20
+ add_library("${PROJECT_NAME}" STATIC ${SRC_FILES})
21
+
22
+ file(GLOB HEADERS "${BASE_DIR}/node_modules/cppjs-lib-*/include")
23
+ include_directories("${HEADERS};${BASE_DIR}/native;${BASE_DIR}/src/native")
package/src/bin.js CHANGED
@@ -2,38 +2,61 @@
2
2
 
3
3
  import packageJSON from '../package.json' assert { type: 'json' };
4
4
  import { Command, Argument } from 'commander';
5
+ import fs from 'fs';
6
+ import glob from 'glob';
7
+ import { createDir } from './utils/createTempDir.js';
5
8
 
6
- import { createBridge, findCMakeListsFile, findOrCreateInterfaceFile, createWasm } from './index.js';
7
- import { createTempDir } from './utils.js';
9
+ import CppjsCompiler from './index.js';
8
10
 
9
11
  const program = new Command();
10
- program
11
- .name('cpp.js')
12
- .description('Compile c++ files to webassembly.')
13
- .version(packageJSON.version)
14
- .showHelpAfterError();
15
12
 
16
- program.addArgument(new Argument('<type>', 'Creation type').choices(['bridge', 'wasm', 'all']));
17
- program.argument('<input>', 'Input paths');
18
- program
19
- .option('-o, --output <string>', 'Output path');
13
+ program
14
+ .name('cpp.js')
15
+ .description('Compile c++ files to webassembly.')
16
+ .version(packageJSON.version)
17
+ .showHelpAfterError();
18
+
19
+ const commandGenerate = program.command('generate')
20
+ .description('Generate app or lib.')
21
+ .addArgument(new Argument('<type>', 'Generation type').choices(['app', 'lib']))
22
+ .option('-b, --base <base>', 'base path')
23
+ .option('-p, --platform <platform>', 'platform (wasm)', 'wasm', ['wasm'])
24
+ .option('-o, --output <string>', 'Output path');
20
25
 
21
26
  program.parse(process.argv);
22
- const options = program.opts();
23
- const args = program.args;
24
-
25
- const [type, ...inputs]= args;
26
- main(type, inputs);
27
-
28
- async function main(type, inputs, output = createTempDir('a'+Math.random())) {
29
- if (type === 'bridge' || type === 'all') {
30
- const interfaceFile = findOrCreateInterfaceFile(process.cwd()+'/'+inputs[0], output);
31
- createBridge(interfaceFile, output);
32
- }
33
-
34
- if (type === 'wasm' || type === 'all') {
35
- const cMakeListsFilePath = findCMakeListsFile();
36
- createWasm(cMakeListsFilePath, output, output, { cc: ['-O3'] });
37
- }
38
- console.log('output: ' + output);
27
+
28
+ switch (program.args[0]) {
29
+ case 'generate':
30
+ const type = commandGenerate.args[0];
31
+ const { output, platform, base } = commandGenerate.opts();
32
+ generate(type, platform, output, base);
33
+ break;
34
+ default:
35
+ break;
36
+ }
37
+
38
+ function generate(type, platform, output, base) {
39
+ if (type === 'lib') generateLib(platform, output, base);
40
+ }
41
+
42
+ function generateLib(platform, output, base) {
43
+ let headers = [];
44
+
45
+ const compiler = new CppjsCompiler();
46
+ compiler.config.paths.header.forEach(headerPath => {
47
+ headers.push(glob.sync("*.h", { absolute: true, cwd: headerPath }));
48
+ });
49
+ headers = headers.filter(path => !!path.toString()).flat();
50
+
51
+ headers.forEach(header => {
52
+ compiler.findOrCreateInterfaceFile(header);
53
+ compiler.createBridge();
54
+ compiler.createWasm({ cc: ['-O3'] });
55
+ createDir('lib', compiler.config.paths.output);
56
+ fs.copyFileSync(`${compiler.config.paths.temp}/${compiler.config.general.name}.js`, `${compiler.config.paths.output}/${compiler.config.general.name}.js`);
57
+ fs.copyFileSync(`${compiler.config.paths.temp}/${compiler.config.general.name}.wasm`, `${compiler.config.paths.output}/${compiler.config.general.name}.wasm`);
58
+ fs.copyFileSync(`${compiler.config.paths.temp}/lib${compiler.config.general.name}.a`, `${compiler.config.paths.output}/lib/lib${compiler.config.general.name}.a`);
59
+ fs.rmSync(compiler.config.paths.temp, { recursive: true, force: true });
60
+ });
61
+
39
62
  }
@@ -0,0 +1,33 @@
1
+ import glob from 'glob';
2
+ import { execFileSync } from 'child_process';
3
+ import pullDockerImage from '../utils/pullDockerImage.js';
4
+ import getBaseInfo from '../utils/getBaseInfo.js';
5
+ import getPathInfo from '../utils/getPathInfo.js';
6
+ import getOsUserAndGroupId from '../utils/getOsUserAndGroupId.js';
7
+
8
+ export default function createBridge(compiler) {
9
+ pullDockerImage();
10
+
11
+ const bridges = [];
12
+ compiler.interfaces.forEach(filePath => {
13
+ const input = getPathInfo(filePath, compiler.config.paths.base);
14
+ const output = getPathInfo(compiler.config.paths.temp+'/bridge', compiler.config.paths.base);
15
+ const projectPath = getPathInfo(compiler.config.paths.project, compiler.config.paths.base);
16
+ const base = getBaseInfo(compiler.config.paths.base);
17
+
18
+ const includePath = [
19
+ glob.sync("node_modules/cppjs-lib-*-web/include", { absolute: false }),
20
+ glob.sync("native", { absolute: false }),
21
+ glob.sync("src/native", { absolute: false }),
22
+ ].filter(path => !!path.toString()).map(path => `-I/live/${projectPath.relative}/${path}`);
23
+
24
+ const options = { cwd: output.absolute, stdio : 'pipe' };
25
+ const args = [
26
+ "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "bugra9/cpp.js",
27
+ "swig", "-c++", '-emscripten', '-o', `/live/${output.relative}/${filePath.split('/').at(-1)}.cpp`, ...includePath, `/live/${input.relative}`
28
+ ];
29
+ execFileSync("docker", args, options);
30
+ bridges.push(`${base.withSlash}${output.relative}/${filePath.split('/').at(-1)}.cpp`);
31
+ });
32
+ return bridges;
33
+ }
@@ -0,0 +1,95 @@
1
+ import { execFileSync } from 'child_process';
2
+ import pullDockerImage from '../utils/pullDockerImage.js';
3
+ import getBaseInfo from '../utils/getBaseInfo.js';
4
+ import getPathInfo from '../utils/getPathInfo.js';
5
+ import getOsUserAndGroupId from '../utils/getOsUserAndGroupId.js';
6
+
7
+ export default function createWasm(compiler, options = {}) {
8
+ const compiler2 = new CppjsCompiler(
9
+ compiler.config.paths.cmake,
10
+ compiler.config.paths.output,
11
+ compiler.config.paths.temp,
12
+ compiler.config.paths.cli,
13
+ compiler.config.general.name,
14
+ options,
15
+ compiler.config.paths.base
16
+ );
17
+ return compiler2.compile();
18
+ }
19
+
20
+ class CppjsCompiler {
21
+ constructor(cMakeFilePath, outputPath, tempPath, cliPath, name, options = {}, basePath = process.cwd()) {
22
+ this.cMakeFilePath = cMakeFilePath;
23
+ this.outputPath = tempPath;
24
+ this.tempPath = tempPath;
25
+ this.cliPath = cliPath;
26
+ this.options = options;
27
+ this.basePath = basePath;
28
+ this.name = name;
29
+ }
30
+
31
+ compile() {
32
+ pullDockerImage();
33
+
34
+ this.cmake(this.name, true, false);
35
+ this.make();
36
+ this.cmake(this.name+'bridge', false, true);
37
+ this.make();
38
+ this.libs = [`lib${this.name}.a`, `lib${this.name}bridge.a`];
39
+
40
+ this.cc();
41
+
42
+ return this.outputPath;
43
+ }
44
+
45
+ cmake(name, isBuildSource, isBuildBridge) {
46
+ const params = [];
47
+ if (isBuildSource) params.push('-DBUILD_SOURCE=TRUE');
48
+ if (isBuildBridge) params.push('-DBUILD_BRIDGE=TRUE');
49
+
50
+ const output = getPathInfo(this.outputPath, this.basePath);
51
+ const projectPath = getPathInfo(process.cwd(), this.basePath);
52
+ const base = getBaseInfo(this.basePath);
53
+
54
+ let cMakeParentPath = this.cMakeFilePath.split('/');
55
+ cMakeParentPath.pop();
56
+ cMakeParentPath = cMakeParentPath.join('/');
57
+ const args = [
58
+ "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${cMakeParentPath}:/cmake`, "--workdir", `/live/${output.relative}`, "bugra9/cpp.js",
59
+ "emcmake", "cmake", "/cmake", `-DBASE_DIR=/live/${projectPath.relative}`,
60
+ `-DCMAKE_INSTALL_PREFIX=/live/${output.relative}`, `-DBRIDGE_DIR=/live/${output.relative}/bridge`, `-DPROJECT_NAME=${name}`, ...params,
61
+ ];
62
+ const options = { cwd: this.outputPath, stdio : 'pipe' };
63
+ execFileSync("docker", args, options);
64
+ return this.outputPath;
65
+ }
66
+
67
+ make() {
68
+ const output = getPathInfo(this.outputPath, this.basePath);
69
+ const base = getBaseInfo(this.basePath);
70
+
71
+ let cMakeParentPath = this.cMakeFilePath.split('/');
72
+ cMakeParentPath.pop();
73
+ cMakeParentPath = cMakeParentPath.join('/');
74
+ const args = [
75
+ "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${cMakeParentPath}:/cmake`, "--workdir", `/live/${output.relative}`, "bugra9/cpp.js",
76
+ "emmake", "make"
77
+ ];
78
+ const options = { cwd: this.outputPath, stdio : 'pipe' };
79
+ execFileSync("docker", args, options);
80
+ return this.outputPath;
81
+ }
82
+
83
+ cc() {
84
+ const input = getPathInfo(this.tempPath, this.basePath);
85
+ const output = getPathInfo(this.outputPath, this.basePath);
86
+ const base = getBaseInfo(this.basePath);
87
+ const args = [
88
+ "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${this.cliPath}:/cli`, "bugra9/cpp.js",
89
+ "emcc", "-lembind", "-Wl,--whole-archive", ...this.libs.map(lib => `/live/${input.relative}/${lib}`), ...(this.options.cc || []), "-s", "WASM=1", "-s", "MODULARIZE=1", '-o', `/live/${output.relative}/${this.name}.js`, '--extern-post-js', '/cli/assets/extern-post.js'
90
+ ];
91
+ const options = { cwd: this.tempPath, stdio : 'pipe' };
92
+ execFileSync("docker", args, options);
93
+ return this.outputPath;
94
+ }
95
+ }
@@ -1,10 +1,11 @@
1
1
  import fs from 'fs';
2
- import { getBaseInfo, getPathInfo } from './utils.js';
2
+ import getBaseInfo from '../utils/getBaseInfo.js';
3
+ import getPathInfo from '../utils/getPathInfo.js';
3
4
 
4
- export default function findOrCreateInterfaceFile(filePath, outputPath, basePath = process.cwd()) {
5
- const input = getPathInfo(filePath, basePath);
6
- const output = getPathInfo(outputPath, basePath);
7
- const base = getBaseInfo(basePath);
5
+ export default function findOrCreateInterfaceFile(compiler, filePath) {
6
+ const input = getPathInfo(filePath, compiler.config.paths.base);
7
+ const output = getPathInfo(compiler.config.paths.temp+'/interface', compiler.config.paths.base);
8
+ const base = getBaseInfo(compiler.config.paths.base);
8
9
 
9
10
  const temp = input.relative.match(/^(.*)\..+?$/);
10
11
  if (temp.length < 2) return null;
@@ -33,5 +34,8 @@ export default function findOrCreateInterfaceFile(filePath, outputPath, basePath
33
34
  `;
34
35
  const outputFilePath = base.withSlash + output.relative+'/'+fileName+'.i';
35
36
  fs.writeFileSync(outputFilePath, content);
37
+
38
+ compiler.interfaces.push(outputFilePath);
39
+
36
40
  return outputFilePath;
37
41
  }
package/src/index.js CHANGED
@@ -1,4 +1,23 @@
1
- export { default as createBridge } from './createBridge.js';
2
- export { default as findCMakeListsFile } from './findCMakeListsFile.js';
3
- export { default as findOrCreateInterfaceFile } from './findOrCreateInterfaceFile.js';
4
- export { default as createWasm } from './createWasm.js';
1
+ import createBridge from './functions/createBridge.js';
2
+ import findOrCreateInterfaceFile from './functions/findOrCreateInterfaceFile.js';
3
+ import createWasm from './functions/createWasm.js';
4
+ import getConfig from './utils/getConfig.js';
5
+
6
+ export default class CppjsCompiler {
7
+ constructor(param) {
8
+ this.config = getConfig(param);
9
+ this.interfaces = [];
10
+ }
11
+
12
+ findOrCreateInterfaceFile(path) {
13
+ return findOrCreateInterfaceFile(this, path);
14
+ }
15
+
16
+ createBridge() {
17
+ return createBridge(this);
18
+ }
19
+
20
+ createWasm(options) {
21
+ return createWasm(this, options);
22
+ }
23
+ }
@@ -0,0 +1,15 @@
1
+ import fs from 'fs';
2
+ import p from 'path';
3
+
4
+ export default function createTempDir(folder = 'a'+Math.random(), base = process.cwd()) {
5
+ const path = p.join(base, 'node_modules', ".cppjs");
6
+ return createDir(folder, path);
7
+ }
8
+
9
+ export function createDir(folder, base = process.cwd()) {
10
+ const path = p.join(base, folder);
11
+
12
+ if (fs.existsSync(path)) fs.rmSync(path, { recursive: true, force: true });
13
+ fs.mkdirSync(path, { recursive: true });
14
+ return path;
15
+ }
@@ -0,0 +1,12 @@
1
+ import glob from 'glob';
2
+ import getCliPath from './getCliPath.js';
3
+
4
+ export default function findCMakeListsFile(basePath = process.cwd()) {
5
+ let temp = glob.sync("CMakeLists.txt", { absolute: true, cwd: basePath });
6
+ if (temp.length === 0) {
7
+ temp = glob.sync("*/CMakeLists.txt", { absolute: true, cwd: basePath, ignore: ['node_modules/*', 'dist/*', 'build/*'] });
8
+ }
9
+
10
+ if (temp.length > 0) return temp[0];
11
+ return getCliPath() + '/assets/CMakeLists.txt';
12
+ }
@@ -0,0 +1,15 @@
1
+ export default function getBaseInfo(base) {
2
+ let basePath = base;
3
+
4
+ const output = {
5
+ withSlash: '/',
6
+ withoutSlash: '/',
7
+ };
8
+ if (basePath && basePath !== '/') {
9
+ if (basePath.at(-1) !== '/') basePath += '/';
10
+
11
+ output.withSlash = basePath;
12
+ output.withoutSlash = basePath.substring(0, basePath.length - 1);
13
+ }
14
+ return output;
15
+ }
@@ -0,0 +1,12 @@
1
+ import {dirname} from 'path';
2
+ import * as url from 'node:url';
3
+
4
+ const __filename = url.fileURLToPath(import.meta.url);
5
+ const temp = __filename.split('/');
6
+ temp.pop();
7
+ temp.pop();
8
+ const __dirname = temp.join('/');
9
+
10
+ export default function getCliPath() {
11
+ return __dirname;
12
+ }
@@ -0,0 +1,140 @@
1
+ import fs from 'fs';
2
+ import createTempDir, { createDir } from './createTempDir.js';
3
+ import findCMakeListsFile from './findCMakeListsFile.js';
4
+ import p from 'path';
5
+ import * as url from 'node:url';
6
+ import { createRequire } from 'module';
7
+
8
+ const __filename = url.fileURLToPath(import.meta.url);
9
+ const temp = __filename.split('/'); temp.pop(); temp.pop();
10
+ const __dirname = temp.join('/');
11
+ const require = createRequire(import.meta.url);
12
+
13
+ /**
14
+ * @typedef {Object} Config
15
+ * @property {string} general General
16
+ * @property {ConfigPaths} paths Paths
17
+ * @property {ConfigExtensions} extensions Extensions
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} ConfigPaths
22
+ * @property {string} project Project path.
23
+ * @property {string} base Base path (Use for monorepo structure)
24
+ * @property {string} temp Temp path.
25
+ * @property {string} native Native path (default: ['native', 'src/native']).
26
+ * @property {string} module Module path (default: native path)
27
+ * @property {string} header Header path (default: native path)
28
+ * @property {string} bridge Bridge path (default: native and temp path)
29
+ * @property {string} output Output path (default: 'dist')
30
+ * @property {string} cmake CmakeLists.txt path
31
+ */
32
+
33
+ /**
34
+ * @typedef {Object} ConfigExtensions
35
+ * @property {string} header Header extensions (default: ['h', 'hpp', 'hxx', 'hh'])
36
+ * @property {string} source Source extensions (default: ['c', 'cpp', 'cxx', 'cc'])
37
+ * @property {string} module Module extensions (default: ['i'])
38
+ */
39
+
40
+ /**
41
+ * @typedef {Object} ConfigGeneral
42
+ * @property {string} name Project name
43
+ */
44
+
45
+ export default function getConfig(param) {
46
+ let tempConfig = { general: {}, paths: {}, extensions: {} };
47
+
48
+ if (!param || (typeof param === 'string' || param instanceof String)) {
49
+ const ext = (param || '').split('.').at(-1)
50
+ let filePath;
51
+
52
+ if (param && ['json', 'js', 'mjs', 'cjs', 'ts'].includes(ext)) {
53
+ filePath = `${process.cwd()}/${param}`;
54
+ if (!fs.existsSync(filePath)) filePath = null;
55
+ } else {
56
+ filePath = `${process.cwd()}/.cppjs.config.json`;
57
+ if (!fs.existsSync(filePath)) filePath = null;
58
+
59
+ /* filePath = `${process.cwd()}/.cpp.config.js`;
60
+ if (!fs.existsSync(filePath)) filePath = null; */
61
+ }
62
+
63
+ if (filePath) {
64
+ const file = require(filePath);
65
+ if (file.default) file = file.default;
66
+ if (typeof file === 'function') tempConfig = file();
67
+ else if (typeof file === "object") tempConfig = file;
68
+ }
69
+ } else if (typeof param === "object") {
70
+ tempConfig = param;
71
+ } else {
72
+ console.error('Error');
73
+ }
74
+
75
+ return fillConfig(forceToConfigSchema(tempConfig));
76
+ }
77
+
78
+ function forceToConfigSchema(tempConfig) {
79
+ const config = {
80
+ general: tempConfig && tempConfig.general ? tempConfig.general : {},
81
+ paths: tempConfig && tempConfig.paths ? tempConfig.paths : {},
82
+ extensions: tempConfig && tempConfig.extensions ? tempConfig.extensions : {},
83
+ };
84
+ return config;
85
+ }
86
+
87
+ function getAbsolutePath(projectPath, path) {
88
+ if (!path) {
89
+ return null;
90
+ }
91
+ if (p.isAbsolute(path)) {
92
+ return path;
93
+ }
94
+ if (projectPath) {
95
+ return p.resolve(p.join(p.resolve(projectPath), path));
96
+ }
97
+ return p.resolve(path);
98
+ }
99
+
100
+ function fillConfig(tempConfig) {
101
+ const config = {
102
+ general: {},
103
+ paths: {
104
+ project: getAbsolutePath(null, tempConfig.paths.project) || process.cwd(),
105
+ },
106
+ extensions: {},
107
+ };
108
+
109
+ if (!config.general.name) {
110
+ config.general.name = 'cppjssample';
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.general.name = file.name;
116
+ }
117
+ }
118
+ }
119
+
120
+ const getPath = getAbsolutePath.bind(null, config.paths.project);
121
+
122
+ config.paths.base = getPath(tempConfig.paths.base) || config.paths.project;
123
+ config.paths.temp = getPath(tempConfig.paths.temp) || createTempDir(undefined, config.paths.project)
124
+ config.paths.native = (tempConfig.paths.native || ['native', 'src/native']).map(p => getPath(p));
125
+ config.paths.module = (tempConfig.paths.module || config.paths.native).map(p => getPath(p));
126
+ config.paths.header = (tempConfig.paths.header || config.paths.native).map(p => getPath(p));
127
+ config.paths.bridge = (tempConfig.paths.bridge || [...config.paths.native, config.paths.temp]).map(p => getPath(p));
128
+ config.paths.output = getPath(tempConfig.paths.output) || config.paths.temp;
129
+ config.paths.cmake = getPath(tempConfig.paths.cmake || findCMakeListsFile(config.paths.project));
130
+ config.paths.cli = __dirname;
131
+
132
+ config.extensions.header = tempConfig.extensions.header || ['h', 'hpp', 'hxx', 'hh'];
133
+ config.extensions.source = tempConfig.extensions.source || ['c', 'cpp', 'cxx', 'cc'];
134
+ config.extensions.module = tempConfig.extensions.module || ['i'];
135
+
136
+ createDir('interface', config.paths.temp);
137
+ createDir('bridge', config.paths.temp);
138
+
139
+ return config;
140
+ }
@@ -0,0 +1,10 @@
1
+ import os from "os";
2
+
3
+ let osUserAndGroupId;
4
+ export default function getOsUserAndGroupId() {
5
+ const userInfo = os.userInfo();
6
+ if (!osUserAndGroupId) {
7
+ osUserAndGroupId = `${userInfo.uid}:${userInfo.gid}`;
8
+ }
9
+ return osUserAndGroupId;
10
+ }
@@ -0,0 +1,18 @@
1
+ export default function getPathInfo(path, base) {
2
+ let basePath = base;
3
+
4
+ const output = {
5
+ relative: path,
6
+ absolute: path,
7
+ };
8
+ if (basePath) {
9
+ if (basePath.at(-1) !== '/') basePath += '/';
10
+
11
+ if (path.substring(0, basePath.length) === basePath) {
12
+ output.relative = path.substring(basePath.length);
13
+ } else {
14
+ output.absolute = basePath + path;
15
+ }
16
+ }
17
+ return output;
18
+ }
@@ -1,8 +0,0 @@
1
- cmake_minimum_required(VERSION 3.1)
2
- project(cppjs)
3
-
4
- file(GLOB SRC_FILES "${BASE_DIR}/native/**/*.cpp" "${BASE_DIR}/native/*.cpp" "${BASE_DIR}/src/native/**/*.cpp" "${BASE_DIR}/src/native/*.cpp" "${BRIDGE_DIR}/*.i.cpp")
5
- add_library(cppjs STATIC ${SRC_FILES})
6
-
7
- file(GLOB HEADERS "${BASE_DIR}/node_modules/cppjs-lib-*/include")
8
- include_directories("${HEADERS};${BASE_DIR}/native;${BASE_DIR}/src/native")
@@ -1,28 +0,0 @@
1
- import glob from 'glob';
2
- import os from "os";
3
- import { execFileSync } from 'child_process';
4
- import pullDockerImage from './pullDockerImage.js';
5
- import { getBaseInfo, getPathInfo, getOsUserAndGroupId } from './utils.js';
6
-
7
- export default function createBridge(filePath, outputPath, basePath = process.cwd()) {
8
- pullDockerImage();
9
-
10
- const input = getPathInfo(filePath, basePath);
11
- const output = getPathInfo(outputPath, basePath);
12
- const projectPath = getPathInfo(process.cwd(), basePath);
13
- const base = getBaseInfo(basePath);
14
-
15
- const includePath = [
16
- glob.sync("node_modules/cppjs-lib-*-web/include", { absolute: false }),
17
- glob.sync("native", { absolute: false }),
18
- glob.sync("src/native", { absolute: false }),
19
- ].filter(path => !!path.toString()).map(path => `-I/live/${projectPath.relative}/${path}`);
20
-
21
- const options = { cwd: outputPath, stdio : 'pipe' };
22
- const args = [
23
- "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "bugra9/cpp.js",
24
- "swig", "-c++", '-emscripten', '-o', `/live/${output.relative}/${filePath.split('/').at(-1)}.cpp`, ...includePath, `/live/${input.relative}`
25
- ];
26
- execFileSync("docker", args, options);
27
- return `${base.withSlash}${output.relative}/${filePath.split('/').at(-1)}.cpp`;
28
- }
package/src/createWasm.js DELETED
@@ -1,66 +0,0 @@
1
- import { execFileSync } from 'child_process';
2
- import * as url from 'node:url';
3
- import pullDockerImage from './pullDockerImage.js';
4
- import { getBaseInfo, getPathInfo, getOsUserAndGroupId } from './utils.js';
5
-
6
- const __filename = url.fileURLToPath(import.meta.url);
7
- const temp = __filename.split('/');
8
- temp.pop();
9
- temp.pop();
10
- const __dirname = temp.join('/');
11
-
12
- export default function createWasm(cMakeFilePath, outputPath, tempPath, options = {}, basePath = process.cwd()) {
13
- pullDockerImage();
14
- cmake(cMakeFilePath, tempPath, basePath);
15
- make(cMakeFilePath, tempPath, basePath);
16
- cc(tempPath, outputPath, options.cc, basePath);
17
-
18
- return outputPath;
19
- }
20
-
21
- function cmake(cMakeFilePath, outputPath, basePath) {
22
- const output = getPathInfo(outputPath, basePath);
23
- const projectPath = getPathInfo(process.cwd(), basePath);
24
- const base = getBaseInfo(basePath);
25
-
26
- let cMakeParentPath = cMakeFilePath.split('/');
27
- cMakeParentPath.pop();
28
- cMakeParentPath = cMakeParentPath.join('/');
29
- const args = [
30
- "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${cMakeParentPath}:/cmake`, "--workdir", `/live/${output.relative}`, "bugra9/cpp.js",
31
- "emcmake", "cmake", "/cmake", `-DBASE_DIR=/live/${projectPath.relative}`,
32
- `-DCMAKE_INSTALL_PREFIX=/live/${output.relative}`, `-DBRIDGE_DIR=/live/${output.relative}`,
33
- ];
34
- const options = { cwd: outputPath, stdio : 'pipe' };
35
- execFileSync("docker", args, options);
36
- return outputPath;
37
- }
38
-
39
- function make(cMakeFilePath, outputPath, basePath) {
40
- const output = getPathInfo(outputPath, basePath);
41
- const base = getBaseInfo(basePath);
42
-
43
- let cMakeParentPath = cMakeFilePath.split('/');
44
- cMakeParentPath.pop();
45
- cMakeParentPath = cMakeParentPath.join('/');
46
- const args = [
47
- "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${cMakeParentPath}:/cmake`, "--workdir", `/live/${output.relative}`, "bugra9/cpp.js",
48
- "emmake", "make"
49
- ];
50
- const options = { cwd: outputPath, stdio : 'pipe' };
51
- execFileSync("docker", args, options);
52
- return outputPath;
53
- }
54
-
55
- function cc(tempPath, outputPath, flags = [], basePath) {
56
- const input = getPathInfo(tempPath, basePath);
57
- const output = getPathInfo(outputPath, basePath);
58
- const base = getBaseInfo(basePath);
59
- const args = [
60
- "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${__dirname}:/cli`, "bugra9/cpp.js",
61
- "emcc", "-lembind", "-Wl,--whole-archive", `/live/${input.relative}/libcppjs.a`, ...flags, "-s", "WASM=1", "-s", "MODULARIZE=1", '-o', `/live/${output.relative}/cpp.js`, '--extern-post-js', '/cli/src/extern-post.js'
62
- ];
63
- const options = { cwd: tempPath, stdio : 'pipe' };
64
- execFileSync("docker", args, options);
65
- return outputPath;
66
- }
@@ -1,17 +0,0 @@
1
- import fs from 'fs';
2
- import glob from 'glob';
3
- import {dirname} from 'path';
4
- import * as url from 'node:url';
5
-
6
- export const __filename = url.fileURLToPath(import.meta.url);
7
- export const __dirname = dirname(dirname(__filename)+'..');
8
-
9
- export default function findCMakeListsFile() {
10
- let temp = glob.sync("CMakeLists.txt", { absolute: true });
11
- if (temp.length === 0) {
12
- temp = glob.sync("*/CMakeLists.txt", { absolute: true, ignore: ['node_modules/*', 'dist/*', 'build/*'] });
13
- }
14
-
15
- if (temp.length > 0) return temp[0];
16
- return __dirname + '/assets/CMakeLists.txt';
17
- }
package/src/utils.js DELETED
@@ -1,101 +0,0 @@
1
- import fs from 'fs';
2
- import p, {dirname} from 'path';
3
- import os, { tmpdir } from "os";
4
- import * as url from 'node:url';
5
-
6
- export const __filename = url.fileURLToPath(import.meta.url);
7
- export const __dirname = dirname(__filename);
8
-
9
- let config;
10
- export const mainPath = process.cwd();
11
-
12
- export function createTempDir(folder) {
13
- let path = p.join(tmpdir(), "cppjs-app-cli");
14
- if (folder) path = p.join(path, folder);
15
-
16
- if (fs.existsSync(path)) fs.rmdirSync(path);
17
- fs.mkdirSync(path, { recursive: true });
18
-
19
- return path;
20
- }
21
-
22
- export function getFilesGivenDir(dir, options = {}) {
23
- return new Promise((resolve, reject) => {
24
- fs.readdir(dir, (err, files) => {
25
- if (err) reject(err);
26
-
27
- let filteredFiles = files;
28
- if (options.ext && Array.isArray(options.ext) && options.ext.length > 0) {
29
- const regex = new RegExp(`\.(${options.ext.join('|')})$`, 'g');
30
- filteredFiles = filteredFiles.filter(file => regex.test(file));
31
- }
32
- if (options.filter) filteredFiles = filteredFiles.filter(options.filter);
33
- resolve(filteredFiles);
34
- });
35
- });
36
- }
37
-
38
- export async function getConfig(projectPath) {
39
- if (config) return config;
40
- if (!projectPath) projectPath = mainPath;
41
-
42
- config = {
43
- projectPath,
44
- modulesPath: projectPath,
45
- modulesTempPath: createTempDir('modules'),
46
- bridgesTempPath: createTempDir('bridges'),
47
- output: `${projectPath}/dist`,
48
- };
49
-
50
- const configFilePath = `${projectPath}/.cppjs.config.js`;
51
- if (fs.existsSync(configFilePath)) {
52
- config = Object.assign({}, config, (await import(configFilePath)).default);
53
- }
54
-
55
- return config;
56
- }
57
-
58
- let osUserAndGroupId;
59
- export function getOsUserAndGroupId() {
60
- const userInfo = os.userInfo();
61
- if (!osUserAndGroupId) {
62
- osUserAndGroupId = `${userInfo.uid}:${userInfo.gid}`;
63
- }
64
- return osUserAndGroupId;
65
- }
66
-
67
- export function getBaseInfo(base) {
68
- let basePath = base;
69
-
70
- const output = {
71
- withSlash: '/',
72
- withoutSlash: '/',
73
- };
74
- if (basePath && basePath !== '/') {
75
- if (basePath.at(-1) !== '/') basePath += '/';
76
-
77
- output.withSlash = basePath;
78
- output.withoutSlash = basePath.substring(0, basePath.length - 1);
79
- }
80
- return output;
81
- }
82
-
83
-
84
- export function getPathInfo(path, base) {
85
- let basePath = base;
86
-
87
- const output = {
88
- relative: path,
89
- absolute: path,
90
- };
91
- if (basePath) {
92
- if (basePath.at(-1) !== '/') basePath += '/';
93
-
94
- if (path.substring(0, basePath.length) === basePath) {
95
- output.relative = path.substring(basePath.length);
96
- } else {
97
- output.absolute = basePath + path;
98
- }
99
- }
100
- return output;
101
- }
File without changes