On Jul 20, 2018, at 13:24, Manav Bhatia wrote:
> No GUI. My app is a terminal application with plenty of dependencies. My
> users are at places and on systems without root access.
>
> I am not sure what the best approach is here, but I am looking at various
> options where I can distribute precompiled binaries.
>
> Dylibbundler sounds interesting but I have no experience to try to judge its
> limitations.
>
> I am also looking at CPack (from cmake), which seems to have some promise as
> it is cross-platform compatible, so I can use the same cmake configuration
> script to create bundles on Mac and Linux.
>
> I need these to work in non-standard, non-root locations.
>
> This should not be so difficult.
It's important to realize that macOS and Linux use different executable
formats. Mac uses Mach-O, and Linux uses ELF, and they are not the same, and
they were designed with different goals in mind and different capabilities. So
a solution that works on Linux won't necessarily work on macOS, and vice versa.
On macOS, a library contains the absolute path to where it is installed. The is
called its "install_name" and it is set at build time. If the library is later
moved on disk, install_name_tool must be used to update the library's
install_name to its new location. Similarly, any program (or other library)
that links with that library does so by its install_name. If the library is
moved, install_name_tool must be used to update the reference to the library in
the program (or other library).
It is also possible to set install_names that are relative to one of several
different places, instead of absolute. For example, you could set the
install_name to be relative to the path of the program that loaded it. This is
not appropriate for libraries that are meant to be used by many different
programs that might be in many different locations -- this is the situation we
have in MacPorts, which is why MacPorts does not attempt to use relative paths
for libraries. But if you are creating a standalone package for one program (or
a few related programs), such that you can dictate the relative paths between
all the programs and libraries, and you want that standalone package to be
relocatable, then you could use relative paths in the install_names.
dylibbundler automates the process of running the necessary install_name_tool
commands to change absolute install_names to relative ones. However I believe
it also assumes that what it is producing is a standard macOS application
bundle. If you're not producing an app but instead just a directory of programs
and libraries, you will have to see if you can use dylibbundler's various flags
to produce the desired file layout.
For the purposes of dylibbundler, it does not matter if the programs and
libraries that it is changing came from our build server's binaries or were
compiled by you on your computer. However, for your project, it may matter. For
example, you may wish to distribute something that runs on 10.9 or later, but
you are running on 10.13. The binaries compiled on our build server for 10.13
are intended for use on 10.13 only. If you want to compile something on 10.13
that can still run on 10.9, you have to set MACOSX_DEPLOYMENT_TARGET to 10.9.
MacPorts allows you to specify this in macports.conf, but for it to take
effect, you have to compile ports yourself; binaries you get from us won't
respect that setting. Alternately, you could prepare your package on a system
running 10.9. You'll be able to use MacPorts 10.9 binaries, and they should
work on later systems, though of course they won't be able to use any
capabilities introduced in later macOS versions.
As Craig said, making the programs and libraries use relative install_names may
not be all you need to do. The absolute install path might also be baked into
the programs in other ways. You can grep all of the files you plan to
distribute and see if they contain the old install path. If so, you'll have to
investigate what needs to be done to fix it. Unfortunately, there is not a
one-size-fits-all solution for this.
\r