7

I've been developing a school project in XCode. The final product has to be submitted in source code with a makefile, so I wrote a makefile and to start compiling that way, to make sure I had a working copy. Here's my makefile:

all: main.o StackList.o world.o Farm.o
        gcc main.o StackList.o world.o Farm.o -g -o Project1

main.o:
        gcc -g -c main.cpp

StackList.o:
        gcc -g -c Stacklist.cpp

world.cpp:
        gcc -g -c world.cpp

Farm.cpp:
        gcc -g -c Farm.cpp

clean:
        rm *.o Project1

Compiling each of the object files works fine, but when it gets to "all," the linking step, it appears to not be aware of the standard library. I get "undefined symbols" error for everythin from "cin", to "basic_string", to "operator new".

I was under the impression that these things didn't need to be indicated directly, and in fact have not needed to do so in the past.

Any idea what might be happening?

EDIT:

If it helps, here's the start of the (very long) error message:

Undefined symbols for architecture x86_64:
  "std::cin", referenced from:
  _main in main.o
  "std::cout", referenced from:
      _main in main.o
      Farm::print(int)  in Farm.o
  "std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)", referenced from:
      _main in main.o
  "std::ios_base::Init::Init()", referenced from:
      __static_initialization_and_destruction_0(int, int)in main.o
      __static_initialization_and_destruction_0(int, int)in StackList.o
      __static_initialization_and_destruction_0(int, int)in world.o
      __static_initialization_and_destruction_0(int, int)in Farm.o
  "std::ios_base::Init::~Init()", referenced from:
      ___tcf_0 in main.o
      ___tcf_0 in StackList.o
      ___tcf_0 in world.o
      ___tcf_0 in Farm.o
  "operator new(unsigned long)", referenced from:
      doStackSearch(std::basic_istream<char, std::char_traits<char> >*, std::list<Farm*, std::allocator<Farm*> >*&)in world.o
xanderflood
  • 826
  • 2
  • 12
  • 22

4 Answers4

24

To link C++ code, you need to use the g++ command, not the gcc command.

When compiling, the gcc command knows that it's compiling C++ code because of the .cpp suffix (but it's a good idea to use the g++ command anyway).

When linking, the gcc command just sees a bunch of .o files. The g++ command differs from the gcc command in that it knows where to find the C++-specific libraries.

(The fact that the name gcc refers both to the command, which is usually used to compile C code, and the "GNU Compiler Collection" as a whole, can be a little confusing.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 3
    Sorry for the stupid question, that did indeed fix it. It's just frustrating because I've used GCC for C++ before, and my instructor told us that both GCC and G++ would call each other when necessary, and were essentially the same. Thanks a lot! – xanderflood Jan 18 '12 at 03:24
  • 3
    Not a stupid question. I have 12 years of C++ development experience, but not on Linux. It's always the things that "everyone knows" that get you in a new environment. – Resource Mar 04 '21 at 17:57
3

I know this is old, but if you are compiling and linking C++, you can specify the standard library yourself. Add -lstdc++ at end of your command.

RegioMouse
  • 31
  • 4
3

You need to use g++ to compile and link C++ source code, not gcc.

Also, you can leave out all targets besides the first and last ones. make knows how to compile .cpp files to .o already -- you don't have to tell it how.

-3
    gcc main.o StackList.o world.o Farm.o -g -o Project1

What in this command line do you think tells gcc to link in the C++ standard library? There are no C++ files being linked. You haven't specified a language. And you invoke the compilter as gcc.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278