#!/usr/bin/perl # build GTK+ from scratch for Mac OS X into a framework as cleanly as possible # (run as "UPDATE=1 ./build" to resume an interrupted build) # (use ARCH to override the architecture, e.g "ARCH=ppc ./build") # # Author: Simon Urbanek # #$Id$ #---- Default setup: $root="/Library/Frameworks/GTK+.framework"; $ver="2.18.X11"; # <-- adjust as you please $bdir=`pwd`; $bdir=~s/[\r\n]+//g; $buildfile="gtk2.build"; #---- no need to modify anything beyond this point --- if ( ! -e $buildfile ) { print STDERR "\nERROR: missing '$buildfile' config file\n\n"; exit 1; } $gtkver="2.18.0"; # just a fallback, we'll update this from the GTK+ tar ball open IN, $buildfile; sub sys { system $_[0]; if ($? == -1) { print "system $_[0]\nERROR: failed to execute: $!\n"; exit 1; } elsif ($? & 127) { printf "system $_[0]\nERROR: died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; exit 2; } else { $ev=$? >> 8; if ($ev != 0) { printf "system $_[0]\nERROR: exited with value %d\n", $? >> 8; exit 3; } } 1; } $arch=$ENV{ARCH}; $arch=`arch` if ($arch eq ''); $arch=~s/[\r\n]+//g; print "Architecture: $arch\n"; if ($ENV{ARCH} ne '') { $chost="--host=$arch-apple-darwin".`uname -r`; chomp $chost; $chost.=" "; $chost=~s/i386/i686/; $chost=~s/ppc/powerpc/; print "Using additional host flag: $chost\n"; } $CC=$ENV{CC}; $CC='gcc' if ($CC eq ''); $CXX=$ENV{CXX}; $CXX='g++' if ($CXX eq ''); $MAKE=$ENV{MAKE}; $MAKE='make' if ($MAKE eq ''); print "Tools: cc=$CC, cxx=$CXX, make=$MAKE\n"; if ($ENV{UPDATE} ne '') { print "Update requested, checking versions...\n"; if (! -e "$root/Versions/$ver/Resources/bin") { print " ** $ver not present, forcing clean build\n"; } else { print " - OK, performing update build\n"; $UPDATE=1; } } if ($UPDATE == 0) { sys "rm -rf $root/Versions/$ver"; sys "mkdir -p $root $root/Versions/$ver/Resources/bin"; system "rm -rf $bdir/OK-* $bdir/build-script-* $bdir/bld"; # clean up from previous builds } # the symlinks must be correct even if we perform an update sys "ln -sfn $ver $root/Versions/Current"; sys "ln -sfn Versions/Current/Resources $root/Resources"; sys "ln -sfn Resources/include $root/Headers"; sys "ln -sfn Resources/lib $root/Libraries"; #$prefix="$root/Resources"; # non-versioned root $prefix="$root/Versions/$ver/Resources"; # versioned root $cpus=`sysctl -n hw.ncpu` + 0; $cpus=8 if ($cpus < 1); $defaultmj="-j$cpus"; $makef=''; $basic=; chop $basic; if ( ! -e "$root/Versions/$ver/Resources/lib/pkgconfig/libxml-2.0.pc" ) { # create libxml-2.0 system library stub $xmlver='2.6.16'; # this is the version reported by Tiger and Leopard #$xmldv=`grep 'define LIBXML_DOTTED_VERSION' /usr/include/libxml2/libxml/xmlversion.h`; #$xmlver=$1 if ($xmldv=~/\"(.*)\"/); system "mkdir -p $root/Versions/$ver/Resources/lib/pkgconfig 2>/dev/null"; open LX, ">$root/Versions/$ver/Resources/lib/pkgconfig/libxml-2.0.pc"; print LX 'prefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include/libxml2 Name: libxml-2.0 Description: libxml2 system stub pc Version: '.$xmlver.' Libs: -lxml2 Cflags: -I${includedir} '; close LX; } sub build { my ($fn); $fn=$_[0]; $tar="tar fxz"; $tar="tar fxj" if ($fn=~/.tar.bz2/); $td=$fn; $td=~s/.*\///; $td=~s/.tar.gz//; $td=~s/.tar.bz2//; print "$fn -> $td\n"; if ($UPDATE > 0 && -e "$bdir/OK-$td") { print " - already built, skipping\n"; return 1 } chdir "$bdir"; system "rm -rf bld; mkdir bld"; open OUT, ">build-script-$td.sh"; $inst="&& make install"; $preconf="$preconf && \\\n" if ($preconf ne ''); $premake="$premake && \\\n" if ($premake ne ''); $inst='' if ($NOINST > 0); print OUT "#!/bin/sh\nROOT=$root\nexport ROOT\narch=$arch\nexport arch\nPATH=$root/Resources/bin:\$PATH\nexport PATH\nPKG_CONFIG_PATH=$root/Resources/lib/pkgconfig\nexport PKG_CONFIG_PATH\nGCC='$CC'\nexport GCC\nGCXX='$CXX'\nexport GCXX\nMAKE='$MAKE'\nexport MAKE\ncd $bdir && $tar $fn && \\\n( if [ -e '$bdir/$td.patch' ]; then cd '$bdir/$td'; patch -p1 < '$bdir/$td.patch'; fi ) && \\\n cd $bdir/bld && \\\n${preconf}../$td/configure ${chost}'--prefix=$prefix' $_[1] && \\\n${premake}make $makej $makef $inst && \\\necho '$fn' > $bdir/OK-$td\n"; close OUT; sys "sh $bdir/build-script-$td.sh"; } if ($UPDATE == 0 || ! -e "$root/Resources/bin/pkg-config" ) { # buid pkg-config first sys "cd $bdir && if [ ! -e pkg-config-0.23.tar.gz ]; then curl -O http://pkg-config.freedesktop.org/releases/pkg-config-0.23.tar.gz; fi"; $NOINST=1; build "pkg-config-0.23.tar.gz", "'--enable-static' 'CC=$CC -arch $arch' 'CPP=$CC -arch $arch -E' 'CXX=$CC -arch $arch' '--disable-shared' 'CPPFLAGS=-I$root/Headers' 'LDFLAGS=-L$root/Libraries'"; sys "cp $bdir/bld/pkg-config $root/Resources/bin"; $NOINST=0; } while () { chop; next if (/^#/); $url=$_; $cf=; chop $cf; $makej=$defaultmj; # $SERIAL_MAKE means that the package cannot be build with -j if ($cf=~/\$SERIAL_MAKE/) { $cf=~s/\$SERIAL_MAKE//; $makej=''; } $premake=''; $preconf=''; if ($cf=~/<>/) { $premake=$1; $cf=~s/<>//; } if ($cf=~/<>/) { $preconf=$1; $cf=~s/<>//; } $fn=$url; $fn=~s/.*\///; sys "cd $bdir && if [ ! -e $fn ]; then echo 'downloading $fn'; curl -O $url; fi"; $flags="$basic $cf"; $flags=$1 if ($cf =~ /^\!(.*)/); # leading ! means replace all flags $gtkver=$1 if ($url=~/\/gtk\+\-(.*)\.tar/); build $fn, $flags; } close IN; open PL, ">$root/Resources/Info.plist"; print PL ' CFBundleIdentifier org.gtk.gtk-framework CFBundleInfoDictionaryVersion 6.0 CFBundleName GTK CFBundlePackageType FMWK CFBundleVersion '.$gtkver.' '; close PL; print "\nDONE - GTK+ $gtkver\n";