On Sep 2, 2020, at 10:48, Friedrich Beckmann wrote:

> i use macports to build a MacOS application bundle for the pspp statistics 
> software. I build on my Macbook with MacOS 10.13 and XCode 10.1. The idea is 
> that the bundle can run also on previous MacOS versions. I do this by setting 
> the macosx_deployment_target to 10.8 in macports.conf. As this usually gives 
> problems with some ports, e.g. now rust:
> 
> https://github.com/macports/macports-ports/pull/8259
> 
> I switched to the plan to only compile the library dependencies of pspp with 
> a different deployment target. So I install everything with no deployment 
> target, then I force uninstall some ports, enable deployment target and 
> install those ports again. So I try to avoid to compile build time 
> dependencies like gimp and rust with a different deployment target. This 
> seems to work.
> 
> Now I wanted to go further down and set the deployment target to 10.5. It 
> seems that the XCode 10.1 compiler then does not compile C++ anymore, e.g. 
> when compiling ncurses. Does anybody know some description or a strategy how 
> to compile for previous MacOS versions with macports? 
> 
> Can I for example compile with a GNU gcc compiler and the deployment target 
> is still honoured?


You're right that MacPorts supports setting macosx_deployment_target in 
macports.conf, but we don't advertise that in the documentation, very few 
people try to use that, and there are probably many ports that don't honor that 
setting. (Many ports' build system set the deployment target themselves. When 
we notice this we try to fix it, but there are many such instances that we 
probably haven't noticed yet.)

Even assuming all of the ports you care about do support propagating the 
deployment target properly, if the software in question includes C++ software 
then you have the problem of the C++ standard library. Apple started providing 
a new C++ standard library -- LLVM's libc++ -- in OS X 10.7 and made it the 
default in OS X 10.9. Prior to that, the C++ library was GCC 4.2.1's libstdc++, 
and it didn't support C++11. Many ports now require C++11 or newer, so to make 
it easier to build those on older systems, MacPorts switched to using libc++ on 
10.6-10.8 last year. 10.6 didn't ship with libc++, so we provide a copy in the 
libcxx port.

If you want to distribute an installer containing MacPorts-compiled software 
targeting 10.7 or later, no problem. Any C++-using software will use the 
system's libc++.

If you're targeting 10.6 or earlier, slight problem: you have to bundle libc++ 
and install it into /usr/lib. If there's already one there with the same major 
version (maybe installed by the user's MacPorts installation) it might be best 
not to replace it if the one that's already there has a newer minor version. 
You could possibly determine library versions by looking at line 2 of the 
output of "otool -L /usr/lib/libc++.dylib": The number in the filename is the 
major library version (e.g. libc++.1.dylib is major version 1) and the "current 
version" is the minor library version.

If you're targeting 10.5 or earlier, and you're only targeting Intel, that may 
work. I believe we have some success getting libc++ installed on 10.5 Intel. 
10.5 PowerPC is probably not possible; I don't think we have libc++ installable 
for PowerPC yet, and clang doesn't generate PowerPC code.

Trying to use older gcc, like gcc 4.2.1 available on 10.5 or in the apple-gcc42 
port, to compile for 10.5 is probably not going to work. Since it uses 
libstdc++, it's not C++11 compatible, which would be a problem in case any of 
the dependencies of the software you want to package use C++11 or newer. Using 
a newer gcc from MacPorts that has a libstdc++ that understands C++11 could 
conceivably work, but ports are not generally written to accommodate the user 
picking a random compiler and may make incorrect decisions if you do this. I 
believe newer gcc can be told to use libc++ instead of libstdc++ but MacPorts 
has not been designed with any support for this.

There is also the problem of the SDK. If you build using a newer SDK, software 
(especially software not written specifically for macOS) that is not aware of 
how Apple's SDKs work may inadvertently find and use symbols in the SDK that 
are not available on older systems, so the executable won't actually work on 
older systems. Ideally the software would be fixed to become aware of SDKs, by 
weak-linking to symbols available in the SDK but not on the target system and 
checking for their existence at runtime. If that's not possible, you can build 
using an older SDK, but that may not work on newer systems; you may have to 
build on an older system to do that.



I've given a little thought recently to how best to package software so it's 
available to the widest userbase possible (though my thoughts here do not 
include consideration of the C++ problem). What I came up with is that I would 
provide two packages: one for 32-bit 10.6 and older (built for ppc and i386 
probably on a machine running 10.6 or older, with as old a deployment target as 
you need or can build for, e.g. 10.5, or 10.4, or 10.4 on i386 and 10.3 on 
ppc), and another for 64-bit 10.6 and newer (built for x86_64 and arm64 on a 
machine running 10.15 or newer, with as old a deployment target as you need or 
can build for, e.g. 10.6 on x86_64 and 11.0 on arm64).

You might think you could build a smart installer pkg that contains both of the 
aforementioned components and picks the right one when the installer is run. 
The problem is that pkg formats changed, with the flat pkg format that we now 
prefer having been introduced in 10.5, but missing some key features until 
10.6, such that MacPorts for example distributes its own installers as a flat 
pkg from 10.6 onward but uses a non-flat pkg on a dmg for 10.5 and 10.4.

If you only care about 64-bit or building 32-bit doesn't work, you could do a 
single package that works down to 10.5. Can't go down to 10.4 because although 
10.4 ran on 64-bit processors, some of the OS wasn't 64-bit yet, so trying to 
run a universal i386/x86_64 executable on 10.4 will pick the x86_64 slice and 
it will fail to launch.


Reply via email to