2

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.

3
  • 2
    Are you sure auxfile.c is getting built at all? Can you add an error in that file just to be sure? Commented Aug 5, 2015 at 22:13
  • No, it's not. I added a random open curly brace { to auxfile.c, and the error message is the same. So my code isn't even seeing it. Commented Aug 5, 2015 at 22:17
  • 1
    You never compiled auxfile.c Commented Aug 5, 2015 at 23:22

1 Answer 1

4

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...

Sign up to request clarification or add additional context in comments.

8 Comments

The above will work better if you put a space character after the -o options.
Cool, Felix! Your commands totally work without any errors (as you probably knew would happen.) Unfortunately, my code is so minimized that I have no way of making the final executable do anything...but I'll see about that. Also, it'll take me some time to digest your instructions and apply them to the big program...but I think you've solved my problem. Thanks a whole lot.
@Jeff well, can't say anything about that here .. it's example code after all. Try this with a real project and you will see it works and you will get crazy and then explore the power of a Makefile ;)
@Felix Okay, well it's a good start. By the way, I've now gotten the final mainfile to print "Hey." so I'm well on my way. :) (I'll keep the possibility of Makefile in mind.) Thank you again.
@Jeff see my edit for a basic Makefile automating the build process.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.