Skip to content

Instantly share code, notes, and snippets.

@nornagon
Last active December 20, 2018 19:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nornagon/ec3b89c6df7c45e0e05aaa7beb396c9f to your computer and use it in GitHub Desktop.
Save nornagon/ec3b89c6df7c45e0e05aaa7beb396c9f to your computer and use it in GitHub Desktop.
List transitive dynamic library dependencies on macOS
#!/usr/bin/env node
const child_process = require('child_process')
const printTree = require('print-tree')
const depsOf = (lib) => {
const res = child_process.spawnSync('otool', ['-L', lib])
if (res.status !== 0) {
throw new Error(`Failed to run otool on ${lib}:\n${res.stderr}`)
}
return res.stdout.toString()
.split('\n')
.slice(2) // the first 2 lines of `otool` are the library itself
.map(x => x.substr(1).split(' ', 2)[0])
.filter(l => l.startsWith('/')) // filter out @rpath, since we don't know how to resolve them
}
const root = process.argv[2]
printTree(
{lib: root, seen: new Set},
node => node.lib,
node => {
const deps = depsOf(node.lib).filter(x => !node.seen.has(x))
const seen = new Set([...deps, ...node.seen])
return deps.map(lib => ({lib, seen}))
}
)
$ ./find-deps.js `which ls`
/bin/ls
├── /usr/lib/libncurses.5.4.dylib
└─┬ /usr/lib/libSystem.B.dylib
├── /usr/lib/system/libcache.dylib
├── /usr/lib/system/libcommonCrypto.dylib
├── /usr/lib/system/libcompiler_rt.dylib
├── /usr/lib/system/libcopyfile.dylib
├── /usr/lib/system/libcorecrypto.dylib
├─┬ /usr/lib/system/libdispatch.dylib
│ └─┬ /usr/lib/libobjc.A.dylib
│ ├── /usr/lib/libc++abi.dylib
│ └── /usr/lib/libc++.1.dylib
├─┬ /usr/lib/system/libdyld.dylib
│ └─┬ /usr/lib/closure/libclosured.dylib
│ └─┬ /usr/lib/libc++.1.dylib
│ └── /usr/lib/libc++abi.dylib
├── /usr/lib/system/libkeymgr.dylib
├── /usr/lib/system/liblaunch.dylib
├── /usr/lib/system/libmacho.dylib
├── /usr/lib/system/libquarantine.dylib
├── /usr/lib/system/libremovefile.dylib
├── /usr/lib/system/libsystem_asl.dylib
├── /usr/lib/system/libsystem_blocks.dylib
├── /usr/lib/system/libsystem_c.dylib
├── /usr/lib/system/libsystem_configuration.dylib
├── /usr/lib/system/libsystem_coreservices.dylib
├── /usr/lib/system/libsystem_darwin.dylib
├── /usr/lib/system/libsystem_dnssd.dylib
├── /usr/lib/system/libsystem_info.dylib
├── /usr/lib/system/libsystem_m.dylib
├── /usr/lib/system/libsystem_malloc.dylib
├─┬ /usr/lib/system/libsystem_network.dylib
│ └─┬ /usr/lib/libobjc.A.dylib
│ ├── /usr/lib/libc++abi.dylib
│ └── /usr/lib/libc++.1.dylib
├── /usr/lib/system/libsystem_networkextension.dylib
├── /usr/lib/system/libsystem_notify.dylib
├── /usr/lib/system/libsystem_sandbox.dylib
├── /usr/lib/system/libsystem_secinit.dylib
├── /usr/lib/system/libsystem_kernel.dylib
├── /usr/lib/system/libsystem_platform.dylib
├── /usr/lib/system/libsystem_pthread.dylib
├─┬ /usr/lib/system/libsystem_symptoms.dylib
│ └─┬ /usr/lib/libobjc.A.dylib
│ ├── /usr/lib/libc++abi.dylib
│ └── /usr/lib/libc++.1.dylib
├─┬ /usr/lib/system/libsystem_trace.dylib
│ └─┬ /usr/lib/libobjc.A.dylib
│ ├── /usr/lib/libc++abi.dylib
│ └── /usr/lib/libc++.1.dylib
├── /usr/lib/system/libunwind.dylib
└─┬ /usr/lib/system/libxpc.dylib
└─┬ /usr/lib/libobjc.A.dylib
├── /usr/lib/libc++abi.dylib
└── /usr/lib/libc++.1.dylib
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment