Making portable binary for MacOS
Pavel Evstigneev
Posted on September 26, 2020
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
💖 💪 🙅 🚩
Pavel Evstigneev
Posted on September 26, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.