cpp.js 0.4.2 → 0.6.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.4.2",
3
+ "version": "0.6.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,37 +1,45 @@
1
1
  cmake_minimum_required(VERSION 3.25)
2
2
  project("${PROJECT_NAME}")
3
+ set(PACKAGE_HOST "${CMAKE_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
3
4
 
4
5
  option(BUILD_BRIDGE "Build Bridge" OFF)
5
6
  option(BUILD_SOURCE "Build Source" OFF)
6
7
 
7
- if(BUILD_SOURCE)
8
- file(GLOB_RECURSE BUILD_SRC_FILES ${NATIVE_GLOB})
8
+ foreach(depend IN ZIP_LISTS DEPENDS_CMAKE_PATHS DEPENDS_CMAKE_NAMES)
9
+ add_subdirectory("${depend_0}" "${CMAKE_CURRENT_BINARY_DIR}/dependencies/${depend_1}")
10
+ endforeach()
11
+
12
+ if (BUILD_SOURCE)
13
+ file(GLOB_RECURSE BUILD_SRC_FILES ${NATIVE_GLOB})
9
14
  endif(BUILD_SOURCE)
10
15
 
11
- if(BUILD_BRIDGE)
12
- file(GLOB BRIDGE_SRC_FILES "${BRIDGE_DIR}/*.i.cpp")
16
+ if (BUILD_BRIDGE)
17
+ file(GLOB BRIDGE_SRC_FILES "${BRIDGE_DIR}/*.i.cpp")
13
18
  endif(BUILD_BRIDGE)
14
19
 
15
20
  set(SRC_FILES "${BUILD_SRC_FILES}" "${BRIDGE_SRC_FILES}")
16
21
  add_library("${PROJECT_NAME}" STATIC ${SRC_FILES})
17
22
 
18
- file(GLOB LIB_HEADERS_DIR "${BASE_DIR}/node_modules/cppjs-lib-*/include" "${BASE_DIR}/node_modules/cppjs-lib-*/node_modules/cppjs-lib-*/include")
19
- file(GLOB_RECURSE HEADER_FILES ${HEADER_GLOB})
20
- target_include_directories("${PROJECT_NAME}" PUBLIC "${LIB_HEADERS_DIR}" "${HEADER_DIR}")
21
-
22
- if(BUILD_SOURCE)
23
- target_sources("${PROJECT_NAME}"
24
- PUBLIC FILE_SET HEADERS
25
- BASE_DIRS "${HEADER_DIR}"
26
- FILES "${HEADER_FILES}")
23
+ if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "")
24
+ target_link_libraries("${PROJECT_NAME}" "${DEPENDS_CMAKE_NAMES}")
25
+ endif()
27
26
 
28
- string(REPLACE "-" ";" HEADER_FOLDER ${PROJECT_NAME})
29
- list(GET HEADER_FOLDER 2 HEADER_FOLDER)
30
- install(TARGETS "${PROJECT_NAME}" FILE_SET HEADERS DESTINATION "include/cppjs-lib-${HEADER_FOLDER}")
27
+ file(GLOB_RECURSE HEADER_FILES ${HEADER_GLOB})
28
+ target_include_directories("${PROJECT_NAME}" PUBLIC "${HEADER_DIR}")
29
+
30
+ if (BUILD_SOURCE)
31
+ target_sources("${PROJECT_NAME}"
32
+ PUBLIC FILE_SET HEADERS
33
+ BASE_DIRS "${HEADER_DIR}"
34
+ FILES "${HEADER_FILES}")
35
+ string(REPLACE "-" ";" HEADER_FOLDER ${PROJECT_NAME})
36
+ list(GET HEADER_FOLDER 2 HEADER_FOLDER)
37
+ install(TARGETS "${PROJECT_NAME}" DESTINATION "prebuilt/${PACKAGE_HOST}/lib")
38
+ install(TARGETS "${PROJECT_NAME}" FILE_SET HEADERS DESTINATION "prebuilt/${PACKAGE_HOST}/include/cppjs-lib-${HEADER_FOLDER}")
31
39
  endif(BUILD_SOURCE)
32
40
  unset(BUILD_SOURCE CACHE)
33
41
 
34
- if(BUILD_BRIDGE)
35
- install(TARGETS "${PROJECT_NAME}")
42
+ if (BUILD_BRIDGE)
43
+ install(TARGETS "${PROJECT_NAME}")
36
44
  endif(BUILD_BRIDGE)
37
45
  unset(BUILD_BRIDGE CACHE)
