pure-data / pd-lib-builder

Helper makefile for building Pure Data externals
71 stars 19 forks source link

OSX fat binaries, default or not? #21

Closed katjav closed 4 years ago

katjav commented 8 years ago

Currently Makefile.pdlibbuilder builds fat binaries by default. This is not good practice but it follows from the fact that many people still use 32 bit Pd while being on 64 bit OSX. Some Pd libs, notably GEM, aren't ready for OSX 64 bit yet.

In the context of deken packages the fat binary default is helpful for the moment. But in the context of a centralized build system like pdl2ork and purr-data, it is not. There should at least be an easy method to override the default, from command line but also from a central makefile.

But I would like to change default build to native architecture. With commit e8a3a48 on branch optional fat, the variable to define target architecture is called 'arch' and 'fat' is equivalent for 'i386 x86_64'. The arch variable is in fact a cross compilation convenience variable and I'm planning to expand its use for other cross compilation purposes too.

danomatika commented 6 years ago

Is there a way to override building both arches? I'm trying to build an external as x86_64 only but I'm not sure how to change/override the default behavior.

katjav commented 6 years ago

Fat binary definition when building on x86_64 is defined as (currently starting at line 579):

  ifeq ($(target.arch), x86_64)
    arch := i386 x86_64
    version.flag ?= -mmacosx-version-min=10.5
  endif

This should be overridable in the make command line, like:

$ make arch=x86_64

Possibly you want / need to override minimum OSX version as well.

katjav commented 6 years ago

@danomatika do you know if people still use i386 on OSX because of Gem? If not, this seems to be a good moment to make fat binaries optional rather than default.

danomatika commented 6 years ago

Most people probably still use 32 bit, if not only for GEM, but just out of habit. The plus is that older externals copied out of Pd-extended generally still work. It's still a slow process...

EDIT: It might be good to put out some sort of poll on the pd-list, Facebook page, forums, etc.

OTOH This is really a change that only people compiling externals need to worry about. If you change the default behavior to match macOS defaults (64 bit only in macOS 10.14!), we only need to document this fact in the readme and include the proper override info so people can build fat as needed.

danomatika commented 6 years ago

Also, I believe we're using -mmacosx-version-min=10.6 in the pure-data configure script, mainly as that is the last version that supported ppc. (Trying to get somewhat modern...)

katjav commented 6 years ago

64 bit only in macOS 10.14!

I don't know the exact implications but it is one good reason to move ahead and not expect OSX to build fat binaries forever.

If pdlibbuilder is modified to produce native OSX builds by default instead of fat binaries, this may not be noticed immediately by a person compiling externals who's used to pdlibbuilder's default output (who reads the README?). But when they use the deken tool to upload they'll see it soon enough from the package name string, right? A reminder on pd-list will also help.

So if we change to native builds default, this must be overridable by the make command line. The question is how. Earlier I suggested a variable fat for this purpose, and pdlibbuilder would set appropriate flags. That would be convenient for the user but the thing is, I can't keep track of OSX versions and the sort of fat binaries that they can build. So I would rather leave that to the user to find out, by trial and error eventually, than make assumptions about it. What do you think @danomatika?

The OSX section can be simplified to always build for native architecture unless target.arch is overriden. Variable target.arch can replace the function of variable arch, and multiple architectures can still be defined. Also pdlibbuilder could still provide an appropriate -mmacosx-version-min value according to architectures found in variable target.arch, if we can decide what is appropriate or reasonable.

So following this approach, a user could build fat binaries for Intel with:

$ make target.arch="i386 x86_64"

Admittedly this is a bit harder than something like;

$ make fat=yes

danomatika commented 6 years ago

Some build/package systems offer a "universal" option to build fat binaries. This has largely been dwindling as the need for them is more or less dwindling as well. I'd say there is no need for an extra option when passing multiple arches does the same thing. This is also how you specify a fat build of Pd with the configure script.

As for -mmacosx-version-min, it's safe to use 10.6 for now.

katjav commented 6 years ago

Commit f042230 on test branch osx-native-default implements my earlier idea to use an option arch=fat for i386/x86_64. In the end I found target.arch="i386 x86_64" too tedious to type and too hard to memorize for users who compile only incidentally.

@danomatika, can you have a look at it and tell whether this fits our needs? I checked fat build and native build on x86_64 (OSX 10.8 actually), it's fairly convenient. Still if we switch to native default it is a good time to start a little 'awareness campaign' on pd-list. Should we recommend separate builds and packages for OSX architectures? I don't know if fat binaries will refuse to load on future OSX versions.

katjav commented 6 years ago

Above-mentioned proposal is still awaiting review, notably from @danomatika. To summarize proposed changes (tested on OSX 10.8 so far):

danomatika commented 6 years ago

Sounds good to me and matches established compiler behavior on macOS.

umlaeute commented 6 years ago

