How can I make a function have library-internal linkage?

c, compilation, gcc, ld, linker

Solution

With standard C you can only either export the function or not, there is no “export only to these files” option. So basically you would have to move `bar()` to `foo.c` and declare it as `static`. If you wish to keep the file separate, an ugly hack would be to `#include` it from `foo.c` (and not compile `bar.o`)…

With tools outside the scope of standard C you can remove the public export from the library at or after linking. Some linker solutions are shown below, and with GCC and clang (in cases where you can modify the code) you can hide a function by prefixing it with the non-standard attribute: `__attribute__ ((visibility ("hidden")))` – the compilation-unit-wide equivalent of this would be the option `-fvisibility=hidden` when compiling, e.g., `bar.c`.

C workaround

If you can edit the C code freely, a workaround in standard C would be to make `bar()` `static` within `bar.c` and deliver a function pointer to it for use in `foo()` through some means, e.g., export a pointer to a `struct` containing the function pointer (and any other “private” data), and do not expose the details of the `struct` outside of a private header used only by your library.

For example:

In `bar.h` (private, do not share with the library's user):

struct bar_private_struct { int (*bar)(int); };
extern struct bar_private_struct *bar_functions;

In `bar.c`:

#include "bar.h"
static int bar (int x) { /* … */ return x; }
static struct bar_private_struct functions = { bar };
struct bar_private_struct *bar_functions = &functions;

In `foo.c`:

#include "bar.h"
int foo (int x) { x = bar_functions->bar(x); /* … */ }

In this solution there will be an exported pointer called `bar_functions`, but no details about the data/functions pointed to are revealed through this export. Without access to `bar.h` the user of the library would have to reverse engineer the contents to call the “private” functions correctly. In case of multiple “private” functions this approach can also condense them to a single exported pointer, removing clutter from the list of exports.

Linker solutions

Exploring specific linkers, I found a way to exclude specific symbols from a dynamic library:

With GNU `ld`, create a version script, such as `libfoobar.version`:

FOOBAR {
    global: *;
    local: bar;
};

Invocation through `gcc`:

gcc -shared -o libfoobar.so foo.o bar.o -Wl,-version-script=libfoobar.version

With the `clang` `ld` (on OS X) create a list of unexported symbols, such as `unexported` (one symbol per line):

_bar

Invocation through `clang`:

clang -shared -o libfoobar.dylib foo.o bar.o -Wl,-unexported_symbols_list,unexported

In both cases the function `bar` is hidden and externally uncallable but `foo` remains operational (and calls `bar` internally), even though both had the same external visibility in their respective source (and object) files.

Test code, `foo.c`:

int bar(int x);
int foo (int x) { return bar(x) * 3; }

`bar.c`:

int bar (int x) { return x * 2; }

`main.c` (link against the library before removing the export for `bar`):

#include <stdio.h>
int foo(int x);
int bar(int x);
int main () {
    (void) printf("foo(2) = %d\n", foo(2));
    (void) printf("bar(2) = %d\n", bar(2));
    return 0;
}

Test case:

# before unexporting bar:
$ nm -gU libfoobar.dylib
0000000000000f70 T _bar
0000000000000f50 T _foo
$ ./main
foo(2) = 12
bar(2) = 4

# after unexporting bar:
$ nm -gU libfoobar.dylib
0000000000000f50 T _foo
$ ./main
foo(2) = 12
dyld: lazy symbol binding failed: Symbol not found: _bar

Problem

For example, if I have two files `foo.c` and `bar.o`, and `foo.c` contains a function `foo()` that references a function `bar()` in `bar.o`: ``` int foo(int x) { x = bar(x); /* ... */ } ``` How can I compile a static or dynamic library that exposes `foo()`, but does not expose `bar()`? In other words, I want `bar()` to be linked only inside the library.

Original source