This takes account of your comments:
Then I tried ld -o Cuteee main.o -L. -lmyhello but still fails with ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0 ./libmyhello.a(hello.o): In function 'hello': hello.c:(.text+0x1e): undefined reference to 'printf' I am puzzled again.
gcc
is the GCC tooldriver for compiling and linking C programs.
When you invoke it with options and inputs that signify you want to a compile a C
source file, say hello.c
, it first invokes the GNU C compiler, cc1
, to compile hello.c
file to a temporary assembly file, say /tmp/cc8bfSqS.s
. It quietly adds to the compiler commandline
various boilerplate options that are invariant for compiling C
on your system, to spare you the trouble.
Then it invokes the GNU assembler, as
, to assemble /tmp/cc8bfSqS.s
to the object file
hello.o
.
You can pick out all of this from the compilation output if you ask gcc
to be verbose,
e.g.
gcc -v -c hello.c
When you invoke gcc
with options and inputs that signify you want to link
object files and possibly libraries into a program or shared library,
it invokes the GCC internal tool collect2
to do it - which
in turn invokes the system linker ld
- and gcc
quietly adds to the commandline
many boilerplate options, libraries and object files that are always
required for linking a C language program or shared library, once again to
spare you trouble.
You have used gcc
to compile hello.c
and main.c
and allowed it to Do The Right
Thing behind the scenes. You haven't attempted to invoke cc1
and as
yourself.
But in contrast, when you come to link your program, you haven't used gcc
; you've
invoked ld
yourself, without any of the boilerplate additions to the
the commandline that gcc
would make. That's why the linkage fails.
If you link your program with gcc
in verbose mode:
gcc -v -o Cuteee main.o -L. -lhello
you can pick the collect2
commandline out of the output, something like:
/usr/lib/gcc/x86_64-linux-gnu/7/collect2 \
-plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so \
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper \
-plugin-opt=-fresolution=/tmp/ccgWPdno.res \
-plugin-opt=-pass-through=-lgcc \
-plugin-opt=-pass-through=-lgcc_s \
-plugin-opt=-pass-through=-lc \
-plugin-opt=-pass-through=-lgcc \
-plugin-opt=-pass-through=-lgcc_s \
--sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu \
--as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
-pie -z now -z relro -o Cuteee \
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o \
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o \
/usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o -L. \
-L/usr/lib/gcc/x86_64-linux-gnu/7 \
-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu \
-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib \
-L/lib/x86_64-linux-gnu -L/lib/../lib \
-L/usr/lib/x86_64-linux-gnu \
-L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. \
main.o -lhello -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc \
--as-needed -lgcc_s --no-as-needed \
/usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o \
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
All of those options that are passed to collect2
are passed through to
ld
. So if you replace /usr/lib/gcc/x86_64-linux-gnu/7/collect2
with
ld
in that monster commandline (or rather the commandline you get on
your own system), you will find that it links your program ./Cuteee
.
That is what linking the program with gcc
does, over an above:
ld -o Cuteee hello.o -lmyhello
One of the errors that your linkage attempt fails on:
cannot find entry symbol _start
is due to the fact that you haven't linked Scrt1.o
(/usr/lib/x86_64-linux-gnu/Scrt1.o
,
in the commandline above) which contains the C runtime initialization code for
a dynamically linked C program: it defines the symbol _start
, whose address is the entry point of the program,
to which the loader passes initial control at runtime, and after program initialization
is complete it calls main
.
The other linkage error:
undefined reference to 'printf
is due to the fact that you haven't linked the standard C library, -lc
(/lib/x86_64-linux-gnu/libc.so.6
).
Programmers don't link with ld
directly if they don't have to - e.g.
unless they're targeting an application to a bare-metal environment, and you
can see why.