Reputation: 70
I've been given a package of files (one .cpp, and some .c and .h) and want to make some modifications. But right now I'm just trying to get the original version to compile (in Linux).
Here's a (really) minimal working example:
mainfile.cpp
extern "C"{
#include "auxfile.h"
}
int main(int argc, char * argv[]){
getfoo(temperature);
return 0;}
auxfile.h
#define PUBLIC
#define PRIVATE static
extern int temperature;
int getfoo( int inputint);
auxfile.c
#include "auxfile.h"
int temperature = 37;
PUBLIC int getfoo( int inputint){
return 7;
}
When I type
g++ mainfile.cpp
I get
mainfile.cpp(.text+0x11): undefined reference to `temperature'
mainfile.cpp(.text+0x18): undefined reference to `getfoo'
collect2: ld returned 1 exit status
For what it's worth, I've looked through numerous "undefined reference" questions and spent dozens of hours working on my own. The above code presents the essence of the problem. Any help would be massively appreciated. Thanks.
Upvotes: 2
Views: 87
Reputation:
At the time of linking, all symbols (except those for dynamic linking, aka shared libraries) have to be defined. To create an object file with possibly unresolved symbols for later linking, there is the -c
flag, that means just compile, do not link.
So, the following would work:
g++ -c -omainfile.o mainfile.cpp
gcc -c -oauxfile.o auxfile.c
g++ -o mainfile mainfile.o auxfile.o
Only the last line actually invokes the linker and as you have both object files, all symbols are found.
Just for completeness, in a real-world scenario you'd handle compiling and linking using make
. Create a Makefile
with the following contents:
OBJS:= mainfile.o auxfile.o
all: mainfile
# $@ means what to build (in this case "mainfile"), $^ is replaced by all
# dependencies (here the contents of the variable OBJS)
mainfile: $(OBJS)
g++ -o$@ $^
# pattern for *.cpp -> create a *.o file with same name using g++
%.o: %.cpp
g++ -c -o$@ $<
# the same for *.c, but using gcc here
%.o: %.c
gcc -c -o$@ $<
clean:
rm -f $(OBJS)
# "PHONY" are targets, that are not actually the names of output files
.PHONY: all clean
Then just type make
and see the "magic" happening. Of course this is just for starters, no dependencies are tracked etc...
Upvotes: 4