@@ -0,0 +1,19 @@
1
+ cmake_minimum_required(VERSION 3.25)
2
+ set(CMAKE_CXX_STANDARD 11)
3
+ set(PROJECT_NAME "___PROJECT_NAME___")
4
+ project("${PROJECT_NAME}")
5
+
6
+ set(PACKAGE_HOST "${CMAKE_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
7
+
8
+ find_library(PROJECT_LIBRARY
9
+ NAMES "${PROJECT_NAME}"
10
+ PATHS "${PROJECT_SOURCE_DIR}/${PACKAGE_HOST}/lib"
11
+ NO_CACHE
12
+ NO_DEFAULT_PATH
13
+ NO_CMAKE_FIND_ROOT_PATH
14
+ REQUIRED
15
+ )
16
+
17
+ add_library("${PROJECT_NAME}" INTERFACE)
18
+ target_link_libraries("${PROJECT_NAME}" INTERFACE "${PROJECT_LIBRARY}")
19
+ target_include_directories("${PROJECT_NAME}" INTERFACE "${PROJECT_SOURCE_DIR}/${PACKAGE_HOST}/include")
package/src/bin.js CHANGED
@@ -55,11 +55,14 @@ function generateLib(platform, output, base) {
55
55
 
56
56
  compiler.createBridge();
57
57
  compiler.createWasm({ cc: ['-O3'] });
58
- createDir('lib', compiler.config.paths.output);
58
+ createDir('prebuilt', compiler.config.paths.output);
59
59
  fs.copyFileSync(`${compiler.config.paths.temp}/${compiler.config.general.name}.js`, `${compiler.config.paths.output}/${compiler.config.general.name}.js`);
60
60
  fs.copyFileSync(`${compiler.config.paths.temp}/${compiler.config.general.name}.wasm`, `${compiler.config.paths.output}/${compiler.config.general.name}.wasm`);
61
- fs.copyFileSync(`${compiler.config.paths.temp}/lib${compiler.config.general.name}.a`, `${compiler.config.paths.output}/lib/lib${compiler.config.general.name}.a`);
62
- fs.rmSync(`${compiler.config.paths.output}/include`, { recursive: true, force: true });
63
- fs.renameSync(`${compiler.config.paths.temp}/include`, `${compiler.config.paths.output}/include`);
61
+ fs.rmSync(`${compiler.config.paths.output}/prebuilt`, { recursive: true, force: true });
62
+ fs.renameSync(`${compiler.config.paths.temp}/prebuilt`, `${compiler.config.paths.output}/prebuilt`);
63
+
64
+ const distCmakeContent = fs.readFileSync(`${compiler.config.paths.cli}/assets/dist.cmake`, { encoding: 'utf8', flag: 'r' })
65
+ .replace('___PROJECT_NAME___', compiler.config.general.name);
66
+ fs.writeFileSync(`${compiler.config.paths.output}/prebuilt/CMakeLists.txt`, distCmakeContent);
64
67
  fs.rmSync(compiler.config.paths.temp, { recursive: true, force: true });
65
68
  }
@@ -4,6 +4,7 @@ import pullDockerImage, { getDockerImage } from '../utils/pullDockerImage.js';
4
4
  import getBaseInfo from '../utils/getBaseInfo.js';
5
5
  import getPathInfo from '../utils/getPathInfo.js';
6
6
  import getOsUserAndGroupId from '../utils/getOsUserAndGroupId.js';
7
+ import { getCliCMakeListsFile } from '../utils/findCMakeListsFile.js'
7
8
 
8
9
  export default function createWasm(compiler, options = {}) {
9
10
  const compiler2 = new CppjsCompiler(
@@ -13,6 +14,29 @@ export default function createWasm(compiler, options = {}) {
13
14
  return compiler2.compile();
14
15
  }
15
16
 
17
+ function setPath(arr, dependency, type, filter = () => {}) {
18
+ if (filter(dependency)) {
19
+ if (type === 'this') {
20
+ arr.push(dependency);
21
+ } else if (Array.isArray(dependency.paths[type])) {
22
+ arr.push(...dependency.paths[type]);
23
+ } else {
24
+ arr.push(dependency.paths[type]);
25
+ }
26
+ }
27
+
28
+ dependency.dependencies.forEach(dep => {
29
+ setPath(arr, dep, type, filter);
30
+ });
31
+ }
32
+
33
+ function getParentPath(path) {
34
+ const pathArray = path.split('/');
35
+ pathArray.pop();
36
+ return pathArray.join('/');
37
+ }
38
+
39
+
16
40
  class CppjsCompiler {
17
41
  constructor(config, options) {
18
42
  this.config = config;
@@ -22,16 +46,23 @@ class CppjsCompiler {
22
46
  compile() {
23
47
  pullDockerImage();
24
48
 
49
+ this.prepare();
25
50
  this.cmake(this.config.general.name, true, false);
26
51
  this.make();
27
52
  this.cmake(this.config.general.name+'bridge', false, true);
28
53
  this.make();
29
54
 
55
+ const dependLibs = [
56
+ ...glob.sync(`${this.config.paths.temp}/dependencies/**/*.a`, { absolute: true, cwd: this.config.paths.project }),
57
+ ];
58
+ this.cmakeDepends.forEach((d) => {
59
+ dependLibs.push(...glob.sync(`${d.paths.output}/prebuilt/Emscripten-x86_64/**/*.a`, { absolute: true, cwd: d.paths.project }));
60
+ });
61
+
30
62
  this.libs = [
31
63
  `${this.config.paths.temp}/lib${this.config.general.name}.a`,
32
64
  `${this.config.paths.temp}/lib${this.config.general.name}bridge.a`,
33
- ...glob.sync("node_modules/cppjs-lib-*-wasm/lib/lib*.a", { absolute: true, cwd: this.config.paths.project }),
34
- ...glob.sync("node_modules/cppjs-lib-*-wasm/node_modules/cppjs-lib-*-wasm/lib/lib*.a", { absolute: true, cwd: this.config.paths.project }),
65
+ ...dependLibs,
35
66
  ].filter(path => !!path.toString()).map(path => `/live/${getPathInfo(path, this.config.paths.base).relative}`);
36
67
 
37
68
  this.cc();
@@ -39,6 +70,42 @@ class CppjsCompiler {
39
70
  return this.config.paths.temp;
40
71
  }
41
72
 
73
+ prepare() {
74
+ const sourceFilter = (d) => d === this.config || d.export.type === 'source';
75
+ this.headerPathWithDepends = [];
76
+ setPath(this.headerPathWithDepends, this.config, 'header', sourceFilter);
77
+ this.headerPathWithDepends = this.headerPathWithDepends.map(p => `/live/${getPathInfo(p, this.config.paths.base).relative}`).join(';');
78
+
79
+ this.headerGlob = [];
80
+ this.headerPathWithDepends.split(';').forEach(h => {
81
+ this.config.ext.header.forEach(ext => {
82
+ this.headerGlob.push(`${h}/*.${ext}`);
83
+ });
84
+ });
85
+
86
+
87
+ this.nativePathWithDepends = [];
88
+ setPath(this.nativePathWithDepends, this.config, 'native', sourceFilter);
89
+ this.nativePathWithDepends = this.nativePathWithDepends.map(p => `/live/${getPathInfo(p, this.config.paths.base).relative}`).join(';');
90
+
91
+ this.nativeGlob = [];
92
+ this.nativePathWithDepends.split(';').forEach(h => {
93
+ this.config.ext.source.forEach(ext => {
94
+ this.nativeGlob.push(`${h}/*.${ext}`);
95
+ });
96
+ });
97
+
98
+ const cliCMakeListsFile = getCliCMakeListsFile();
99
+ const cmakeFilter = (d) => d !== this.config && d.export.type === 'cmake' && d.paths.cmake !== cliCMakeListsFile;
100
+ this.cmakeDepends = [];
101
+ setPath(this.cmakeDepends, this.config, 'this', cmakeFilter);
102
+
103
+ this.pathsOfCmakeDepends = this.cmakeDepends
104
+ .map(d => getParentPath(d.paths.cmake))
105
+ .map(p => `/live/${getPathInfo(p, this.config.paths.base).relative}`).join(';');
106
+ this.nameOfCmakeDepends = this.cmakeDepends.map(d => d.general.name).join(';');
107
+ }
108
+
42
109
  cmake(name, isBuildSource, isBuildBridge) {
43
110
  const params = [];
44
111
  if (isBuildSource) params.push('-DBUILD_SOURCE=TRUE');
@@ -46,20 +113,19 @@ class CppjsCompiler {
46
113
 
47
114
  const output = getPathInfo(this.config.paths.temp, this.config.paths.base);
48
115
  const projectPath = getPathInfo(process.cwd(), this.config.paths.base);
49
- const native = this.config.paths.native.map(p => `/live/${getPathInfo(p, this.config.paths.base).relative}`).join(';');
50
- const header = this.config.paths.header.map(p => `/live/${getPathInfo(p, this.config.paths.base).relative}`).join(';');
51
116
  const base = getBaseInfo(this.config.paths.base);
52
117
 
53
- let cMakeParentPath = this.config.paths.cmake.split('/');
54
- cMakeParentPath.pop();
55
- cMakeParentPath = cMakeParentPath.join('/');
118
+ const cMakeParentPath = getParentPath(this.config.paths.cmake);
119
+
56
120
  const args = [
57
121
  "run", "--user", getOsUserAndGroupId(), "-v", `${base.withoutSlash}:/live`, "-v", `${cMakeParentPath}:/cmake`, "--workdir", `/live/${output.relative}`, getDockerImage(),
58
122
  "emcmake", "cmake", "/cmake", '-DCMAKE_BUILD_TYPE=Release',
59
123
  `-DBASE_DIR=/live/${projectPath.relative}`,
60
- `-DNATIVE_GLOB=${this.config.ext.source.map(ext => `${native}/*.${ext}`).join(';')}`,
61
- `-DHEADER_GLOB=${this.config.ext.header.map(ext => `${header}/*.${ext}`).join(';')}`,
62
- `-DHEADER_DIR=${header}`,
124
+ `-DNATIVE_GLOB=${this.nativeGlob.join(';')}`,
125
+ `-DHEADER_GLOB=${this.headerGlob.join(';')};`,
126
+ `-DHEADER_DIR=${this.headerPathWithDepends}`,
127
+ `-DDEPENDS_CMAKE_PATHS=${this.pathsOfCmakeDepends}`,
128
+ `-DDEPENDS_CMAKE_NAMES=${this.nameOfCmakeDepends}`,
63
129
  `-DCMAKE_INSTALL_PREFIX=/live/${output.relative}`, `-DBRIDGE_DIR=/live/${output.relative}/bridge`, `-DPROJECT_NAME=${name}`, ...params,
64
130
  ];
65
131
  const options = { cwd: this.config.paths.temp, stdio : 'pipe' };
@@ -67,6 +133,7 @@ class CppjsCompiler {
67
133
  return this.config.paths.temp;
68
134
  }
69
135
 
136
+
70
137
  make() {
71
138
  const output = getPathInfo(this.config.paths.temp, this.config.paths.base);
72
139
  const base = getBaseInfo(this.config.paths.base);
@@ -31,6 +31,9 @@ export default function findOrCreateInterfaceFile(compiler, filePath) {
31
31
  #include "${headerPath}"
32
32
  %}
33
33
 
34
+ %feature("shared_ptr");
35
+ %feature("polymorphic_shared_ptr");
36
+
34
37
  %include "${headerPath}"
35
38
 
36
39
  #endif
package/src/index.js CHANGED
@@ -4,8 +4,8 @@ import createWasm from './functions/createWasm.js';
4
4
  import getConfig from './utils/getConfig.js';
5
5
 
6
6
  export default class CppjsCompiler {
7
- constructor(param) {
8
- this.config = getConfig(param);
7
+ constructor() {
8
+ this.config = getConfig();
9
9
  this.interfaces = [];
10
10
  }
11
11
 
@@ -2,7 +2,7 @@ import fs from 'fs';
2
2
  import p from 'path';
3
3
 
4
4
  export default function createTempDir(folder = 'a'+Math.random(), base = process.cwd()) {
5
- const path = p.join(base, 'node_modules', ".cppjs");
5
+ const path = p.join(base, ".cppjs");
6
6
  return createDir(folder, path);
7
7
  }
8
8
 
@@ -8,5 +8,9 @@ export default function findCMakeListsFile(basePath = process.cwd()) {
8
8
  }
9
9
 
10
10
  if (temp.length > 0) return temp[0];
11
+ return getCliCMakeListsFile();
12
+ }
13
+
14
+ export function getCliCMakeListsFile() {
11
15
  return getCliPath() + '/assets/CMakeLists.txt';
12
16
  }
@@ -3,16 +3,15 @@ import createTempDir, { createDir } from './createTempDir.js';
3
3
  import findCMakeListsFile from './findCMakeListsFile.js';
4
4
  import p from 'path';
5
5
  import * as url from 'node:url';
6
- import { createRequire } from 'module';
7
6
 
8
7
  const __filename = url.fileURLToPath(import.meta.url);
9
8
  const temp = __filename.split('/'); temp.pop(); temp.pop();
10
9
  const __dirname = temp.join('/');
11
- const require = createRequire(import.meta.url);
12
10
 
13
11
  /**
14
12
  * @typedef {Object} Config
15
13
  * @property {string} general General
14
+ * @property {any[]} dependencies Dependencies
16
15
  * @property {ConfigPaths} paths Paths
17
16
  * @property {ConfigExtensions} ext Extensions
18
17
  */
@@ -42,44 +41,37 @@ const require = createRequire(import.meta.url);
42
41
  * @property {string} name Project name
43
42
  */
44
43
 
45
- export default function getConfig(param) {
46
- let tempConfig = { general: {}, paths: {}, ext: {} };
44
+ let tempConfig = { general: {}, dependencies: [], paths: {}, ext: {}, export: {} };
45
+ await initDefaultConfigFile();
47
46
 
48
- if (!param || (typeof param === 'string' || param instanceof String)) {
49
- const ext = (param || '').split('.').at(-1)
50
- let filePath;
47
+ async function initDefaultConfigFile() {
48
+ let filePath;
49
+ ['json', 'js', 'mjs', 'cjs', 'ts'].some(e => {
50
+ filePath = `${process.cwd()}/cppjs.config.${e}`;
51
+ if (!fs.existsSync(filePath)) filePath = null;
52
+ else return true;
53
+ });
51
54
 
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;
55
+ if (filePath) {
56
+ let file = await import(filePath);
57
+ if (file.default) file = file.default;
58
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');
59
+ if (typeof file === 'function') tempConfig = file();
60
+ else if (typeof file === "object") tempConfig = file;
73
61
  }
62
+ }
74
63
 
64
+ export default function getConfig() {
75
65
  return fillConfig(forceToConfigSchema(tempConfig));
76
66
  }
77
67
 
78
68
  function forceToConfigSchema(tempConfig) {
79
69
  const config = {
80
70
  general: tempConfig && tempConfig.general ? tempConfig.general : {},
71
+ dependencies: tempConfig && tempConfig.dependencies ? tempConfig.dependencies : [],
81
72
  paths: tempConfig && tempConfig.paths ? tempConfig.paths : {},
82
73
  ext: tempConfig && tempConfig.ext ? tempConfig.ext : {},
74
+ export: tempConfig && tempConfig.export ? tempConfig.export : {},
83
75
  };
84
76
  return config;
85
77
  }
@@ -97,13 +89,15 @@ function getAbsolutePath(projectPath, path) {
97
89
  return p.resolve(path);
98
90
  }
99
91
 
100
- function fillConfig(tempConfig) {
92
+ function fillConfig(tempConfig, options = {}) {
101
93
  const config = {
102
94
  general: {},
95
+ dependencies: tempConfig.dependencies ? tempConfig.dependencies.map(d => fillConfig(forceToConfigSchema(d), { depend: true })) : [],
103
96
  paths: {
104
97
  project: getAbsolutePath(null, tempConfig.paths.project) || process.cwd(),
105
98
  },
106
99
  ext: {},
100
+ export: {},
107
101
  };
108
102
 
109
103
  if (!config.general.name) {
@@ -126,13 +120,18 @@ function fillConfig(tempConfig) {
126
120
  config.paths.header = (tempConfig.paths.header || config.paths.native).map(p => getPath(p));
127
121
  config.paths.bridge = (tempConfig.paths.bridge || [...config.paths.native, config.paths.temp]).map(p => getPath(p));
128
122
  config.paths.output = getPath(tempConfig.paths.output) || config.paths.temp;
129
- config.paths.cmake = getPath(tempConfig.paths.cmake || findCMakeListsFile(config.paths.project));
123
+ config.paths.cmake = options.depend ? findCMakeListsFile(config.paths.output) : getPath(tempConfig.paths.cmake || findCMakeListsFile(config.paths.project));
130
124
  config.paths.cli = __dirname;
131
125
 
132
126
  config.ext.header = tempConfig.ext.header || ['h', 'hpp', 'hxx', 'hh'];
133
127
  config.ext.source = tempConfig.ext.source || ['c', 'cpp', 'cxx', 'cc'];
134
128
  config.ext.module = tempConfig.ext.module || ['i'];
135
129
 
130
+ config.export.type = tempConfig.export.type || 'cmake';
131
+ config.export.header = tempConfig.export.header || 'include';
132
+ config.export.libPath = getPath(tempConfig.export.libPath || 'lib');
133
+ config.export.libName = tempConfig.export.libName || [`lib${config.general.name}.a`];
134
+
136
135
  createDir('interface', config.paths.temp);
137
136
  createDir('bridge', config.paths.temp);
138
137
 
@@ -0,0 +1,7 @@
1
+ import * as url from 'node:url';
2
+
3
+ export default function getDirName(importUrl) {
4
+ const __filename = url.fileURLToPath(importUrl);
5
+ const temp = __filename.split('/'); temp.pop();
6
+ return temp.join('/');
7
+ }