Tracking C++ lib public API changes
I'm currently working on large C++ Qt based project which is a about to go under a major re-factor of its public API and it would be nice to have a tool that can generate a report on which methods have been added or removed from build to build.
I know there is a tool for Java to do this and I think there might be one for .NET but I couldn't, after a bit of sea开发者_StackOverflowrching, find anything for C++.
Does one exist. Cross platform would be nice, or if only in Linux that would be fine too.
If you use Doxygen or some similar tool to document your API then you can diff
the table-of-contents.
- This is something you should be doing anyway.
- (You can also tell Doxygen to find undocumented functions.)
- You can apply it easily to ancient checkins without changing anything.
- The Doxygen and its ilk know enough about the language to be sensitive to
private
andpublic
. - This solution can be applied to many languages and is not dependent on a particular IDE.
- No third-party software is required (given that you already have a documentation generator).
Check the bottom of the commercial list for apidiff, I think it'll be the closest match.
The suggestion of using 'nm' isn't a bad one, you can run
nm <binary_or_lib> | c++filt
And it'll generate a decent snapshot, that will need a fair amount of post-processing.
There's lots of ways to roll your own on this one:
Doxygen can generate an XML file that has all the class / member / method information that you could then mine for building class trees. It would then be a matter of comparing trees. Some useful post-processing scripts / utilities can be found @ http://www.doxygen.nl/helpers.html
If you're compiling with gcc, egypt is a novel approach that uses the intermediate RTL to produce call-dependency graphs - it seems like it wouldn't be that difficult to use a similar method to generate basic API information.
GCC-XMLwill generate an XML representations of compiled code, a bit more low level than Doxygen as it provides a mechanism for writing wrapper code.
cppHeaderParser, a python module will generate nice python object representations of headers giving an easy way to generate the API maps.
ctags generates a tag database which could probably be processed. It has problems with C++ namespaces though.
Some commercial solutions
scitool's Understand does a great job of mapping software out and has a perl API for querying its database.
MagicDraw is kind of a heavy-weight tool centered around UML, but it can reverse-engineer an existing C++ code-base and generate meta-information.
apidiff seems to be a pretty affordable tool and given the criteria (cross-platform, C++) is likely the closest match.
Instead of allowing all the visible symbols to export from your library automatically, you can use an explicit list of exported symbols. For larger libraries this is even recommended.
In Windows you use a .DEF file to export symbols from a DLL.
In Unix-likes you use a linker script to do it.
Add an automatic build step that uses nm
on Unix-likes and whichever Windows tool (dumpbin
?) to dump a list of exported functions. Use some scripting language to strip off unimportant bits that change from build to build, like addresses.
After each build commit this file to version control. Then you can see the differences from each build.
Because it is a C++ application, the names will also catch the parameter type changes.
Try abi-compliance-checker. This tool shows added/removed symbols in your API, changes in parameters/data types and other changes from the binary compatibility point of view. It's cross-platform. The best performance is on Linux, but it's able to run on Windows and Mac too.
Usage:
abi-compliance-checker -lib NAME -old OLD.abidump -new NEW.abidump
*.abidump files are ABI dumps generated by the abi-dumper tool.
This compatibility table for Qt library is created using this tool:
Feel free to ask any usage questions in the comments below.
If you use git you should create a new branch and use a shell script to compare all header files that define the API bwetween the branches. If you have not yet done so, you should use the impl pattern for your API header files to make the library binary compatible/more stable for future versions. See the entry for d_pointer in the Qt developer wiki or the part about D-Pointers in the KDE techbase.
In addition to the option of using Doxygen to roll your own analysis tool I would also suggest looking into using the BSC Toolkit. This allows you to access the code/class browser information generated by MS compilers and is available for free. The toolkit provides programmatic access to all definitions, usage references, source and line numbers, parameters, access modifiers, etc. Names are provided in their mangled form and facilities are included for translating them to human readable format if necessary.
Here is some very basic output from a project I am working on:
IXConnection (struct_name)
IXConnection::STATE (enum_name)
IXConnection::setState(enum STATE) (mem_func public)
IXConnection::setAccount(struct IXAccount *) (mem_func public)
IXConnection::setDisplayName(class String *) (mem_func public)
IXConnection::setProtocolData(void *) (mem_func public)
IXConnection::getState(enum STATE *) (mem_func public)
IXConnection::getAccount(struct IXAccount * *) (mem_func public)
IXConnection::getProtocol(struct IXProtocol * *) (mem_func public)
IXConnection::getPassword(class String * *) (mem_func public)
IXConnection::getDisplayName(class String * *) (mem_func public)
IXConnection::getProtocolData(void * *) (mem_func public)
IXConnection::setProgress(class String *,int,int) (mem_func public)
IXConnection::notice(class String *) (mem_func public)
IXConnection::error(enum REASON,class String *) (mem_func public)
精彩评论