I've been having a lot of trouble creating shared libraries. As the scale of the library grows, I think that naturally the inside will be divided into files and the API will be defined in the library for development.
At this time, I was always wondering if there was any way.
If you do it normally, it will be like this. ** The header API defined in the library is also included in the APIs available in the created shared library **
The public header is specified, but if you forcibly read the header used internally, that API will also be used. Especially when publishing a library on github, it's a bit crap to be able to use unintended APIs as you like.
So I checked it without expecting it.
There's nothing you can't do, yes with GNU! So, it seems that you can restrict publication with existing Linux functions.
Reference: http://0xcc.net/blog/archives/000108.html
For example, suppose you have a library public header like this: (Previously created time measurement library)
timetestlog.h
void * timetestlog_init(char *delimiter, size_t maxloglen, unsigned long maxstoresize);
int timetestlog_store_printf(void * handle, const char *format, ...);
void timetestlog_exit(void * handle);
As a library creator, I want you to use only this API.
Suppose you used this API when developing this library.
testfile.h
int testfunction(void);
If you compile normally with this, you can use testfunction
if you include testfile.h.
You can check the published API with the nm -D
command or ʻobjdump -t`.
Looking at the command execution result, you can see that the test function is included. Besides that, there are extra APIs here and there
Linux env$ nm -D .libs/libtimelog.so | grep " T "
0000000000000dec T _fini
00000000000007d8 T _init
0000000000000dc0 T testfunction
0000000000000d90 T timetestlog_exit
0000000000000b10 T timetestlog_init
0000000000000c90 T timetestlog_store_printf
Linux env$ objdump -t .libs/libtimelog.so | grep " g"
0000000000000dc0 g F .text 000000000000002c testfunction
0000000000202068 g .data 0000000000000000 _edata
0000000000000dec g F .fini 0000000000000000 _fini
0000000000000c90 g F .text 00000000000000fc timetestlog_store_printf
0000000000000b10 g F .text 000000000000017f timetestlog_init
0000000000202070 g .bss 0000000000000000 _end
0000000000202068 g .bss 0000000000000000 __bss_start
0000000000000d90 g F .text 0000000000000022 timetestlog_exit
00000000000007d8 g F .init 0000000000000000 _init
Use "--version-script" to limit the public API. Specify the configuration file (libtimelog.map in this case) that defines version-script and public API in this way.
LDFLAGS+=-Wl,--version-script,libtimelog.map
In the configuration file, specify the API you want to expose to global, and specify other (*) in local.
libtimelog.map
{
global:
timetestlog_init;
timetestlog_store_printf;
timetestlog_exit;
local: *;
};
Here is the public API of the library built by specifying the above configuration file. You can see that only the minimal API is exposed.
Linux env$ nm -D .libs/libtimelog.so | grep " T "
0000000000000cb0 T timetestlog_exit
0000000000000a30 T timetestlog_init
0000000000000bb0 T timetestlog_store_printf
Linux env$ objdump -t .libs/libtimelog.so | grep " g"
0000000000000bb0 g F .text 00000000000000fc timetestlog_store_printf
0000000000000a30 g F .text 000000000000017f timetestlog_init
0000000000000cb0 g F .text 0000000000000022 timetestlog_exit
You can specify the public API by using ** --version-script **. Until now, I was concerned about the API to be published, and I actually put together the files I wanted to separate, but With this, you can create a library with your favorite file structure without hesitation.
Recommended Posts