Force GCC to notify about undefined references in shared libraries
-Wl,--no-undefined
linker option can be used when building shared library, undefined symbols will be shown as linker errors.
g++ -shared -Wl,-soname,libmylib.so.5 -Wl,--no-undefined \
-o libmylib.so.1.1 mylib.o -lthirdpartylib
What is the g++ flag that permits undefined references in shared libraries?
This can only be a linker flag... and then, it depends on what linker you're using.
On Linux (and probably BSD, at least FreeBSD) this should be the default behaviour. Not on Mac though.
From the GNU ld
man page:
--allow-shlib-undefined
--no-allow-shlib-undefined
Allows or disallows undefined symbols in shared libraries.
This switch is similar to --no-undefined except that it determines
the behaviour when the undefined symbols are in a shared library rather
than a regular object file. It does not affect how undefined symbols in
regular object files are handled.
The default behaviour is to report errors for any undefined symbols
referenced in shared libraries if the linker is being used to create an
executable, but to allow them if the linker is being used to create a
shared library.
From the Apple ld
man page:
-undefined treatment
Specifies how undefined symbols are to be treated. Options
are: error, warning, suppress, or dynamic_lookup. The
default is error.
How to make linker fail for undefined references when building shared library in Linux
When I'm building and want to avoid this situation, I compile the library with the options: -Wl,--no-allow-shlib-undefined -Wl,-z,defs
The first option causes the link of the shared library to fail in the situation that a symbol is not defined in the code, when used in combination with the second option, which causes the linker to report the missing symbols.
This works well to prevent missing symbols at run-time by detecting them at link time. I do, however, need to link the .so
with all the libraries it uses, as otherwise it will fail to build.
sample (src.c):
#include <math.h>
extern
double share_the_stuff(double val)
{
return acos(val * val);
}
Build with missing symbol:
gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs
/usr/bin/ld: /tmp/ccFmD5uY.o: in function `share_the_stuff':
src.c:(.text+0x17): undefined reference to `acos'
collect2: error: ld returned 1 exit status
link in libm.so:
gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs -lm
It behaves the same with missing internal symbols.
Can GCC not complain about undefined references?
Yes, it is possible to avoid reporting undefined references - using --unresolved-symbols
linker option.
g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files
From man ld
--unresolved-symbols=method
Determine how to handle unresolved symbols. There are four
possible values for method:ignore-all
Do not report any unresolved symbols.
report-all
Report all unresolved symbols. This is the default.
ignore-in-object-files
Report unresolved symbols that are contained in shared
libraries, but ignore them if they come from regular object
files.
ignore-in-shared-libs
Report unresolved symbols that come from regular object
files, but ignore them if they come from shared libraries. This
can be useful when creating a dynamic binary and it is known
that all the shared libraries that it should be referencing
are included on the linker's command line.
The behaviour for shared libraries on their own can also be
controlled by the --[no-]allow-shlib-undefined option.Normally the linker will generate an error message for each
reported unresolved symbol but the option --warn-unresolved-symbols can
change this to a warning.
Undefined reference from shared library in static one
Static libraries are just an agglomeration of object files (their members), perhaps with a ranlib(1) generated index.
On Linux, if you link an object file (3) foo.o
with a static library (2) libee.a
and a shared library (1) libyz.so
and if you pass -rdynamic
at link time (i.e. gcc -rdynamic foo.o libee.a libyz.so -o myprog
or gcc -rdynamic foo.o -lee -lyz -o myprog
) then dynamic linker would resolve the get_object
name at dynamic link time (in ld-linux.so
)
Details are explained in ELF wikipage and Drepper's paper: How To Write Shared Libraries. Read also Levine's book: Linkers and loaders & ld(1) man page.
Why does g++ detect undefined reference when dynamically linking
With the ELF format it indeed isn't necessary to know which symbols belong to which library, as the actual symbol resolution happens when the program is executed. By convention though ld
will still resolve the symbols when producing the binary. It's for your convenience, so that you get immediate feedback when you have missing symbols, since in that case the chance is big your program won't work.
Using the --warn-unresolved-symbols
flag you can change ld
behavior in this case from an error to a warning:
$ g++ -Wl,--warn-unresolved-symbols main.cpp -lusertest
Should emit a warning but still create the executable. Note that you still need to provide the library name, otherwise ld
won't know where to look for the needed symbols.
On Windows, the linker needs to know exactly which symbol belongs to which library in order to produce the necessary import tables. So it is impossible to build a PE binary with unresolved symbols.
Easy check for unresolved symbols in shared libraries?
Check out the linker option -z defs
/ --no-undefined
. When creating a shared object, it will cause the link to fail if there are unresolved symbols.
If you are using gcc to invoke the linker, you'll use the compiler -Wl
option to pass the option to the linker:
gcc -shared ... -Wl,-z,defs
As an example, consider the following file:
#include <stdio.h>
void forgot_to_define(FILE *fp);
void doit(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (fp != NULL)
{
forgot_to_define(fp);
fclose(fp);
}
}
Now, if you build that into a shared object, it will succeed:
> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded
But if you add -z defs
, the link will fail and tell you about your missing symbol:
> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed
Related Topics
Why Does Gcc Compiler Output Pow(10,2) as 99 Not 100
Should We Pass a Shared_Ptr by Reference or by Value
Best Documentation for Boost:Asio
C++ Auto Keyword. Why Is It Magic
What Does 'Const Static' Mean in C and C++
C++ Compiling on Windows and Linux: Ifdef Switch
What's the Best Way to Do Fixed-Point Math
Efficient Unsigned-To-Signed Cast Avoiding Implementation-Defined Behavior
What Is the Performance Cost of Having a Virtual Method in a C++ Class
What Does the "Lock" Instruction Mean in X86 Assembly
Get 3D Coordinates from 2D Image Pixel If Extrinsic and Intrinsic Parameters Are Known
When Do Extra Parentheses Have an Effect, Other Than on Operator Precedence
Extract Year/Month/Day etc. from Std::Chrono::Time_Point in C++
How to Convert Euler Angles to Directional Vector
How Std::Bind Works with Member Functions
C++ Modules - Why Were They Removed from C++0X? Will They Be Back Later On