I have files foo.c bar.c and baz.c, plus wrapper code myfn.c defining a function myfn() that uses code and data from those other files.
I would like to create something like an object file or archive, myfn.o or libmyfn.a, so that myfn() can be made available to other projects without also exporting a load of symbols from {foo,bar,baz}.o as well.
What's the right way to do that in Linux/gcc? Thanks.
Update: I've found one way of doing it. I should've emphasised originally that this was about static archives, not DSOs. Anyway, the recipe:
#define PUBLIC __attribute__ ((visibility("default")))
then markmyfn()
asPUBLIC
inmyfn.c
. Don't mark anything elsePUBLIC
.Compile objects with
gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden
, which marks everything as hidden except formyfn()
.Create a convenience archive using
ld
's partial-linking switch:ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
Localise everything that wasn't
PUBLIC
like so:objcopy --localize-hidden libmyfn.a
Now
nm
saysmyfn
is the only global symbol inlibmyfn.a
and subsequent linking into other programs works just fine:gcc -o main main.c -L. -lmyfn
(here, the program callsmyfn()
; if it tried to callfoo()
then compilation would fail).
If I use ar
instead of ld -r
in step 3 then compilation fails in step 5: I guess ar
hasn't linked foo
etc to myfn
, and no longer can once those functions are localised, whereas ld -r
resolves the link before it gets localised-away.
I'd welcome any response that confirms this is the "right" way, or describes a slicker way of achieving the same.
Unfortunately, C linkage for globals is all-or-nothing, in the sense that the globals of all modules would be available in
libmyfn.a
's final list of external symbols.gcc
tool chain offers an extension that lets you hide symbols from outside users, while making them available to other translation units in your library:foo.h:
foo.c:
myfn.h:
myfn.c:
For portability, you would probably benefit from making a macro for
__attribute__ ((visibility ("hidden")))
, and placing it in a conditional compilation block conditioned ongcc
.In addition, Linux offers a utility called
strip
, which lets you remove some of the symbols from compiled object files. Options-N
and-K
let you identify individual symbols that you want to keep or remove.Suppose myfn.c has function myfun() which you want to use in other three files foo.c, bar.c & baz.c
Now create a shared library from code in myfn.c viz libmyf.a
Use this function call myfun() in other three files. Declare function as extern in these files. Now you can create object code of these thee files and link the libmyf.a at linking phase.
Refer to following link for using shared libraries.
http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
Start with this to build a static library
Compile and link with other programs like:
Now your
libmyfunctions.a
will ultimately have extra stuff from the source that isn't required by the code in myfn.c But the linker should do a reasonable job of removing this when it creates the final program.