backport of r58600

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@58601 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2009-02-01 17:19:25 +00:00
parent 66ddd74d23
commit a00dee1c36
2 changed files with 97 additions and 14 deletions

View File

@@ -3,13 +3,13 @@
0. Purpose 0. Purpose
---------- ----------
This is broad technote covering all aspects of binary compatibility with This is a broad technote covering all aspects of binary compatibility with
wxWidgets. wxWidgets.
1. Releases 1. Releases
----------- -----------
General overview of releases can be found in tn0012.txt, but for General overview of releases can be found in tn0012.txt, but for
completeness the wxWidgets release version number is as follows: completeness the wxWidgets release version number is as follows:
2.6.2 2.6.2
@@ -37,12 +37,12 @@ also section (4).
------------------------------------------------- -------------------------------------------------
If its still up, the KDE guide is a good reference: If its still up, the KDE guide is a good reference:
http://developer.kde.org/documentation/other/binarycompatibility.html http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++
The changes that are NOT binary compatible: The changes that are NOT binary compatible:
- Adding a virtual function - Adding a virtual function
- Changing the name of a any function or variable - Changing the name of a any function or variable
- Changing the signature of a virtual function (adding a parameter, - Changing the signature of a virtual function (adding a parameter,
even a default one) even a default one)
- Changing the order of the virtual functions in a class - Changing the order of the virtual functions in a class
["switching" them, etc.] ["switching" them, etc.]
@@ -63,6 +63,7 @@ even a default one)
- Adding a new class - Adding a new class
- Adding a new non-virtual method to an existing class - Adding a new non-virtual method to an existing class
- Adding a new constructor to an existing class
- Overriding the implementation of an existing virtual function - Overriding the implementation of an existing virtual function
[this is considered to be backwards binary compatible until we find a [this is considered to be backwards binary compatible until we find a
counter example; currently it's known to work with Apple gcc at least] counter example; currently it's known to work with Apple gcc at least]
@@ -113,7 +114,7 @@ bool ShowPlayerControls(
//helpers for the wxPython people //helpers for the wxPython people
bool LoadURI(const wxString& fileName) bool LoadURI(const wxString& fileName)
{ return Load(wxURI(fileName)); } { return Load(wxURI(fileName)); }
bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy) bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
{ return Load(wxURI(fileName), wxURI(proxy)); } { return Load(wxURI(fileName), wxURI(proxy)); }
#endif #endif
@@ -139,7 +140,7 @@ wxShadowObject resides in include/wx/clntdata.h.
To use wxShadowObject, you first call AddMethod or AddField with To use wxShadowObject, you first call AddMethod or AddField with
the first parameter being the name of the field and/or method the first parameter being the name of the field and/or method
you want, and the second parameter being the value of the you want, and the second parameter being the value of the
field and/or method. field and/or method.
In the case of fields this is a void*, and in the case of method In the case of fields this is a void*, and in the case of method
@@ -150,15 +151,15 @@ After you add a field, you can set it via SetField with the same
parameters as AddField, the second parameter being the value to set parameters as AddField, the second parameter being the value to set
the field to. You can get the field after you call AddField the field to. You can get the field after you call AddField
via GetField, with the parameters as the other two field functions, via GetField, with the parameters as the other two field functions,
only in the case the second parameter is the fallback only in the case the second parameter is the fallback
value for the field in the case of it not being found in the value for the field in the case of it not being found in the
hash map. hash map.
You can call a method after you add it via InvokeMethod, which You can call a method after you add it via InvokeMethod, which
returns a bool indicating whether or not the method was found returns a bool indicating whether or not the method was found
in the hash map, and has 4 parameters. The first parameter is in the hash map, and has 4 parameters. The first parameter is
the name of the method you wish to call, the second is the first the name of the method you wish to call, the second is the first
parameter passed to the wxShadowObjectMethod, the third is the parameter passed to the wxShadowObjectMethod, the third is the
second parameter passed to that wxShadowObjectMethod, and the second parameter passed to that wxShadowObjectMethod, and the
fourth is the return value of the wxShadowObjectMethod. fourth is the return value of the wxShadowObjectMethod.
@@ -183,7 +184,7 @@ The file has the layout as follows:
Where X is the current Release as mentioned earlier, i.e. 2. This Where X is the current Release as mentioned earlier, i.e. 2. This
is following by an opening bracket "{", followed by "global:", is following by an opening bracket "{", followed by "global:",
followed by patterns matching added symbols, then followed by "}", and then followed by patterns matching added symbols, then followed by "}", and then
the file is either followed by earlier Releases or ended by the file is either followed by earlier Releases or ended by
a @WX_VERSION_TAG@ block without the period or Release. a @WX_VERSION_TAG@ block without the period or Release.
The patterns used to specify added symbols are globbing patters and can The patterns used to specify added symbols are globbing patters and can
@@ -270,10 +271,15 @@ binary compatibility between those releases.
You can also break into your debugger or whatever program you want You can also break into your debugger or whatever program you want
to use and check the memory layout of the class. If it is the same to use and check the memory layout of the class. If it is the same
then it is binary compatible. then it is binary compatible.
(In GDB the command x/d will show addresses as pointers to functions if
possible so you can see if the order of the functions in vtbl doesn't change.)
Also remember to look at http://www.wxwidgets.org/bincompat.html page which Another way to check for binary compatibility is to build wxWidgets in shared mode
summarizes the results of testing of all the samples built against old and use the 'abicheck.sh --generate' script before doing your changes to generate
libraries headers with the new library binaries under Unix. the current ABI (if the 'expected_abi' file is not already in the repo).
Then rebuild wxWidgets with your changes and use 'abicheck.sh' to compare the
resulting ABI with the expected one.
Note that the abicheck.sh script is in the "lib" folder.
=== EOF === === EOF ===

77
lib/abicheck.sh Executable file
View File

@@ -0,0 +1,77 @@
#!/bin/bash
# Script originally based on GTK+'s own abicheck.sh; it should be run anytime
# there is a change in the stable branch of wxWidgets which could lead to an
# ABI breakage and thus result in a binary-incompatible change (see tech docs).
#
# $Id$
expected_abi_file="expected_abi"
actual_abi_file="actual_abi"
if [[ "$1" == "--generate" ]]; then
# IMPORTANT: we need a shared build of wxWidgets to proceed
if [[ $(echo *.so) == "*.so" ]]; then
echo "No shared objects (*.so) were found... aborting"
exit 1
fi
# generated the "expected ABI" for later comparison
rm -f $expected_abi_file
for library in *.so; do
# NOTE: don't use -C option as otherwise cut won't work correctly
nm -D -g --defined-only $library | cut -d ' ' -f 3 | sort >>$expected_abi_file
done
echo "Expected wxWidgets ABI generated in \"$expected_abi_file\"..."
elif [[ -z "$1" ]]; then
if [[ ! -f "$expected_abi_file" ]]; then
echo "The file containing the expected wxWidgets ABI '$expected_abi_file' does not exist!"
echo "Please generate it first using the '--generate' option"
exit 1
fi
echo "Comparing actual ABI with the expected ABI (loading it from \"$expected_abi_file\")..."
# IMPORTANT: we need a shared build of wxWidgets to do the check
if [[ $(echo *.so) == "*.so" ]]; then
echo "No shared objects (*.so) were found... aborting"
exit 1
fi
rm -f $actual_abi_file
for library in *.so; do
# NOTE: don't use -C option as otherwise cut won't work correctly
nm -D -g --defined-only $library | cut -d ' ' -f 3 | sort >>$actual_abi_file
done
result=`diff -u $expected_abi_file $actual_abi_file`
if [[ -z "$result" ]]; then
echo "No binary (in)compatible changes were found."
else
echo "========================================================="
echo "WARNING: Possible binary-incompatible changes were found:"
echo "========================================================="
echo
echo "$result"
# this doesn't necessarly indicate that binary compatibility was surely
# broken; e.g. adding non-virtual methods will generate a new line in the
# $actual_abi_file but that's a compatible change.
fi
else
echo "Usage: $0 [--generate]"
echo "When running without options, compares the wxWidgets ABI saved in '$expected_abi_file'"
echo "with the current ABI of the .so files of the working directory."
echo "When --generate is given, saves in '$expected_abi_file' the ABI of the .so files"
echo "(for later comparisons)."
fi