g++ link against static library does not work - c++

I have a simle file main.cpp and static library MyLib.lib and I am trying to link program against static library like this:
g++ -o m main.cpp -static -L c:\lib\path -l MyLib
or like this:
g++ -o m main.cpp -L c:\lib\path -Wl,-Bstatic -l MyLib -Wl,-Bdynamic
The compilation process exits successfully and without error. However when I try to run m.exe from command line I get error that it cannot be run because MyLib.dll cannot be found.
I specificaly said it should compile against static lib MyLib.lib so why is it searching for a dynamic library? Did I made an error in commands above?

It really looks like you linked with a shared library.
You need to add the location of the folder containing MyLib.dll to the PATH.
In a Command Prompt type this:
SET PATH=<dll_location>;%PATH%
m.exe
or make sure MyLib.dll is in the same folder as m.exe.
If gcc only finds a shared library there is a chance the static flags didn't work.
Why is your library not called libMyLib.a? The name MyLib.lib seems to imply you got it prebuilt from MSVC. If so, how do you know MyLib.lib is not a shared library?
Is there a way you can build MyLib yourself as a static library?

Related

How to link to shared object library in msys2?

I have some c++ code in msys2 that I am trying to link dynamically to show how a dynamic link library works.
In linux, showing the call is no problem. stepping in gdb, we can watch the call go through the jump vector, eventually landing in the desired function.
But in msys2, they wanted to eliminated dlls and all the libraries I can find are .dll.a, I think they are really static libraries.
I build a trivial little function like this:
#include <cstdint>
extern "C" {
uint64_t f(uint64_t a, uint64_t b) {
return a + b;
}
}
compiling in the makefile with:
g++ -g -fPIC -c lib1.cc
g++ -g -shared lib1.o -o libtest1.so
When I run the file utility, it says that:
libtest1.so: PE32+ executable (DLL) (console) x86-64, for MS Windows
When I compile the code using it:
g++ -g main.cc -ltest1 -o prog
The error is -ltest1 no such file or directory.
MinGW uses the .dll extension for shared libraries, not .so.
lib??.dll.a is an import library, a shim that will load the corresponding lib??.dll at runtime.
At some point in time, you couldn't link .dlls directly, and had to link .dll.as instead. The modern MinGW can link .dlls directly, so you shouldn't need to use import libraries anymore.
-ltest1 no such file or directory
Wouldn't you get the same error on Linux? You have to specify the library search path with -L. -ltest1 needs either libtest1.a or libtest1.dll.a or libtest1.dll (perhaps some other variants are checked too).
The reason your linker cannot find the library is because your current working directory is not in the search path for libraries. Add -L. to your linking command.
It is untrue that MSYS2 "wanted to eliminate DLLs". Just run ls /mingw64/bin/*.dll and you will see plenty of DLLs (assuming you have some MINGW64 packages installed). The .dll.a files used for linking are called import libraries.

How to link libraries with g++ compiler?

I'm trying to link a game library for my game project in C++. I am using the g++ compiler and Atom Code Editor. Also on a Windows machine.
To link the library it needs to link those things:
Include path
Library path
Additional dependencies
The main.cpp file is at ProjectRoot/src/main.cpp and the library is at ProjectRoot/deps/lib_name
Inside the library there is and include folder, with the .h file for including, and a lib folder, with the .lib file. It's a static linking library.
So far, I've tried the following commands:
g++ -o ExecutableName.exe -I /deps/lib_name/include -L /deps/lib_name/lib src/main.cpp
Well, that didn't work though... It said that there was no such file or directory as library_name.h...
I need to know if I'm doing anything wrong and also how to specify the additional dependencies.
Every thing is correct . You just forgot to link the libraries . Do it as follows -
g++ -o ExecutableName.exe -I /deps/lib_name/include -L /deps/lib_name/lib src/main -l[library name] -l[library name]

Can't make executable portable

I made a little c++ program with this library: http://libtins.github.io
I compile with: g++ -o arp arp.cpp -ltins
It runs fine (Ubuntu 14.04 64 bit), however if i send the executable to a friend, he gets this error when running:
error while loading shared libraries: libtins.so.3.4: cannot open shared object file: No such file or directory
I've looked up on stackoverflow and found something about statically linking and dynamically linking, also tried some g++ arguments but no success.
Is it even possible, to create a binary that "contains" the shared object itself?
Thanks
You can use -static to link the libraries statically.
g++ -o arp arp.cc -ltins -static
To build libtins statically, you could refer to the following section in its README:
Static/shared build
Note that by default, only the shared object is compiled. If you would
like to generate a static library file, run:
cmake ../ -DLIBTINS_BUILD_SHARED=0

Linking to a static library with a makefile and g++

I want to link my C++ executable to both a static (libStatic.a) and a shared (libShared.so) library, using a makefile.
The makefile so far has the following content:
myExe: main.cpp libStatic.a libShared.so
g++ main.cpp libStatic.a libShared.so
I'm fairly sure that the static linking is correct, as I have seen similar things elsewhere. What I am unsure of is the shared linking part. Is this correct? Or is linking to a static library done differently?
If I run make, then it seems to be ok, and creates the executable. However, when I execute this, I reveive the error:
/usr/bin/ld: cannot find -lShared
However, my executable and libShared.so are in the same directory.
You need to set LD_LIBARY_PATH to this directory where the shared object is sitting before you run your program.
You can read up on 'rpath' in man ld for other possibilities.

Makefile - cannot find shared library

I have a Makefile for a c++ Linux project:
MODE ?= dbg
DIR = ../../../../../somdir/$(MODE)
SRC_FILES = a.cpp b.cpp
H_FILES = a.h
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
CPPFLAGS = -I$(DIR)/include
LIBRARIES = -lsomeso
ifeq (rel, $(MODE))
CFLAGS = -Wall -g -DNDEBUG
else
CFLAGS = -Wall -ansi -pedantic -Wconversion -g -DDEBUG -D_DEBUG
endif
sample: $(SRC_FILES) $(H_FILES) Makefile
g++ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LIBRARIES) $(SRC_FILES) -o sample
when i run 'make' it builds the project, with no errors.
but when i run the project it complains that:
error while loading shared libraries: libsomeso.so: cannot open shared object file: No such file or directory
The path that i give in DIR goes to the folder where the shared object is held(relatively to where the makefile is placed), and if it was the wrong path why didn't it complain during the make process.
does someone know what am i missing?
Thanks
Matt
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
The above should be:
LDFLAGS += -L$(DIR)/lib/linux -Wl,-R$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
That is, for each non-standard dynamic library location -L a corresponding -Wl,-R should be specified. $ORIGIN is needed to locate dynamic libraries relative to the executable, not sure if you need it here.
People often advise using LD_LIBRARY_PATH. This is a bad advice, in my opinion, because it makes deployment more complicated.
When you run your application, location of libsomeso.so should be in LD_LIBRARY_PATH environment variable. Try running program like this:
LD_LIBRARY_PATH="path_to_libsomeso_so:$LD_LIBRARY_PATH" myprogram
Here path_to_libsomeso_so is full path to a directory where libsomeso.so is located, and myprogram is your program executable. Note, that you should specify path to a directory containing libsomeso.so, not to libsomeso.so file itself.
The trouble is not during compilation time. Everything goes fine. There's a problem at runtime.
Indeed, your program has been linked with a shared object library. Therefore, at runtime, it need to load this shared object file. During compilation, you instructs the compiler where this file was with the -L flag.
For the runtime, you have to set the LD_LIBRARY_PATH environment variable to point to the directory where your libsomeso.so file resides.
Alternatively, you can place this file in one of the standard directory where these shared object files are searched for: /usr/local/lib, /usr/lib, /lib, but this should be what you'll do for the final distributed version of your library.
As told from Maxim Egorushkin, LD_LIBRARY_PATH is a bad choice. Meanwhile, using -L$(your lib path) -l$(your lib name) gcc/g++ argument to link shared library isn't a good choice. Because, after build the exe, you should told exe where the shared library directory is. By default, executable file only search shared library at /usr/lib or /usr/local/lib. Although, you have told makefile where the shared library is when build the executable file. But when you execute this exe file, they are different.
However, link static library don't have such problem.
So, the best way to deal with your problem is change the way you link your custom shared file. Like this:
DYNAMIC_LIB_DIR = ../lib (your lib path ,this is a example)
OBJLIBS = xxx.so (your lib name)
gcc/g++ -o exe_name sourcefile/object_file $(DYNAMIC_LIB_DIR)/$(OBJLIBS)
Refresh that dynamic library cache!
After adding a custom, non-standard library to /usr/local/lib, first check that /usr/local/lib is listed under /etc/ld.so.conf.d/libc.conf.
Then, finish off with a dynamic link library cache refresh:
$ sudo ldconfig