]> git.saurik.com Git - wxWidgets.git/blob - docs/tech/tn0020.txt
moving forward
[wxWidgets.git] / docs / tech / tn0020.txt
1 Binary Compatibility and wxWidgets
2 ==================================
3 0. Purpose
4 ----------
5
6 This is a broad technote covering all aspects of binary compatibility with
7 wxWidgets.
8
9 1. Releases
10 -----------
11
12 General overview of releases can be found in tn0012.txt, but for
13 completeness the wxWidgets release version number is as follows:
14
15 2.6.2
16
17 Where
18
19 2 6 2
20 Major Minor Release
21
22 (I.E. Major.Minor.Release).
23
24 All versions with EVEN minor version component (e.g. 2.4.x, 2.6.x etc.)
25 are expected to be binary compatible (ODD minors are development versions
26 and the compatibility constraints don't apply to them). Note that by
27 preserving binary compatibility we mean BACKWARDS compatibility only,
28 meaning that applications built with old wxWidgets headers should continue
29 to work with new wxWidgets (shared/dynamic) libraries without the need to
30 rebuild. There is no requirement to preserve compatibility in the other
31 direction (i.e. make new headers compatible with old libraries) as this
32 would preclude any additions whatsoever to the stable branch. But see
33 also section (4).
34
35
36 2. What kind of changes are NOT binary compatible
37 -------------------------------------------------
38
39 If its still up, the KDE guide is a good reference:
40 http://developer.kde.org/documentation/other/binarycompatibility.html
41
42 The changes that are NOT binary compatible:
43 - Adding a virtual function
44 - Changing the name of a any function or variable
45 - Changing the signature of a virtual function (adding a parameter,
46 even a default one)
47 - Changing the order of the virtual functions in a class
48 ["switching" them, etc.]
49 - Changing access privileges of a function: some compilers (among which MSVC)
50 use the function access specifier in its mangled name. Moreover, while
51 changing a private function to public should be compatible (as the old
52 symbol can't be referenced from outside the library anyhow), changing a
53 virtual private function to public is NOT compatible because the old symbol
54 is referenced by the virtual tables in the executable code and so an old
55 program compiled with MSVC wouldn't start up with a new DLL even if it
56 doesn't use the affected symbol at all!
57 - Adding a member variable
58 - Changing the order of non-static member variables
59
60
61 3. Changes which are compatible
62 -------------------------------
63
64 - Adding a new class
65 - Adding a new non-virtual method to an existing class
66 - Overriding the implementation of an existing virtual function
67 [this is considered to be backwards binary compatible until we find a
68 counter example; currently it's known to work with Apple gcc at least]
69 - Anything which doesn't result in ABI change at all, e.g. adding new
70 macros, constants and, of course, private changes in the implementation
71
72
73 4. wxABI_VERSION and "forward" binary compatibility
74 --------------------------------------------------
75
76 As mentioned we do not support "forward" binary compatibility, that is the
77 ability to run applications compiled with new wxWidgets headers on systems
78 with old wxWidgets libraries.
79
80 However, for the developers who want to ensure that their application works
81 with some fixed old wxWidgets version and doesn't (inadvertently) require
82 features added in later releases, we provide the macro wxABI_VERSION which
83 can be defined to restrict the API exported by wxWidgets headers to that of
84 a fixed old release.
85
86 For this to work, all new symbols added to binary compatible releases must
87 be #if'ed with wxABI_VERSION.
88
89 The layout of wxABI_VERSION is as follows:
90
91 20602
92
93 where
94
95 2 06 02
96 Major Minor Release
97
98 I.E. it corresponds to the wxWidgets release in (1).
99
100 An example of using wxABI_VERSION is as follows for symbols
101 only in a 2.6.2 release:
102
103 #if wxABI_VERSION >= 20602 /* 2.6.2+ only */
104 bool Load(const wxURI& location, const wxURI& proxy);
105
106 wxFileOffset GetDownloadProgress();
107 wxFileOffset GetDownloadTotal();
108
109 bool ShowPlayerControls(
110 wxMediaCtrlPlayerControls flags =
111 wxMEDIACTRLPLAYERCONTROLS_DEFAULT);
112
113 //helpers for the wxPython people
114 bool LoadURI(const wxString& fileName)
115 { return Load(wxURI(fileName)); }
116 bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
117 { return Load(wxURI(fileName), wxURI(proxy)); }
118 #endif
119
120
121 5. Workarounds for adding virtual functions
122 -------------------------------------------
123
124 Originally the idea for adding virtual functions to binary compatible
125 releases was to pad out some empty "reserved" functions and then
126 rename those later when someone needed to add a virtual function.
127
128 However, after there was some actual testing of the idea a lot of
129 controversy erupted. Eventually we decided against the idea, and
130 instead devised a new method for doing so called wxShadowObject.
131
132 wxShadowObject is a class derived from wxObject that provides a means
133 of adding functions and/or member variables to a class internally
134 to wxWidgets. It does so by storing these in a hash map inside of
135 it, looking it up when the function etc. is called. wxShadowObject
136 is generally stored inside a reserved member variable.
137
138 wxShadowObject resides in include/wx/clntdata.h.
139
140 To use wxShadowObject, you first call AddMethod or AddField with
141 the first parameter being the name of the field and/or method
142 you want, and the second parameter being the value of the
143 field and/or method.
144
145 In the case of fields this is a void*, and in the case of method
146 is a wxShadowObjectMethod which is a typedef:
147 typedef int (*wxShadowObjectMethod)(void*, void*);
148
149 After you add a field, you can set it via SetField with the same
150 parameters as AddField, the second parameter being the value to set
151 the field to. You can get the field after you call AddField
152 via GetField, with the parameters as the other two field functions,
153 only in the case the second parameter is the fallback
154 value for the field in the case of it not being found in the
155 hash map.
156
157 You can call a method after you add it via InvokeMethod, which
158 returns a bool indicating whether or not the method was found
159 in the hash map, and has 4 parameters. The first parameter is
160 the name of the method you wish to call, the second is the first
161 parameter passed to the wxShadowObjectMethod, the third is the
162 second parameter passed to that wxShadowObjectMethod, and the
163 fourth is the return value of the wxShadowObjectMethod.
164
165 6. version-script.in
166 --------------------
167
168 For ld/libtool we use sun-style version scripts. Basically
169 anything which fits the conditions of being #if'ed via wxABI_VERSION
170 needs to go here also.
171
172 See 'info ld scripts version' on a GNU system, it's online here:
173 http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_node/ld_25.html
174
175 Or see chapter 5 of the 'Linker and Libraries Guide' for Solaris, available
176 online here:
177 http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWdev/LLM/p1.html
178
179 The file has the layout as follows:
180
181 @WX_VERSION_TAG@.X
182
183 Where X is the current Release as mentioned earlier, i.e. 2. This
184 is following by an opening bracket "{", followed by "global:",
185 followed by patterns matching added symbols, then followed by "}", and then
186 the file is either followed by earlier Releases or ended by
187 a @WX_VERSION_TAG@ block without the period or Release.
188
189 The patterns used to specify added symbols are globbing patters and can
190 contain wildcards such as '*'.
191
192 For example for a new class member such as:
193 wxFont wxGenericListCtrl::GetItemFont( long item ) const;
194
195 the mangled symbol might be:
196 _ZNK17wxGenericListCtrl11GetItemFontEl
197
198 so a line like this could be added to version-script.in:
199 *wxGenericListCtrl*GetItemFont*;
200
201 Allow for the fact that the name mangling is going to vary from compiler to
202 complier.
203
204 When adding a class you can match all the symbols it adds with a single
205 pattern, so long as that pattern is not likely to also match other symbols.
206 For example for wxLogBuffer a line like this:
207 *wxLogBuffer*;
208
209
210 7. Checking the version information in libraries and programs
211 -------------------------------------------------------------
212
213 On Sun there is a tool for this, see pvs(1). On GNU you can use objdump, below
214 are some examples.
215
216 To see what versions of each library a program (or library) depends on:
217
218 $ objdump -p widgets | sed -ne '/Version References/,/^$/p'
219 Version References:
220 required from libgcc_s.so.1:
221 0x0b792650 0x00 10 GCC_3.0
222 required from libwx_based-2.6.so.0:
223 0x0cca2546 0x00 07 WXD_2.6
224 required from libstdc++.so.6:
225 0x056bafd3 0x00 09 CXXABI_1.3
226 0x08922974 0x00 06 GLIBCXX_3.4
227 required from libwx_gtk2d_core-2.6.so.0:
228 0x0a2545d2 0x00 08 WXD_2.6.2
229 0x0cca2546 0x00 05 WXD_2.6
230 required from libc.so.6:
231 0x09691a75 0x00 04 GLIBC_2.2.5
232
233 To see what WXD_2.6.2 symbols a program uses:
234
235 $ objdump -T widgets | grep 'WXD_2\.6\.2'
236 0000000000000000 g DO *ABS* 0000000000000000 WXD_2.6.2 WXD_2.6.2
237 00000000004126d8 DF *UND* 0000000000000177 WXD_2.6.2 _ZN19wxTopLevelWindowGTK20RequestUserAttentionEi
238
239 To see what WXD_2.6.2 symbols a library defines:
240
241 $ objdump -T libwx_based-2.6.so | grep 'WXD_2\.6\.2' | grep -v 'UND\|ABS'
242 0000000000259a10 w DO .data 0000000000000018 WXD_2.6.2 _ZTI19wxMessageOutputBest
243 00000000002599e0 w DO .data 0000000000000028 WXD_2.6.2 _ZTV19wxMessageOutputBest
244 000000000010a98e w DF .text 000000000000003e WXD_2.6.2 _ZN19wxMessageOutputBestD0Ev
245 0000000000114efb w DO .rodata 000000000000000e WXD_2.6.2 _ZTS11wxLogBuffer
246 0000000000255590 w DO .data 0000000000000018 WXD_2.6.2 _ZTI11wxLogBuffer
247 000000000011b550 w DO .rodata 0000000000000016 WXD_2.6.2 _ZTS19wxMessageOutputBest
248 00000000000bfcc8 g DF .text 00000000000000dd WXD_2.6.2 _ZN11wxLogBuffer5DoLogEmPKcl
249 000000000010a3a6 g DF .text 0000000000000153 WXD_2.6.2 _ZN19wxMessageOutputBest6PrintfEPKcz
250 00000000000c0b22 w DF .text 000000000000004b WXD_2.6.2 _ZN11wxLogBufferD0Ev
251 00000000000bfc3e g DF .text 0000000000000089 WXD_2.6.2 _ZN11wxLogBuffer5FlushEv
252 00000000000c0ad6 w DF .text 000000000000004b WXD_2.6.2 _ZN11wxLogBufferD1Ev
253 00000000000b1130 w DF .text 0000000000000036 WXD_2.6.2 _ZN11wxLogBufferC1Ev
254 00000000000c095c w DF .text 0000000000000029 WXD_2.6.2 _ZN19wxMessageOutputBestC1Ev
255 00000000000c08e8 w DF .text 000000000000003e WXD_2.6.2 _ZN19wxMessageOutputBestD1Ev
256 00000000002554c0 w DO .data 0000000000000038 WXD_2.6.2 _ZTV11wxLogBuffer
257 00000000000bfda6 g DF .text 0000000000000036 WXD_2.6.2 _ZN11wxLogBuffer11DoLogStringEPKcl
258 00000000000abe10 g DF .text 0000000000000088 WXD_2.6.2 _ZN14wxZipFSHandler7CleanupEv
259
260
261 8. Testing binary compatibility between releases
262 ------------------------------------------------
263
264 An easy way of testing binary compatibility is just to build wxWidgets
265 in dll/dynamic library mode and then switch out the current library
266 in question with an earlier stable version of the library, then running
267 the application in question again. If it runs OK then there is usually
268 binary compatibility between those releases.
269
270 You can also break into your debugger or whatever program you want
271 to use and check the memory layout of the class. If it is the same
272 then it is binary compatible.
273
274 Also remember to look at http://www.wxwidgets.org/bincompat.html page which
275 summarizes the results of testing of all the samples built against old
276 libraries headers with the new library binaries under Unix.
277
278
279 === EOF ===
280
281 Author: RN
282 Version: $Id$