Valentin Lorentz
Valentin Lorentz

Reputation: 9753

Using only g++ works, but not "g++ -c" and ld

I have the following source code in main.cpp:

#include <iostream>
#include <iomanip>

int main() {
    std::cout << "Hi" << std::endl;
    return 0;
}

Using this command works, and creates the executable file:

g++ -o main main.cpp

But this commands don't work:

g++ -c main.cpp
ld -o main main.o

The second one errors with:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004000e8
main.o: In function `main':
main.cpp:(.text+0xa): undefined reference to `std::cout'
main.cpp:(.text+0xf): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
main.cpp:(.text+0x14): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
main.cpp:(.text+0x1c): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
main.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x4a): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0x4f): undefined reference to `std::ios_base::Init::~Init()'
main.cpp:(.text+0x54): undefined reference to `__dso_handle'
main.cpp:(.text+0x61): undefined reference to `__cxa_atexit'

Upvotes: 11

Views: 21503

Answers (4)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361462

When you use g++, it also links the libstd++ library which linker uses to resolve the names. But using g++ -c and then ld do not link the library automatically. You've to link the library manually now.

Try (untested):

ld -o main main.o -llibstd++

Or you can look into the correct syntax by reading this manual:

Upvotes: 8

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385154

Well, you didn't link in the standard library. g++ does this for you automatically; that's why we use it: it wraps calls to ccplus1 and ld with all the extras taken care of.

BTW, strictly speaking, the equivalent of g++ main.cpp -o main is:

cc1plus main.cpp -o main.o
ld -o main main.o

(cc1plus may well not be on your path; I found mine in /usr/libexec/gcc/i386-redhat-linux/4.1.1/)

g++ -c main.cpp does traditionally perform that first step. g++ main.cpp -o main wraps both.

g++ is a wrapper to the individual compilation and linkage tools, tuned for C++. As such, it provides arguments to cc1plus and ld as it sees fit, including the argument to link in the C++ Standard Library:

ld -o main main.o -llibstd++

It'll also link in the runtime and possibly some other stuff.

In general, there is no need to try to do these things yourself: let g++ take care of it.

Upvotes: 1

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506985

GCC internally links against a few additional libraries and object files. To see what those are, execute -###, which will print the tool commands it would execute, including the linker. The linker command used by my GCC is (I made the actual .o file I invoked g++ on bold, so you can spot it easily).

/usr/lib/gcc/i686-pc-linux-gnu/4.6.0/collect2 --build-id --eh-frame-hdr -m elf_i386 "--hash-style=both" -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../crt1.o /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../crti.o /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/crtbegin.o -L/usr/lib/gcc/i686-pc-linux-gnu/4.6.0 -L/usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../.. main1.o "-lstdc++" -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/crtend.o /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../crtn.o

You can substitute the collect2 path by ld (if I remember correctly, collect2 is only needed as a proxy for the real ld by GCC backends that don't support modern binary formats, to collect constructor and destructor functions according to their mangled name. The ELF format has native sections support for that).

Executing that command, with ld substituted literally, successfully links the executable.

Upvotes: 13

Sodved
Sodved

Reputation: 8588

I think if you use ld directly it does not include the C++ libraries by default. You can use g++ to do the linking as well, it will call ld with the correct settings.

g++ -c main.cpp
g++ -o main main.o

Upvotes: 15

Related Questions