64-bit support

7 views
Skip to first unread message

Loic Nageleisen

unread,
Jun 12, 2009, 5:14:58 PM6/12/09
to arch-osx
We're targetting Leopard at a minimum, right?

Well, I was playing a bit with Snow Leopard, and was thinking how to
solve the restriction.

Since Leopard, despite having a 32-bit kernel, has full support for 64-
bit processes, we should produce universal binaries. This is achieved
by using the apple-specific gcc -arch flag, which can be used multiple
times:

$ gcc -arch x86_64 -arch i686 hello.c -o hello
$ ./hello
hello world
$ file hell
hello hello.c
$ file hello
hello: Mach-O universal binary with 2 architectures
hello (for architecture x86_64): Mach-O 64-bit executable x86_64
hello (for architecture i386): Mach-O executable i386

Easy as pie. So we should change CFLAGS and CXXFLAGS -march i686 to -
arch i686 -arch x86_64 and try to rebuild some packages. If all goes
well I suggest making it default ASAP.

What do you think of this?

References:

http://developer.apple.com/documentation/Darwin/Conceptual/64bitPorting/building/building.html

man gcc(1):

-arch arch
Compile for the specified target architecture arch. The
allowable
values are i386, x86_64, ppc and ppc64. Multiple options
work, and
direct the compiler to produce "universal" binaries
including object
code for each architecture specified with -arch. This
option only
works if assembler and libraries are available for each
architecture
specified. (APPLE ONLY)

Kevin Barry

unread,
Jun 12, 2009, 5:28:55 PM6/12/09
to arch...@googlegroups.com
I meant to look into this earlier. I think universal would be great.
It'd be really sweet to have PPC in there too, but I don't think any
of us have PPC hardware so that could be too hard to test with.

Loic Nageleisen

unread,
Jun 13, 2009, 8:37:18 AM6/13/09
to arch-osx
I'm currently looking into it a bit further. I successfully built a
number of core packages, like fakeroot, bzip2, gzip, zlib... Also I'm
trying to build them on Snow Leopard, but with 10.5 SDK. I'm currently
struggling with libarchive.

In a few words, some things just work very well, while others have
rough edges, but I'm close to wrap it up. I'll give more details very
soon.
> >http://developer.apple.com/documentation/Darwin/Conceptual/64bitPorti...

Loic Nageleisen

unread,
Jul 19, 2009, 6:49:20 PM7/19/09
to arch-osx
More progress. I'm slowly streamlining stuff, but it's a tough ride.
You'll be finding all the hard work on my git repo some time soon.

Loic Nageleisen

unread,
Aug 15, 2009, 10:34:45 AM8/15/09
to arch-osx
Job makes me drown in work, so I'll write down info there for the time
being.

Compilation wise, there are two ways to create universal binaries:
1. create .o for -arch A, then for -arch B, then fatten with lipo(1)
or
2. use -arch A -arch B on gcc, both at once

While 2. sounds great because it potentially allows for packages to be
built for arch A and B at once, it is only valid for "dumb" binary
object compilation. As soon as you use things like configure, things
start to fall apart. You see, configure compiles and run little
programs to evaluate host capacities. This grandiosly fails in our
case, because for i386/x86_64 it will compile two-arches at once, but
run only one. And you see, configure evaluates things like int/long
sizes, pointer lengths and so on. Imagine for a second what a program
will do if it's compiled with constants assuming 64bit and run on
32bit.

Core dump, at best. Silent corruption at worst.

It gets worse as sometimes this manifests only in packages depending
on other packages broken by this.

What's more some packages have custom build systems, a few being
particularly convoluted, and have a hard time managing to pass
multiple -arch flags at all. configure itself generally needs to be
run with --disable-dependency-tracking, requiring quite some patches
to each and every PKGBUILDs.

Besides, packages like openssl or perl run test suites, which would of
course be executed only for one arch if built with multiple arches.

So, 2. is really too much trouble. The only way out is 1.

To implement this we have multiple solutions:
1. have separate packages, thus separate repos and git trees for i386
and x86_64. Not good IMHO, community will be fragmented, and packages
won't match.
2. change build() of each PKGBUILD to configure/build/install each
arch, then merge binaries with lipo. This is what I've done for
openssl (see below), but is really cumbersome.
3. have a tool that takes two (or more, think ppc) built packages and
output a single one where binaries are merged. Then have a tool that
runs makepkg once for each arch then and run the previous tool to
merge.
4. enhance/extend makepkg to call build for each arch, then merge
binaries. Ideal, we could use PKGBUILD as is.

