1

I've noticed that I can't compile my code with cpp files in the end of the command:

ars@Arsmint$ g++ -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor main.cpp 
/tmp/ccxlyIri.o: In function `main':
main.cpp:(.text+0x10c): undefined reference to `createDevice'
collect2: error: ld returned 1 exit status

If I put them before linking directives, it compiles fine:

ars@Arsmint$ g++ main.cpp -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor
ars@Arsmint$

I've read some explanations here and there, but I still don't quite get it when it comes to compiled sources, not library-library dependencies. I had thought that a compiler always compiles the code first, and only then calls the linker. In that case, it should know that object file built from main.cpp needs createDevice function even before start of the linking process. Where is my mistake?

P.S. This question, proposed as a duplicate, doesn't explain it at all.

Community
  • 1
  • 1
ars
  • 1,509
  • 3
  • 18
  • 29

1 Answers1

2

You may be confused (as it seems many people are) by taking the shortcut of compiling and linking in one command.

g++ -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor main.cpp

is a shortcut functionally equivalent to:

# g++ invokes the C++ compiler (cc1plus). The linkage options are ignored.
g++ -c -o deleteme.o main.cpp

# g++ invokes the system linker (ld). The linkage options are passed.
g++ -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor -o a.out deleteme.o
rm deleteme.o

If you executed both steps explicitly, you would do, e.g.

# Compile step
g++ -c -o main.o main.cpp
# Link step.
g++ -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor -o prog main.o

In the link step, g++ covertly adds the default C++ linkage options for the host system to the commandline, then hands it off to the linker. The C++ compiler is not involved.

By default, the linker will examine a library at most once, when it is encountered in the commandline linkage sequence, and it will examine the library only to see if the library can resolve any hitherto unresolved symbols referenced earlier in the linkage sequence. At the end of the linkage sequence, if all referenced symbols are resolved, the linkage succeeds and otherwise fails.

The linkage:

g++ -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor -o a.out deleteme.o

will fail because all the libraries appear before any object file. When each library is reached, the linker has discovered no unresolved symbols yet so the library is ignored. When the linker finally reaches the trailing object file and discovers some unresolved symbols, they remain unresolved.

Conversely,

g++ main.cpp -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor

is equivalent to:

g++ -c -o deleteme.o main.cpp    
g++ -o a.out deleteme.o -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor
rm deleteme.o

in which the linkage order is correct, with the symbols that require definitions being discovered before the libraries that provide them.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182