Compiling with g++ and having GraphicsMagick++ as static library - c++

The following command works
g++ file.cpp $( GraphicsMagick++-config --cppflags --cxxflags --ldflags --libs )
but i want a static executable that is not linked to the library, so i have tried
g++ file.cpp $( GraphicsMagick++-config --cppflags --cxxflags --ldflags --libs ) -static
but it only generates the following errors
/usr/bin/ld.bfd.real: /usr/lib/gcc/x86_64-linux-gnu/4.6/crtbeginT.o: relocation R_X86_64_32 against `__DTOR_END__' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/4.6/crtbeginT.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
adding -fPIC gives the same result.
I'm using the GraphicsMagick++ version that comes with the standard repository in Ubuntu 12.04 64 bit.
Since GraphicsMagick++ is a fork of ImageMagick some old trick for ImageMagick will probably work but i have never used ImageMagick, only GraphicsMagick++.

To link statically against that particular library, use -Wl,-Bstatic before it, i.e.:
g++ $( GraphicsMagick++-config --cppflags --cxxflags ) -fPIC file.cpp -o file -Wl,-Bstatic $( GraphicsMagick++-config --ldflags --libs )
If you then wanted to pass more libraries, and link dynamically against them, you can pass -Wl,-Bdynamic to switch back and add more libraries afterwards.
Edit: Also note the specific argument order. First compiler flags, then file, then linker flags and libraries at the end. With other order, you can run into random failures. Really.

Related

how to link specific version of shared library in g++

I have the following shared libraries:
libssl.so, libssl.so.1.1, libcurl.so, libcurl.so.4, libcurl.so.4.4.0, libcrypto.so, libcrypto.so.1.1.
All of the libraries are in the openssl folder.
My question is, how can I link version 1.1 of libssl? Is it done automatically?
I've tried the following:
g++ -c my_file_name.cpp -std=c++11 -w -fpermissive -lpthread --coverage $(INCLUDES) `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0` -O0 -Lopenssl -lcrypto -lcurl -lssl
g++ my_file_name.o -o ex -std=c++11 -w -fpermissive -lpthread --coverage -lgtest -lgtest_main -lpthread `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0` -O0 -Lopenssl -lcrypto -lcurl -lssl
But it seems that the link doesn't happen. As I still get errors like:
error: ‘X509_STORE_CTX_get0_chain’ was not declared in this scope
Later edit
nm libssl.so.1.1 | grep X509_STORE_CTX_get0_chain results in 0000000000218210 T X509_STORE_CTX_get0_chain. That would mean that the link that I've done does not happen.
It's worth mentioning that the error comes from a .c file included in the .cpp file.
Probably the libssl.so is a symbolic link to libssl.so.1.1 etc. etc.
The problem seems to be related to the missing implementation in one of these library of this function :X509_STORE_CTX_get0_chain.
Now you have to check if this symbol is defined in one of these library you link, or if you need to link someone else.
To check this you can execute the following command over each library:
nm libToCheck.so | grep X509_STORE_CTX_get0_chain
if no one have this symbol defined maybe you missing some library to link.
If exist, check the scope of the utilizzation of the function, it could not correspond to the scope declared in the library. Check the namespace or similar.

Can't link GLFW library with it's header file on Ubuntu 18.04

I've installed the libglfw3-dev:amd64 package on Ubuntu using the standard sudo apt get etc. My following compiling line is:
g++ -o output -IL/usr/lib/x86_64-linux-gnu -lglfw driver.o
My current c++ file is:
#include <GLFW/glfw3.h>
int main(void)
{
GLFWwindow* window;
if (!glfwInit())
return -1;
}
I've tried using local libraries of glfw and setting the -I and -L locations but nothing has seemed to work. I've made sure the .so and .h files are in their respective locations but I always get this error while running make:
g++ -o output -I/usr/include/GLFW -L/usr/lib/x86_64-linux-gnu -lglfw
driver.o
driver.o: In function `main':
driver.cpp:(.text+0x5): undefined reference to `glfwInit'
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'output' failed
make: *** [output] Error 1
I've tried looking at all the other SO posts and they recommend compiling with tons of extra flags, but the only thing I've been able to draw from them is that something is wrong with my library since VScode detects the .h files. How can I compile this without any errors?
Have you tried swapping the linker arguments around? That is, compile with
g++ -o output driver.o -lglfw
The linker goes through the files from left to right, and it has to know which symbols from libraries you need, before the libraries are processed.
All is perfectly explained in the manual https://www.glfw.org/docs/latest/build_guide.html#build_link_pkgconfig
The key problem is in your -I/usr/include/GLFW and #include <GLFW/glfw3.h> that gives in sum the path /usr/include/GLFW/GLFW/glfw3.h. I suppose this is a wrong path to glfw3.h. compilation was successful because of the system default include path -I/usr/include.
Do not tune compiler flags manually, let pkg-config do
it for you.
A typical compile and link command-line when using the static version of the GLFW library may look like this:
g++ -o output `pkg-config --cflags glfw3` yourprog.c `pkg-config --static --libs glfw3`
If you are using the shared version of the GLFW library, simply omit the --static flag.
g++ -o output `pkg-config --cflags glfw3` yourprog.c `pkg-config --libs glfw3`

Static compilation fails: dynamic STT_GNU_IFUNC symbol `tan' .. can not be used when making an executable

