Nested cmake library - c++

We have a C/C++ project organized like this:
lib1/
CMakeLists.txt
sublib1/
CMakeLists.txt
foo.c
log.c
log.h
Directory sublib1/ is linked with the add_library and target_link_libraries CMake commands in its CMakeLists.txt file.
Change:
We cannot call from foo.c/some-func a function in log.c/some-func-2. Linker is complaining that those functions are undefined.

The order that libraries and object files appear in your link command matters and can result in perplexing problems with undefined symbols. You don't give much info your post, but try telling the linker to treat all your libraries as a group. As in:
--start-group <all your libs> --end-group
From the linker documentation:
Normally, an archive is searched only once in the order that it is specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references are resolved. Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.

Related

Why does ld need library that my executable depends on?

I'm trying to build my executable (that depends on library utils.so) using the following command
g++ -L/path/to/libutils -lutils -I/path/to/utils_headers executable.cpp -o executable
Actually I don't have utils.so - only the header files of utils library.
I'm getting the error:
ld: cannot find -lutils
Does linker really need to access all the libraries my executable depends on in order to build my executable? If it does then I'd like to know why it needs to access them.
My executable is a shared library. I'm sure that header files of the utils lib are enough to build it (i.e without having utils.so).
The linkage option -lutils by default directs the linker to search,
first in the specified library search directories (-Ldir) and then
in its default search directories, for either of the files libutils.so (
shared library) or libutils.a (static library), preferring libutils.so
if both of them are found in the same search directory.
If such a file is found, the linker stops searching and adds that file
to the input files of the linkage, whether or not it resolves any references in
the linkage. The linker cannot know whether the file resolves any references
if it does not input the file.
If no such file is found, the linker gives the error: cannot find -lutils. Because
you told it to find libutils.{so|a} and it could not.
You say:
My executable is a shared library
But it isn't. Your compile-and-link command:
$ g++ -L/path/to/libutils -lutils -I/path/to/utils_headers executable.cpp -o executable
is not an attempt to link a shared library. It is an attempt to link a program.1
This would be an attempt to link a shared library:
$ g++ -shared -I/path/to/utils_headers -o libexecutable.so executable.cpp -L/path/to/libutils -lutils
You cannot link a program with unresolved references. But you can link a shared library
with unresolved references.
So, you could link a libexecutable.so like that, or you could link it simply like:
$ g++ -shared -I/path/to/utils_headers -o libexecutable.so executable.cpp
These are two different linkages: if they succeed they produce different output files.
In the first linkage, some symbols will (let's assume) be resolved to definitions provided in libutils.so or libutils.a
(whichever one is found), and this will be reflected by:
libutils.so is found: The .dynamic section of libexecutable.so contains a DT_NEEDED
structure that expresses a runtime dependency on libutils.so. libutils.so will need to be included in any linkage that includes libexecutable.so, but the output file of such a linkage will itself contain a runtime dependency only on libexecutable.so.
libutils.a is found: libexecutable.so itself contains the definitions for all the symbols
it uses that are defined by object files in libutils.a.2 libexecutable.so may be included in subsequent linkages with no need for libutils.{so|a}.
In the second linkage, the .dynamic section of libexecutable.so will not express a runtime
dependency on libutils.so nor will the file contain definitions of any symbols provided by libutils.{so|a}. libutils.so will (again) need to be included in an subsequent linkage that includes libexecutable.so, but the output file of such a linkage will acquire independent runtime dependencies on both libexecutable.so and libutils.so.
But, if you specify -lutils in the linkage - or any linkage - and the linker cannot find libutils.{so|a}
in any of its search directories, then you get the error you observe, because you told the linker
to input a file, whose effects on the linkage can only be determined and implemented if that file is found - and it cannot be found.
[1] An attempt that is likely to fail, because it consumes libraries before the object
files that refer to them
[2] See static-libraries to understand
why.
In general, an ELF linker needs a sufficiently accurate representation of the shared object that is linked in. It does not have to be an actually working shared objects, just a sufficiently close representation of it. A few things absolute require data that is not available in the object itself:
When compiling C programs, a reference to a global data object of incomplete type does not contain size information. The linker cannot place the object into the data segment unless it obtains the size information from somewhere. By default (when compiling for executables, including PIE) the object needs to be allocated in the data segment on many targets because of the relocations the compiler uses for compiling accesses to global data objects.
Similarly, the link editor might get the alignment of global data objects wrong if it has insufficient information.
Many libraries use symbol versioning. Symbol version information is only available when the link editor can see the shared object. If that information is missing, the link editor will not emit a symbol version, which instructs the dynamic linker to bind the symbol to the base version at run time, leading to subtle bugs.
However, if you only use C function symbols (not data symbols, or the varieties of symbols that C++ requires) and the target library does not use symbol versioning, you can use a stub library for linking. This is a library that defines all the functions you need and has the appropriate soname, but the functions are just dummies which do not actually do anything.

Linking error with cmake

I'm trying to understand why I get a linking error while compiling a project generated with CMake.
The CMakeFiles.txt builds a static library for each folder of the project and then link all of them together in the following way:
# root CMakeLists.txt
add_subdirectory(subfolder1)
add_subdirectory(subfolder2)
add_subdirectory(...)
add_executable(target ${SOURCES})
set(LIBRARIES
LIB_FOO
LIB_BAR
...
)
target_link_libraries(target
${LIBRARIES}
)
then in each subfolder I have a simple CMakeLists.txt like
file(GLOB FOO_SOURCE *.cpp)
add_library(LIB_FOO ${FOO_SOURCE})
Now this works and compiles everything fine but I get an undefined reference while linking, so I tried to investigate if everything was available at the end and it looks like so. The actual error is the following:
libLIB_WORLD.a(World.cpp.o): In function `World::generate(WorldGenOptions)':
World.cpp:(.text+0x803): undefined reference to `MapGenerator::MapGenerator(BlockMap*)'
World.cpp:(.text+0x837): undefined reference to `MapGenerator::generate(bool, WorldGenOptions)'
Now, MapGenerator.cpp is part of LIB_MAP, so I checked if the file exists and contains the symbols:
:~$ nm libLIB_MAP.a | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions
:~$ nm CMakeFiles/LIB_MAP.dir/MapGenerator.cpp.o | grep generate
....
00000000000044dc T _ZN12MapGenerator8generateEb15WorldGenOptions
So the symbol is present, at this point I checked if it was correctly linked by ld:
:~$ make VERBOSE=1
/usr/bin/g++ ... libLIB_MAP.a libLIB_WORLD.a ...
So it is actually present in linking phase together with the other library that is not able to find the symbol.
Is there something trivial I'm missing? I'm quite new to CMake so I'm out of ideas.
This is a problem of a library dependency that was not modeled correctly in CMake.
Your LIB_WORLD references methods from LIB_MAP. This dependency is not modeled in your CMake scripts. As both of those are static libraries, they will still build fine on their own. (Remember that static libraries are essentially a bunch of object files packed together, but they never pass through the linker.)
However, as soon as you link them to an executable or a shared library, you will get the problem. Even though your executable links against both LIB_WORLD and LIB_MAP, it does so in the wrong order. So when the linker is trying to resolve the missing symbols for LIB_WORLD, it does not know yet about the symbols exported by LIB_MAP, hence the error message you experienced.
The proper fix is to introduce the dependency on LIB_WORLD:
add_library(LIB_WORLD [...])
target_link_libraries(LIB_WORLD LIB_MAP)
Now whenever you link something against LIB_WORLD you will always also link against LIB_MAP and CMake will take care that the order is right. (In particular, if your executable does not make direct use of methods from LIB_MAP you might want to remove it from its target_link_libraries altogether.)
As an additional benefit, it now allows you to build LIB_WORLD as a shared library, which would have failed with a linker error before.

Linking shared, static, and dynamic library

I built and installed the source code of spidermonkey, I want to link its library and its include folder with my C++ application, so I wrote this command on linux
g++ -I/home/SpiderMonkey/js-1.8.5/js/src/dist/include
-L/home/SpiderMonkey/js1.8.5/js/src/dist/lib -lmozjs185 helloworld.cpp -o
but it gives me undefined reference error, so what is the problem with this command:
the path which the src code was built in is home/SpiderMonkey/js1.8.5/src
and when I installed the src code, its libs and include folder exist now in usr/local/lib and usr/local/include/js respectively, so which path should I use in the command to compile my hellowrorld.cpp.
Also, I found 3 libraries with the same name but with different extension:
libname.so, libname.so.1.0, libname.so.1.0.0 and libname.a
which library should I use and what are the differences?
Put the libraries after your main.cpp on the compilation command. The linker determines which symbols to pull out of those libraries based on the objects it's already seen, left to right.
As for your addendum question:
libname.a is for static linking.
libname.so, libname.so.1.0 and libname.so.1.0.0 are all the same file, just with names that give you an increasing level of version information granularity.
Which to use is beyond the scope of this answer, but you can find plenty of information about that already existing on the web.

how to disable C++ dead code stripping in xcode

I'm trying to link in all unreferenced symbols from a few static libraries (my own libraries) for my C++ xcode app. I have tried all the properties related to 'strip' (by searching the properties for 'strip'), but the unreferenced symbols, specifically classes, are not linked in.
I have also tried the -r linker flag, but then the linker only complains with:
'ld: -r and -dead_strip cannot be used together'
I have tried adding '-no_dead_strip' to the linker flags, but then the linker just tells me
'-no_dead_strip' is ignored.
I get the same results with both 'Apple LLVM' and 'LLVM GCC'.
So, my question is: what linker flag(s) or target properties should I use to switch off all dead code stripping and force unreferenced classes to be linked in?
The standard linking mechanism - i.e. using the -l option to link a .a file will intelligently filter out object files that are not used, so the reason why the symbols are not present in the resultant binary is that they're not actually linked in.
If you want to get all the symbols from one archive, you can use the flag: -force_load libraryarchive, used like: -Wl,-force_load,libfoobar.a where libfoobar.a is the archive that you want to get all the symbols from.
In order to get all the symbols from the all archives, you should use the linker flag: -all_load, or if you're driving it from gcc/clang the flag -Wl,-all_load.
It produces hideous symbol tables, though!

How to make gcc/ld iterate over many '-l library' when using -static?

I want to compile statically pdf2svg so I will be able to use newest version in stable Debian. The ./configure doesn't give --enable-static option so I added manually in Makefile -static option for linker.
Unfortunately the result wasn't quite as I suspected. The linking gave me enormous amounts of undefined reference errors. After some googling I figured out that the problem is caused by wrong order of -lsome_lib. Gcc linker tries to statically link in each library once, when it first sees it - info and Stackoverflow question: Why does the order in which libraries are linked sometimes cause errors in GCC?.
Is there a possibility of making linker make multiple passes through the list of libraries?
Maybe this is what you search for (from gnu ld manpage):
-( archives -)
--start-group archives --end-group
The archives should be a list of archive files. They may be either explicit file names, or -l options.
The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched only once in the order that it is
specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on
the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references
are resolved.
Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.
A tick is, whenever possible, to add a static reference to an object of the class (or to the function) that were not linked in another cpp file of the same library (or in another library already used).
I have this situation:
library A with class clsA in clsA.cpp that gives the error
library A with foo.cpp that gives no reference errors
library B that uses class clsA
Application uses both libraries and uses classes/functions from foo.cpp
I get the unresolved reference in Application while using the object in library B that uses the clsA class.
Linking Application with library A and B give me the error. Since i use CodeLite, it's hard to change library order. I simply put a static object in foo.cpp:
#include "clsA.h"
clsA objA;
The linker now see that clsA are referenced in library A (between foo.cpp) and will link correctly in application because foo.cpp were already linked.
But the trick works even if the object were created in a dummy function, never called, so the object would never been allocated:
// foo.cpp
#include "clsA.h"
void dummyf()
{
clsA objA;
}