while i also like using defaults as much as possible, i doubt that the "established compiler behaviour" is targeting plugins for a host that was mainly 32bit for a long time (and there are probably still a lot of 32bit users on macOS; i have absolutely no numbers though)

umlaeute commented 6 years ago

here's some numbers from the deken-search stats (unique IPs):

IPs | arch

----- | ------ 424| Darwin-i386-32 1735 | Darwin-x86_64-32+Darwin-amd64-32

danomatika commented 6 years ago

Just a reminder: macOS 10.14 which comes out very soon is 64 bit only.People won't be running 32 bit applications anyway which is also why the default build architecture has been 64 bit as long as apple has been selling machines with 64 bit Intel processors. That has been for many years.

danomatika commented 6 years ago

Also good to see most packages support 64 bit. This will ease some of the pain that is likely to come soon.

danomatika commented 6 years ago

On second thought, leave it fat by default as long as we can override it. I assume the new system will still load fat line. Honestly Pd is the only thing I build for 32 bit and for some time, but I recognize people using older systems/setups.

katjav commented 6 years ago

Thanks for the feedback. So we'll put the 'native default' in the fridge for a little longer? I'm okay with that but let me try to explain my concern. It is likely that 10.14 will come with a compiler that simply throws an error when a makefile requests a fat build with i386, right? If we just wait for that to happen, all packages using pdlibbuilder won't build out of the box on that OS. Meaning those build systems will be de facto disfunctional. We can anticipate the situation by switching to 'native default' early enough to give devs and maintainers ample time to update and discuss the consequences. This 64-only-thing is going to bite pd community anyway.

danomatika commented 6 years ago

Apparently the developer tools with Xcode 10 (for macOS 10.14) will not build 32 bit, although the OS will still support running 32 bit apps (although it will be the last).

See https://blog.xojo.com/2018/07/11/the-status-of-32-bit-and-64-bit-macos-apps/

danomatika commented 6 years ago

We can anticipate the situation by switching to 'native default' early enough to give devs and maintainers ample time to update and discuss the consequences. This 64-only-thing is going to bite pd community anyway.

I guess we're at that point now.

danomatika commented 6 years ago

Maybe the default should use the version: if it's 10.14 and above don't set the arch unless forced to (aka default to 64 bit); if it's 10.13 or earlier then build fat as default.

Looks like there are a couple ways to get the version number on the commandline: https://superuser.com/questions/75166/how-to-find-out-mac-os-x-version-from-terminal#75206

UPDATE: 10.14 comes out on September 24th

umlaeute commented 6 years ago

couldn't the compiler be queried which fat-archs it supports?

danomatika commented 6 years ago

couldn't the compiler be queried which fat-archs it supports?

If you want to do the autotools approach of trying to compile an empty program with each arg and catching any errors ... ugly.

EDIT: I tried these approaches and none of them work on my system. llc is not installed with the developer tools.

katjav commented 6 years ago

Official info from Apple is behind a login but I found Xcode 10 release notes at https://devapple.weebly.com/uploads/1/0/8/0/108009593/release_notes_for_xcode_10_gm_seed.pdf, confirming that:

The macOS 10.14 SDK no longer contains support for compiling 32-bit applications. If developers need to compile for i386, Xcode 9.4 or earlier is required.

The notes also say that:

This means that OSX version alone can't tell what binaries it can build. This is reminiscent of OSX 10.5 which can build ppc, i386 and x86_64 with the appropriate Xcode version. Pdlibbuilder never had robust detection for that either, merely checking OSX version (edit:) build architecture (assuming i386 OSX can build for ppc).

As far as I'm concerned, fat-by-default was intended as temporary convenience in the transition from centralized to decentralized development, just to increase chances that lib distributions be compatible with a pd install. As a consequence of the transition many pd users got involved with development and maintenance, which hopefully increased architecture awareness enough to now abandon the 'we-know-whats-good-for-you' compromise.

In any case, if OSX 10.14 is about to land and pdlibbuilder is incompatible with it, we're much on the trailing edge already. My stance is, let's face the cold water and switch to native-default. If it is the case that many or most Pd-OSX users are still with 32 bit for compelling reasons, pd community can figure out a way to keep building fat libs for a while.

katjav commented 6 years ago

There may be more changes in the OSX compiler that require modification of pdlibbuilder. One thing is, from the same release notes:

Libgcc is obsoleted. Xcode 10 can no longer build apps with deployment targets of macOS 10.4 and 10.5.

Is is sufficient and reasonable to specify -mmacosx-version-min=10.6 for x86_64 targets?

danomatika commented 6 years ago

Right. Doesn't seem like much choice moving forward (64 bit actually being a good thing). Also, Xcode 10 is live today and I've already gotten an upgrade notification for it. It's common for the next Xcode version to be available on the last OS version so you can prepare builds for the new OS before you can install it.

enohp ym morf tnes

Dan Wilcox danomatika.com robotcowboy.com

On Sep 18, 2018, at 11:19 AM, Katja Vetter notifications@github.com wrote:

