CompileMPlayerStatic

Version 6 (Adrian Stutz, 10/06/2008 08:07 pm)

1 1
2 6 Adrian Stutz
h1. Compile MPlayer with static libraries
3 6 Adrian Stutz
4 6 Adrian Stutz
5 4 Adrian Stutz
[[PageOutline]]
6 1
7 1
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). 
8 1
9 6 Adrian Stutz
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":http://en.wikipedia.org/wiki/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).
10 1
11 1
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.
12 1
13 1
There are two possible ways to go about linking the extra libraries statically:
14 6 Adrian Stutz
* the install_name_tool way
15 6 Adrian Stutz
* the search_paths_first way
16 1
17 1
18 6 Adrian Stutz
h2. The install_name_tool Way
19 1
20 2 Adrian Stutz
21 6 Adrian Stutz
OSX uses the "Mach-O":http://en.wikipedia.org/wiki/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":http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/install_name_tool.1.html later to change the paths of the libraries to point to static ones.
22 6 Adrian Stutz
23 6 Adrian Stutz
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_.
24 6 Adrian Stutz
25 2 Adrian Stutz
I didn't use this method for the binaries included with MPlayerOSX Extended, mainly because the official version didn't use that way either.
26 1
27 1
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
28 1
29 1
30 6 Adrian Stutz
h2. The search_paths_first Way
31 6 Adrian Stutz
32 6 Adrian Stutz
33 1
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.
34 1
35 1
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.
36 1
To statically link libraries, 
37 6 Adrian Stutz
* they cannot be in the same location as their shared counterparts
38 6 Adrian Stutz
* they have to be in an earlier path than their shared counterparts
39 6 Adrian Stutz
* the search_paths_first options has to be passed to the linker to make it stop searching when it found the static library
40 1
41 6 Adrian Stutz
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.
42 2 Adrian Stutz
43 2 Adrian Stutz
44 6 Adrian Stutz
h2. Building Preface
45 6 Adrian Stutz
46 6 Adrian Stutz
47 1
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.
48 1
49 2 Adrian Stutz
To build against the OSX SDK, you have to set the correct CFLAGS and LDFLAGS:
50 6 Adrian Stutz
<pre>
51 2 Adrian Stutz
export MACOSX_DEPLOYMENT_TARGET=10.4
52 2 Adrian Stutz
export CFLAGS="-mmacosx-version-min=10.4 -isystem /Developer/SDKs/MacOSX10.4u.sdk"
53 1
export LDFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk"
54 1
export CXXFLAGS="-mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk"
55 6 Adrian Stutz
</pre>
56 2 Adrian Stutz
This defines 10.4 as the target and minimum OS for the build to run on.
57 2 Adrian Stutz
58 2 Adrian Stutz
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.
59 2 Adrian Stutz
60 2 Adrian Stutz
To try to directly build an universal binary, specify the arch options:
61 6 Adrian Stutz
<pre>
62 2 Adrian Stutz
export CFLAGS="$CFLAGS -arch i386 -arch ppc"
63 2 Adrian Stutz
export LDFLAGS="$LDFLAGS -arch i386 -arch ppc"
64 2 Adrian Stutz
export CXXFLAGS="$CXXFLAGS -arch i386 -arch ppc"
65 6 Adrian Stutz
</pre>
66 6 Adrian Stutz
It's also needed to set _--disable-dependency-tracking_ with the respective configure script, if the option is available.
67 1
68 1
And to cross compile for PPC (with altivec):
69 6 Adrian Stutz
<pre>
70 1
export CFLAGS="$CFLAGS -arch ppc -faltivec -mcpu=7450"
71 1
export LDFLAGS="$LDFLAGS -arch ppc"
72 1
export CXXFLAGS="$CXXFLAGS -arch ppc -faltivec -mcpu=7450"
73 6 Adrian Stutz
</pre>
74 1
75 6 Adrian Stutz
If all goes well, we'll end up with a universal binary. You can check this with the "lipo":http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/lipo.1.html tool:
76 6 Adrian Stutz
<pre>
77 1
Coil:mplayer adrian$ lipo -detailed_info mplayer 
78 1
Fat header in: mplayer
79 1
fat_magic 0xcafebabe
80 1
nfat_arch 2
81 3 Adrian Stutz
architecture i386
82 1
    cputype CPU_TYPE_I386
83 3 Adrian Stutz
    cpusubtype CPU_SUBTYPE_I386_ALL
84 1
    offset 4096
85 3 Adrian Stutz
    size 11510420
86 3 Adrian Stutz
    align 2^12 (4096)
87 1
architecture ppc7400
88 1
    cputype CPU_TYPE_POWERPC
