g++ failing to link statically when compiling to binary format: "skipping incompatible libm.a when searching for -lm" - c++

While attempting to write a kernel in C++, I've run into a peculiar issue.
When prompting g++ to compile even a very basic C++ file statically and to binary, it simply keeps skipping over the static math library (libm.a), ultimately failing to compile.
Attempting to compile a simple C++ file:
test.cpp
int main() {
return 0;
}
using this g++ command:
g++ -static test.cpp -Wl,--oformat=binary
I receive the following error output:
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm: No such file or directory
I am running Linux Mint Cinnamon V. 21 (Vanessa) on a VirtualBox VM.
In my attempt to narrow down the issue, I have also attempted to exclude the -static flag:
g++ test.cpp -Wl,--oformat=binary
Which results in a different error entirely:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
After thorough research, I was made aware that this could be caused by an incompatibility between 32-bit libraries and 64-bit files. Everything is supposed to be in 64 bit.
I did attempt to determine bitness of libm.a using file.
When using the file command on /usr/lib/x86_64-linux-gnu/libm.a, I receive the following output:
libm.a: ASCII text
indicating neither bitness. This led me to conclude that perhaps the library is damaged and needs updating. After running sudo apt-get install libc6-dev, the issue persists, however.
I'm not sure what to do at this point.
Update:
I've opened libm.a in a text editor and the entire contents of the file are:
/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libmvec.a )
Update 2: apparently this is a linker script. Both referenced files libm-2.35.a and libmvec.a are present in my directory and are, according to objdump, 64-bit-versions.
Based on the compiler's error output, it seems that in my case, for whatever reason, g++ (or more specifically, ld) fails to use this linker script. What could possibly cause this?

I have come to the conclusion that it is not normally possible to statically link C++ code involving object oriented features into a fully functional binary file, as libm.a can apparently be linked to ELF only.
besides: even the static version of glibc, which is also required, references other dynamic libraries, making it useless for kernel code.
there might be some sort of workaround, but it seems that g++ does not support this functionality by default.

Related

Facebook warpdrive build - D Programming language

Of late, facebook opensourced warp, C/C++ preprocessor.
https://github.com/facebook/warp
I'm trying to build it using dmd and stuck with some build errors.
I downloaded dmd.2.065.0.zip for dmd compiler - dmd2/linux/bin64/dmd
I also see a bunch of libraries, for example libphobos2.a
Then when I build warp, I see some errors from ld, that keep complaining that phobos2.a could not be found. I exported LD_LIBRARY_PATH to the dir where this library is stored but no luck.
I compiled in verbose mode, and it doesn't give more info.
Command:
/path/to//building_stuff/dmd2/linux/bin64/dmd -O -inline -release -ofwarp cmdline.d constexpr.d context.d directive.d expanded.d file.d id.d lexer.d loc.d macros.d main.d number.d outdeps.d ranges.d skip.d sources.d stringlit.d textbuf.d -v
Error excerpt:
function textbuf.Textbuf!char.Textbuf.length
function textbuf.Textbuf!char.Textbuf.resize
gcc warp.o -o warp -m64 -L/path/to/building_stuff/dmd2/linux/bin64/../lib64 -Xlinker --export-dynamic -l:libphobos2.a -lpthread -lm -lrt
/usr/bin/ld: cannot find -l:libphobos2.a
collect2: ld returned 1 exit status
--- errorlevel 1
I was hoping the D language experts here, or those who know about warp already could give me some hint.
I was not on CentOS, as warp demands. I wonder if that could anyway be the reason.
I was not using gcc 4.7.x as warp demands, but, to me, the library could just not be located doesn't look like a problem from old gcc I have.
I was on redhat5.5 machine with 4.1 gcc.
CentOS is basically a RedHat, so everything should work OK. As people commented, your real problem is the -l:libphobos2.a in your link line. Remember, GNU/Linux allows colons in file-names, so :libphobos2.a is a perfectly valid file, and GNU ld won't find it in the library search paths.
Note that they've added a make file to easy on your compilation, I managed to compile it using "make -j" and only editing the dmd command line in the make.
just rename "libphobos2.a" to "lib:libphobos2.a.a"
I faced a similar problem with ld version 2.17, but with version 2.20 this 'l:<libfilename>' kinda syntax works fine.

Linkage fails, what's going on?

