Question

I have a main program:

#include <stdio.h>
extern int a;
int main (int argc, char ** argv) {
    int i;
    printf ("Hello %p, %p\n", & i, & a);
    return 0;
}

and a separate file, foo.c, which contains my definition for the variable a:

int a;

If I build like this:

clang -c main.c foo.c
clang main.o foo.o
./a.out

all is well. But, if I do the following:

ar rvs bar.a foo.o

I get a warning that I don't understand

r - foo.o
warning: /<elided>/ranlib: 
warning for library: bar.a the table of contents is empty 
(no object file members in the library define global symbols)

so I check my library, ensuring that my symbol is in there

nm bar.a

bar.a(foo.o):
0000000000000004 C _a

and then I do

clang main.o bar.a

I get the following error

Undefined symbols for architecture x86_64:
  "_a", referenced from:
      _main in main-5121f1.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

what did I miss?

Was it helpful?

Solution

I think the trouble is that the int a; in foo.c is a tentative definition. It is marked C (common) in the output from nm. If you explicitly initialized (to 0 for consistency; to some non-zero value to make sure for testing purposes), I believe you'd have no problem.

I'm not completely convinced because at the end of a TU, tentative definitions should be converted to definitions:

ISO/IEC 9899:2011 §6.9.2 External Object Definitions

¶2 A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

See also How do I share a variable between source files in C?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top