tn0020.txt 12 KB

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