update new-module skill and record linking debug strategy in README
This commit is contained in:
@@ -90,6 +90,49 @@ rm -rf ~/.cache/Pmodules/distfiles
|
||||
common modbuild traps ("done" without success — no errexit in hooks,
|
||||
partial downloads reused silently, slow installs on shared /opt/psi).
|
||||
|
||||
## Debugging shared-library errors (lib vs lib64, RPATH)
|
||||
|
||||
Compiled modules often build fine and then fail at load/run time with
|
||||
`cannot open shared object file` or `GLIBCXX_x.y.z not found`. Diagnose
|
||||
with binutils (works on any binary or `.so`, e.g. `/bin/cmake`):
|
||||
|
||||
```bash
|
||||
objdump -p <binary-or-.so> | grep NEEDED # which libs it links
|
||||
objdump -p <binary-or-.so> | grep -E 'RPATH|RUNPATH' # usually EMPTY on RHEL
|
||||
ldd <binary-or-.so> # how each resolves; look for "not found"
|
||||
```
|
||||
|
||||
The dynamic linker searches in this order: `DT_RPATH` (if set) →
|
||||
`LD_LIBRARY_PATH` → `DT_RUNPATH` (if set) → `/etc/ld.so.cache` →
|
||||
`/lib64`, `/usr/lib64`. On RHEL, RPATH/RUNPATH are normally **not set**,
|
||||
and the build-time `-L` paths are not recorded in the binary — so build
|
||||
time and runtime resolve libraries completely independently.
|
||||
|
||||
Situations where the default order is not what you expect:
|
||||
|
||||
1. **Compiled with a newer-gcc module** → the binary needs a newer
|
||||
libstdc++, but at runtime the old system `/usr/lib64/libstdc++.so.6`
|
||||
resolves first (no RPATH) → `GLIBCXX_... not found`. Fix: add the gcc
|
||||
module to `runtime_deps:` so its lib dir is prepended to
|
||||
`LD_LIBRARY_PATH` (see `pymol-open-source/files/config.yaml`).
|
||||
2. **lib vs lib64 install dir**: system 64-bit libs live in `/usr/lib64`,
|
||||
but local installs may land in `$PREFIX/lib` (autotools default, venvs)
|
||||
or `$PREFIX/lib64` (CMake GNUInstallDirs picks lib64 on RHEL). Check
|
||||
which dir the install actually produced and prepend that one:
|
||||
`prepend-path LD_LIBRARY_PATH $PREFIX/lib` (see `ImageMagick/modulefile`).
|
||||
3. **Vendor binary WITH RPATH baked in**: `DT_RPATH` beats
|
||||
`LD_LIBRARY_PATH`, so the modulefile cannot override it — patchelf or
|
||||
rebuild are the only fixes. With `DT_RUNPATH` instead, it is the other
|
||||
way round: `LD_LIBRARY_PATH` wins, so a leftover loaded module can
|
||||
shadow the vendor's bundled libs (another contaminated-environment
|
||||
source — `module purge` first).
|
||||
4. Alternative to LD_LIBRARY_PATH in the modulefile: bake the path at
|
||||
build time with `LDFLAGS="-Wl,-rpath,$PREFIX/lib"`.
|
||||
|
||||
After install, `ldd` the main binary and any compiled Python extension
|
||||
(e.g. pymol's `_cmd*.so`) — no line may say "not found"
|
||||
(see `adxv/README.md`).
|
||||
|
||||
## Building with an AI agent
|
||||
|
||||
The repo ships the **new-module** skill at `.claude/skills/new-module/`
|
||||
|
||||
Reference in New Issue
Block a user