Android Exports

If you're building shared objects to be used with Android, you'll probably want to be careful about what exactly is the API that you're making available.

There are a few gotchas along the way that I'll be covering here.

Linking

While there are ways of annotating your source directly, I usually find this rather messy. The APIs exposed form a proper contract, and it's good to be clear and explicit about that.

The Visual C++ linker supports .def files, while define various properties of a module (a DLL for our purposes). The EXPORTS directive gives you a way to list all the functions that you want exported. You then simply provide the .def file to the linker with something like /DEF:mydll.def and off you go.

For example, it might look something like this:

EXPORTS
    my_fun_1
    my_fun_2

The ld linker, on the other hand, doesn't support .def files, but you can get some measure of control with version scripts.

You can then feed a text file such as the following one to the linker, with something like -Wl,--version-script=my-exports.txt and you should then see the right symbols exposed.

CODEABI_1.0 {
    global:
        my_fun_1;
        my_fun_2;
        with_prefix_matching_*;
    local:
        *;
};

Libraries and objects

Note that the way the shared object is put together is quite different from the way DLLs are built on Windows.

On Windows, you'll typically have a number of exports (including things like DllMain). The linker can then do reachability analysis for those, and include all the code it needs, and discard all the code it doesn't need.

When building shared objects, however, the model is different. Instead, the linker will including all of the object files referenced, but not any static libraries.

Which means that you might very well find yourself with a mostly empty binary if you just refer to a static library they way you might on Windows. Note that even if you use the linker script, the tools won't complain if the APIs are not available.

If you run into this while building a cmake-based project, read on for some tips.

CMake OBJECT libraries

CMake has two ways of building libraries of code with static linking.

If you use normal libraries and get the "empty shared object" effect, you might want to start by switching to an object library.

There are a few more interesting kinds of "libraries" you can define in CMake: imported libraries (usually .so on non-Windows, the import lib on Windows), interface (settings only, no code), and alias. In general, understanding these will give you more options to better organize your project.

Happy exports!

Tags:  androidcppcoding

Home