Find static library unresolved dependencies before linking executable - c++

So let's say we have static library mylib.a, which contains compiled cpp files.
file1.cpp:
int do_stuff();
int func_unres()
{
int a = do_stuff();
return a;
}
file2.cpp:
int do_other_stuff();
int func_res()
{
int a = do_other_stuff();
return a;
}
file3.cpp:
int do_other_stuff()
{
return 42;
}
So, as we can see here, no file contains definition of do_stuff function.
Library created this way:
g++ -c file1.cpp -o file1.o
g++ -c file2.cpp -o file2.o
g++ -c file3.cpp -o file3.o
ar r mylib.a file1.o file2.o file3.o
Now we try to make some binary with this library. Simple example main file:
#include <iostream>
int func_res();
int main()
{
std::cout << func_res() << std::endl;
}
Compiling:
g++ main.cpp mylib.a -o my_bin
Everything works just fine.
Now consider case of main file like this:
#include <iostream>
int func_unres();
int main()
{
std::cout << func_unres() << std::endl;
}
In this case binary won't link, cause func_unres requires function do_stuff to be defined.
Is there a way to find out that static library requires symbol which no object file in the library contains before linking it with executable, which uses such symbol?
EDIT:
The question is not how to simple list such symbols, but to get an output with linker like error.
Like if i linked this library with executable using all of symbols it should contain.

It seems that as pointed in comments and in How to force gcc to link an unused static library, linker option --whole-archive is enough to force resolve all symbols and output linker error for all unresolved symbols in static library. So referring the question examples, compiling and linking this way first main file, which doesn't refer undefined symbol, will output linker error anyway:
g++ main.cpp -Wl,--whole-archive mylib.a -Wl,--no-whole-archive
Linking fails despite main doesn't use func_unres:
mylib.a(file1.o): In function func_unres(): file1.cpp:(.text+0x9):
undefined reference to do_stuff()
Second option --no-whole-archive is used so the rest of required libraries' symbols will not be force resolved like this.

Related

ldd does not show the dependency which make then needs