I'm trying to build a specific program on Ubuntu 12.04 64 bit.
The program needs to be compiled 32 bits.
I installed the ia32-libs and gcc-multilib packages.
I managed to compile it on 3 different computers, but on this one, it fails with a weird error.
for some reason, libm.so is not picked up correctly, or something is wrong with the library.
This is the actual compilation line that fails as it was extracted from the Makefile.
gcc -o x86_32_obj/foo x86_32_obj/foomain.o -m32 -fPIC -fno-stack-protector -lc -lgcc -lm -lpthread -lrt -lstdc++ ../libfoo/lib/./libfii.x86_32.a
This is the output
/usr/bin/ld: ../libfoo/lib/./libfoo.x86_32.a(NK_Meas.o): undefined reference to symbol 'expf##GLIBC_2.0'
/usr/bin/ld: note: 'expf##GLIBC_2.0' is defined in DSO /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib32/libm.so so try adding it to the linker command line
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib32/libm.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
make[1]: *** [foo] Error 2
make: *** [foo] Error 2
I have seen errors such as this in relation to the linking order. It may be possible to address the error by placing the libm linking directive at the very end of your linking configuration.
These interdependencies are very much system dependent, which is probably why the same command works on other systems.
Found the problem.
Apparently, the library file I was linking against was compiled using a different version of GCC.
I don't know how exactly it's related, but once I replaced the gcc compiler to the one used with the library it worked.

Incorrect $SystemID in Mathematica

I am trying to link Mathlink libraries in mathematica. I am using a x86_64-suse-linux OS, but when I check $SystemID in Mathematica, it tells me I am using 'Linux' instead of 'Linux-x86-64'.
This is a problem because if I try to link the library as
g++ cpp2mma.cpp -L/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux/CompilerAdditions/ -lML32i3 -lpthread -lstdc++ -lm -lrt
(the 32 bit version - and the only library in Linux/)
I get the following error:
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld: skipping incompatible
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux/CompilerAdditions//libML32i3.so when searching for -lML32i3
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld: skipping incompatible
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux/CompilerAdditions//libML32i3.a when searching for -lML32i3
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld: cannot find -lML32i3
collect2: ld returned 1 exit status
however, if I try to link it as
g++ cpp2mma.cpp -L/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions/ -lML64i3 -lpthread -lstdc++ -lm -lrt
it compiles just fine, but if I try to run it I get the following error:
./a.out: error while loading shared libraries: libML64i3.so: cannot open shared object file: No such file or directory
This file obviously exists as running 'locate libML64i3.so' yields:
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Libraries/Linux-x86-64/libML64i3.so
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions/libML64i3.so
Am I correct in assuming that the problem lies in the fact that Mathematica thinks that I am not running a 32 bit system? If so, what do I do?
The problem is not in Mathematica. The kernel is never running -- from the perspective of e system you are compiling and launching an ELF executable. libML64i3 will start a kernel for you, but its not getting loaded here.
There are several ways to get the linker to find libML64i3.so at runtime
Export the directory containing libML64i3.so through LD_LIBRARY_PATH (generally not a good idea)
use an entry in /etc/ld.so.conf.d or /etc/ld.so.conf to indicate that /usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions should be part of the library search path -- look at ldconfig(8).
Symlink libML64i3.so somewhere already in the library search path
Link to a static version of libML, as described in this StackOverflow post.
To deal with the compile-time linker errors, you could compile your application 32-bit (by passing -m32 to g++). If you did this, you would get a runtime message griping about not being able to find the 32-bit version of libML, which would require the same solution as above.
I'm not sure why $SystemID is returning a value indicating you are running the 32-bit kernel. That probably has something to do with how you are starting Mathematica. On CentOS 5-7-x86_64, I have
host 11% ls -l $(which math)
lrwxrwxrwx 1 root root 51 Nov 8 16:27 /usr/local/bin/math -> \
/usr/local/Wolfram/Mathematica/8.0/Executables/math
host 12% math
Mathematica 8.0 for Linux x86 (64-bit)
Copyright 1988-2011 Wolfram Research, Inc.
In[1]:= $SystemID
Out[1]= Linux-x86-64

Adding Boost Library to a C++ project in OS X Eclipse

