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