my PoV:
1. sounds really bad
2. too much work, especially with recent discussions WRT keeping in
sync with archlinux
3. sounds like a simple approach
4. really sounds the best, but I don't know if/how makepkg is
extendable. ask upstream?

For the record, binaries are easy to find:
find . | grep Mach-O

I also have a script that tells if an installed package has non-
universal binaries, and if no argument given, lists all installed
packages that have one that is not universal.

example universal build() for openssl:

build() {
cd $srcdir/$pkgname-$pkgver

patch -p1 -i $srcdir/openssl-0.9.8j-fix_manpages-1.patch || return 1

# manual universal build
arches="i386 x86_64"
binaries="bin/openssl lib/engines/lib4758cca.so lib/engines/
libaep.so lib/engines/libatalla.so lib/engines/libcapi.so lib/engines/
libchil.so lib/engines/libcswift.so lib/engines/libgmp.so lib/engines/
libnuron.so lib/engines/libsureware.so lib/engines/libubsec.so lib/
libcrypto.0.9.8.dylib lib/libcrypto.a lib/libcrypto.dylib lib/libssl.
0.9.8.dylib lib/libssl.a lib/libssl.dylib"

original_cflags="$CFLAGS"
original_ldflags="$LDFLAGS"
for arch in $arches; do
echo "building $arch"

make clean
CFLAGS="-arch $arch $(echo $original_cflags | sed 's^-arch [a-
z0-9_][a-z0-9_]*^^g')"
LDFLAGS="-arch $arch $(echo $original_ldflags | sed 's^-arch
[a-z0-9_][a-z0-9_]*^^g')"
CC="gcc -arch $arch"

configuration="--prefix=/opt/arch --openssldir=/opt/arch/etc/ssl
shared zlib"

case "$arch" in
"i386")
./Configure $configuration darwin-i386-cc
;;
"x86_64")
./Configure $configuration darwin64-x86_64-cc
;;
esac

make || return 1
make test || return 1
mkdir -p $startdir/src/build/$arch
make INSTALL_PREFIX=$startdir/src/build/$arch MANDIR=/opt/arch/
share/man install
done

make INSTALL_PREFIX=$pkgdir MANDIR=/opt/arch/share/man install