I am have been attempting to get a C++ project setup using boost file system library using eclipse. I followed these directions to install boost on my system. The directions where pretty much
download
extract
run bootstrap.sh
run ./bjam architecture=combined
That seemed to go fine, no errors. I then fired up eclipse and created a new test project called test with a single file called test.cpp. The code in it is:
#include <stdio.h>
#include <boost/filesystem.hpp>
int main() {
boost::filesystem::path path("/Users/schoen"); // random pathname
bool result = boost::filesystem::is_directory(path);
printf("Path is a directory : %d\n", result);
return 0;
}
This is just something simple to make sure it is all set up correctly. Of course I tried to compile at this point and it failed. Did some googling and found this site. It said to add the boost library to the linker by going to project properties and adding "boost_filesystem". I tried this, and well it didn't work.
Can someone point me in the right direction or give me a hint to how to set up Boost in an Eclipse project?
I am new to C++ and Eclipse, and most my experience is in Java with Netbeans. So I am pretty lost at the moment.
UPDATE
I just wanted to update on what I have tried based on the answers given.
Based on Alex's suggestion I added boost_system and boost_filesystem to the linker list. I was still getting the same compiler errors.
Following the suggestion from rve I added the path to the boost libraries to the Library search path. When this did not work. I cleared out the linker list and tried it with just the library search path. This also did not work.
I then cleared the Library search path. I then manually edited the command on the linker window to be 'g++ -L/Users/jacobschoen/Library/boost_1_45_0/stage/lib -lboost -lboost_filesystem'. This also did not work.
In all of these I tried setting the path to boost to be '/Users/jacobschoen/Library/boost_1_45_0' and '/Users/jacobschoen/Library/boost_1_45_0/stage/lib'. Neither worked.
As requested the comiler error for the above code is:
**** Build of configuration Debug for project test ****
make all
Building file: ../src/test.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.d" -o"src/test.o" "../src/test.cpp"
../src/test.cpp:10:32: warning: boost/filesystem.hpp: No such file or directory
../src/test.cpp: In function 'int main()':
../src/test.cpp:13: error: 'boost' has not been declared
../src/test.cpp:13: error: expected `;' before 'path'
../src/test.cpp:14: error: 'boost' has not been declared
../src/test.cpp:14: error: 'path' was not declared in this scope
make: *** [src/test.o] Error 1
If any one has any further suggestions I am still trying.
Second Update
On a suggestion by rholmes I added an include library along with the linker list and library search path. So now the compile error is:
**** Build of configuration Debug for project test ****
make all
Building target: test
Invoking: MacOS X C++ Linker
g++ -L/Users/jacobschoen/Library/boost_1_45_0 -o "test" ./src/test.o -lboost_system -lboost_filesystem
ld: library not found for -lboost_system
collect2: ld returned 1 exit status
make: *** [test] Error 1
Any ideas?
Just wanted to be clear on what actually worked, since it was kinda pieced together from a few answers.
Download the boost files and extract them to where you want to put them.
In your terminal navigate to the directory and run ./bootstrap.sh
When that is done run ./bjam (this takes a while so go smoke and get a cup of coffee)
Open up your eclipse Project and go to Project > Properties > C/C++ Build > Settings
Click on MacOS X C++ Linker > Libraries.
You should see a split window with the top being for 'Libraries (-l)'. In this section add both boost_system and boost_filesystem. In the bottom section it should be for 'Library Search Path (-L)'. Here you want to put the path to the stage/lib directory inside where you extracted the boost download. It should look similar to below:
Click GCC C++ Compiler > Includes. This will be a single pane where it says 'Include Paths (-I)', well I think it is an I as he font is weird and could be a lower case l also. Anyway in that section add the path to where you put boost without the stage/lib part. It should look like below:
Everything should compile now with out a problem, and if you need to use any other boost libraries it should be just a matter of adding it to the linker section where boost_filesystem and boost_system are. Enjoy.
Not sure where you do this in Eclipse these days, but under the include paths for Eclipse should be the path to the main boost directory (/Users/jacobschoen/Library/boost_1_45_0?). The compiler line should have something like the following in it, I would think:
Invoking: GCC C++ Compiler
g++ -I/Users/jacobschoen/Library/boost_1_45_0 -O0 -g3 -Wall -c -fmessage-length=0 -MMD (etc..)
Update: Looking at my system, the linker path on yours might be more appropriately:
-I/Users/jacobschoen/Library/boost_1_45_0/stage/lib
Depending, of course, upon how you've installed and built boost -- this is with my most recent attempt with a full source build. Depending upon how you obtained boost, this may or may not be different. I recently redid the boost on my Mac for 64 bit and haven't had much time to try it yet....
Add boost_system to the linker list, together with boost_filesystem.
I had recently uninstalled the boost rpm and installed Boost like how you did. I had no problems running Boost programs in Eclipse. I didn't add any extra parameters. Just installed boost and ran Boost programs. It works fine.
Tried your program in the vi editor. Commented out everything in main
#include <cstdio>
#include <boost/filesystem.hpp>
int main() {
/*boost::filesystem::path path("/Users/schoen"); // random pathname
bool result = boost::filesystem::is_directory(path);
printf("Path is a directory : %d\n", result);*/
return 0;
}
and it still gave this error:
/tmp/cc7TAIYS.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cpp:(.text+0x29): undefined reference to `boost::system::get_system_category()'
test.cpp:(.text+0x35): undefined reference to `boost::system::get_generic_category()'
test.cpp:(.text+0x41): undefined reference to `boost::system::get_generic_category()'
test.cpp:(.text+0x4d): undefined reference to `boost::system::get_generic_category()'
test.cpp:(.text+0x59): undefined reference to `boost::system::get_system_category()'
collect2: ld returned 1 exit status
I'm puzzled. Boost programs work on my system, but your program's header files itself are giving a problem. I doubt it's a problem with Eclipse. It has to be something else.
I just ran into something very similar to this using eclipse and CDT... It turns out, using ubuntu and apt-get, libboost_system installs as libboost_system.1.40.0 in /usr/lib
If you try to add it via the library tab in Helios it will complain because it is looking for *.so and *.s0.1.40.0 clearly doesn't match that. However after looking closely at what the linker was trying to doo, I just typed the raw string "boost_system" into the include path adder. This resulted in the linker doing a " -lboost_system" which is a format the linker knows how to deal with in resolving version dependency... If you instead put in the full path to the .so file, the linker will just complain because it tries to do a " -l/usr/lib/libboost_system.so.1.40.0" .
So take my advice and just type in the simple " boost_system" after doing an apt-get install.. It will make it all very easy.

