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
By default, GCC assumes that libraries are in a system library path, such as /lib64 and /usr/lib64 .
But gcc does not link object files. Instead it uses collect2 which is just wrapper for the GNU ld linker: ~$ /usr/lib/gcc/x86_64-linux-gnu/4.9/collect2 --version collect2 version 4.9.
GCC uses a separate linker program (called ld.exe ) to perform the linking.
g++ does find the library in /usr/local/lib : once you do things properly and actually tell it the name of the library to look for. Also note that discussion of -L is a red herring for the same reason.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With