I am having problems with the linker when porting a C library from Linux (Ubuntu) to OS X. The C code is auto-generated from Matlab, so ideally I don't want to change the code itself.
The problem seems to be in a C file which contains ONLY uninitialised variable declarations, which are then EXTERNed by other C files to implement the Matlab algorithms. The OS X linker is apparently unable to recognise symbols from this file. The same source code works fine on Linux, so I want to understand how the OS X linker is behaving differently, and whether there is a flag I can pass to it to change the behaviour.
The static library builds without errors/warnings. But when building an application which references the static library, the following error message (on OS X) is thrown:
Undefined symbols for architecture x86_64:
"_my_var", referenced from:
_algorithm in libtestlibrary.a(algorithm.o)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
An 'nm' shows that libtestlibrary.a does indeed contain symbol _my_var.
A much simplified version of the code from Matlab follows below.
Library code:
// DATA.C : declaration of data
#include "data.h"
int my_var;
// DATA.H - extern declaration of data
#ifndef H_DATA
#define H_DATA
extern int my_var;
#endif
// ALGORITHM.C - performs the calculation
#include "data.h"
int algorithm(int x) {
my_var += x;
return my_var;
}
//ALGORITHM.H - declaration of library API
#ifndef H_ALGORITHM
#define H_ALGORITHM
int algorithm(int x);
#endif
Library build commands:
gcc -c algorithm.c
gcc -c data.c
ar rcs libtestlibrary.a data.o algorithm.o
Application code:
// MAIN.C : Code which calls into the static library
#include "algorithm.h"
int main() {
int x = 1;
x = algorithm(x);
return 0;
}
Application build commands:
gcc -c main.c
gcc -o testapp main.o -ltestlibrary
If I change the definition in data.c to 'int my_var=0', so that the variable is initialised, then the library and application build correctly on both Linux and OS X. However, as I said above, I don't want to change the code because it is auto-generated from Matlab.
Thanks in advance for your help!
Your problem is that you do not initialise may_var
.
If you do not initialise a data symbol and put it into a static library then it will be created as a common symbol. Those are not recognised my the OS X linker when linking static libraries.
If you initialise it (data.c):
#include "data.h"
int my_var = 0;
Then the compiler will put it into a different section and it will properly link in a static library.
Edit:
Alternatively you can pass the -fno-common
option to gcc
gcc -c data.c -fno-common
Then this will instruct gcc
not to generate common symbols for uninitialised variables and then you can link them in libraries.
This is an issue with the Mach-O executable format on OS X and is described here.