Reputation: 890
Context: I'm learning C as I go and I'm at a point where I'm finding I can't link my project. I'm also finding C's diagnostics are not the best when it comes to pinpointing issues. (Or at least not the best given my knowledge.)
I do see a lot of StackOverflow questions about this but it's very difficult to generalize unless the situation seems to match your particular code.
Project Context: I have a project like this:
src
zmachine
main.c
zmachine.h
terp_cheap
terp.cheap.c
terp_cheap.h
What gets built in each of these directories is a static library. I then have a linking step that takes the library .a
files and links them into an executable.
Problem: All was fine until I added a structure. Once I did that, when I build the whole project, the link step fails:
COMPLETE: Z-Machine architecture built.
COMPLETE: Cheap Interface built.
gcc -o quendorc build/zmachine.a build/terp_cheap.a
Undefined symbols for architecture x86_64:
"_quendor_startup", referenced from:
_terp_process_arguments in terp_cheap.a(terp_cheap.o)
ld: symbol(s) not found for architecture x86_64
The error is telling me I haven't defined the symbols (this: _quendor_startup
, I guess) but as far as I can tell, I have.
The _quendor_startup
that it's referring to is defined in zmachine.h
:
typedef struct quendor_startup_struct {
char *story_file;
} quendor_startup_t;
extern quendor_startup_t quendor_startup;
Note that I also extern it there as quendor_startup
.
The main file in this library (main.c
) also has an extern:
extern quendor_startup_t quendor_startup;
Although I'm not even sure if I need that one. All of that is the zmachine library. Now on to the terp_cheap library.
The two files in that library terp_cheap.h
and terp_cheap.c
also have the extern:
extern quendor_startup_t quendor_startup;
The terp_cheap
library is the one that the linker seems to be saying the problem is with. So given the above, I'm not sure why that is. I should note that the include file for the terp_cheap
library does reference the zmachine.h
include:
#include "../zmachine/zmachine.h"
So the structure in zmachine
should be able to be referenced in the terp_cheap
library. Meaning, I don't know where else I could put externs.
How I'm using this structure is in the terp_cheap.c
file like this:
void terp_process_arguments( int argc, char *argv[] ) {
...
quendor_startup.story_file = strdup(argv[optind]);
printf("Loading %s.\n", quendor_startup.story_file);
...
}
Note that those lines are in a terp_process_arguments()
function, which seems to be referenced in my linker fail.
So what I don't see how to do here is effectively diagnose why this is happening. I know what the linker thinks is missing. What I don't understand is why it thinks it's missing, given what I defined above.
Is the likely situation that I'm missing an extern somewhere? Or that perhaps my link action isn't appropriately set up? Or is it that my structure is not done correctly?
Upvotes: 1
Views: 102
Reputation: 223739
You haven't actually defined the variable in question.
When you do this:
extern quendor_startup_t quendor_startup;
You have a declaration, meaning you're saying the variable exists somewhere. The failure happens when you link because this declaration cannot be resolved.
You need to define it in exactly one source file as follows:
quendor_startup_t quendor_startup;
Given that you have a declaration in zmachine/zmachine.h, it would make sense to put the definition in zmachine/main.c. Also, you shoudn't need to explicitly add that declaration elsewhere as long as the source file that needs it includes zmachine.h.
Upvotes: 2