ld can't link with a main executable

On OSX 10.6.4 with i686-apple-darwin10-g++-4.2.1 compiling using TextMate and a Makefile which in the first place has been made für a Linux and I am trying to translate for OSX.
When compiling a c++ project I get the "can't link with a main executable" error:
g++ -Wall -g -I ~/svnX-Repository/axp-Projekte/xrlfupa/trunk/src/ -I ~/svnX-Repository/boost_1_44_0 -I /opt/local/var/macports/software/boost/1.44.0_0/opt/local/lib/ -I /opt/local/var/macports/software/gsl/1.14_0/opt/local/include/ -o xrfLibTest xrfLibTest.o excitFunctions.o xrfFunctions.o filterFunctions.o detectorFunctions.o -L/opt/local/var/macports/software/boost/1.44.0_0/opt/local/lib/ -L/opt/local/var/macports/software/gsl/1.14_0/opt/local/lib/ -lm -lxrlTUB -lboost_serialization -lgsl -lgslcblas # Debug 1
ld: in /usr/local/lib/libxrlTUB.so, can't link with a main executable
collect2: ld returned 1 exit status
make: *** [prog] Error 1
The library that is mentioned (libxrlTUB.so) is in its place (/usr/local/lib/libxrlTUB.so) but, possibly that is where the problem came from, the libxrlTUB.so has been compiled by myself beforehand as well.
The compile process went through, it was generated by swig, though there was a warning:
g++ -arch x86_64 -m32 -g -fpic -I /usr/include/python2.6 -c PyXrl_wrap.cxx
In function 'void SWIG_Python_AddErrorMsg(const char*)':
warning: format not a string literal and no format arguments
which, as far as I could find out, shouldnt be a problem. (Or is it?)
Unfortunately this whole thing is part of a project from the university. Actually I am supposed to write an X-ray-analysis script in python, which would be fine, if... well if I wouldn't be expected to use the librarys that are meant to result from this c++ project.
(Afterwards they should be used via import in python.)
I am not really experienced with c++, neither with compiling on OSX systems. So far I have been bothering with scipting (python, bash, etc). So Maybe I am just missing something simple. Hopefully someone can give me an hint where I can continue reading in order to deal with the above "can't link with a main executable" error...
Thanx in advance,
Liam
The error message is telling you the problem—it is that /usr/local/lib/libxrlTUB.so is not a shared library; it's an executable. You can't link against an executable. Probably whatever build process you used for libxrlTUB.so didn't understand how to build shared libraries on the Mac (it's more suspect because .dylib is the correct extension to use.)
Take a look at Apple's documentation on compiling dynamic libraries. You can use file to make sure your output is of the correct type, for example:
% gcc -c foo.c
% gcc -dynamiclib foo.o -o foo.dylib
% file foo.dylib
foo.dylib: Mach-O 64-bit dynamically linked shared library x86_64
Without -dynamiclib you end up with an executable, which may be the problem you've run into.