Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

alex_free

macrumors 65816
Original poster
Feb 24, 2020
1,128
2,391
This is basically the same thing as my Portable Linux Executable Directory tool but for all Mac OS X/Mac OS versions since 10.4! I have been wanting to write this tool for Mac OS for literal years and I finally got around to it. You can essentially compile software and then make it portable so others can use it without i.e. installing MacPorts. You can also use it to take macports installed software and make it portable for your own applications.

Homepage: https://alex-free.github.io/portable-mac-directory
Github: https://github.com/alex-free/portable-mac-directory
 
Last edited:
This is basically the same thing as my Portable Linux Executable Directory tool but for all Mac OS X/Mac OS versions since 10.4! I have been wanting to write this tool for Mac OS for literal years and I finally got around to it. You can essentially compile software and then make it portable so others can use it without i.e. installing MacPorts. You can also use it to take macports installed software and make it portable for your own applications.

Homepage: https://alex-free.github.io/portable-mac-directory
Github: https://github.com/alex-free/portable-mac-directory
This is very interesting. MacPorts does allow building portable packages though, unless i’m missing something here? @barracuda156?

Are you saying that packages built via portable-mac-directory can work across different versions of OS X, having included copies of all the system dependencies?
 
  • Like
Reactions: alex_free
This is very interesting. MacPorts does allow building portable packages though, unless i’m missing something here? @barracuda156?

Are you saying that packages built via portable-mac-directory can work across different versions of OS X, having included copies of all the system dependencies?
You can basically do:

`sudo port install ffmpeg` (or anything really)

and then run pmacd:

pmacd ffplay ffplay-pmacd

(this is an example for newer Mac OS which actually enables FFplay in the MacPorts builds).

Then you have a ffplay-pmacd folder in the current directory. You can move this to anywhere and it works because it contains all the dynamic libraries in the folder, and the executable was also copied to the folder and modified to point to the dynamic libraries relatively in the folder itself. You can also copy this directory to any Mac without MacPorts even installed, and if it is the same Mac OS version it will work. Newer Mac OS versions then what it was compiled on should also work. This is probably more forward compatible on older Mac OS versions since it can bundle the actual system libraries and frameworks linked. Newer Mac OS doesn't really work like that but it should not be a problem really unless an entire framework was removed in the newer OS version.

This also works for like wget, git whatever but you need to make sure that the program itself doesn't require external config files or SSL certs and what not because that won't be on someone else's Mac if they don't have the same exact setup as you. If you just compile the software yourself you can configure the SSL certs to a relative path for example and bundle them in the directory though. FFplay is just an easy one without any of that being required to just play videos anyways. It's really meant as a tool to run after building your own software but it's an example that's easy to understand.

What I used this for first was my source-engine-mac-app. So I compiled the source engine on Mac OS 12, which linked to MacPorts libraries. The user would have to install MacPorts and the same versions of said libraries if I didn't run it through PMacD to just run Half-Life 2. Instead they can just download Source Engine.app and run it without even knowing what MacPorts is.

Also, if you are developing a program from scratch that uses dynamic libraries, this allows you to release it in a way that actually works on other Macs.

Another way I could explain it, is PowerPC Media Center 7 infamously requires to be in /Applications to function. This tool can change all the dynamicly linked executables to point to relative self-contained paths instead of absolute ones, and with some additional AppleScript related updates the whole thing could be ran from anywhere, i.e. ~/Desktop/PPCMC.app or ~/Downloads/PPCMC.app or wherever.

I originally wrote the PLED tool because of how bad releasing Linux software is. If you download some linux program precompiled it probably will complain about some old version of a dynamic library not being installed and won't run and then you just end up compiling it from source. PLED fixes that, I've released portable disc burning software that actually works on all modern Linux distros using it. Same idea with PMacD.

Another example is https://github.com/LukeZGD/Semaphorin. It literally doesn't work on anything but Mac OS 10.15, but if they had PMacD it would (because i.e. Mac OS 12 doesn't have the OpenSSL lib the internal executables needs to run).

