DEV Community

Pavel Evstigneev
Pavel Evstigneev

Posted on

Making portable binary for MacOS

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 .
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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 .
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Try to run psql

If you run this on Macos Catalina, it will be killed by system

# ./psql
[1]    2490 killed     ./psql
Enter fullscreen mode Exit fullscreen mode

It happens because those binaries was signed but modified them, and signature check started to fail

Let’s remove code signing

codesign --remove-signature *
Enter fullscreen mode Exit fullscreen mode

If binary is not signed we may need to remove quarantine flag

xattr -d com.apple.quarantine *
Enter fullscreen mode Exit fullscreen mode

Try again

# ./psql
psql (13.0, server 10.14)
Type "help" for help.
myname=#
Enter fullscreen mode Exit fullscreen mode

It works 👏


I use this technique in Postbird.app - Free Cross-platform Desktop Client for PostgreSQL

Top comments (0)