-
-
Notifications
You must be signed in to change notification settings - Fork 218
Expand file tree
/
Copy pathload-addon.ts
More file actions
119 lines (104 loc) · 3.06 KB
/
load-addon.ts
File metadata and controls
119 lines (104 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import path from "path"
import fs from "fs"
function errStr(error: unknown) {
return error instanceof Error
? `${error.name}: ${error.message}\n${error.stack}`
: String(error)
}
function devWarn(message: string) {
if (process.env.NODE_ENV !== "production") {
console.warn(message)
}
}
function findAddon(): any | undefined {
let addon: undefined | any = undefined
try {
const buildDir = path.resolve(__dirname, "..", "build")
const manifest = JSON.parse(
fs.readFileSync(path.resolve(buildDir, "manifest.json"), "utf-8"),
) as Record<string, string>
// compatible addons (abi -> addon path)
const compatibleAddons: Record<string, string> = {}
const configs = Object.keys(manifest)
for (const configStr of configs) {
const config = JSON.parse(configStr) as BuildConfiguration
// check if the config is compatible with the current runtime
if (config.os !== process.platform || config.arch !== process.arch) {
continue
}
const libc = detectLibc()
if (config.libc !== libc) {
continue
}
const addonRelativePath = manifest[configStr]
compatibleAddons[config.abi ?? 0] = path.resolve(
buildDir,
addonRelativePath,
)
}
// sort the compatible abis in descending order
const compatibleAbis = Object.keys(compatibleAddons).sort((a, b) => {
return Number.parseInt(b, 10) - Number.parseInt(a, 10)
})
// try each available addon ABI
for (const abi of compatibleAbis) {
const addonPath = compatibleAddons[abi]
try {
addon = require(addonPath)
break
} catch (err) {
if (fs.existsSync(addonPath)) {
devWarn(
`Failed to load addon at ${addonPath}: ${errStr(err)}\nTrying others...`,
)
} else {
devWarn(`No addon.node found in ${addonPath}\nTrying others...`)
}
}
}
} catch (err) {
throw new Error(`Failed to load zeromq.js addon.node: ${errStr(err)}`)
}
if (addon === undefined) {
throw new Error("No compatible zeromq.js addon found")
}
return addon
}
/**
* Build configuration (from cmake-ts)
*/
type BuildConfiguration = {
name: string
dev: boolean
os: typeof process.platform
arch: typeof process.arch
runtime: string
runtimeVersion: string
toolchainFile: string | null
CMakeOptions?: {name: string; value: string}[]
addonSubdirectory: string
// list of additional definitions to fixup node quirks for some specific versions
additionalDefines: string[]
/** The ABI number that is used by the runtime. */
abi?: number
/** The libc that is used by the runtime. */
libc?: string
}
/**
* Detect the libc used by the runtime (from cmake-ts)
*/
function detectLibc() {
if (process.platform === "linux") {
if (fs.existsSync("/etc/alpine-release")) {
return "musl"
}
return "glibc"
} else if (process.platform === "darwin") {
return "libc"
} else if (process.platform === "win32") {
return "msvc"
}
return "unknown"
}
const addon = findAddon()
export default addon