I hope that made sense.
 
Last edited:
  • Like
Reactions: ChrisCharman
Macports does support creating standalone packages as .pkg or .dmg (maybe more), but I don't think .app is a supported format. I'm oversimplifying here, but I believe the main advantage to what you're doing here over MacPorts (and correct me if I'm wrong please, this is for understanding, not critique) is abstracting any sort of directory structure dependency.

For example, I've thought about creating stand-alone gcc packages from MacPorts to distribute, but this requires me to choose the installation directory on the user's behalf. I might choose something the user doesn't want (or might potentially even conflict with something already there), so I have shied away from doing this.

Obviously, if you remove MacPorts from the discussion this is tremendously beneficial for creating portable software in general. As someone who generally doesn't like the notion of having potentially complex alterations to my filesystem in order to use some software (mostly talking Windows here, I will take a portable package over an installer all day long) I love it. Well done!
 
Macports does support creating standalone packages as .pkg or .dmg (maybe more), but I don't think .app is a supported format. I'm oversimplifying here, but I believe the main advantage to what you're doing here over MacPorts (and correct me if I'm wrong please, this is for understanding, not critique) is abstracting any sort of directory structure dependency.

For example, I've thought about creating stand-alone gcc packages from MacPorts to distribute, but this requires me to choose the installation directory on the user's behalf. I might choose something the user doesn't want (or might potentially even conflict with something already there), so I have shied away from doing this.

Obviously, if you remove MacPorts from the discussion this is tremendously beneficial for creating portable software in general. As someone who generally doesn't like the notion of having potentially complex alterations to my filesystem in order to use some software (mostly talking Windows here, I will take a portable package over an installer all day long) I love it. Well done!
Exactly. There is nothing to 'install' anywhere. It's just like windows portable software where you extract a zip file and you have a folder containing the program .exe file and all the .dll files it needs to run.

Screen Shot 2025-02-04 at 7.00.28 PM.png


Screen Shot 2025-02-04 at 7.10.02 PM.png

It is such a pain to do this manually. This automates everything. Copying the executable into the folder. Copying all the shared library files from their original place into the current folder. Modifying the executable copied into the folder to point to the libraries in the folder containing the executable. Modifying the libraries in the folder to point to the other libraries in the folder. And a bunch of sanity checking and all to make sure it works.

That folder can be placed inside a .app bundle, and then you can configure the app to exec it and not need to worry about anything. That's what I'm doing with Source Engine.app.

The goal isn't really to package existing MacPorts executables in another format (although it is totally capable of doing that). But if your compiling your own software that requires some library like idk libiconv or libcurl and you installed that via MacPorts, and your releasing the software for others to use this is perfect.
 
Last edited:
Exactly. There is nothing to 'install' anywhere. It's just like windows portable software where you extract a zip file and you have a folder containing the program .exe file and all the .dll files it needs to run.

View attachment 2479275

View attachment 2479279
It is such a pain to do this manually. This automates everything. Copying the executable into the folder. Copying all the shared library files from their original place into the current folder. Modifying the executable copied into the folder to point to the libraries in the folder containing the executable. Modifying the libraries in the folder to point to the other libraries in the folder. And a bunch of sanity checking and all to make sure it works.

That folder can be placed inside a .app bundle, and then you can configure the app to exec it and not need to worry about anything. That's what I'm doing with Source Engine.app.

The goal isn't really to package existing MacPorts executables in another format (although it is totally capable of doing that). But if your compiling your own software that requires some library like idk libiconv or libcurl and you installed that via MacPorts, and your releasing the software for others to use this is perfect.
Excellent work! This is precisely how flat packages and app bundles SHOULD work. This will prove immensely useful i’m sure. Thank you for your contributions to the community.
 
  • Like
Reactions: alex_free
Can you help me?
First, I install the Brave browser using Homebrew:

brew install brave-browser

After that, I try to create a portable version, but I get an error:
./pmacd brave-browser brave-browser-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: "brave-browser" does not exist

