tags:

views:

304

answers:

3

I've created a static library in GCC, but I'd like to hide most of the symbols.

For example, test1.c:

extern void test2(void);
void test1(void) {
  printf("test1: ");
  test2();
}

test2.c:

extern void test1(void);
void test2(void) {
  printf("test2\n");
}

library_api.c:

extern void test1(void);
extern void test2(void);
void library_api(void) {
  test1();
  test2();
}

Now compile with:

gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc -c library_api.c -o library_api.o
ar rcs libapi.a test1.o test2.o library_api.o

How do I get only the "library_api()" function to show up for:

nm libapi.a

instead of the functions "test1()", "test2()", and "library_api()"? In other words, how do I hide "test1()" and "test2()" from showing up and being callable to external users of libapi.a? I don't want external users to know anything about internal test functions.

+4  A: 

The simplest solution is to #include test1.c and test2.c into library_api.c, and only compile that file. Then you can make test1() and test2() static.

Alternatively, you can combine the object files with ld -r, and use objcopy --localize-symbols to make the test functions static after linking. As this can get fairly tedious, I really recommend the first option, though.

Martin v. Löwis
Declaring symbol `static` doesn't help with hiding it in static library either.
Pavel Shved
@Pavel: it sure does. You cannot link against a static symbol; if desired, you can also strip all static symbols after compilation.
Martin v. Löwis
I tried "ld -r --retain-symbols-file tmp.list test1.o test2.o library_api.o -o libapi.a" where tmp.list just contains "library_api" and "nm libapi.a" still shows the test1 and test2 symbols as global. Any ideas?
Will
@Martin: what command could you use to "strip all static symbols after compilation" from libapi.a?
Will
@Will: apparently, --retain-symbols-file doesn't work for ld -r. I have edited my responsive to recommend objcopy instead. You can strip (some) static symbols with `strip --strip-unneeded`. This works as long as the symbols aren't used for relocations, which works for calls that the assembler had resolved on x86.
Martin v. Löwis
@Martin: I like the objcopy solution, except I just discovered "objcopy --localize-hidden" to localize all symbols with "__attribute__((visibility("hidden")))". I can even tell GCC to set all functions hidden by default except the ones I mark visible. Thanks for the help finding this solution! (BTW - I steered away from including all functions in 1 file because the real project has tons of files with potentially overlapping static variable names in each file)
Will
+2  A: 

With gcc, you can use __attribute__((visibility("hidden"))) extern

lhf
I don't think this helps with a static library.
Martin v. Löwis
I agree - I just tried this and it had no effect on "nm libapi.a".
Will
+1  A: 

ld has the option

--retain-symbols-file FILE Keep only symbols listed in FILE

to allow you to explicitly name the symbols you want to keep.

themis