Strange linking error at runtime

This is my Makefile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
../ImageLibrary.dll: export_functions.o FreeImageStream.o ImageFunctions.o LibraryState.o
	c++ -std=c++14 export_functions.o ImageFunctions.o LibraryState.o -O3 -shared -fPIC -s -L. -lfreeimage -o ../bin64/ImageLibrary.dll

export_functions.o: export_functions.cpp common_types.h FreeImageStream.h ImageFunctions.h LibraryState.h utf8.h
	c++ -c -std=c++14 export_functions.cpp -O3 -fPIC -o export_functions.o

FreeImageStream.o: FreeImageStream.cpp common_types.h FreeImageStream.h ImageFunctions.h LibraryState.h utf8.h
	c++ -c -std=c++14 FreeImageStream.cpp -O3 -fPIC -o FreeImageStream.o

ImageFunctions.o: ImageFunctions.cpp common_types.h FreeImageStream.h ImageFunctions.h LibraryState.h utf8.h
	c++ -c -std=c++14 ImageFunctions.cpp -O3 -fPIC -o ImageFunctions.o

LibraryState.o: LibraryState.cpp common_types.h FreeImageStream.h ImageFunctions.h LibraryState.h utf8.h
	c++ -c -std=c++14 LibraryState.cpp -O3 -fPIC -o LibraryState.o

clean:
	rm *.o
Notice that I forgot to add FreeImageStream.o to the final link command. This builds fine, but fails at runtime because the library doesn't contain a function referenced by one of the object files. I'm trying to understand why GCC allowed this to build correctly.

$ c++ --version
c++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1
2
../ImageLibrary.dll: export_functions.o FreeImageStream.o ImageFunctions.o LibraryState.o
	c++ -std=c++14 export_functions.o ImageFunctions.o LibraryState.o -O3 -shared -fPIC -s -L. -lfreeimage -o ../bin64/ImageLibrary.dll

Why is the -o going to a different place to the supposed target?

https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
1
2
../ImageLibrary.dll: export_functions.o FreeImageStream.o ImageFunctions.o LibraryState.o
	c++ -std=c++14 $^ -O3 -shared -fPIC -s -L. -lfreeimage -o $@

Good catch, although I don't think it would have any influence on this particular problem.
You could look into the dll with depends, a visual check on what's going on.
I already know there are missing symbols in the SO. What I don't understand is why the compiler generated an SO with missing symbols, rather than report a linker error.
How, at the point the linker is creating your library, is it supposed to know that a symbol which is ultimately resolved by FreeImageStream.o should be flagged as unresolved, whereas another symbol such as say strlen resolved by the standard library should be let through without comment.

A single object file is just a bag of bits with some defined symbols, and some unresolved symbols.
A library is just a bigger bag of bits with more defined symbols, and some unresolved symbols.

I'd say level up your makefile skills so you don't have to do quite so much running maintenance (ie, opportunities to forget something) every time you add a file to your project.

rtfm wrote:

--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.

Unless your library has no external dependencies at all, adding --unresolved-symbols=ignore-in-object-files is likely to report more noise than help.
That's assuming that this option even has an effect when generating a library.





Are shared objects not fully linked like DLLs are? When you build a DLL the toolchain follows the same procedure as when building an EXE and ensures that every symbol that's reachable from an exported function is defined, and if it's not defined the build fails. Is this not done for shared objects? I knew static libraries where just bundled up object files that weren't linked until they were included in an executable, I didn't know the same was true for shared objects.
That's so lame, if that's the case.
Last edited on
Topic archived. No new replies allowed.