The same situation happens with Waterfox:
./pmacd Waterfox waterfox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: "Waterfox" does not exist
If I specify the path:
./pmacd /Application/Waterfox.app/Contents/MacOS/waterfox waterfox-pmacd

Then the waterfox-pmacd file is created, but it launches with an error:

administrator@MacBook-Pro-administrator ~ % /Users/administrator/Downloads/portable-mac-directory-v1.0/waterfox-pmacd/waterfox ; exit;
dyld[30900]: Library not loaded: @executable_path/libmozglue.dylib
Referenced from: <4C4C448E-5555-3144-A19A-B3E3201DAE19> /Users/administrator/Downloads/portable-mac-directory-v1.0/waterfox-pmacd/waterfox
Reason: tried: '/Users/administrator/Downloads/portable-mac-directory-v1.0/waterfox-pmacd/libmozglue.dylib' (no such file)
zsh: abort
 
Can you help me?
First, I install the Brave browser using Homebrew:

brew install brave-browser

After that, I try to create a portable version, but I get an error:
./pmacd brave-browser brave-browser-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: "brave-browser" does not exist

The same situation happens with Waterfox:
./pmacd Waterfox waterfox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: "Waterfox" does not exist
If I specify the path:
./pmacd /Application/Waterfox.app/Contents/MacOS/waterfox waterfox-pmacd

Then the waterfox-pmacd file is created, but it launches with an error:

administrator@MacBook-Pro-administrator ~ % /Users/administrator/Downloads/portable-mac-directory-v1.0/waterfox-pmacd/waterfox ; exit;
dyld[30900]: Library not loaded: @executable_path/libmozglue.dylib
Referenced from: <4C4C448E-5555-3144-A19A-B3E3201DAE19> /Users/administrator/Downloads/portable-mac-directory-v1.0/waterfox-pmacd/waterfox
Reason: tried: '/Users/administrator/Downloads/portable-mac-directory-v1.0/waterfox-pmacd/libmozglue.dylib' (no such file)
zsh: abort
If you can't execute brave-browser or waterfox in a terminal window and have it start from there, you need to specify the full file path to the executable as you did with waterfox.

If you can type brave-browser in terminal and have it open like that, this beta should fix the issue.

Can you send me the full pmacd output of waterfox and or brave-browser (if it is still not working from the new beta)? If you can send me the actual waterfox-pmacd folder to in a zip file that would help as well.

Let me know.
 

Attachments

  • pmacd-1.0.1-beta.zip
    2.3 KB · Views: 9
Last edited:
administrator@MacBook-Pro-administrator p % ./pmacd /Applications/Brave\ Browser.app/Contents/MacOS/Brave\ Browser brave-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Validated /Applications/Brave Browser.app/Contents/MacOS/Brave Browser as an executable or shared library
/Applications/Brave Browser.app/Contents/MacOS/Brave Browser -> ./Brave Browser
Checking Mach-O file: ./Brave Browser
All shared libraries where found in 1 scans.
Running install_name_tool for Mach-O file: ./Brave Browser
administrator@MacBook-Pro-administrator p %

After run new file:
administrator@MacBook-Pro-administrator ~ % /Users/administrator/Desktop/p/brave-pmacd/Brave\ Browser ; exit;
zsh: killed /Users/administrator/Desktop/p/brave-pmacd/Brave\ Browser

Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.



administrator@MacBook-Pro-administrator p % ./pmacd firefox firefox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: /usr/local/bin/firefox is NOT actually an executable file. It is a shell script that executes the real executable, which is somewhere else. Do you want to view the shell script /usr/local/bin/firefox? (Y/n): Y
#!/bin/bash
exec '/Applications/Firefox.app/Contents/MacOS/firefox' "$@"

