How to resolve linker error "cannot find -lgcc_s" - c++

I have 3 tiny files which I use to make a static library and an app:
test.h
#ifndef TEST_H
#define TEST_H
class Test
{
public:
Test();
};
extern Test* gpTest;
#endif
test.cpp
#include "test.h"
Test::Test()
{
gpTest = this;
}
Test test;
main.cpp
#include "test.h"
#include <iostream>
using namespace std;
Test* gpTest = NULL;
int main()
{
return 0;
}
BUILD
g++ -c test.cpp -o test.o
ar cr test.a test.o
g++ -c main.cpp -o main.o
g++ main.o -o app -Wl,--whole-archive -L/home/dumindara/intest/test.a -Wl,-no--whole-archive
ERROR (linking step)
/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
I tried everything: using -static-libgcc and linking to static libstdc++. Can't get this to work. It is all due to --whole-archive flag. But I can't do without it.

You have a typo. -no--whole-archive should be --no-whole-archive. Fixing the typo fixes the linker error.

I think -- is the problem here:
-Wl,-no--whole-archive
Try with
-Wl,-no-whole-archive
edit
About not seeing the test symbol in your app with nm app: I think you don't need -L since you give full path and name of test.a - do either
-Wl,--whole-archive -L/home/dumindara/intest/ -ltest -Wl,-no-whole-archive
or
-Wl,--whole-archive /home/dumindara/intest/test.a -Wl,-no-whole-archive

With regards to the comments so far: just drop the -Wl option
entirely. Let g++ do its thing.
As for not finding the symbol test with nm, why would you expect
anything else? You don't use it, your program doesn't need it,
so it isn't pulled in. (If for some reason you need to include
an object file which isn't referenced, e.g. because static
initializers will make it visible, then specify the object
file---don't put it in a library, which is the standard way of
saying don't include it unless needed.)
--
James Kanze

whole-archive works, you are just not linking the lib. The correct thing to do is :
ar cr libtest.a test.o
and link with
-Wl,--whole-archive -L/home/dumindara/intest/ -ltest

Just a note: whole-archive only works with static libraries (.a) not with shared libraries (.so) is my experience.

Related

Compiles error:Undefined reference, which is caused mainly by dependency with libraries?

I met a c++ compile error that almost drives me mad these days. The output info is
(/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: undefined reference to symbol '__libc_start_main##GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libc.so.6: error adding symbols: DSO missing from command line
it's not undefined reference to `main', to be careful.)
The basic case is very simple. library B depends on library C. excutable A depends on library B, and thus depends on library C.
Below is my code, it's very simple as well.
**c.h**
void kk();
**c.cpp**
#include <iostream>
using namespace std;
void kk()
{
cout<<"111"<<endl;
}
**b.h**
#include "c.h"
void pp();
**b.cpp**
#include "b.h"
void pp()
{
kk();
}
**a.cpp**
#include "b.h"
int main()
{
pp();
}
And This is my Compiling process: make c && b respectively to be a shared library, and build a
through linking against them.
1. g++ -fpic -shared c.cpp -o libc.so
2. g++ -fpic -shared b.cpp -o libb.so
3. g++ a.cpp -o a -lb -lc -L.
Besides,I tried many ways to solve this problem. None worked. And I found that in the fianl step, If I do not link library c, the output is the same.It seems that I failed to link c finally,But I just did it, who knows the reason. The g++ version??
Your libc.so conflicts with the one installed by glibc. You would need to change to use another name

Why one definition rule (ODR) is not honoured by g++ in this case ? .

As you see, there are multiple definitions of testfn symbol while linking, but the linker takes the first occurence (in linking order) and ignores the other occurances in other libraries.
This probably is the way how the linker works.
But Is there any way to enforce linker to flag error on seeing multiple symbols in different linked libraries ? Or any other options to catch such duplicate definitions ?
Content of test1.h:
#ifndef TEST1
#define TEST1
void testfn();
#endif
Content of test1.cpp
#include "test1.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file1" << endl;
}
Content of test.h:
#ifndef TEST
#define TEST
void testfn();
#endif
Content of test.cpp:
#include "test.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file" << endl;
}
Content of main.cpp:
#include "test.h"
#include "test1.h"
int main()
{
testfn();
return 0;
}
Created a shared libraries.
g++ -fPIC -shared libtest1.so test1.cpp
g++ -fPIC -shared libtest.so test.cpp
Created executable with library order#1
g++ -o main main.cpp -ltest -ltest1
Created executable with library order#2
g++ -o main1 main.cpp -ltest1 -ltest
Ouput of main
./main
file
Ouput of main1
./main1
file1
First of all, it is honoring the ODR, by only taking one of the methods out of the library. And that's just the way shared libraries work.
If you want to see the compiler complain about this, link them all together, without the library step.
g++ -o main1 main.cpp test1.cpp test.cpp
So your question becomes, "How do I tell if I have two libraries which both contain a indentifier with the same name?" Keep in mind that this is often not a problem and sometimes done intentionally. I'd suggest running the library tool (I'm not familiar with the g++ toolset) to get listing of the libraries, and run DIFF of them.
I don't see a way to get GNU ld to complain about multiple symbol definitions across shared libraries. However, if normal static library archives are involved, you might be able to use the --whole-archive/--no-whole-archive set of options to get what you want:
For example, after building libtest.a and libtest1.a instead of the shared library versions, I get no errors with the following link commands:
$ g++ -o main main.cpp -ltest1 -ltest -L.
$ ./main
file1
$ g++ -o main main.cpp -ltest -ltest1 -L.
$ ./main
file
But do get errors for the following:
$ g++ -o main main.cpp -Wl,--whole-archive -ltest1 -ltest -Wl,--no-whole-archive -L.
./libtest.a(test.o): In function `testfn()':
test.cpp:(.text+0x0): multiple definition of `testfn()'
./libtest1.a(test1.o):test1.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
I'm not sure you would want to use --whole-archive for release builds - maybe only as a sanity check for possibly name conflicts (I think that using --whole-archive normally will increase the size of your binary for no good reason).
Also, as mentioned before, this seems to have no effect on shared libraries.

