Skip to content
This repository has been archived by the owner on Sep 1, 2023. It is now read-only.

Commit

Permalink
feat: add support for Node.js environment
Browse files Browse the repository at this point in the history
  • Loading branch information
luoxuhai committed Oct 24, 2022
1 parent b9d32d9 commit c52850f
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 67 deletions.
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
"module": "dist/pcl.esm.js",
"exports": {
".": {
"import": "./dist/pcl.esm.js",
"require": "./dist/pcl.cjs.js",
"types": "./dist/pcl.d.ts"
"browser": {
"import": "./dist/pcl.esm.js",
"require": "./dist/pcl.cjs.js"
},
"node": {
"import": "./dist/node/pcl.esm.js",
"require": "./dist/node/pcl.cjs.js"
}
},
"./pcl-core.wasm": "./dist/pcl-core.wasm",
"./pcl-core.node.wasm": "./dist/node/pcl-core.wasm",
"./PointCloudViewer": "./dist/visualization/PointCloudViewer.esm.js"
},
"typesVersions": {
Expand Down
49 changes: 36 additions & 13 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,7 @@ ${code}`;
function replaceCode() {
return {
renderChunk(code) {
return (
code
.replace('assert(!flags, flags);', '')
// test environment
.replace(
"ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'",
'ENVIRONMENT_IS_NODE = false',
)
);
return code.replace('assert(!flags, flags);', '');
},
};
}
Expand Down Expand Up @@ -81,8 +73,8 @@ const commonPlugins = [
banner(),
];

const coreConfig = {
input: 'src/core/index.ts',
const browserCoreConfig = {
input: 'src/core/browser.ts',
output: [
{
file: pkg.main,
Expand Down Expand Up @@ -130,6 +122,36 @@ const coreConfig = {
],
};

const nodeCoreConfig = {
input: 'src/core/node.ts',
output: [
{
file: pkg.exports['.'].node.require,
format: 'cjs',
},
{
file: pkg.exports['.'].node.import,
format: 'esm',
},
],
plugins: [
...commonPlugins,
replaceCode(),
replace(constants),
typescript({
useTsconfigDeclarationDir: true,
}),
copy({
targets: [
{
src: 'src/bind/build/pcl-core.node.wasm',
dest: 'dist/node',
},
],
}),
],
};

const visualizationModules = ['PointCloudViewer'];
const globals = {
three: 'THREE',
Expand Down Expand Up @@ -178,10 +200,11 @@ const visualizationConfig = visualizationModules.map((name) => {
});

const config = [
coreConfig,
browserCoreConfig,
nodeCoreConfig,
...visualizationConfig,
{
input: './dist/.types/core/index.d.ts',
input: './dist/.types/core/browser.d.ts',
output: [{ file: 'dist/pcl.d.ts', format: 'es' }],
plugins: collectTypeDefinition('PCL'),
},
Expand Down
3 changes: 2 additions & 1 deletion scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ EMFLAGS=(
emcmake cmake ${EMFLAGS[@]} ..
emmake make -j

mkdir -p ${WASM_OUT_DIR}
mkdir -p ${WASM_OUT_DIR} ${WASM_OUT_DIR}/node
cp pcl-core.wasm ${WASM_OUT_DIR}
cp pcl-core.node.wasm ${WASM_OUT_DIR}/node
23 changes: 14 additions & 9 deletions src/bind/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
cmake_minimum_required(VERSION 3.22)

# Base
set(PROJECT_NAME pcl-core)
project(${PROJECT_NAME})
project(PCL_BIND_WASM)
set(CMAKE_CXX_STANDARD 14)

# Base
set(TARGET_NAME_BROWSER pcl-core)
set(TARGET_NAME_NODE pcl-core.node)

set(PCL_INCLUDE ${PCL_ROOT}/build/include/pcl-1.12)
set(BOOST_INCLUDE ${PCL_ROOT}/wasm/deps/boost/build/include)
set(EIGEN_INCLUDE ${PCL_ROOT}/wasm/deps/eigen)
Expand All @@ -25,19 +27,22 @@ foreach(SRC IN LISTS SRCS)
message(STATUS ${SRC})
endforeach(SRC)

add_executable(${PROJECT_NAME} ${SRCS})
target_link_libraries(${PROJECT_NAME} ${PCL_LINK_LIBS} flann_cpp_s boost_filesystem boost_regex boost_system boost_date_time boost_iostreams)
add_executable(${TARGET_NAME_BROWSER} ${SRCS})
add_executable(${TARGET_NAME_NODE} ${SRCS})
target_link_libraries(${TARGET_NAME_BROWSER} ${PCL_LINK_LIBS} flann_cpp_s boost_filesystem boost_regex boost_system boost_date_time boost_iostreams)
target_link_libraries(${TARGET_NAME_NODE} ${PCL_LINK_LIBS} flann_cpp_s boost_filesystem boost_regex boost_system boost_date_time boost_iostreams)

option(CMAKE_BUILD_TYPE "This is a option for build type" "Debug")

set(INCOMING_MODULE_JS_API "fetchSettings,locateFile,wasmBinary")
set(COMMON_LINK_FLAGS "-lembind -sSTRICT=1 -sSTRICT_JS=1 -sALLOW_MEMORY_GROWTH=1 -sMODULARIZE=1 -sEXPORT_ES6=1 -sUSE_ES6_IMPORT_META=0 -sEXPORT_NAME=PCLCore -sENVIRONMENT=web,webview,worker -sINCOMING_MODULE_JS_API=${INCOMING_MODULE_JS_API} -sEXPORTED_RUNTIME_METHODS=FS --no-entry -sWASM_BIGINT=1")
set(BROWSER_ENV_FLAGS "-sENVIRONMENT=web,webview,worker")
set(NODE_ENV_FLAGS "-sENVIRONMENT=node")
set(COMMON_LINK_FLAGS "-lembind -sSTRICT=1 -sSTRICT_JS=1 -sALLOW_MEMORY_GROWTH=1 -sMODULARIZE=1 -sEXPORT_ES6=1 -sUSE_ES6_IMPORT_META=0 -sEXPORT_NAME=PCLCore -sINCOMING_MODULE_JS_API=${INCOMING_MODULE_JS_API} -sEXPORTED_RUNTIME_METHODS=FS --no-entry -sWASM_BIGINT=1")

set(EM_LINK_FLAGS "${COMMON_LINK_FLAGS} -g -sLLD_REPORT_UNDEFINED -sVERBOSE=1")
if (${CMAKE_BUILD_TYPE} STREQUAL "Release")
set(EM_LINK_FLAGS "${COMMON_LINK_FLAGS} -O3")
endif()

set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS ${EM_LINK_FLAGS})

install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
set_target_properties(${TARGET_NAME_BROWSER} PROPERTIES LINK_FLAGS "${EM_LINK_FLAGS} ${BROWSER_ENV_FLAGS}")
set_target_properties(${TARGET_NAME_NODE} PROPERTIES LINK_FLAGS "${EM_LINK_FLAGS} ${NODE_ENV_FLAGS}")
16 changes: 16 additions & 0 deletions src/bind/build/pcl-core.node.js

Large diffs are not rendered by default.

Binary file added src/bind/build/pcl-core.node.wasm
Binary file not shown.
50 changes: 9 additions & 41 deletions src/core/index.ts → src/core/base.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import initPCLCore from '@/bind/build/pcl-core';
import { ENVIRONMENT_IS_NODE } from '@/utils';
import { Emscripten } from '@/types';
import { ENVIRONMENT_IS_NODE } from '@/utils';

if (window.__PCLCore__) {
if (((ENVIRONMENT_IS_NODE ? global : window) as any).__PCLCore__) {
console.warn('Multiple instances of pcl.js being imported.');
} else {
window.__PCLCore__ = null;
((ENVIRONMENT_IS_NODE ? global : window) as any).__PCLCore__ = null;
}

let isInitialized = false;

interface InitOptions {
export interface InitOptions {
/**
* ArrayBuffer for pcl-core.wasm file.
*/
Expand All @@ -19,6 +16,11 @@ interface InitOptions {
* URL for pcl-core.wasm file.
*/
url?: string;
/**
* path for pcl-core.wasm file.
* **Only supported by nodejs environment.**
*/
path?: string;
/**
* Override the default settings object used when fetching the Wasm module from the network.
*
Expand All @@ -29,40 +31,6 @@ interface InitOptions {
onerror?: (error: unknown) => void;
}

async function init(options?: InitOptions) {
const {
arrayBuffer,
url,
fetchOptions: fetchSettings = { credentials: 'same-origin' },
} = options ?? {};

const moduleOptions: Emscripten.ModuleOpts = {
wasmBinary: arrayBuffer,
locateFile: (path, scriptDirectory) => url || scriptDirectory + path,
fetchSettings,
};

try {
const __PCLCore__ = await initPCLCore(moduleOptions);
if (ENVIRONMENT_IS_NODE) {
(global as any).__PCLCore__ = __PCLCore__;
} else {
window.__PCLCore__ = __PCLCore__;
}
isInitialized = true;
options?.onsuccess?.();
} catch (error) {
options?.onerror?.(error);
throw error;
}
}

function destroy() {
window.__PCLCore__ = null;
isInitialized = false;
}

export { InitOptions, init, destroy, isInitialized };
export * from '@/constants';
export * as fs from '@/modules/fs';
export * from '@/modules/common';
Expand Down
36 changes: 36 additions & 0 deletions src/core/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import initPCLCore from '@/bind/build/pcl-core';
import { Emscripten } from '@/types';
import { InitOptions } from './base';

let isInitialized = false;

async function init(options?: InitOptions) {
const {
arrayBuffer,
url,
fetchOptions: fetchSettings = { credentials: 'same-origin' },
} = options ?? {};

const moduleOptions: Emscripten.ModuleOpts = {
wasmBinary: arrayBuffer,
locateFile: (path, scriptDirectory) => url || scriptDirectory + path,
fetchSettings,
};

try {
window.__PCLCore__ = await initPCLCore(moduleOptions);
isInitialized = true;
options?.onsuccess?.();
} catch (error) {
options?.onerror?.(error);
throw error;
}
}

function destroy() {
window.__PCLCore__ = null;
isInitialized = false;
}

export { init, destroy, isInitialized, InitOptions };
export * from './base';
49 changes: 49 additions & 0 deletions src/core/node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import initPCLCore from '@/bind/build/pcl-core.node';
import { Emscripten } from '@/types';
import { InitOptions } from './base';
import https from 'http';

let isInitialized = false;

async function init(options?: InitOptions) {
const { arrayBuffer, path, url } = options ?? {};

let wasmBinary = arrayBuffer;
if (url) {
wasmBinary = await fetchWASM(url);
}

const moduleOptions: Emscripten.ModuleOpts = {
wasmBinary,
locateFile: (p, scriptDirectory) => path || scriptDirectory + p,
};

try {
(global as any).__PCLCore__ = await initPCLCore(moduleOptions);
isInitialized = true;
options?.onsuccess?.();
} catch (error) {
options?.onerror?.(error);
throw error;
}
}

function fetchWASM(url: string): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
https
.get(url, (res) => {
res.on('data', (data) => {
resolve(data);
});
})
.on('error', reject);
});
}

function destroy() {
(global as any).__PCLCore__ = null;
isInitialized = false;
}

export { init, destroy, isInitialized, InitOptions };
export * from './base';

1 comment on commit c52850f

@vercel
Copy link

@vercel vercel bot commented on c52850f Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

pcl-js – ./

pcl-js-darkce.vercel.app
pcl.js.org
pcl-js-git-master-darkce.vercel.app
pcljs.org
www.pcljs.org

Please sign in to comment.