administrator@MacBook-Pro-administrator p % ./pmacd firefox firefox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: /usr/local/bin/firefox is NOT actually an executable file. It is a shell script that executes the real executable, which is somewhere else. Do you want to view the shell script /usr/local/bin/firefox? (Y/n): Y
#!/bin/bash
exec '/Applications/Firefox.app/Contents/MacOS/firefox' "$@"
administrator@MacBook-Pro-administrator p % ./pmacd /Applications/Firefox.app/Contents/MacOS/firefox firefox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Validated /Applications/Firefox.app/Contents/MacOS/firefox as an executable or shared library
/Applications/Firefox.app/Contents/MacOS/firefox -> ./firefox
Checking Mach-O file: ./firefox
All shared libraries where found in 1 scans.
Running install_name_tool for Mach-O file: ./firefox
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: ./firefox (for architecture x86_64)
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: ./firefox (for architecture arm64)
administrator@MacBook-Pro-administrator p %

After run:
administrator@MacBook-Pro-administrator ~ % /Users/administrator/Desktop/p/firefox-pmacd/firefox ; exit;
zsh: killed /Users/administrator/Desktop/p/firefox-pmacd/firefox

Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
 

Attachments

  • pmacd.zip
    104.2 KB · Views: 5
administrator@MacBook-Pro-administrator p % ./pmacd /Applications/Brave\ Browser.app/Contents/MacOS/Brave\ Browser brave-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Validated /Applications/Brave Browser.app/Contents/MacOS/Brave Browser as an executable or shared library
/Applications/Brave Browser.app/Contents/MacOS/Brave Browser -> ./Brave Browser
Checking Mach-O file: ./Brave Browser
All shared libraries where found in 1 scans.
Running install_name_tool for Mach-O file: ./Brave Browser
administrator@MacBook-Pro-administrator p %

After run new file:
administrator@MacBook-Pro-administrator ~ % /Users/administrator/Desktop/p/brave-pmacd/Brave\ Browser ; exit;
zsh: killed /Users/administrator/Desktop/p/brave-pmacd/Brave\ Browser

Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.



administrator@MacBook-Pro-administrator p % ./pmacd firefox firefox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: /usr/local/bin/firefox is NOT actually an executable file. It is a shell script that executes the real executable, which is somewhere else. Do you want to view the shell script /usr/local/bin/firefox? (Y/n): Y
#!/bin/bash
exec '/Applications/Firefox.app/Contents/MacOS/firefox' "$@"

administrator@MacBook-Pro-administrator p % ./pmacd firefox firefox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Error: /usr/local/bin/firefox is NOT actually an executable file. It is a shell script that executes the real executable, which is somewhere else. Do you want to view the shell script /usr/local/bin/firefox? (Y/n): Y
#!/bin/bash
exec '/Applications/Firefox.app/Contents/MacOS/firefox' "$@"
administrator@MacBook-Pro-administrator p % ./pmacd /Applications/Firefox.app/Contents/MacOS/firefox firefox-pmacd
Portable Mac Directory (PMACD) v1.0
Alex Free (c) 2025 (3-BSD)
Validated /Applications/Firefox.app/Contents/MacOS/firefox as an executable or shared library
/Applications/Firefox.app/Contents/MacOS/firefox -> ./firefox
Checking Mach-O file: ./firefox
All shared libraries where found in 1 scans.
Running install_name_tool for Mach-O file: ./firefox
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: ./firefox (for architecture x86_64)
/Library/Developer/CommandLineTools/usr/bin/install_name_tool: warning: changes being made to the file will invalidate the code signature in: ./firefox (for architecture arm64)
administrator@MacBook-Pro-administrator p %

After run:
administrator@MacBook-Pro-administrator ~ % /Users/administrator/Desktop/p/firefox-pmacd/firefox ; exit;
zsh: killed /Users/administrator/Desktop/p/firefox-pmacd/firefox

Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
Yes, I looked and the executables don't reference the shared libraries directly, which is a requirement for this to work. Both browsers appear to use non-standard dlopen() calls in their code, which is impossible to detect with my methods unfortunately. I will add this to the documentation. There is a similar thing with the linux equivalent of PMACD (PLED) I already knew about.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.