echo "making universal binaries"
for binary in $binaries; do
rm $startdir/pkg/opt/arch/$binary
lipo -create $startdir/src/build/*/opt/arch/$binary -output
$startdir/pkg/opt/arch/$binary
done

sed -i~ -e 's^EX_LIBS= *-lz^EX_LIBS= -L/opt/arch/lib -lz^g'
Makefile

install -D -m644 LICENSE $pkgdir/opt/arch/share/licenses/$pkgname/
LICENSE
}


On Jul 20, 12:49 am, Loic Nageleisen <loic.nagelei...@gmail.com>
wrote:

Kevin Barry

unread,
Aug 15, 2009, 9:59:02 PM8/15/09
to arch...@googlegroups.com
Loic wrote:
[Methods of building universal binaries]
> 4. enhance/extend makepkg to call build for each arch, then merge
> binaries. Ideal, we could use PKGBUILD as is.

> 4. really sounds the best, but I don't know if/how makepkg is
> extendable. ask upstream?

I agree that 4 sounds slick. And less modifications to PKGBUILDs is always good.

makepkg is a bash script, which I don't believe (but it's possible)
has any kind of callbacks/hooks, however it does allow you to call
--repackage (without rebuilding). An issue though is that since
Leopard doesn't have all the 64 bit libraries, some packages might not
be able to build under Leopard in 64 bit mode. So some packages, for
upload to repo use, will require a Snow Leopard build host.

On a related note
fakeroot was having weird problems when building some packages (bash,
bzip2), I traced this to gcc -g, which runs dsymutil, in 64 bit mode
apparently. So I compiled fakeroot as a universal binary, but I did it
by hacking the PKGBUILD pretty badly. ./configure couldn't pass if I
ran with -arch x86_64, and if I ran with both i686 and x86_64, libtool
failed.

-KB

Loic Nageleisen

unread,
Aug 16, 2009, 5:00:31 AM8/16/09
to arch-osx


On Aug 16, 3:59 am, Kevin Barry <bar...@gmail.com> wrote:
> Loic wrote:
>
> [Methods of building universal binaries]
>
> > 4. enhance/extend makepkg to call build for each arch, then merge
> > binaries. Ideal, we could use PKGBUILD as is.
> > 4. really sounds the best, but I don't know if/how makepkg is
> > extendable. ask upstream?
>
> I agree that 4 sounds slick. And less modifications to PKGBUILDs is always good.
>
> makepkg is a bash script, which I don't believe (but it's possible)
> has any kind of callbacks/hooks, however it does allow you to call
> --repackage (without rebuilding). An issue though is that since
> Leopard doesn't have all the 64 bit libraries, some packages might not
> be able to build under Leopard in 64 bit mode. So some packages, for
> upload to repo use, will require a Snow Leopard build host.
>
> On a related note
> fakeroot was having weird problems when building some packages (bash,
> bzip2), I traced this to gcc -g, which runs dsymutil, in 64 bit mode
> apparently. So I compiled fakeroot as a universal binary, but I did it
> by hacking the PKGBUILD pretty badly. ./configure couldn't pass if I
> ran with -arch x86_64, and if I ran with both i686 and x86_64, libtool
> failed.
>
> -KB
>

that's probably because of -march i686 which can't work with x86_64.

here's my makepkg line:
CFLAGS="-arch ${ARCH} -mtune=generic -msse -msse2 -O2 -pipe -I/opt/
arch/include ${SDK_CFLAGS}"

and here's my fat fakeroot PKGBUILD:

pkgname=fakeroot
pkgver=1.12.1
pkgrel=4
pkgdesc="Gives a fake root environment, useful for building packages
as a non-privileged user"
arch=('macx86')
license=('GPL')
url="http://packages.debian.org/fakeroot"
groups=('base-devel')
depends=()
options=('!libtool')
source=(http://ftp.debian.org/debian/pool/main/f/$pkgname/${pkgname}_$
{pkgver}.tar.gz
fakeroot_mac.diff)
md5sums=('87970d6784f536cde84f9bcbaaa52720'
'6f9c9bdb51d97bdfd26cfe118be6fd9a')

build() {
cd $startdir/src/$pkgname-$pkgver
patch -p0 < $startdir/fakeroot_mac.diff

arches="i386 x86_64"
binaries="opt/arch/bin/faked opt/arch/lib/libfakeroot/
libfakeroot-0.dylib opt/arch/lib/libfakeroot
/libfakeroot.dylib"

original_cflags="$(echo $CFLAGS | sed 's^-arch [a-z0-9_][a-z0-9_]
*^^g')"
original_ldflags="$(echo $LDFLAGS | sed 's^-arch [a-z0-9_][a-z0-9_]
*^^g')"
echo $original_cflags
echo $original_ldflags
for arch in $arches; do
echo "building $arch"
make clean
CFLAGS="-arch $arch $original_cflags"
LDFLAGS="-arch $arch $original_ldflags"
echo $CFLAGS
./configure --prefix=/opt/arch --libdir=/opt/arch/lib/libfakeroot
--disable-static
make || return 1
mkdir -p $startdir/src/build/$arch
make DESTDIR=$startdir/src/build/$arch install
done

make DESTDIR=$startdir/pkg install

for binary in $binaries; do
rm $startdir/pkg/$binary
lipo -create $startdir/src/build/*/$binary -output $startdir/pkg/
$binary
done

}

once built, check that they're all fat with 2 arches with:
$ find pkg | xargs file | grep Mach-O

Loic Nageleisen

unread,
Aug 16, 2009, 5:18:33 AM8/16/09
to arch-osx
I've uploaded fakeroot-1.13-2, built as universal. Without it, SL
users can't even build -arch i386 because their gcc stuff starts as 64
bit thus wants fakeroot to dyload as 64-bit.

On Aug 16, 11:00 am, Loic Nageleisen <loic.nagelei...@gmail.com>
> > >> > > > Since Leopard, despite having a 32-bit kernel, has full support for 64-...
>
> read more »

Loic Nageleisen

unread,
Aug 16, 2009, 5:50:41 AM8/16/09
to arch-osx
I've also pushed a new branch in my github repo. its content is based
on the wrong approach as it mostly relies on multiple -arch flags, but
I made it public for reference as it gives a good insight on the
various problems I encountered notably with the various build systems,
to which I tried hard to find a proper solution each time. Also, there
are a number of patches that simply allow for packages to build as 64-
bit at all (e.g curl, which was a pain). So this makes it a useful
reference.

On Aug 16, 11:18 am, Loic Nageleisen <loic.nagelei...@gmail.com>
> > > >> > rough edges, but I'm close to wrap it up. I'll give more details...
>
> read more »
Reply all
Reply to author
Forward
0 new messages