I'm trying to build a self contained executable, which I can run on any/most linux host.
I know I can do that with containers, but for now I'm trying to just statically link my exe.
I compile with:
g++ -std=c++1y -fopenmp -Ofast -g -march=x86-64 -mtune=generic -m64 -c <source>.cpp -MMD -MP -o <object>.o
And link with:
g++ -std=c++1y -fopenmp -Ofast -g -march=x86-64 -mtune=generic -m64 <list of object files> <list of absolute path to static libs .a> -lpthread -static-libgcc -static-libstdc++ -o exe
It used to work just fine, but I just discovered it now breaks on some hosts with
error while loading shared libraries: libmvec.so.1: cannot open shared object file: No such file or directory
I don't know if it's something in the code or system libraries update. I have tried (to no avail):
removing -fopenmp
adding -lmvec -lm to the linker
My exe is indeed statically linked: ldd exe says not a dynamic executable. But it insists on loading libmvec.so at runtime: strace exe says:
execv
a bunch of mmap
open(ld-linux-x86-64.so), read it and close it
open(ld.so.cache), stat, mmap, and close it
open(libpthread.so), read, stat, mmap and close it
open(libmvec.so) => fail on hosts where it doesn't exist
[...]
As I understand libmvec is an extension of libm, dealing with x86 vectorization, used by OpenMP.
So basically, I'm asking if there is a way to make it work statically - I see at least 3 solutions:
disable its use - but that would probably mean performance loss, plus it is used even when I disable OpenMP
statically link it, and somehow explain to the runtime that it then doesn't have to dynamically link to it since it's already linked.
make it optional, i.e. dynamically select a slower code path if it's not available. This sounds complex but could in theory be possible.
Related
Is it possible to link all libraries (from the command line) in a single command? Such as gathering them in a file and supplying the file?
You can use a script or a directly link via single command in the command line such as:
g++ -Wall -Wextra -std=c++17 hello_world.cpp -o hello_world
# Linking many libs
g++ -Wall -Wextra -std=c++17 hello_world.cpp -o hello_world -llib1 -llib2 -llib3
However, as your project grows in size with more source files, multiple sub-directories, linking with many system libraries, third party libraries, with dependencies between libraries and so on, the "command line" is impractical.
A makefile is the way forward (you can also look at cmake too) for managing complexities. Even for trivial projects, a makefile is still useful (rather running a lengthy command line every time).
I am creating a gcc shared library having a static library dependency.
I compile the parts for static library as following:
gcc -c -m64 -O2 -fPIC -std=c99 -Wall ms*.c //there are 10 C files, no warnings
Next I create a static library with:
ar rc static_lib.a ms*.o
Next I compile the parts for my program as following:
g++ -c -m64 -O2 -fPIC -std=c++14 -Wall ab*.cpp //there are 5 C++ files, just -Wunused-variable warnings
Then I create a shared library as following:
g++ -shared -g -Wall ab*.o static_lib.a -o shared_lib.so
in the normal case, this shared_lib.so will be called by a Ruby program using a foreign function interface. There is no problem if I do it on ubuntu or mac(.dylib), but if I try this on debian stretch I get an error related to the static library as if the configurations are not set properly. If I run the application without foreign function interface, such as creating a tester and running with the cpp file main function as following:
> g++ -o library_test ab*.o static_lib.a
> ./library_test
There is no problem!
My question is what kind of configuration for creating a shared library may be missing here to not get that undesirable behaviour. Especially on debian stretch 9.5!
Or is there a way that I can understand if there is a problem in the shared library.
From the comments, you indicate the problem is with a #define. Those are preprocessor directives. Libraries are for the linker.
You might be confused because g++ does include the preprocessor phase, and might call the linker depending on the requested output. Still, g++ follows the C++ language rules.
I am using mingw 64 bit with cygwin.
I know that if I compile using
x86_64-w64-mingw32-g++.exe -std=c++11 hello.cpp
the output .exe does not run unless the library path to libstdc++ and other libraries is specified in the Path environment variable.
An alternative is to link statically
x86_64-w64-mingw32-g++.exe -std=c++11 hello.cpp -static-libgcc -Wl,-Bstatic -lstdc++ -lpthread
Since I want a single .exe that I can easily copy on different machines, the second solution is better for me. My only problem is that, since I link statically, even for a simple helloworld program, the size of the executable rises to more than 10 Mb. So my question is: is it possible to link statically only the library parts that are actually used by the program?
The binutils linker on Windows, ld, does not support the --gc-sections argument properly, which in combination with compiler flags -ffunction-sections and -fdata-sections, allow the linker to throw away blocks of unused code.
You are straight out of luck. The only thing you can do is the usual: strip the executable (by running the strip command on it after it is linked) and compile your code optimising for size with -Os.
Keeping in mind these options do not work on Windows (which for the purpose of this answer, includes the Cygwin platform), this is generally how you can do this:
g++ -c -Os -ffunction-sections -fdata-sections some_file.cpp -o some_file.o
g++ -c -Os -ffunction-sections -fdata-sections main.cpp -o main.o
g++ -Wl,--gc-sections main.o some_file.p -o my_executable
I'm trying to compile this source code from the makefile in a VPS, but its not working. The VPS is a 64 Cent OS
Here's the full error
# make
gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c
g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp
g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp
g++ -O2 -fshort-wchar -shared -o "TCP_V1.so" *.o
/usr/bin/ld: TCP-LINUX_V1.o: relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object; recompile with -fPIC
TCP-LINUX_V1.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [all] Error 1
Here's my makefile:
GPP=g++
GCC=gcc
OUTFILE="TCP_V1.so"
COMPILE_FLAGS=-c -O3 -w -DLINUX -I../SDK/amx/
all:
$(GCC) $(COMPILE_FLAGS) ../SDK/amx/*.c
$(GPP) $(COMPILE_FLAGS) ../SDK/*.cpp
$(GPP) $(COMPILE_FLAGS) *.cpp
$(GPP) -O2 -fshort-wchar -shared -o $(OUTFILE) *.o
Anyone know what's wrong?
Do what the compiler tells you to do, i.e. recompile with -fPIC. To learn what does this flag do and why you need it in this case, see Code Generation Options of the GCC manual.
In brief, the term position independent code (PIC) refers to the generated machine code which is memory address agnostic, i.e. does not make any assumptions about where it was loaded into RAM. Only position independent code is supposed to be included into shared objects (SO) as they should have an ability to dynamically change their location in RAM.
Finally, you can read about it on Wikipedia too.
In my case this error occurred because a make command was expecting to fetch shared libraries (*.so files) from a remote directory indicated by a LDFLAGS environment variable. In a mistake, only static libraries were available there (*.la or *.a files).
Hence, my problem did not reside with the program I was compiling but with the remote libraries it was trying to fetch.
So, I did not need to add any flag (say, -fPIC) to the compilation interrupted by the relocation error.
Rather, I recompiled the remote library so that the shared objects were available.
Basically, it's been a file-not-found error in disguise.
In my case I had to remove a misplaced --disable-shared switch in the configure invocation for the requisite program, since shared and static libraries were both built as default.
I noticed that most programs build both types of libraries at the same time, so mine is probably a corner case. In general, it may be the case that you rather have to enable shared libraries, depending on defaults.
To inspect your particular situation with compile switches and defaults, I would read out the summary that shows up with ./configure --help | less, typically in the section Optional Features. I often found that this reading is more reliable than installation guides that are not updated while dependency programs evolve.
Fixed it with -no-pie option in linker stage:
g++-8 -L"/home/pedro/workspace/project/lib" -no-pie ...
It is not always about the compilation flags, I have the same error on gentoo when using distcc.
The reason is that on distcc server is using a not-hardened profile and on client the profile is hardened. Check this discussion:
https://forums.gentoo.org/viewtopic-p-7463994.html
Simply cleaning the project solved it for me.
My project is a C++ application (not a shared library). I randomly got this error after a lot of successful builds.
I had the same problem. Try recompiling using -fPIC flag.
I'm getting the same solution as #camino's comment on https://stackoverflow.com/a/19365454/10593190 and XavierStuvw's reply.
I got it to work (for installing ffmpeg) by simply reinstalling the whole thing from the beginning with all instances of $ ./configure replaced by $ ./configure --enable-shared (first make sure to delete all the folders and files including the .so files from the previous attempt).
Apparently this works because https://stackoverflow.com/a/13812368/10593190.
We had the same problem. It turned out to be a mix-up in a Makefile. The error occurred when the linker was gcc, but the C++ compiler clang++. Changing the linker to clang++ fixed it.
by accidentally, I linked with --shared flag with a hello world c++ program and got an exe file. but output is segfault when I run it. Can someone tell me the reason behind it?
way to reproduce:
standard c++ hello world problem in eclipse c++.
check the shared flag box in setting--> shared library setting.
build output:
make all
Building file: ../app.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"app.d" -MT"app.d" -o "app.o" "../app.cpp"
Finished building: ../app.cpp
Building target: app
Invoking: GCC C++ Linker
g++ -shared -o "app" ./app.o
Finished building target: app
execution output:
segmentation fault
Thanks
From g++ manual:
--shared
Produce a shared object which can then be linked with other objects to form an executable. Not all systems support this option. For predictable results, you must also specify the same set of options that were used to generate code (-fpic, -fPIC, or model suboptions) when you specify this option.[1]
When you put the --shared option, it means that you don't want an executable, but a shared object.
In your case, you create a shared library and not an executable. This is why you segfault when your launch it.