How to force gcc to link an unused static library

I have a program and a static library:
// main.cpp
int main() {}
// mylib.cpp
#include <iostream>
struct S {
S() { std::cout << "Hello World\n";}
};
S s;
I want to link the static library (libmylib.a) to the program object (main.o), although the latter does not use any symbol of the former directly.
The following commands do not seem to the job with g++ 4.7. They will run without any errors or warnings, but apparently libmylib.a will not be linked:
g++ -o program main.o -Wl,--no-as-needed /path/to/libmylib.a
or
g++ -o program main.o -L/path/to/ -Wl,--no-as-needed -lmylib
Do you have any better ideas?
Use --whole-archive linker option.
Libraries that come after it in the command line will not have unreferenced symbols discarded. You can resume normal linking behaviour by adding --no-whole-archive after these libraries.
In your example, the command will be:
g++ -o program main.o -Wl,--whole-archive /path/to/libmylib.a
In general, it will be:
g++ -o program main.o \
-Wl,--whole-archive -lmylib \
-Wl,--no-whole-archive -llib1 -llib2
The original suggestion was "close":
How to force gcc to link unreferenced, static C++ objects from a library
Try this: -Wl,--whole-archive -lyourlib
I like the other answers better, but here is another "solution".
Use the ar command to extract all the .o files from the archive.
cd mylib ; ar x /path/to/libmylib.a
Then add all those .o files to the linker command
g++ -o program main.o mylib/*.o
If there is a specific function in the static library that is stripped by the linker as unused, but you really need it (one common example is JNI_OnLoad() function), you can force the linker to keep it (and naturally, all code that is called from this function). Add -u JNI_OnLoad to your link command.

C/C++ duplicate symbols error

I'm currently trying to compile an existing project which is a mix of cpp and c.
My makefile is as follows;
execute: mgnsvd.o multifit.o cit.o main.o
g++ -Wall -g multifit.o cit.o main.o mgnsvd.o -lgsl -lgslcblas -o execute
main.o: main.cpp cit.cpp
g++ -Wall -g -c main.cpp
cit.o: cit.cpp mgnsvd.c multifit.h
g++ -Wall -g -c cit.cpp
multifit.o: multifit.c mgnsvd.c multifit.h
g++ -Wall -g -c multifit.c
mgnsvd.o: mgnsvd.c
g++ -Wall -g -c mgnsvd.c
And my main is a rather plain
// global libraries
#include <iostream>
// local files
#include "cit.cpp"
// using directives
using std::endl;
using std::cout;
// main
int main(){
cout << "Hello, world" << endl;
return 0;
}
If is comment out #include "cit.cpp" it compiles fine. However, if i include it the following error happens;
ld: duplicate symbol _first_function_in_cit in main.o and cit.o for architecture x86_64
_first_function is always the first function, and is not defined or even declared/used anywhere else. A grep of the object files confirms the function seems to be incorporated into main.o, but why? I've not worked on a C++/C project before, so maybe I'm making some canonical error? I'm also in OSX, if that makes a difference.
For the record, there are no classes - the .h file contains a few structs and some macros.
cit.cpp is being compiled by itself, and is also included in main.cpp so you're getting two copies of all the code in it.
There is no need for
#include "cit.cpp"
cit.cpp is compiled as a separate unit and later linked.
With the above include you get the code twice with results in duplicate symbols
YOu are compiling cit.cpp to yield cit.o, and you are compiling it again with that #include "cit.cpp" attrocity in your main.cpp. So of course you are getting duplicate symbols.

Why doesn't g++ link with the dynamic library I create?

I've been trying to make some applications which all rely on the same library, and dynamic libraries were my first thought: So I began writing the "Library":
/* ThinFS.h */
class FileSystem {
public:
static void create_container(string file_name); //Creates a new container
};
/* ThinFS.cpp */
#include "ThinFS.h"
void FileSystem::create_container(string file_name) {
cout<<"Seems like I am going to create a new file called "<<file_name.c_str()<<endl;
}
I then compile the "Library"
g++ -shared -fPIC FileSystem.cpp -o ThinFS.o
I then quickly wrote a file that uses the Library:
#include "ThinFS.h"
int main() {
FileSystem::create_container("foo");
return (42);
}
I then tried to compile that with
g++ main.cpp -L. -lThinFS
But it won't compile with the following error:
/usr/bin/ld: cannot find -lThinFS
collect2: ld returned 1 exit status
I think I'm missing something very obvious, please help me :)
-lfoo looks for a library called libfoo.a (static) or libfoo.so (shared) in the current library path, so to create the library, you need to use g++ -shared -fPIC FileSystem.cpp -o libThinFS.so
You can use
g++ main.cpp -L. -l:ThinFS
The use of "colon" will use the library name as it is, rather requiring a prefix of "lib"
the name of the output file should be libThinFS.so, e.g.
g++ -shared -fPIC FileSystem.cpp -o libThinFS.so
The result of g++ -shared -fPIC FileSystem.cpp is not an object file, so it should not end with .o. Also, shared libraries should be named libXXX.so. Rename the library and it will work.
Check out this article.
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
A good resource on how to build different types of libraries. It also describes how and where to use them.