2021-04-27 07:04:25 +00:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
// Licensed under the MIT License.
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
import { spawnSync } from 'child_process';
|
2020-05-05 18:45:12 +00:00
|
|
|
import * as fs from 'fs-extra';
|
2020-05-27 20:30:22 +00:00
|
|
|
import minimist from 'minimist';
|
2021-10-26 23:42:19 +00:00
|
|
|
import * as os from 'os';
|
2020-05-05 18:45:12 +00:00
|
|
|
import * as path from 'path';
|
|
|
|
|
|
|
|
|
|
// command line flags
|
2020-05-27 20:30:22 +00:00
|
|
|
const buildArgs = minimist(process.argv.slice(2));
|
|
|
|
|
|
2021-10-26 03:16:10 +00:00
|
|
|
// --config=Debug|Release|RelWithDebInfo
|
2024-08-14 23:51:22 +00:00
|
|
|
const CONFIG: 'Debug' | 'Release' | 'RelWithDebInfo' =
|
|
|
|
|
buildArgs.config || (os.platform() === 'win32' ? 'RelWithDebInfo' : 'Release');
|
2020-05-27 20:30:22 +00:00
|
|
|
if (CONFIG !== 'Debug' && CONFIG !== 'Release' && CONFIG !== 'RelWithDebInfo') {
|
|
|
|
|
throw new Error(`unrecognized config: ${CONFIG}`);
|
|
|
|
|
}
|
2021-10-26 03:16:10 +00:00
|
|
|
// --arch=x64|ia32|arm64|arm
|
2024-08-14 23:51:22 +00:00
|
|
|
const ARCH: 'x64' | 'ia32' | 'arm64' | 'arm' = buildArgs.arch || os.arch();
|
2021-10-26 03:16:10 +00:00
|
|
|
if (ARCH !== 'x64' && ARCH !== 'ia32' && ARCH !== 'arm64' && ARCH !== 'arm') {
|
|
|
|
|
throw new Error(`unrecognized architecture: ${ARCH}`);
|
|
|
|
|
}
|
|
|
|
|
// --onnxruntime-build-dir=
|
2020-05-27 20:30:22 +00:00
|
|
|
const ONNXRUNTIME_BUILD_DIR = buildArgs['onnxruntime-build-dir'];
|
2024-04-03 03:19:31 +00:00
|
|
|
// --onnxruntime-generator=
|
|
|
|
|
const ONNXRUNTIME_GENERATOR = buildArgs['onnxruntime-generator'];
|
2021-10-26 03:16:10 +00:00
|
|
|
// --rebuild
|
2020-05-27 20:30:22 +00:00
|
|
|
const REBUILD = !!buildArgs.rebuild;
|
2023-08-25 23:57:06 +00:00
|
|
|
// --use_dml
|
|
|
|
|
const USE_DML = !!buildArgs.use_dml;
|
2024-11-04 21:09:07 +00:00
|
|
|
// --use_webgpu
|
|
|
|
|
const USE_WEBGPU = !!buildArgs.use_webgpu;
|
2023-08-25 23:57:06 +00:00
|
|
|
// --use_cuda
|
|
|
|
|
const USE_CUDA = !!buildArgs.use_cuda;
|
|
|
|
|
// --use_tensorrt
|
|
|
|
|
const USE_TENSORRT = !!buildArgs.use_tensorrt;
|
|
|
|
|
// --use_coreml
|
|
|
|
|
const USE_COREML = !!buildArgs.use_coreml;
|
2024-05-09 20:11:07 +00:00
|
|
|
// --use_qnn
|
|
|
|
|
const USE_QNN = !!buildArgs.use_qnn;
|
Fix delay load for WebGPU EP and DML EP (#23111)
### Description
This change fixes the DLL delay load problem for the WebGPU EP and
DirectML EP. See detailed explanation below.
### Problem
When onnxruntime.dll uses delay loading for its dependencies, the
dependencies are loaded using `LoadLibraryEx()`, which search the
directory of process (.exe) instead of this library (onnxruntime.dll).
This is a problem for usages of Node.js binding and python binding,
because Windows will try to find the dependencies in the directory of
node.exe or python.exe, which is not the directory of onnxruntime.dll.
There was previous attempt to fix this by loading DirectML.dll in the
initialization of onnxruntime nodejs binding, which works for DML EP but
is not a good solution because it does not really "delay" the load.
For WebGPU, the situation became worse because webgpu_dawn.dll depends
on dxil.dll and dxcompiler.dll, which are explicitly dynamically loaded
in the code using `LoadLibraryA()`. This has the same problem of the DLL
search.
### Solutions
For onnxruntime.dll loading its direct dependencies, it can be resolved
by set the [`__pfnDliNotifyHook2`
hook](https://learn.microsoft.com/en-us/cpp/build/reference/understanding-the-helper-function?view=msvc-170#structure-and-constant-definitions)
to load from an absolute path that constructed from the onnxruntime.dll
folder and the DLL name.
For webgpu_dawn.dll loading dxil.dll and dxcompiler.dll, since they are
explicitly loaded in the code, the hook does not work. Instead, it can
be resolved by ~~using WIN32 API `SetDllDirectory()` to add the
onnxruntime.dll folder to the search path.~~ preloading the 2 DLLs from
the onnxruntime.dll folder .
2024-12-19 18:23:48 +00:00
|
|
|
// --dll_deps=
|
|
|
|
|
const DLL_DEPS = buildArgs.dll_deps;
|
2020-05-05 18:45:12 +00:00
|
|
|
|
|
|
|
|
// build path
|
|
|
|
|
const ROOT_FOLDER = path.join(__dirname, '..');
|
|
|
|
|
const BIN_FOLDER = path.join(ROOT_FOLDER, 'bin');
|
2020-05-27 20:30:22 +00:00
|
|
|
const BUILD_FOLDER = path.join(ROOT_FOLDER, 'build');
|
2020-05-05 18:45:12 +00:00
|
|
|
|
|
|
|
|
// if rebuild, clean up the dist folders
|
|
|
|
|
if (REBUILD) {
|
|
|
|
|
fs.removeSync(BIN_FOLDER);
|
2020-05-27 20:30:22 +00:00
|
|
|
fs.removeSync(BUILD_FOLDER);
|
2020-05-05 18:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
2020-05-27 20:30:22 +00:00
|
|
|
const args = [
|
2023-03-08 23:03:27 +00:00
|
|
|
'cmake-js',
|
2024-08-14 23:51:22 +00:00
|
|
|
REBUILD ? 'reconfigure' : 'configure',
|
2021-10-26 03:16:10 +00:00
|
|
|
`--arch=${ARCH}`,
|
2023-08-25 06:07:02 +00:00
|
|
|
'--CDnapi_build_version=6',
|
2020-05-27 20:30:22 +00:00
|
|
|
`--CDCMAKE_BUILD_TYPE=${CONFIG}`,
|
|
|
|
|
];
|
|
|
|
|
if (ONNXRUNTIME_BUILD_DIR && typeof ONNXRUNTIME_BUILD_DIR === 'string') {
|
|
|
|
|
args.push(`--CDONNXRUNTIME_BUILD_DIR=${ONNXRUNTIME_BUILD_DIR}`);
|
|
|
|
|
}
|
2024-04-03 03:19:31 +00:00
|
|
|
if (ONNXRUNTIME_GENERATOR && typeof ONNXRUNTIME_GENERATOR === 'string') {
|
|
|
|
|
args.push(`--CDONNXRUNTIME_GENERATOR=${ONNXRUNTIME_GENERATOR}`);
|
|
|
|
|
}
|
2023-08-25 23:57:06 +00:00
|
|
|
if (USE_DML) {
|
|
|
|
|
args.push('--CDUSE_DML=ON');
|
|
|
|
|
}
|
2024-11-04 21:09:07 +00:00
|
|
|
if (USE_WEBGPU) {
|
|
|
|
|
args.push('--CDUSE_WEBGPU=ON');
|
|
|
|
|
}
|
2023-08-25 23:57:06 +00:00
|
|
|
if (USE_CUDA) {
|
|
|
|
|
args.push('--CDUSE_CUDA=ON');
|
|
|
|
|
}
|
|
|
|
|
if (USE_TENSORRT) {
|
|
|
|
|
args.push('--CDUSE_TENSORRT=ON');
|
|
|
|
|
}
|
|
|
|
|
if (USE_COREML) {
|
|
|
|
|
args.push('--CDUSE_COREML=ON');
|
|
|
|
|
}
|
2024-05-09 20:11:07 +00:00
|
|
|
if (USE_QNN) {
|
|
|
|
|
args.push('--CDUSE_QNN=ON');
|
|
|
|
|
}
|
Fix delay load for WebGPU EP and DML EP (#23111)
### Description
This change fixes the DLL delay load problem for the WebGPU EP and
DirectML EP. See detailed explanation below.
### Problem
When onnxruntime.dll uses delay loading for its dependencies, the
dependencies are loaded using `LoadLibraryEx()`, which search the
directory of process (.exe) instead of this library (onnxruntime.dll).
This is a problem for usages of Node.js binding and python binding,
because Windows will try to find the dependencies in the directory of
node.exe or python.exe, which is not the directory of onnxruntime.dll.
There was previous attempt to fix this by loading DirectML.dll in the
initialization of onnxruntime nodejs binding, which works for DML EP but
is not a good solution because it does not really "delay" the load.
For WebGPU, the situation became worse because webgpu_dawn.dll depends
on dxil.dll and dxcompiler.dll, which are explicitly dynamically loaded
in the code using `LoadLibraryA()`. This has the same problem of the DLL
search.
### Solutions
For onnxruntime.dll loading its direct dependencies, it can be resolved
by set the [`__pfnDliNotifyHook2`
hook](https://learn.microsoft.com/en-us/cpp/build/reference/understanding-the-helper-function?view=msvc-170#structure-and-constant-definitions)
to load from an absolute path that constructed from the onnxruntime.dll
folder and the DLL name.
For webgpu_dawn.dll loading dxil.dll and dxcompiler.dll, since they are
explicitly loaded in the code, the hook does not work. Instead, it can
be resolved by ~~using WIN32 API `SetDllDirectory()` to add the
onnxruntime.dll folder to the search path.~~ preloading the 2 DLLs from
the onnxruntime.dll folder .
2024-12-19 18:23:48 +00:00
|
|
|
if (DLL_DEPS) {
|
|
|
|
|
args.push(`--CDORT_NODEJS_DLL_DEPS=${DLL_DEPS}`);
|
|
|
|
|
}
|
2020-05-27 20:30:22 +00:00
|
|
|
|
2021-11-05 22:29:40 +00:00
|
|
|
// set CMAKE_OSX_ARCHITECTURES for macOS build
|
|
|
|
|
if (os.platform() === 'darwin') {
|
|
|
|
|
if (ARCH === 'x64') {
|
|
|
|
|
args.push('--CDCMAKE_OSX_ARCHITECTURES=x86_64');
|
|
|
|
|
} else if (ARCH === 'arm64') {
|
|
|
|
|
args.push('--CDCMAKE_OSX_ARCHITECTURES=arm64');
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error(`architecture not supported for macOS build: ${ARCH}`);
|
|
|
|
|
}
|
2021-10-26 23:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-22 22:05:04 +00:00
|
|
|
// In Windows, "npx cmake-js configure" uses a powershell script to detect the Visual Studio installation.
|
|
|
|
|
// The script uses the environment variable LIB. If an invalid path is specified in LIB, the script will fail.
|
|
|
|
|
// So we override the LIB environment variable to remove invalid paths.
|
2024-08-14 23:51:22 +00:00
|
|
|
const envOverride =
|
|
|
|
|
os.platform() === 'win32' && process.env.LIB
|
|
|
|
|
? { ...process.env, LIB: process.env.LIB.split(';').filter(fs.existsSync).join(';') }
|
|
|
|
|
: process.env;
|
2023-03-22 22:05:04 +00:00
|
|
|
|
2020-05-27 20:30:22 +00:00
|
|
|
// launch cmake-js configure
|
2024-08-14 23:51:22 +00:00
|
|
|
const procCmakejs = spawnSync('npx', args, { shell: true, stdio: 'inherit', cwd: ROOT_FOLDER, env: envOverride });
|
2020-05-27 20:30:22 +00:00
|
|
|
if (procCmakejs.status !== 0) {
|
|
|
|
|
if (procCmakejs.error) {
|
|
|
|
|
console.error(procCmakejs.error);
|
|
|
|
|
}
|
|
|
|
|
process.exit(procCmakejs.status === null ? undefined : procCmakejs.status);
|
2020-05-05 18:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
2020-05-27 20:30:22 +00:00
|
|
|
// launch cmake to build
|
2024-08-14 23:51:22 +00:00
|
|
|
const procCmake = spawnSync('cmake', ['--build', '.', '--config', CONFIG], {
|
|
|
|
|
shell: true,
|
|
|
|
|
stdio: 'inherit',
|
|
|
|
|
cwd: BUILD_FOLDER,
|
|
|
|
|
});
|
2020-05-27 20:30:22 +00:00
|
|
|
if (procCmake.status !== 0) {
|
|
|
|
|
if (procCmake.error) {
|
|
|
|
|
console.error(procCmake.error);
|
2020-05-05 18:45:12 +00:00
|
|
|
}
|
2020-05-27 20:30:22 +00:00
|
|
|
process.exit(procCmake.status === null ? undefined : procCmake.status);
|
2020-05-05 18:45:12 +00:00
|
|
|
}
|