-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfix-python-soname.js
More file actions
executable file
·139 lines (118 loc) · 4.01 KB
/
fix-python-soname.js
File metadata and controls
executable file
·139 lines (118 loc) · 4.01 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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env node
/**
* Post-install script to fix Python library soname on Linux
*
* This script automatically detects the system-installed Python version
* and updates the .node binary to link against the correct libpython.so.
*
* Only runs on Linux - other platforms don't need soname fixing.
* Uses a WASM version of the arwen ELF patcher for cross-platform compatibility.
*/
const { WASI } = require('wasi')
const fs = require('fs')
const path = require('path')
const os = require('os')
const platform = os.platform()
const arch = os.arch()
// Function to detect if this is a development install vs dependency install
function isDevInstall() {
const env = process.env
// Method 1: Check if INIT_CWD and PWD are the same (local dev install)
if (env.INIT_CWD && env.PWD) {
if (env.INIT_CWD === env.PWD || env.INIT_CWD.indexOf(env.PWD) === 0) {
return true
}
}
// Method 2: Check for .git folder existence (dev environment)
if (fs.existsSync(path.join(__dirname, '.git'))) {
return true
}
// Method 3: Check if we're in production mode
if (env.NODE_ENV === 'production' || env.npm_config_production) {
return false
}
return false
}
// Function to find the correct .node file for this platform
function findNodeFile() {
// Only run on Linux - other platforms don't need soname fixing
if (platform !== 'linux') return
// Map Node.js arch to napi-rs target
const archMap = {
'x64': 'x86_64-unknown-linux-gnu',
'arm64': 'aarch64-unknown-linux-gnu',
}
const target = archMap[arch]
if (!target) return
// Try to find the .node file with various naming patterns
const possiblePaths = [
// Specific platform builds
path.join(__dirname, `python-node.${target}.node`),
path.join(__dirname, `index.${target}.node`),
path.join(__dirname, `npm/${target}/python-node.${target}.node`),
// Generic .node files (common during testing)
path.join(__dirname, 'python-node.node'),
path.join(__dirname, 'index.node'),
// Look for any .node file in current directory
...fs.readdirSync(__dirname)
.filter(f => f.endsWith('.node') && !f.includes('node_modules'))
.map(f => path.join(__dirname, f))
]
for (const nodePath of possiblePaths) {
if (fs.existsSync(nodePath)) {
return nodePath
}
}
// Return undefined if no .node file found - this is expected during development
return undefined
}
// Get the node file path
const nodeFilePath = findNodeFile()
if (!nodeFilePath) {
if (isDevInstall()) {
// No .node file found during dev install - this is expected, skip silently
console.log('No .node file found during development install, skipping soname fix')
process.exit(0)
} else {
// No .node file found when installed as dependency - this is an error
console.error('Error: Could not find *.node file to fix soname')
process.exit(1)
}
}
// Check if WASM file exists
const wasmPath = path.join(__dirname, 'fix-python-soname.wasm')
if (!fs.existsSync(wasmPath)) {
if (isDevInstall()) {
// WASM file not found during dev install - this is expected, skip with warning
console.log('WASM file not found during development install, skipping soname fix')
process.exit(0)
} else {
// WASM file not found when installed as dependency - this is an error
console.error('Error: fix-python-soname.wasm not found')
process.exit(1)
}
}
console.log(`Running soname fix on ${nodeFilePath}`)
// Create a WASI instance
const wasi = new WASI({
version: 'preview1',
args: ['fix-python-soname', nodeFilePath],
env: process.env,
preopens: {
'/': '/',
}
})
async function runSonameFixer() {
try {
const wasm = fs.readFileSync(wasmPath);
const { instance } = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport
});
// Run the WASI module
process.exit(wasi.start(instance))
} catch (error) {
console.error('Error: Failed to run soname fixer:', error.message)
process.exit(1) // Fail hard when installed as dependency
}
}
runSonameFixer()