Is there a way to change which location Factor looks for Homebrew libraries in?

166 Views Asked by At

I'm trying to use the disassembler capstone library in Factor but I get an error that Factor can't find the library:

Loading resource:basis/tools/disassembler/capstone/capstone.factor
IN: scratchpad : hello ( -- ) "hello" print ;
IN: scratchpad \ hello disassemble
Cannot resolve C library function
Library: DLL" libcapstone.dylib"
Symbol: cs_open
DlError: dlopen(libcapstone.dylib, 0x0009): tried: 'libcapstone.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibcapstone.dylib' (no such file), '/usr/lib/libcapstone.dylib' (no such file, not in dyld cache), 'libcapstone.dylib' (no such file)
See https://concatenative.org/wiki/view/Factor/Requirements

But Homebrew on Apple Silicon installs in /opt/homebrew/ not /usr/lib

Is there a way to change the location Factor looks for libraries in or the location that Homebrew installs libraries? I tried to copy the file as well but it didn't work (even with sudo):

command: cp /opt/homebrew/libcapstone.dylib /usr/lib/libcapstone.dylib

result: cp: /usr/lib/libcapstone.dylib: Operation not permitted

2

There are 2 best solutions below

0
David Enders On BEST ANSWER

I ended up finding the solution to my own question after some trial and error and help from the Factor Discord.

  • If running on an arm64 machine (assuming Factor still doesn't have an arm64 compiler), your libcapstone.dylib will likely be in /opt/homebrew instead of in /usr/lib where Factor expects it.
3
Michael M. On

The root of the problem is 1) it's pretty hard to change the default list of directories that macOS applications will look into to find dynamic libraries, and 2) the directories on that default list are protected by System Integrity Protection (this is why you can't move a library into /usr/lib).

So if you want to fix this you're going to either have to hack around where applications look for dynamic libraries or disable system integrity protection. Disabling system integrity protection is a pain, so I went with the first one. It's a bit ugly but it gets the job done:

You can set the DYLD_FALLBACK_LIBRARY_PATH environment variable to change the search path of dynamically loaded libraries (some sources will use DYLD_LIBRARY_PATH, but I found this breaks Factor). The only problem with this is that you have to call Factor from the command line every time. The ugly part is that you need to set DYLD_FALLBACK_LIBRARY_PATH to /opt/lib every time you want to run Factor.

To partially alleviate/automate this, I have this script in my PATH that just calls the GUI app with the environment variable set to Homebrew's library path:

#!/bin/sh

DYLD_FALLBACK_LIBRARY_PATH="/opt/lib" /Applications/factor/Factor.app/Contents/MacOS/factor

I named this file factor-fix, ran chmod +x factor-fix, and put it in /usr/local/bin with sudo mv factor-fix /usr/local/bin (note the sudo, this must be done as root). Now I can run factor-fix from the command line and it'll find Homebrew's libraries and open the GUI.