I just have a simple structure:
main.cpp
#include <iostream>
#include "../header_files/h.h"
int main(void)
{
f();
g();
}
src1.cpp
#include <iostream>
void f() { std::cout << "f()" << std::endl; };
void g() { std::cout << "g()" << std::endl; };
h.h
void f(); void g();
I am trying to (only) compile main.cpp and src1.cpp with:
PS> g++ -c main.cpp src.cpp
Then get an executable from the created .obj files:
PS> g++ main.o src.o -o exec.exe
.\ss.o:ss.cpp:(.text+0x17): undefined reference to std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
\ss.o:ss.cpp:(.text+0x26): undefined reference to std::ostream::operator<<(std::ostream& (*)(std::ostream&))
\ss.o:ss.cpp:(.text+0x41): undefined reference to std::ios_base::Init::~Init()
\ss.o:ss.cpp:(.text+0x71): undefined reference to std::ios_base::Init::Init()
Here I am getting a verbose linker error; that's because I am using iostream library; I just need to tell g++ how to link to this library or any other standard library I want to use. How I can do that?
Actually I can use g++ main.cpp src1.cpp -o test, or using any IDE, but I do not need to do this. Just need a way to tell g++ (maybe via command-line args) how to go to the actual definitions. I need to produce the .exe file from the generated obj files, not something else.
Windows: x64
g++ -ver: x86_64-8.1.0-posix-seh-rt_v6-rev0 (mingw64)
Not using any IDEs
Related
I'm learning the use of std::thread, I used to think std::thread is a completely different threading library independent of pthread , I use the following code to test:
void run(void) {
std::cout << "Hello World" <<endl;
}
int main(void) {
std::thread t(run);
t.join();
}
I thought it could be compiled directly via:
$ g++ main.cpp -o main
But it tells me that the "pthread_create" function is not defined:
/usr/bin/ld: /tmp/ccZpJ3EI.o: in function `std::thread::thread<void (&)(), , void>(void (&)())':
main.cpp:(.text._ZNSt6threadC2IRFvvEJEvEEOT_DpOT0_[_ZNSt6threadC5IRFvvEJEvEEOT_DpOT0_]+0x2f): undefined reference to `pthread_create'
collect2: error:ld return 1
I have to add the link for pthread:
$ g++ main.cpp -o main -lpthread
My OS is archlinux/manjaro, the C++ standard version is C++ 17.
Do I also need to link pthreads if I'm on another OS?
I have created 2 object files hello.o and hi.o, each containing a function with the same name, respectively. Also, greetings.h was created containing the function prototypes of the two object files.
When I link these two object files with main.o in any order, the process succeeds and I get a.out. But if you make a static library from the hello.o and hi.o files, then the linking succeeds only in the order g++ main.o glib.a.
As I understand it, the order should be from the file that declares to the file that contains the definition, but when linking object files alone, it doesn't work. What is the difference between linking a library and object files, and only object files?
Example:
Source code:
greetings.hpp
#ifndef GREETINGS_HPP
#define GREETINGS_HPP
void hello();
void hi();
#endif
hello.cpp
#include <iostream>
void hello() {
std::cout << "Hello!" << std::endl;
}
hi.cpp
#include <iostream>
void hi() {
std::cout << "Hi!" << std::endl;
}
main.cpp
#include "greetings.hpp"
int main () {
hello();
hi();
return 0;
}
Actions:
ar -src glib.a hello.o hi.o
g++ glib.a main.o
Error:
main.o: In function `main':
main.cpp:(.text+0x5): undefined reference to `hello()'
main.cpp:(.text+0xa): undefined reference to `hi()'
collect2: error: ld returned 1 exit status
I have doubt is it possible if I built lib1.so using source file common.cppand lib2.so using same source file common.cpp again. Now I want to build my application APP using this two library ,
My question are
is it possible Or it will give me error ?
If it will successfully built then how naming gets resolved?
F.e. let say foo is class in common.cpp. foo_v1 is object of foo in lib1.so and foo_v2 is object of foo in lib2.so. Now during bulid of APP what would happen? Also is it possible to create object of foo in APP application ?
Naturally one would suggest you consider building the common functionality shared
by lib1.so and lib2.so into a distinct shared library, libcommon.so.
But if you want nevertheless to statically link the common functionality
identically1
into both lib1.so and lib2.so, you can link these two shared libraries with
your program. The linker will have no problem with that. Here is an
illustration:
common.h
#ifndef COMMON_H
#define COMMON_H
#include <string>
struct common
{
void print1(std::string const & s) const;
void print2(std::string const & s) const;
static unsigned count;
};
common.cpp
#include <iostream>
#include "common.h"
unsigned common::count = 0;
void common::print1(std::string const & s) const
{
std::cout << s << ". (count = " << count++ << ")" << std::endl;
}
void common::print2(std::string const & s) const
{
std::cout << s << ". (count = " << count++ << ")" << std::endl;
}
foo.h
#ifndef FOO_H
#define FOO_H
#include "common.h"
struct foo
{
void i_am() const;
private:
common _c;
};
#endif
foo.cpp
#include "foo.h"
void foo::i_am() const
{
_c.print1(__PRETTY_FUNCTION__);
}
bar.h
#ifndef BAR_H
#define BAR_H
#include "common.h"
struct bar
{
void i_am() const;
private:
common _c;
};
#endif
bar.cpp
#include "bar.h"
void bar::i_am() const
{
_c.print2(__PRETTY_FUNCTION__);
}
Now we'll make two shared libraries, libfoo.so and libbar.so. The
source files we need are foo.cpp, bar.cpp and common.cpp. First
compile them all to PIC (Position Independent Code
object files:
$ g++ -Wall -Wextra -fPIC -c foo.cpp bar.cpp common.cpp
And here are the object files we just made:
$ ls *.o
bar.o common.o foo.o
Now link libfoo.so using foo.o and common.o:
$ g++ -shared -o libfoo.so foo.o common.o
Then link libbar.so using bar.o and (again) common.o
$ g++ -shared -o libbar.so bar.o common.o
We can see that common::... symbols are defined and exported by libfoo.so:
$ nm -DC libfoo.so | grep common
0000000000202094 B common::count
0000000000000e7e T common::print1(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
0000000000000efa T common::print2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
(T means defined in the code section, B means defined in the uinitialized data section). And exactly the same is true about libbar.so
$ nm -DC libbar.so | grep common
0000000000202094 B common::count
0000000000000e7e T common::print1(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
0000000000000efa T common::print2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
Now we'll make a program linked with these libraries:
main.cpp
#include "foo.h"
#include "bar.h"
int main()
{
foo f;
bar b;
common c;
f.i_am();
b.i_am();
c.print1(__PRETTY_FUNCTION__);
return 0;
}
It calls foo; it calls bar,
and it calls common::print1.
$ g++ -Wall -Wextra -c main.cpp
$ g++ -o prog main.o -L. -lfoo -lbar -Wl,-rpath=$PWD
It runs like:
$ ./prog
void foo::i_am() const. (count = 0)
void bar::i_am() const. (count = 1)
int main(). (count = 2)
Which is just fine. You might perhaps have worried that two copies of the static class variable
common::count would end up in the program - one from libfoo.so and another from libbar.so,
and that foo would increment one copy and bar would increment the other. But that didn't happen.
How did the linker resolve the common::... symbols? Well to see that we need to find their mangled forms,
as the linker sees them:
$ nm common.o | grep common
0000000000000140 t _GLOBAL__sub_I_common.cpp
0000000000000000 B _ZN6common5countE
0000000000000000 T _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
000000000000007c T _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
There they all are and we can tell which one is which with c++filt:
$ c++filt _ZN6common5countE
common::count
$ c++filt _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
common::print1(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
$ c++filt _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
common::print2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
Now we can re-do the linkage of prog, this time asking the linker to tell us the names of the
input files in which these common::... symbols were defined or referenced. This diagnostic
linkage is a bit of a mouthful, so I'll \-split it:
$ g++ -o prog main.o -L. -lfoo -lbar -Wl,-rpath=$PWD \
-Wl,-trace-symbol=_ZN6common5countE \
-Wl,-trace-symbol=_ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE \
-Wl,-trace-symbol=_ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
main.o: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: definition of _ZN6common5countE
./libfoo.so: definition of _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: definition of _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: reference to _ZN6common5countE
./libbar.so: reference to _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
So the linker tells us that it linked the definition of common::count from ./libfoo.so. Likewise the
definition of common::print1. Likewise the definition of common::print2. It linked all the
common::... symbol definitions from libfoo.so.
It tells us that the reference(s) to common::print1 in main.o was resolved to the definition in libfoo.so. Likewise
the reference(s) to common::count in libbar.so. Likewise the reference(s) to common::print1 and
common::print2 in libbar.so. All the common::... symbol references in the program were resolved to the
definitions provided by libfoo.so.
So there were no multiple definition errors, and there is no uncertainty about which "copies" or "versions" of the common::... symbols are used
by the program: it just uses the definitions from libfoo.so.
Why? Simply because libfoo.so was the first library in the linkage that provided definitions
for the common::...symbols. If we relink prog with the order of -lfoo and -lbar reversed:
$ g++ -o prog main.o -L. -lbar -lfoo -Wl,-rpath=$PWD \
-Wl,-trace-symbol=_ZN6common5countE \
-Wl,-trace-symbol=_ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE \
-Wl,-trace-symbol=_ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
main.o: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: definition of _ZN6common5countE
./libbar.so: definition of _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: definition of _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: reference to _ZN6common5countE
./libfoo.so: reference to _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
then we get exactly the opposite answers. All the common::... symbol references in the program
are now resolved to the definitions provided by libbar.so. Because libbar.so provided them first.
There is still no uncertainty, and it makes no difference to the program, because both libfoo.so
and libbar.so linked the common::... definitions from the same object file, common.o.
The linker does not try to find multiple definitions of symbols. Once it has found a
definition of a symbol S, in an input object file or shared library, it binds references to
S to the definition it has found and is done with resolving S. It does
not care if a shared library it finds later can provide another definition of S, the same or different,
even if that later shared library resolves symbols other than S.
The only way in which you can cause a multiple definition error is by compelling the linker
to statically link multiple definitions, i.e. compel it to physically merge into the output binary
two object files obj1.o and obj2.o both of which contain a definition S.
If you do that, the competing static definitions have exactly the same status, and only
one definition can be used by the program, so the linker has to fail you. But it does not need to take any notice of a
dynamic symbol definition of S provided by a shared library if it has already resolved S, and it does not do so.
[1] Of course, if you compile and link lib1 and lib2 with different preprocessor, compiler or linkage options, you can sabotage the "common" functionality to an arbitary extent.
This question already has answers here:
How to mix C++ and C correctly
(2 answers)
Closed 4 years ago.
I'm trying to write a C++ library that can be called from C. However, whenever I try to even write a bare minimum example, it crashes with undefined references. Here is my code:
mylibrary.h
#ifndef __MY_CPP_THING_H
#define __MY_CPP_THING_H
#ifdef __cplusplus
extern "C" {
#endif
void printSomething();
#ifdef __cplusplus
}
#endif
#endif
mylibrary.cpp
#include <iostream>
#include "mylibrary.h"
extern "C" {
void printSomething() {
std::cout << "PLEASE PRINT\n";
}
}
main.c
#include "mylibrary.h"
int main() {
printSomething();
return 0;
}
The compiling process goes something like this:
g++ -c mylibrary.cpp -o mylibrary.o (create "mylibrary.o")
ar rcs libmylibrary.a mylibrary.o (create static library "libmylibrary.a")
gcc main.c -L. -lmylibrary (link static library and compile C source file)
However, I receive this error dump:
mylibrary.o:mylibrary.cpp:(.text+0x17): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
mylibrary.o:mylibrary.cpp:(.text+0x32): undefined reference to `std::ios_base::Init::~Init()'
mylibrary.o:mylibrary.cpp:(.text+0x62): undefined reference to `std::ios_base::Init::Init()'
mylibrary.o:mylibrary.cpp:(.rdata$.refptr._ZSt4cout[.refptr._ZSt4cout]+0x0): undefined reference to `std::cout'
collect2.exe: error: ld returned 1 exit status
Any suggestions on how to resolve the error?
mylibrary.o still depends on C++ standard library and gcc doesn't know about it. Call gcc with -lstdc++ in the last step.
Creating a dynamic library instead of a static library should do the trick :
$ gcc -c main.c
$ g++ -fPIC -shared -o mylibrary.so mylibrary.cpp
$ gcc -o main main.o mylibrary.so
and then :
$ LD_LIBRARY_PATH=".:${LD_LIBRARY_PATH}" ./main
PLEASE PRINT
with :
$ objdump -p main | grep NEEDED
NEEDED mylibrary.so
NEEDED libc.so.6
$ objdump -p mylibrary.so | grep NEEDED
NEEDED libstdc++.so.6
NEEDED libc.so.6
To try the C++ code wrapping within C, I used the following:
header.h
#ifdef __cplusplus
extern "C"
#endif
void func();
source.cpp
#include "header.h"
#include <iostream>
extern "C" void func()
{
std::cout << "This is C++ code!" << std::endl;
}
and source.c
#include "header.h"
int main()
{
func();
}
To compile and link, I used the following sequence:
g++ -c source.cpp
gcc source.c source.o -o myprog
The error I get is:
ence to std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
source.cpp:(.text+0x1c): undefined reference tostd::basic_ostream >::operator<<(std::basic_ostream >& (*)(std::basic_ostream >&))'
source.o: In function __static_initialization_and_destruction_0(int, int)':
source.cpp:(.text+0x45): undefined reference tostd::ios_base::Init::Init()'
source.cpp:(.text+0x4a): undefined reference to std::ios_base::Init::~Init()'
source.o:(.eh_frame+0x12): undefined reference to__gxx_personality_v0'
collect2: ld returned 1 exit status
How can I make this simple code compile and run? It should serve as a basis for my future
development.
Link with g++ as well:
g++ -c source.cpp
g++ source.c source.o -o myprog
Or better:
g++ -c source.cpp -o source_cpp.o
gcc -c source.c -o source_c.o
g++ -o myprog source_cpp.o source_c.o
Best to avoid the common prefix source.{cpp,c} as it causes confusion.
You'll still have to link with the C++ linker:
gcc -o source-c.o source.c
g++ -o source-p.o source.cpp
g++ -o myprog source-c.o source-p.o
Your C++ object file will need to resolve symbols from the C++ library, which only the C++ linker will pull in automatically. (Alternatively, you could specify the library manually for the C linker.)
you can't do that, you can compile C code with gcc, and then link it with c++ objects with g++, referring to the symbols defined in the C objects via the extern keyword, but you can't do the opposite