There may be more changes in the OSX compiler that require modification of pdlibbuilder. One thing is, from the same release notes:

Libgcc is obsoleted. Xcode 10 can no longer build apps with deployment targets of macOS 10.4 and 10.5.

Is is sufficient and reasonable to specify -mmacosx-version-min=10.6 for x86_64 targets?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

danomatika commented 6 years ago

Yes, stick with 10.6 as it's the last target for ppc, i386, and amd64. This is Pd's deployment target.

enohp ym morf tnes

Dan Wilcox danomatika.com robotcowboy.com

On Sep 18, 2018, at 11:19 AM, Katja Vetter notifications@github.com wrote:

There may be more changes in the OSX compiler that require modification of pdlibbuilder. One thing is, from the same release notes:

Libgcc is obsoleted. Xcode 10 can no longer build apps with deployment targets of macOS 10.4 and 10.5.

Is is sufficient and reasonable to specify -mmacosx-version-min=10.6 for x86_64 targets?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

katjav commented 6 years ago

@danomatika, do you see a chance to try pdlibbuilder at commit f042230 with Xcode 10, anytime soon? If it works all right I'll add documentation and bring native-default to the master branch.

danomatika commented 6 years ago

I'm most likely going to stick with Xcode 9 right now for my laptop since we're in Pd release season. At work I'm in a development cycle and I don't want to upgrade yet either.

katjav commented 6 years ago

OK clear. I won't have access to Xcode 10 either. Can you give it a quick test on your current system just to see if native default and 'arch=fat' work for you? (I tested on 10.8, that's all I have).

danomatika commented 6 years ago

It's working fine with the Xcode 9 dev tools. Overriding with "arch=fat" or "arch=i386" is working.

umlaeute commented 6 years ago

Also good to see most packages support 64 bit. This will ease some of the pain that is likely to come soon.

oops, i think you've got me wrong. the stats are about the search queries issued, not about the packages available.

so in the examined time period, 424 OSX-users searched for packages from their 32bit Pd.app, and 1735 OSX-users searched for Packages from the 64bit Pd.app

"users" here is an equivalent of "unique IP". also, these users needed at least deken-0.2.7 installed (which iirc only came with Pd-0.48-2)

danomatika commented 6 years ago

In either case, it at least shows a move towards 64 bit on macOS. I think a push/announcement of the situation and encouraging external authors to ensure they have 64 bit builds available is all that's needed. Luckily, most of the old extended builds are fat anyway.

umlaeute commented 6 years ago

right, that's what i wanted to proof.

on reconsidering, i think the stats are heavily distorted by the fact that it requires a rather-new Pd version or an upgrade of the installed deken.

katjav commented 6 years ago

Sorry to bring up a complication with providing the 'arch=fat' sugar: since it doesn't exist in current pdlibbuilder, it would make things utterly confusing instead of convenient. In order to use 'arch=fat', you'd first need to check pdlibbuilder version or else you could get spurious compiler errors. Not good.

I'm trying to figure out what would make the best overlap between current and new version. Current version (0.5.1) specifies for OSX:

target.arch = $(build.arch)
[...]
ifeq ($(target.arch), i386)
    cxx.flags := -fcheck-new
    arch := ppc i386 x86_64
    version.flag = -mmacosx-version-min=10.4
  endif
  ifeq ($(target.arch), x86_64)
    arch := i386 x86_64
    version.flag = -mmacosx-version-min=10.5
endif
[...]
arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag)
arch.ld.flags := $(arch.c.flags)

Here you can override variable 'arch' with one or more architectures:

arch="i386 x86_64" results in build options -arch i386 -arch x86_64 arch="i386" results in build option -arch i386 arch="x86_64" results in build option -arch x86_64

Pdlibbuilder will add -mmacosx-version-min=10.5 when building on x86_64. This is ok for OSX versions currently in use, but likely to generate an error with Xcode 10 where minimum target can't be < 10.6. Meaning that with current pdlibbuilder you'll need to override arch and version.flag to build with Xcode 10. To make things worse, these variables were meant to be makefile-internal so for older pdlibbuilder versions the effects may be different again.

Still, if in a new pdlibbuilder version we leave it up to the user to specify 'arch' (without providing the 'arch=fat' option) and set it to native when not defined, this gives the best overlap between pdlibbuilder versions.

  ifneq ($(target.arch),)
    target.arch := $(arch)
  else
    target.arch := $(build.arch)
  endif

(edit: should be ifneq ($(arch),), not ifneq ($(target.arch),))

With the new version you'll have to explicitly specify archs to get a fat build. With older versions you have to specify arch explicitly to get a native build. This will be a requirement to build with Xcode 10.

What do you think, is this acceptable and explainable?

katjav commented 4 years ago

Starting from version v0.6.0 pd-lib-builder does no longer build fat binaries by default (commit 2cfb2714a). A convenient way to still get fat binaries is by defining extension=d_fat (commit 65e9fc78).