OSXHorrors » History » Version 29

Chris Cannam, 2012-11-08 01:06 PM

1 1 Chris Cannam
h1. OS/X version, hardware platform, and Qt version compatibility
2 1 Chris Cannam
3 22 Chris Cannam
{{>toc}}
4 22 Chris Cannam
5 29 Chris Cannam
*Last updated* Feb 2012. It may be possible to drop all pre-64-bit platforms by now (end of 2012) and rely on users of older platforms simply sticking with older builds.
6 22 Chris Cannam
7 6 Chris Cannam
*Executive summary:* For a program like EasyHg that demands the widest possible compatibility, we currently want to hit the following targets:
8 6 Chris Cannam
9 6 Chris Cannam
* 10.4 PPC 32-bit Carbon
10 6 Chris Cannam
* 10.4 Intel 32-bit Carbon
11 6 Chris Cannam
* 10.6 Intel 64-bit Cocoa
12 1 Chris Cannam
13 8 Chris Cannam
To do this, we currently need at least two builds of Qt:
14 8 Chris Cannam
15 12 Chris Cannam
* 10.6 gcc-4.2 Cocoa x86_64
16 8 Chris Cannam
* 10.4 gcc-4.0 Carbon PPC and i386
17 1 Chris Cannam
18 24 Chris Cannam
And we need at least three builds of our PyQt (Python plus C++) modules:
19 1 Chris Cannam
20 24 Chris Cannam
* Python 2.6 gcc-4.2 Cocoa x86_64
21 24 Chris Cannam
* Python 2.6 gcc-4.0 Carbon PPC and i386
22 24 Chris Cannam
* Python 2.5 gcc-4.0 Carbon PPC and i386
23 24 Chris Cannam
24 24 Chris Cannam
Our Qt builds need to be custom rather than stock distribution (see Qt Plugins below).
25 24 Chris Cannam
26 1 Chris Cannam
Note it is not possible to cover all platforms in a single build step, we always need to do at least two separate builds plus lipo.
27 12 Chris Cannam
28 12 Chris Cannam
If we are going to make a 3-way universal binary, we need to ensure the 10.4 build gets selected for i386 -- i.e. to pull only the x86_64 architecture from any 10.5 or 10.6 SDK build we do.  The inability to select between different i386 versions from a single universal binary is a strong incentive to stick to a single 10.4+ Carbon build for all 32-bit platforms.
29 1 Chris Cannam
30 24 Chris Cannam
So our bundle layout will look like this (beneath the Contents directory):
31 24 Chris Cannam
32 24 Chris Cannam
<pre>
33 24 Chris Cannam
 Contents/
34 24 Chris Cannam
  +- Frameworks/
35 24 Chris Cannam
  |   +- QtCore [ppc] [i386] [x86_64]
36 24 Chris Cannam
  |   +- QtGui [ppc-carbon] [i386-carbon] [x86_64-cocoa]
37 24 Chris Cannam
  |   `- QtNetwork [ppc] [i386] [x86_64]
38 24 Chris Cannam
  +- MacOS/
39 24 Chris Cannam
      +- Py2.5/
40 24 Chris Cannam
      |   +- sip.so [ppc] [i386]
41 24 Chris Cannam
      |   +- PyQt4
42 24 Chris Cannam
      |       +- Qt.so [ppc] [i386]
43 24 Chris Cannam
      |       +- QtCore.so [ppc] [i386]
44 24 Chris Cannam
      |       `- QtGui.so [ppc-carbon] [i386-carbon]
45 24 Chris Cannam
      +- Py2.6/
46 24 Chris Cannam
      |   +- sip.so [ppc] [i386] [x86_64]
47 24 Chris Cannam
      |   +- PyQt4
48 24 Chris Cannam
      |       +- Qt.so [ppc] [i386] [x86_64]
49 24 Chris Cannam
      |       +- QtCore.so [ppc] [i386] [x86_64]
