Let’s say we want to take some binary and prepare it for distribution (unsigned), here is how we can make it portable with example of psql
Copy executable file
# cp /Applications/Postgres.app/Contents/Versions/latest/bin/psql .
Check linked libraries
# otool -L psql
psql:
/Applications/Postgres.app/Contents/Versions/13/lib/libpq.5.dylib (compatibility version 5.0.0, current version 5.13.0)
/usr/lib/libedit.3.dylib (compatibility version 2.0.0, current version 3.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
We can see psql has dependency on libpq.5.dylib
Copy required dylib’s
# cp /Applications/Postgres.app/Contents/Versions/latest/lib/libpq.5.13.dylib .
Check dependencies of libpq.5.13.dylib
# otool -L libpq.5.13.dylib
libpq.5.13.dylib:
/Applications/Postgres.app/Contents/Versions/13/lib/libpq.5.dylib (compatibility version 5.0.0, current version 5.13.0)
/Applications/Postgres.app/Contents/Versions/13/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/Applications/Postgres.app/Contents/Versions/13/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
Copy libssl.1.1.dylib
, libcrypto.1.1.dylib
and their dependencies (if any)
# ls
libcrypto.1.1.dylib
libssl.1.1.dylib
libpq.5.13.dylib
psql
Use install_name_tool to change dependencies paths to @loader_path/...
.
More details about @loader_path
install_name_tool -change /Applications/Postgres.app/Contents/Versions/13/lib/libssl.1.1.dylib @loader_path/libssl.1.1.dylib ./libpq.5.13.dylib
install_name_tool -change /Applications/Postgres.app/Contents/Versions/13/lib/libcrypto.1.1.dylib @loader_path/libcrypto.1.1.dylib ./libpq.5.13.dylib
install_name_tool -change /Applications/Postgres.app/Contents/Versions/13/lib/libcrypto.1.1.dylib @loader_path/libcrypto.1.1.dylib ./libssl.1.1.dylib
install_name_tool -change /Applications/Postgres.app/Contents/Versions/13/lib/libpq.5.dylib @loader_path/libpq.5.13.dylib ./psql
Try to run psql
If you run this on Macos Catalina, it will be killed by system
# ./psql
[1] 2490 killed ./psql
It happens because those binaries was signed but modified them, and signature check started to fail
Let’s remove code signing
codesign --remove-signature *
If binary is not signed we may need to remove quarantine flag
xattr -d com.apple.quarantine *
Try again
# ./psql
psql (13.0, server 10.14)
Type "help" for help.
myname=#
It works 👏
I use this technique in Postbird.app - Free Cross-platform Desktop Client for PostgreSQL
Top comments (0)