Compile MPlayer with static libraries

PageOutline

If you want to compile MPlayer (the command-line player behind MPlayerOSX), there are two ways to go at it. MPlayer depends on various libraries and you can compile a version linked to the libraries installed on your system (shared) or put the libraries into one self-contained binary (static).

Compiling MPlayer with statically linked libraries is a bit more tricky. On a regular Unix, you can use _--enable-static_ to create a build that links everything it uses statically. On OSX, this method will fail because Apple has deliberately broken static linking of its system libraries by excluding a static version of the libc library that contains the most basic C functions. You could just download the source code of that library and build a static version yourself but that would be besides the point. Apple excluded it because it doesn't want its system libraries to be statically linked and therefore to be able to update them at a later time (which is not possible for statically linked libraries because they are built into the application binary).

So, instead of statically linking all libraries, you'd only want to statically link any non-system library. It's not needed to statically link the system libraries anyway. They are guaranteed to exist on all OSX installations and Apple takes care of making sure OSX is backwards-compatible if they change anything.

There are two possible ways to go about linking the extra libraries statically:
  • the install_name_tool way
  • the search_paths_first way

The install_name_tool Way

OSX uses the Mach-O binary structure that contains paths to all linked libraries. One way to statically link libraries is to first compile mplayer with shared libraries and then use install_name_tool later to change the paths of the libraries to point to static ones.

This way, the libraries and the application binary will be separate and the libraries have to be in a fixed relative location to the application binary. On OSX this is not so much of a concern since it's possible to bundle everything in an .app package. To the user the application binary and the libraries will appear as one single file. The most common way is to keep the libraries in a Frameworks folder, so that the paths are changed to ../Frameworks/libexample.a.

I didn't use this method for the binaries included with MPlayerOSX Extended, mainly because the official version didn't use that way either.

If you'll need further instructions for this method, you'll find some with Google. Here's one: http://qin.laya.com/tech_coding_help/dylib_linking.html

The search_paths_first Way

With this method you link the libraries statically at compile time and they are included in the application binary. This creates only one single file, that will be rather large, since it includes all dependencies. But this way you will get an mplayer binary that can simply be copied anywhere and used without the GUI and the .app package.

But to get OSX to statically link the libraries is not very straight forward. OSX's compiler will search all paths and will link shared libraries preferentially, even if it found a static version in an earlier path.
To statically link libraries,
  • they cannot be in the same location as their shared counterparts
  • they have to be in an earlier path than their shared counterparts
  • the search_paths_first options has to be passed to the linker to make it stop searching when it found the static library

You could use this method together with MacPorts by copying all static libraries into a separate directory structure and then specify this library path first. I chose to build everything by hand, mostly because I was curious and a little bit adventurous.

Building Preface

Another thing to keep in mind is OSX backward compatibility. If you just build away then the resulting binary will be only compatible with the OSX version you build it upon and may even run only on your system alone. What you need to do is to build it against the OSX SDK (installed with the developer tools) that only contains those parts that are guaranteed to exist on all installations and there are also SDKs to build for older OSX versions.

To build against the OSX SDK, you have to set the correct CFLAGS and LDFLAGS:

export MACOSX_DEPLOYMENT_TARGET=10.4
export CFLAGS="-mmacosx-version-min=10.4 -isystem /Developer/SDKs/MacOSX10.4u.sdk" 
export LDFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk" 
export CXXFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk" 

This defines 10.4 as the target and minimum OS for the build to run on.

Then there are universal binaries. There are still many PPC macs around and so we need to compile for i386 and ppc. On some projects is possible to build an universal binary in one swoop but others need separate builds for both architectures.

To try to directly build an universal binary, specify the arch options:

export CFLAGS="$CFLAGS -arch i386 -arch ppc" 
export LDFLAGS="$LDFLAGS -arch i386 -arch ppc" 
export CXXFLAGS="$CXXFLAGS -arch i386 -arch ppc" 

It's also needed to set _--disable-dependency-tracking_ with the respective configure script, if the option is available.

