tags:

views:

2980

answers:

4

There seem to be 3 ways of telling GCC to weak link a symbol:

  • __attribute__((weak_import))
  • __attribute__((weak))
  • #pragma weak symbol_name

None of these work for me:

#pragma weak asdf
extern void asdf(void) __attribute__((weak_import, weak));
...
{
    if(asdf != NULL) asdf();
}

I always get a link error like this:

Undefined symbols:
  "_asdf", referenced from:
      _asdf$non_lazy_ptr in ccFA05kN.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

I am using GCC 4.0.1 on OS X 10.5.5. What am I doing wrong?

A: 

From the gcc doc manual:

`weak'

 The weak attribute causes the declaration to be emitted as a weak
 symbol rather than a global.  This is primarily useful in defining
 library functions which can be overridden in user code, though it
 can also be used with non-function declarations.  Weak symbols are
 supported for ELF targets, and also for a.out targets when using
 the GNU assembler and linker.

which means that an object is legitimated to overwrite a weak symbol (defined in another object/library) without getting errors at link time. What is unclear is whether you are linking the library with the weak symbol or not. It's seems that both you have not defined the symbol and the library is not properly linked.

Nicola Bonelli
There seems to be two uses of weak linking: http://gcc.gnu.org/ml/gcc/1999-02n/msg01219.htmlI'm trying to link against an old version of a library. The current version defines functions the old one didn't. I want to be able to use the new functions if they are available at runtime.
+2  A: 

You need to set the MACOSX_DEPLOYMENT_TARGET variable to 10.2 or later. See Apple's documentation and their technote on weak linking.

Martin v. Löwis
I've seen it, and it is set that way. That's not the error I'm getting.
+1  A: 

Add -Wl,-flat_namespace,-undefined,dynamic_lookup to the gcc compiler line that you use to do the final link.

+1  A: 

I just looked into this and thought some others might be interested in my findings.

Weak linking with weak_import really only works well with dynamic libraries. You can get it to work with static linking (by specifying -undefined dynamic_lookup as suggested above) but this isn't such a hot idea. It means that no undefined symbols will be detected until runtime. This is something I would avoid in production code, personally.

Here is a Mac OS X Terminal session showing how to make it work:

Here is f.c

   int f(int n)
   {
       return n * 7;
   }

Here is whatnof.c

   #include <stdio.h>
   #include <stdlib.h>

   extern int f (int) __attribute__((weak_import));

   int main() {
       if(f == NULL)
           printf("what, no f?\n");
       else
           printf("f(8) is %d\n", f(8));
       exit(0);
   }

Make a dynamic library from f.c:

   $ cc -dynamiclib -o f.dylib f.c

Compile and link against the dynamic lib, list dynamic libs.

   $ cc -o whatnof whatnof.c f.dylib
   $ otool -L whatnof
   whatnof:
           f.dylib (compatibility version 0.0.0, current version 0.0.0)
           /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Run whatnof to see what happens:

   $ whatnof
   f(8) is 56

Now replace f.dylib with an empty library (no symbols):

   $ mv f.dylib f.dylib.real
   $ touch null.c
   $ cc -dynamiclib -o f.dylib null.c

Run same whatnof to see what happens:

   $ whatnof
   what, no f?

The basic idea (or "use case") for weak_import is that it lets you link against a set of dynamic (shared) libraries, but then run the same code against earlier versions of the same libraries. You can check functions against NULL to see if they're supported in the particular dynamic library that the code is currently running against. This seems to be part of the basic development model supported by Xcode. I hope this example is useful; it has helped put my mind at ease about this part of the Xcode design.

Jeffrey Scofield