I'm trying to compile expect statically on my PC, but I seem to run into some strange compiling errors.
I was able to compile tcl statically like this:
./configure --disable-load --disable-shared
Then add to the makefile CFLAGS variable -static keyword. Now after compiling I seem to have a static tcl, and a library:
-rw-rw-r-- 1 jlumme jlumme 3284332 loka 2 11:27 libtcl8.6.a
After this, I configure expect:
./configure --with-tclconfig=${TCL_DIR}/unix --disable-shared --disable-load
And then compile (first dynamic):
$ gcc -pipe -O2 -fomit-frame-pointer -Wall -Wl,--export-dynamic -o expect exp_main_exp.o -L/home/jlumme/Downloads/compile/expect5.45 -lexpect5.45 -L/home/jlumme/Downloads/compile/tcl8.6.4/unix -ltcl8.6 -lieee -lm -lpthread -lz
The result looks ok:
$ file expect
expect: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=a613c260944117f43bcaebc43c51c421dce273a7, not stripped
But now if I want to attempt a static compilation, I get errors that I dont understand:
gcc -pipe -O2 -fomit-frame-pointer -Wall -Wl,--export-dynamic -o expect exp_main_exp.o -L/home/jlumme/Downloads/compile/expect5.45 -lexpect5.45 -L/home/jlumme/Downloads/compile/tcl8.6.4/unix -ltcl8.6 -lieee -lm -lpthread -lz -static
/home/jlumme/Downloads/compile/tcl8.6.4/unix/libtcl8.6.a(tclUnixCompat.o): In function `TclpGetGrGid':
tclUnixCompat.c:(.text+0x41c): warning: Using 'getgrgid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/home/jlumme/Downloads/compile/tcl8.6.4/unix/libtcl8.6.a(tclUnixCompat.o): In function `TclpGetGrNam':
tclUnixCompat.c:(.text+0x31c): warning: Using 'getgrnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
<HANDFUL OF WARNINGS REMOVED>
/usr/bin/ld: dynamic STT_GNU_IFUNC symbol `tan' with pointer equality in `/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libm.a(s_tan.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
I dont really understand what this final linking problem is, can someone help ?

Link error with my own C++ library

This is my first time trying to make a simple library. I worked in Ubuntu 12.04 with g++ 4.6.3. Here is the problem:
[[mylib.cpp]]
#include<sqlite3.h>
void Mylib::blahblah() {...}
void Mylib::evenmoreblah() {...}
...
[[mylib.h]]
#include <...>
class Mylib {
...
};
Then I made the lib by:
gcc -c -Wall -fpic mylib.cpp
gcc -shared -o libmylib.so mylib.o
I used the library in a single test.cpp which contains only the main(). I put libmylib.so in ./libdir, and compiled by using:
g++ -g test.cpp -o test -lpthread -L/usr/local/lib -lsqlite3 -L./libdir -lmylib
The error I got:
./libdir/libmylib.so: undefined reference to `sqlite3_close'
./libdir/libmylib.so: undefined reference to `sqlite3_exec'
./libdir/libmylib.so: undefined reference to `sqlite3_free'
./libdir/libmylib.so: undefined reference to `sqlite3_open'
You could link -lsqlite3 into your shared library with
gcc -shared mylib.o -o libmylib.so -lsqlite3
If you do that, you don't need to explicitly link -lsqlite3 to your program, but that won't harm.
and the order of linking arguments for your program is important:
g++ -Wall -g test.cpp -o mytest \
-L./libdir -lmylib -L/usr/local/lib -lsqlite3 -lpthread
it should go from higher-level libraries to lower-level (i.e. system) ones. And don't forget -Wall to get almost all warnings from the compiler, which is very useful.
Read the Program Library HowTo.
PS. Don't call your program test which is a shell builtin (and the standard /usr/bin/test). Use some other name.
If your library make references to sqlite3, you should link sqlite after linking your library :
g++ -g test.cpp -o test -lpthread -L/usr/local/lib -L./libdir -lmylib -lsqlite3
Otherwise ld won't find anything useful in libsqlite3 before linking your library and won't be able to find the requested symbols after that.
Since your library uses sqlite3, you need to add that AFTER your own library in the linker command. I think you could add it to the linking of your shared library too, but not certain.
The linker resolves libraries and their references in the order you list them, so the order is important.

GCC linker error while compiling a static library

I want to create a static library of all my files so that i could give my mylib.a file to others to execute on their system. I use opencv library in my code. I used the following command to compile my code.
g++ index.cpp -o display1 -Wl,-Bdynamic pkg-config --cflags --libs opencv -lglut -lGL -lGLU -Wl,-Bstatic mylib.a
But it is giving the following error.
/usr/bin/ld: cannot find -lgcc_s
collect2: ld returned 1 exit status
I believe the Kerrek SB is right in the comment. The command should be
g++ index.cpp -o display1 mylib.a $(pkg-config --cflags --libs opencv) -lglut -lGL -lGLU
Explanation:
The -Wl,-Bdynamic and -Wl,-Bstatic flags are useless. The linker automatically picks static or dynamic library depending on what it finds. If you give it path to a library (as you do with mylib.a) it can't choose and will link the library you provided. If you give it an -lX flag, it will look for libX.so or libX.a and link whichever it finds, but most Linux installations won't have static variants of system libraries, so there is nothing to choose from either.
It's worse, the -Wl,-Bdynamic and -Wl,-Bstatic are wrong. -Wl,-Bstatic prohibits linking of shared libraries. That has the side-effect of selecting static libgcc, which implicitly comes last on the linker command line. And you don't seem to have that installed. Most Linux systems don't.
Each object must be listed on the command-line before the libraries it refers to. I would expect mylib.a contains functions that need opencv or opengl, so it must be listed before those -l flags.