50 24 Chris Cannam
      |       `- QtGui.so [ppc-carbon] [i386-carbon] [x86_64-cocoa]
51 24 Chris Cannam
      +- EasyMercurial [ppc-carbon] [i386-carbon] [x86_64-cocoa]
52 24 Chris Cannam
</pre>
53 24 Chris Cannam
54 25 Chris Cannam
We also need to make sure the dependency paths are correct.  Beware!  It appears the dependency paths are stored separately for each architecture in a fat binary, but otool won't report them separately if you run it on a single fat binary with multiple architectures. We need to ensure each architecture is correct before we can lipo them together.
55 25 Chris Cannam
56 1 Chris Cannam
h2. Qt Plugins
57 1 Chris Cannam
58 1 Chris Cannam
Qt will by default load any plugins for e.g. image format support that it finds in the system.  There are various ways to block plugin loading (e.g. through build key) but I can't see any way that will prevent Qt from at least dlopen()ing the shared object and rifling through its drawers.
59 1 Chris Cannam
60 1 Chris Cannam
This is a problem, because the plugins have dependencies on the Qt framework components, so we may end up with two different versions of Qt (the one in our bundle and the system one) being loaded at once.  Result: mysterious crashes.
61 1 Chris Cannam
62 1 Chris Cannam
For the moment we "fix" this by applying the following elegant patch to our Qt build:
63 1 Chris Cannam
64 1 Chris Cannam
<pre>
65 1 Chris Cannam
--- src/corelib/plugin/qfactoryloader.cpp_	2011-03-14 12:21:11.000000000 +0000
66 1 Chris Cannam
+++ src/corelib/plugin/qfactoryloader.cpp	2011-03-14 12:22:04.000000000 +0000
67 1 Chris Cannam
@@ -104,7 +104,7 @@
68 1 Chris Cannam
 
69 1 Chris Cannam
 void QFactoryLoader::update()
70 1 Chris Cannam
 {
71 1 Chris Cannam
-#ifdef QT_SHARED
72 1 Chris Cannam
+#ifdef NO_WE_DONT_WANT_PLUGINS_THANKS
73 1 Chris Cannam
     Q_D(QFactoryLoader);
74 1 Chris Cannam
     QStringList paths = QCoreApplication::libraryPaths();
75 1 Chris Cannam
     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
76 1 Chris Cannam
--- src/corelib/plugin/qpluginloader.cpp_	2011-03-14 12:23:31.000000000 +0000
77 1 Chris Cannam
+++ src/corelib/plugin/qpluginloader.cpp	2011-03-14 12:23:53.000000000 +0000
78 1 Chris Cannam
@@ -285,7 +285,7 @@
79 1 Chris Cannam
 */
80 1 Chris Cannam
 void QPluginLoader::setFileName(const QString &fileName)
81 1 Chris Cannam
 {
82 1 Chris Cannam
-#if defined(QT_SHARED)
83 1 Chris Cannam
+#if defined(NO_WE_DONT_WANT_PLUGINS_THANKS)
84 1 Chris Cannam
     QLibrary::LoadHints lh;
85 1 Chris Cannam
     if (d) {
86 1 Chris Cannam
         lh = d->loadHints;
87 1 Chris Cannam
</pre>
88 1 Chris Cannam
89 1 Chris Cannam
h2. Python versions
90 1 Chris Cannam
91 26 Chris Cannam
Python versioning and compatibility is a bit of a nightmare.  We need to load a Python module with native components (using PyQt) in Mercurial, so we need to take into account both the Python version and the architecture.
92 1 Chris Cannam
93 27 Chris Cannam
The system Python is 2.5 on 10.4/10.5 and 2.6 on 10.6.  (It's quite likely that users of older (10.4) OS/X will have updated their Python to 2.6 as well, since that's advisable for installing Mercurial.)  PyQt compiled for 2.5 will not work in 2.6, and vice versa.  This makes it difficult to provide a single bundle for all platforms, as we have no static way (without an installer script) to ensure that the PyQt modules for the right version of Python get loaded; we have to do it by explicitly loading modules from a different location depending on the version, in the Python code itself.
94 1 Chris Cannam
95 26 Chris Cannam
On 10.6, Python is 32-/64-bit universal which runs in 64-bit by default on a 64-bit system, so any native modules need to be available both ways as well (troubleshooting this when it goes wrong is quite tricky).  There is an environment variable @VERSIONER_PYTHON_PREFER_32_BIT@ which you can set to cause it always to run in 32-bit.
96 1 Chris Cannam
97 26 Chris Cannam
So, any 64-bit Python is guaranteed (as far as anything ever is) to be (at least) version 2.6, but any version could also exist in a 32-bit form.
98 26 Chris Cannam
99 1 Chris Cannam
Where things get complicated is when users install additional versions of Python from other ports repositories; this seems to be quite common around these parts.  Then your user-installed Python is likely to get picked up before the system one, and you don't know whether it's going to be 32- or 64-bit, and it won't support the versioning environment variable.  My impression is that people get custom Python installs dragged in as dependencies of other packages, and that tends to break quite a lot of things.
100 1 Chris Cannam
101 26 Chris Cannam
So we have two discriminations to make:
102 26 Chris Cannam
103 26 Chris Cannam
 * Python 2.5 vs 2.6 -- discriminate at run time, in the Python extension, before loading the native module -- we can set the module load path appropriately for our version
104 26 Chris Cannam
 * 32-bit vs 64-bit Python -- discriminate at native module load time via fat binaries
105 23 Chris Cannam
106 23 Chris Cannam
h2. OS/X versions
107 23 Chris Cannam
108 28 Chris Cannam
h3. 10.7
109 28 Chris Cannam
110 28 Chris Cannam
h4. As target
111 28 Chris Cannam
112 28 Chris Cannam
* Not supported on PPC or on 32-bit Intel (Core Duo)
113 28 Chris Cannam
* Runs in 64-bit mode always
114 28 Chris Cannam
115 28 Chris Cannam
h4. As build host
116 28 Chris Cannam
117 28 Chris Cannam
* Builds 64-bit by default
118 28 Chris Cannam
* Can be used to do 32-bit Intel builds (not sure about PPC?)
119 28 Chris Cannam
120 23 Chris Cannam
h3. 10.6
121 23 Chris Cannam
122 23 Chris Cannam
h4. As target
123 23 Chris Cannam
124 23 Chris Cannam
* By far the most common version as of Feb 2011 (apparently >80%)
125 23 Chris Cannam
* Not supported on PPC
126 23 Chris Cannam
* Runs in 64-bit mode by default where possible
127 23 Chris Cannam
* Note Python is also 64-bit by default, so PyQt needs to be as well
128 23 Chris Cannam
* Is _not_ always 64-bit -- it is supported on 32-bit-only hardware such as Core Duo (first Intel Macs)
129 23 Chris Cannam
130 23 Chris Cannam
h4. As build host
131 23 Chris Cannam
132 23 Chris Cannam
* Builds 64-bit by default
133 23 Chris Cannam
* Can be used to do 32-bit Intel and PPC builds
134 23 Chris Cannam
135 23 Chris Cannam
h3. 10.5
136 23 Chris Cannam
137 23 Chris Cannam
h4. As target
138 23 Chris Cannam
139 23 Chris Cannam
* Not all that much more widely used than 10.4 -- if we were dropping 10.4, we probably might as well drop 10.5 as well
140 23 Chris Cannam
* Last version supported for PPC platforms
141 23 Chris Cannam
* Runs in 32-bit mode by default
142 23 Chris Cannam
* Can build for it from 10.5, 10.6
143 23 Chris Cannam
* Requires SDK @/Developer/SDKs/MacOSX10.5.SDK@
144 23 Chris Cannam
* First version to support Objective-C 2.0
145 23 Chris Cannam
* Qt Cocoa supported
146 23 Chris Cannam
147 23 Chris Cannam
h4. As build host
148 23 Chris Cannam
149 23 Chris Cannam
* Builds 32-bit by default
150 23 Chris Cannam
* Can be used to do 64-bit builds
151 23 Chris Cannam
152 23 Chris Cannam
h3. 10.4
153 23 Chris Cannam
154 23 Chris Cannam
h4. As target
155 23 Chris Cannam
156 23 Chris Cannam
* Oldest version still apparently in use as of Feb 2011: not very widespread (low single digit %age of Mac users), but at least two researchers here use it
157 23 Chris Cannam
* Appears in PPC and i386 systems
158 23 Chris Cannam
* Runs in 32-bit mode only
159 23 Chris Cannam
* Can build for it from 10.4, 10.5, 10.6
160 23 Chris Cannam
* Requires SDK @/Developer/SDKs/MacOSX10.4u.SDK@
161 23 Chris Cannam
* Requires @-mmacosx-version-min=10.4@ on 10.5+
162 23 Chris Cannam
* Requires gcc-4.0 to be requested explicitly on 10.6
163 23 Chris Cannam
* Does not support Objective-C 2.0
164 23 Chris Cannam
* Not a supported target for Qt's Cocoa builds, Qt Carbon needed
165 23 Chris Cannam
166 23 Chris Cannam
h4. As build host
167 23 Chris Cannam
168 23 Chris Cannam
* Does not support Objective-C 2.0
169 23 Chris Cannam
* 10.4u SDK can be used to build 64-bit executables of simple C/C++ programs such as plugins, but not of GUIs or anything using Core frameworks