89 3 Adrian Stutz
    cpusubtype CPU_SUBTYPE_POWERPC_7400
90 1
    offset 11517952
91 1
    size 10988308
92 1
    align 2^12 (4096)
93 6 Adrian Stutz
</pre>
94 3 Adrian Stutz
95 6 Adrian Stutz
If it doesn't go well, the i386 and ppc builds have to be done separately, and then merged with _lipo_:
96 6 Adrian Stutz
<pre>
97 1
lipo -create libi386.a libppc.a -output libuniversal.a
98 6 Adrian Stutz
</pre>
99 3 Adrian Stutz
100 3 Adrian Stutz
101 6 Adrian Stutz
h2. Build Environment and Libraries
102 6 Adrian Stutz
103 6 Adrian Stutz
104 1
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.
105 6 Adrian Stutz
<pre>
106 1
mkdir ~/dev/mplayer
107 1
cd ~/dev/mplayer
108 6 Adrian Stutz
export MPPREFIX=@pwd@
109 6 Adrian Stutz
</pre>
110 1
111 6 Adrian Stutz
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.
112 6 Adrian Stutz
<pre>
113 3 Adrian Stutz
export PATH="$MPPREFIX:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin"
114 1
export PKG_CONFIG_PATH=""
115 6 Adrian Stutz
</pre>
116 1
117 3 Adrian Stutz
The libraries that compile fine under OSX can then usually be compiled with:
118 6 Adrian Stutz
<pre>
119 3 Adrian Stutz
./configure --disable-shared --disable-dependency-tracking --prefix=$MPPREFIX
120 3 Adrian Stutz
make
121 3 Adrian Stutz
make install
122 6 Adrian Stutz
</pre>
123 3 Adrian Stutz
124 6 Adrian Stutz
Detailed information regarding compiling the different libraries can be found here: [[CompileMPlayerLibraries|Compile MPlayer Libraries]]
125 5 Adrian Stutz
126 3 Adrian Stutz
127 6 Adrian Stutz
h2. Build MPlayer
128 6 Adrian Stutz
129 6 Adrian Stutz
130 3 Adrian Stutz
MPlayer needs some more flags to be set to compile:
131 6 Adrian Stutz
<pre>
132 3 Adrian Stutz
export CFLAGS="-O4 -fomit-frame-pointer -pipe $CFLAGS"
133 3 Adrian Stutz
export CXXFLAGS="-O4 -fomit-frame-pointer -pipe $CXXFLAGS"
134 6 Adrian Stutz
</pre>
135 3 Adrian Stutz
136 3 Adrian Stutz
And here's the configure I use:
137 6 Adrian Stutz
<pre>
138 3 Adrian Stutz
./configure --extra-libs="-ldvdcss" --disable-x11 --disable-gl --disable-mencoder --disable-dvdread-internal --enable-apple-remote --prefix=$MPPREFIX
139 6 Adrian Stutz
</pre>
140 3 Adrian Stutz
141 3 Adrian Stutz
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?).
142 3 Adrian Stutz
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.
143 3 Adrian Stutz
144 3 Adrian Stutz
To make the PPC build, these additional options are needed for the cross compile (with the right C/LDFLAGS):
145 6 Adrian Stutz
<pre>
146 3 Adrian Stutz
--enable-cross-compile --cc="cc -arch ppc" --host-cc="cc -arch i386" --target=ppc-darwin --disable-win32dll --enable-altivec
147 6 Adrian Stutz
</pre>
148 3 Adrian Stutz
149 3 Adrian Stutz
150 6 Adrian Stutz
h2. The _XOPEN_SOURCE issue
151 6 Adrian Stutz
152 6 Adrian Stutz
153 3 Adrian Stutz
This only affects compiling from OSX 10.5 against the 10.4 SDK.
154 3 Adrian Stutz
155 6 Adrian Stutz
At some point you might run into compile errors about some standard functions not being found, that are appended by *$UNIX2003*.
156 3 Adrian Stutz
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.
157 3 Adrian Stutz
158 3 Adrian Stutz
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.
159 3 Adrian Stutz
160 6 Adrian Stutz
Unless a source code file defines _XOPEN_SOURCE, _POSIX_C_SOURCE, _APPLE_C_SOURCE or !+LP64!+. 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.
161 3 Adrian Stutz
162 3 Adrian Stutz
To work around this, all occurrences of those definitions have either to be removed or have to check for an OSX system like this:
163 6 Adrian Stutz
<pre>
164 6 Adrian Stutz
#if !defined(+APPLE+)
165 1
#define _XOPEN_SOURCE 600
166 1
#endif
167 6 Adrian Stutz
</pre>