And to cross compile for PPC (with altivec):

export CFLAGS="$CFLAGS -arch ppc -faltivec -mcpu=7450" 
export LDFLAGS="$LDFLAGS -arch ppc" 
export CXXFLAGS="$CXXFLAGS -arch ppc -faltivec -mcpu=7450" 

If all goes well, we'll end up with a universal binary. You can check this with the lipo tool:

Coil:mplayer adrian$ lipo -detailed_info mplayer 
Fat header in: mplayer
fat_magic 0xcafebabe
nfat_arch 2
architecture i386
    cputype CPU_TYPE_I386
    cpusubtype CPU_SUBTYPE_I386_ALL
    offset 4096
    size 11510420
    align 2^12 (4096)
architecture ppc7400
    cputype CPU_TYPE_POWERPC
    cpusubtype CPU_SUBTYPE_POWERPC_7400
    offset 11517952
    size 10988308
    align 2^12 (4096)

If it doesn't go well, the i386 and ppc builds have to be done separately, and then merged with lipo:

lipo -create libi386.a libppc.a -output libuniversal.a

Build Environment and Libraries

To build all the libraries, I created a separate root for the libraries to go into, downloaded the libraries one-by-one, compiled and finally installed them in the root.

mkdir ~/dev/mplayer
cd ~/dev/mplayer
export MPPREFIX=@pwd@

But first, it's important to make sure that nothing interferes with the build process, especially MacPorts. For this we reset the PATH to the defaults and make sure that PKG_CONFIG_PATH is empty.

export PATH="$MPPREFIX:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin" 
export PKG_CONFIG_PATH="" 

The libraries that compile fine under OSX can then usually be compiled with:

./configure --disable-shared --disable-dependency-tracking --prefix=$MPPREFIX
make
make install

Detailed information regarding compiling the different libraries can be found here: Compile MPlayer Libraries

Build MPlayer

MPlayer needs some more flags to be set to compile:

export CFLAGS="-O4 -fomit-frame-pointer -pipe $CFLAGS" 
export CXXFLAGS="-O4 -fomit-frame-pointer -pipe $CXXFLAGS" 

And here's the configure I use:

./configure --extra-libs="-ldvdcss" --disable-x11 --disable-gl --disable-mencoder --disable-dvdread-internal --enable-apple-remote --prefix=$MPPREFIX

Mostly I disable stuff that's not needed. X11 and GL video outputs, the whole mencoder, the internal dvdread because I have dvdread and dvdnav external and finally I enable the apple remote because it doesn't pick that up automatically (maybe because I don't have an IR reciever?).
The --extra-libs tells the linker that it needs to include libdvdcss that is used by the external dvdread and doesn't get included automatically.

To make the PPC build, these additional options are needed for the cross compile (with the right C/LDFLAGS):

--enable-cross-compile --cc="cc -arch ppc" --host-cc="cc -arch i386" --target=ppc-darwin --disable-win32dll --enable-altivec

The _XOPEN_SOURCE issue

This only affects compiling from OSX 10.5 against the 10.4 SDK.

At some point you might run into compile errors about some standard functions not being found, that are appended by $UNIX2003.
Those symbols were introduced with OSX 10.5's UNIX 2003 compliance. Apple kept the old functions for backwards compatibility and postfixed the new UNIX 2003 compatible functions with $UNIX2003.

When compiling for 10.4 the old functions have obviously to be used. If you set the CFLAGS/LDFLAGS above, the compiler will do that automatically for you.

Unless a source code file defines _XOPEN_SOURCE, _POSIX_C_SOURCE, _APPLE_C_SOURCE or +. Any of those flags make the headers use the postfixed symbols and when the linker then tries to link against those symbols in the 10.4 SDK, they obviously cannot be found.

To work around this, all occurrences of those definitions have either to be removed or have to check for an OSX system like this:

#if !defined(+APPLE+)
#define _XOPEN_SOURCE 600
#endif

Also available in: HTML TXT