I have the program which needs v2xmvtest.so. When i try to build it via make i get undefined reference to *
Seems like that function from libssl1.0. (If i install it, it's built fine)
But i do not see the place where these function are used. More than that, when i try ldd v2xmvtest.so it does show only libvssl1.1 dependency.
Summary:
Is there a way to find out where those finctions from libvssl1.0 are used in the program ? (i have source code of the v2xmvtest.so and try to search, but there no any of these)
I need a description why ldd does not show me libssl1.0 dependency, but during linkning it's needed
Thank you!
Libraries are not required to fully define used symbols. For instance you can have lib.cpp:
int foo();
int bar(int x)
{
return x + foo();
}
and it compiles even foo is actually not defined yet:
g++ lib.cpp -shared -o lib.so
Then you can have main.cpp:
#include <iostream>
int bar(int);
int foo()
{
return 10;
}
int main()
{
std::cout << bar(42) << std::endl;
}
which defines foo and compiles successfully with lib.so:
g++ main.cpp lib.so -o main
The foo function in lib.so is expected just to be provided when the application is linked and is not specified where exactly from, even not necessary from a library.
You can check for undefined symbols in a library using nm tool:
nm -C -u lib.so
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U foo()
w __cxa_finalize##GLIBC_2.17
w __gmon_start__
And finally you can force gcc to ensure no undefined symbols are used by the object files by compiling with -Wl,-z,defs linker flag:
g++ lib.cpp -shared -Wl,-z,defs -o lib.so
...
lib.cpp:(.text+0x24): undefined reference to `foo()'

Calling C code from C++ with using extern "C"

I have 3 files with me, one c++ file, main.cpp, one c file, test.c and one header file, test.h
I wanted to try and use C code into C++ file. For the same reason, I have declared an function in test.h and defined that in test.c and using that in main.cpp
main_temp.c is just for explanation.
test.h
void test(int);
test.c
#include <stdio.h>
void test(int a) {
printf("%d", a);
main_temp.cpp
#include "test.h"
int main() {
foo(5);
}
Here, I understand why this would not work. C symbol would be simple 'foo' but since C++ does more things while creating symbols, it might be 'void#test(int)' and to solve this name mangling problem, I have to treat C++ symbol as a C symbol. So, I would use extern "C" and my main.cpp becomes as like:
main.cpp
extern "C" {
#include "test.h"
}
int main() {
foo(5);
}
I could not understand as to why this would not work! I get :
main.cpp:(.text+0xa): undefined reference to `test`
Can somebody share the insights?
I trust you compile or link them together? Else that would be the cause. On gcc it would be something like:
g++ -c -o main.o main.cpp
gcc -c -o test.o test.c
g++ -o a.out main.o test.o
Assuming you have no bugs with compiling/linking, compile both main.cpp and test.c into object files and run nm on both. It will show what symbol main.o wants and what symbol test.o exports. It should become clear then why linker cannot do its job.

Unable to link static library to main program [duplicate]

I want to know how I can use a static library in C++ which I created, first the lib:
// header: foo.h
int foo(int a);
.
// code: foo.cpp
#include foo.h
int foo(int a)
{
return a+1;
}
then I compile the library first:
g++ foo.cpp
ar rc libfoo.a foo.o
now I want to use these library in some file like:
// prog.cpp
#include "foo.h"
int main()
{
int i = foo(2);
return i;
}
how must I compile these now?
I made:
g++ -L. -lfoo prog.cpp
but get an error because the function foo would not be found
You want:
g++ -L. prog.cpp -lfoo
Unfortunately, the ld linker is sensitive to the order of libraries. When trying to satisfy undefined symbols in prog.cpp, it will only look at libraries that appear AFTER prog.cpp on the command line.
You can also just specify the library (with a path if necessary) on the command line, and forget about the -L flag:
g++ prog.cpp libfoo.a

Static Libraries which depend on other static libraries

I have a question about making static libraries that use other static libraries.
I set up an example with 3 files - main.cpp, slib1.cpp and slib2.cpp. slib1.cpp and slib2.cpp are both compiled as individual static libraries (e.g. I end up with slib1.a and slib2.a) main.cpp is compiled into a standard ELF executable linked against both libraries.
There also exists a header file named main.h which prototypes the functions in slib1 and slib2.
main.cpp calls a function called lib2func() from slib2. This function in turn calls lib1func() from slib1.
If I compile the code as is, g++ will return with a linker error stating that it could not find lib1func() in slib1. However, if I make a call to lib1func() BEFORE any calls to any functions in slib2, the code compiles and works correctly.
My question is simply as follows: is it possible to create a static library that depends on another static library? It would seem like a very severe limitation if this were not possible.
The source code for this problem is attached below:
main.h:
#ifndef MAIN_H
#define MAIN_H
int lib1func();
int lib2func();
#endif
slib1.cpp:
#include "main.h"
int lib1func() {
return 1;
}
slib2.cpp:
#include "main.h"
int lib2func() {
return lib1func();
}
main.cpp:
#include <iostream>
#include "main.h"
int main(int argc, char **argv) {
//lib1func(); // Uncomment and compile will succeed. WHY??
cout << "Ans: " << lib2func() << endl;
return 0;
}
gcc output (with line commented out):
g++ -o src/slib1.o -c src/slib1.cpp
ar rc libslib1.a src/slib1.o
ranlib libslib1.a
g++ -o src/slib2.o -c src/slib2.cpp
ar rc libslib2.a src/slib2.o
ranlib libslib2.a
g++ -o src/main.o -c src/main.cpp
g++ -o main src/main.o -L. -lslib1 -lslib2
./libslib2.a(slib2.o): In function `lib2func()':
slib2.cpp:(.text+0x5): undefined reference to `lib1func()'
collect2: ld returned 1 exit status
gcc output (with line uncommented)
g++ -o src/slib1.o -c src/slib1.cpp
ar rc libslib1.a src/slib1.o
ranlib libslib1.a
g++ -o src/slib2.o -c src/slib2.cpp
ar rc libslib2.a src/slib2.o
ranlib libslib2.a
g++ -o src/main.o -c src/main.cpp
g++ -o main src/main.o -L. -lslib1 -lslib2
$ ./main
Ans: 1
Please, try g++ -o main src/main.o -L. -Wl,--start-group -lslib1 -lslib2 -Wl,--end-group.
Group defined with --start-group, --end-group helps to resolve circular dependencies between libraries.
See also: GCC: what are the --start-group and --end-group command line options?
The order make the difference. Here's from gcc(1) manual page:
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.

Compile shared object library, which call function from so too

I have got a f2.cpp file
// f2.cpp
#include <iostream>
void f2()
{
std::cout << "It's a call of f2 function" << std::endl;
}
I use cygwin with crosstool compiler gcc.
g++ -fPIC -c f2.cpp
g++ -shared -o libf2.so f2.o
I have got a libf2.so file. Now I want to call f2 function in f1 library (shared object too) libf1.so.
It's a f1.cpp and i want take f1.so
// f1.cpp
#include <iostream>
void f1()
{
std::cout << "f1 function is calling f2()..." << std::endl;
f2();
}
How i must compile f1.cpp? I don't want to use dlclose, dlerror, dlopen, dlsym...
Аt last i want to use f1.so in main.cpp as a shared object library too... without using use dlclose, dlerror, dlopen, dlsym. How I must compile main.cpp, when i will have a f1.so ?
// main.cpp
#include <iostream>
int main()
{
f1();
return 0;
}
declare f2() in a header file. and compile libf1.so similar to libf2.
Now compile main linking against f1 and f2.
It should look something like this
g++ -lf2 -lf1 -L /path/to/libs main.o
You can simply link them together (if f2 is compiled into libf2.so, you pass -lf2 to the linker). The linker will take care of connecting calls from f1 to f2. Naturally, at runtime f1 will expect to find f2 in the SO load path and the dynamic loader will load it.
Here's a more complete sample, taken from a portion of a Makefile I found lying around. Here, mylib stands for your f2, and main_linked is f1:
mylib: mylib.c mylib.h
gcc $(CFLAGS) -fpic -c mylib.c
gcc -shared -o libmylib.so mylib.o
main_linked: main_linked.c mylib.h mylib.c
gcc $(CFLAGS) -L. -lmylib main_linked.c -o main_linked
Note:
mylib is compiled into a shared library with -shared
main_linked is then built with a single gcc call passing -lmylib to specify the library to link and -L. to say where to find it (in this case - current dir)
Check the -L and -l flags to g++.