I have Ubuntu 12.01 with gcc 4.8.2 and would like to cross compile for the Vortex86DX CPU running an old 2.6.23 kernel.
I´m trying the following testing code:
#include <iostream>
int main()
{
std::cout << "Hello world" << std::endl;
}
That is compiled using the following command line:
g++ -static-libgcc -static-libstdc++ -march=i586 test.cpp -otest586
When I run the test586 on the target architecture I´m getting this error:
$ ./test586
./teste586: symbol lookup error: ./test586: undefined symbol: _ZMSbIwSt11char_traitsIwESaIwEE4_Rep20_S_empty_rep_storageE
Any ideas of what is going on here ? This is just a small code - the real code has around 10 different libraries all written in C++ 11.
In fact the comment from Marco was right. The code still need some dynamics libraries:
$ ldd ./test586
linux-gate.so.1 => (0xb776b000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75a4000)
/lib/ld-linux.so.2 (0xb776e000)
I have to avoid all dynamic library as the target system either does not have them or will have in a very old version.
Help appreciated to accomplish that.
I think the problem is the order of the command switches, i.e. the linker first discovers the dependencies (libgcc, libstdc++) and only then resolves them.
If you give it -static-libgcc before it found the dependency then it will simply ignore it.
the following works for me:
$ g++ -m32 -march=i586 test.cpp -o test586 -static -static-libgcc -static-libstdc++
$ ./test586
Hello world
$ ldd test586
not a dynamic executable
Related
I'm working on a C++ application. I would like to embed SpiderMonkey in the application.
I'm working with CMake, but I couldn't get that build. So, in an attempt to reduce complications, I tried the example code on this page. This wouldn't link using cmake or gcc from the command line.
So, even simpler, just to ensure I can link properly I am trying to get the following to work.
From the command line with gcc:
g++ --std=c++11
-I/home/thetasinner/moz/js/src/build_DBG.OBJ/dist/include
-L/home/thetasinner/moz/js/src/build_DBG.OBJ/js/src -DDEBUG
-Wl,--verbose -lmozjs-54a1 -lm -lz -ldl test.cpp -o test
On the following minimal code example:
#include <iostream>
#include <stdexcept>
#include "jsapi.h"
#include "js/Initialization.h"
int main(int argc, char** args) {
if (!JS_Init()) {
throw std::runtime_error("failed to initialise.");
}
std::cout << "It's alive!\n";
JS_ShutDown();
return 0;
}
Even this doesn't link. I get the errors
/tmp/ccqjx5RY.o: In function `main':
custom.cpp:(.text+0xf2): undefined reference to `JS_ShutDown()'
/tmp/ccqjx5RY.o: In function `JS_Init()':
custom.cpp:(.text._Z7JS_Initv[_Z7JS_Initv]+0xa): undefined reference to
'JS::detail::InitWithFailureDiagnostic(bool)'
collect2: error: ld returned 1 exit status
The headers are found and the linker is finding the mozjs library
attempt to open /home/thetasinner/moz/js/src/custom_build_DBG.OBJ/js/src
/libmozjs-54a1.so succeeded
-lmozjs-54a1 (/home/thetasinner/moz/js/src/custom_build_DBG.OBJ/js/src
/libmozjs-54a1.so)
I am working on Linux (Ubuntu 16.04 and Debian 8.7 tried) because that's where the build tools are. I don't even want to touch Window's yet.
The 'js' executable built in the spidermonkey build works fine, which I assume has the lib I'm trying to link inside it. So I would have thought the lib itself is built okay.
Can anybody help me resolve these linker errors? There are lots of answers to questions about much older versions of SpiderMonkey, but there's nothing for more recent versions. I'm interested in version 45 (which I've tried with very similar errors) or the tip version 52.
I'm comfortable enough digging around in the code working out how to do what I want with it once it builds, hence the interest in the latest version which isn't properly documented, I'm just completely stumped with the building step.
I suspect it's just an ordering problem on the command line:
g++ --std=c++11
-I/home/thetasinner/moz/js/src/build_DBG.OBJ/dist/include
-L/home/thetasinner/moz/js/src/build_DBG.OBJ/js/src -DDEBUG
test.cpp -o test
-Wl,--verbose -lmozjs-54a1 -lm -lz -ldl
Compilation first, followed by linking, with libraries in order of dependency. (My first guess was you'd neglected to mention mozjs on the command line. It took a second look to see it was just in the wrong place.)
I'm working on a shared library which support SSL connection and transmission. I want to release it as a *.so file. After compiling it in my Ubuntu14.04(64bit Desktop) with g++ 4.8.2, it can not work in the CentOS5.8.
The First Round
I compile the shared library with following command:
g++ -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o -lz -lssl -lcrypto
I use command objdump -p libmyssl.so.1.0|grep NEEDED to know it depends on following libraries:
NEEDED libz.so.1
NEEDED libssl.so.1.0.0
NEEDED libcrypto.so.1.0.0
NEEDED libstdc++.so.6
NEEDED libc.so.6
Then I write a demo to use libmyssl.so.1.0.
g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto
I compile the demo in Ubuntu14.04(the same version), it works fine.
I compile the demo in CentOS(openssl 0.9.8e), it linked failed because invalid openssl's version
The Second Round
I removed the "-lz lssl -lcrypto", so the command as following
g++ -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o
I use command objdump -p libmyssl.so.1.0|grep NEEDED to know it depends on following libraries:
NEEDED libstdc++.so.6
NEEDED libc.so.6
I use the libmyssl.so.1.0 in above demo code in the same way:
g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto
I compile the demo in Ubuntu14.04(the same version), it works fine.
I compile the demo in CentOS(openssl 0.9.8e), it didn't report ssl linked errors, but it report glibc linked errors as follows:
undefined reference to `memcpy#GLIBC_2.14'
After updating CertOS's glibc, the demo work fine.
The Third Round
I try to remove the depends to "libc.so.6" and "libstdc++.so.6", so I added option "-nodefaultlibs" to the compile command:
g++ -nodefaultlibs -v -shared -Wl,-soname,libmyssl.so.1,-o libmyssl.so.1.0 myssl.o
I use command objdump -p libmyssl.so.1.0|grep NEEDED only get empty string.
I use command ldd libmyssl.so.1.0 get result "statically linked", no sure why it said "statically linked".
I use the libmyssl.so.1.0 in above demo code in the same way:
g++ -D UNIX64 -o ssldemo ssldemo.cpp ./libmyssl.so.1.0 -lz -lssl -lcrypto
It always report following error both in Ubuntu14.04 and CentOS5.8:
Ubuntu:
hidden symbol `atexit' in /usr/lib/x86_64-linux-gun/libc_nonshared.a(atexit.oS) is referenced by DSO
/usr/bin/ln: final link failed: Bad value
CentOS:
hidden symbol `atexit' in /usr/lib64/libc_nonshared.a(atexit.oS) is referenced by DSO
/usr/bin/ln: final link failed: Nonrepresentable section on output
Questions:
Which version of GLIBC should be linked when I compile my *.so file so that it can work fine in as many as possible Linux?
Do have a way to avoid the dependency to the GLIBC? I tried it in The Third Round but failed.
Any other suggestions ?
Which version of GLIBC should be linked when I compile my *.so file
so that it can work fine in as many as possible Linux?
You should select the oldest distro that you want to target and build on this one. This would ensure that your library would require the minimum possible Glibc version. So simply select the distro with oldest Glibc and build there.
Version of your Glibc is usually encoded in libc.so name (e.g. /lib64/libc-2.12.so) but you can also do
$ strings //lib64/libc-2.12.so | grep GLIBC
GLIBC_2.2.5
GLIBC_2.2.6
...
GLIBC_2.12
GLIBC_PRIVATE
Do have a way to avoid the dependency to the GLIBC? I tried it in The Third Round but failed.
Writing entirely Glibc-independent library sounds like an overkill (you'll need to re-implement IO, memcpy, etc., with lower quality/performance compared to Glibc). Are you sure you want to go down this path?
Any other suggestions ?
For complete applications two common solutions are
static linking
bundling them together with stdlibs they were linked against (they'll of course need to be run with special LD_LIBRARY_PATH or -Wl,-rpath)
But in your case (isolated shared library) targeting the lowest supported Glibc seems to be the only option.
I am using g++ in a cygwin terminal to link several c object files and c++ object files together into a single shared executable. The linker tells me that there are several libraries it cannot find. However, I can list them, using the locations where the linker states that it is looking for them:
g++ -g -o myProg.so *.o -shared
c:/cygwin/bin/../lib/gcc/x86_64-vityan-linux-gnu/4.6.0/../../../../x86_64-vityan-linux-gnu/bin/ld.exe: *cannot find /lib/libc.so.6*
c:/cygwin/bin/../lib/gcc/x86_64-vityan-linux-gnu/4.6.0/../../../../x86_64-vityan-linux-gnu/bin/ld.exe: *cannot find /x86_64-vityan-linux-gnu/lib/libc_nonshared.a*
c:/cygwin/bin/../lib/gcc/x86_64-vityan-linux-gnu/4.6.0/../../../../x86_64-vityan-linux-gnu/bin/ld.exe: *cannot find /lib/ld-linux-x86-64.so.2*
collect2: ld returned 1 exit status
$ ls /lib/libc.so.6
/lib/libc.so.6
$ ls /x86_64-vityan-linux-gnu/lib/libc_nonshared.a
/x86_64-vityan-linux-gnu/lib/libc_nonshared.a
$ ls /lib/ld-linux-x86-64.so.2
/lib/ld-linux-x86-64.so.2
I have tried renaming the .so files to .dll with no success.
I have tried to use the g++ switch '--sysroot' ( --sysroot=/cygdrive/c/cygwin/) with no success.
I have tried adding the g++ switch '-B /cygdrive/c/cygwin/lib/' with no success.
The thing that's really got me confused is that I did this same thing on a similar project about 6 months ago - no issues. And, the system clearly shows that the libraries are there.
What is missing that ld.exe needs to find these files?
I ran a quick analysis of what packages I had installed in Cygwin. I had several of the mingw g++ toolchain packages as well (which don't get used), and a bunch of other stuff. I only use Cygwin for a few specific projects, so I reinstalled: removed all of the other g++ toolchain items, and just installed the cygwin gcc 64 bit toolchain packages. Project now compiles without issue. Closing question.
I can't get gcc in Ubuntu 11.10 to properly link in the google perftools -lprofiler.
The problem seems to be that the linker discards libraries which are not directly used in a program.
An example will help.
Let's call this main.cpp:
#include <math.h>
int main()
{
double value;
for (int i=0; i < 1000000; i++)
{
for (int j=0; j < 1000; j++)
value = sqrt(100.9);
}
return 0;
}
Compile using:
g++ -c main.cpp -o main.o
g++ main.o -o main -lm -lprofiler
Check the executable using ldd ./main:
linux-vdso.so.1 => (0x00007fff5a9ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f32bc1c9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f32bc593000)
Normally, I would run:
CPUPROFILE=/tmp/profile ./main
to produce profile output. But since the profile library is not linked in no profile output is generated.
I've made sure the profiler library is in my search path, and have tried directly linking against the shared library and static library.
The above test works fine on Ubuntu 10.04, Ubuntu 10.10, Ubuntu 11.04, SUSE 12.1, and Fedora 16.
Also, once I include function calls that use the profiler (such as ProfilerStart() and ProfilerStop()), then the profiler library gets linked into the executable.
Any ideas on how to get gcc to link in the profiler library?
Thanks.
g++ main.o -o main -lm -lprofiler
As another.anon.coward commented, you are likely falling victim of your g++ using --as-needed linker flag. Try this instead:
g++ main.o -Wl,--no-as-needed -lprofiler -Wl,--as-needed
Notes:
g++ already adds -lm, no need to add it again
It is important to turn --as-needed back on. Not doing so will likely cause you to link to additional libraries that you don't really need.
In my case, the problem was that there was only a libprofiler.so.0, and no libprofiler.so in /usr/lib/:
user#compy:/usr/include$ dpkg -L libgoogle-perftools4
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libgoogle-perftools4
/usr/share/doc/libgoogle-perftools4/README.Debian
/usr/share/doc/libgoogle-perftools4/copyright
/usr/lib
/usr/lib/libprofiler.so.0.4.5
/usr/lib/libtcmalloc.so.4.2.6
/usr/lib/libtcmalloc_debug.so.4.2.6
/usr/lib/libtcmalloc_and_profiler.so.4.2.6
/usr/share/doc/libgoogle-perftools4/AUTHORS
/usr/share/doc/libgoogle-perftools4/TODO
/usr/share/doc/libgoogle-perftools4/README.gz
/usr/share/doc/libgoogle-perftools4/NEWS.gz
/usr/share/doc/libgoogle-perftools4/changelog.Debian.gz
/usr/lib/libtcmalloc.so.4
/usr/lib/libtcmalloc_and_profiler.so.4
/usr/lib/libprofiler.so.0
/usr/lib/libtcmalloc_debug.so.4
I don't know what the official fix to this is, but I simply created a symlink in /usr/lib:
user#compy:/usr/lib$ sudo ln -s libprofiler.so.0 libprofiler.so
This will make -lprofiler work.
If you don't mind changing your Makefile you can alternatively specify -l:libprofiler.so.0 instead of -lprofiler (note the extra colon) (source).
EDIT: The official way to get the .so is apparently to install the libgoogle-perftools-dev package as explained here:
user#compy:/usr/lib$ dpkg -S libprofiler.so
libgoogle-perftools-dev: /usr/lib/libprofiler.so
libgoogle-perftools4: /usr/lib/libprofiler.so.0.4.5
libgoogle-perftools4: /usr/lib/libprofiler.so.0
I understand that if you want to link to a certain lib, you should install the libx-dev package, which will contain the /usr/lib/libx.so. This file will only be a symlink to a specific version, such as /usr/lib/libx.so.1.2. When you link against /usr/lib/libx.so by specifying -lx to your linker, you will actually create a link in your program against the specific version linked at the time by recording a SONAME of libx.so.1 (the last version number is stripped as oulined here). So when you run your program at a later point in time the dynamic linker will look only for /usr/lib/libx.so.1, which is symlinked to /usr/lib/libx.so.1.2, and no /usr/lib/libx.so hence no dev package needs to exist.
So the libx-dev packages is for compiling and linking against libx, and the libx package is for running a precompiled program against libx.
Here's the current situation I'm in:
I want to distribute a binary app on Linux that would run on several distros (not all of them, just the main ones matter at the moment, let's focus on Ubuntu and Fedora for the sake of this discussion). The app in question links to libbz2 for some of its work. A simple "Hello World" will illustrate the situation :
/* main.cpp */
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << "Hello World!\n";
return 0;
}
The app is built as such :
g++ -lbz2 -o test.bin main.cpp
My build system is on Ubuntu. When I perform a check with ldd on the resulting binary, it lists libbz2.so.1.0 as a runtime dependency. When I take this app to a Fedora machine, the app doesn't run and ldd reveals that it can't find libbz2.so.1.0. Fedora only has libbz2.so.1 and libbz2.so.1.0.4, but not libbz2.so.1.0.
Red Hat's Bugzilla database reveals that this behavior is not a bug, but a feature. I don't really need libbz2.so.1.0, and I would be satisfied with simply linking to libbz2.so.1, but I have yet to figure out how.
I have seen a similar question asked here previously, but the accepted answer (You can pass the actual .so file instead of -l on the linker command line) doesn't seem to work. I tried building with the following command :
g++ /lib/libbz2.so.1 -o test.bin main.cpp
However, ldd still mentions that the app depends on libbz2.so.1.0, even though I passed the full name to g++.
Now, the question is, is there a way on Ubuntu to build the app to have it depend only on libbz2.so.1 rather than on libbz2.so.1.0?
Thanks.
Here's a bit of background to explain what got linked. On ELF platforms the -L and -l flags you pass only locate the binary at link time. If the linker linker determines that a library is required it generates a reference to the SONAME in that binary, regardless of what it was called. For example:
$ objdump -p /lib64/libbz2.so.1 | grep SONAME
SONAME libbz2.so.1
So regardless of what libbz2 is named, that is what will show up as a dependency. Again by example, doing something totally whacked:
$ ln -s /lib64/libbz2.so.1 libblah.so
$ g++ t.C -L. -l blah
You have the apparency of having linked to libblah but because its the SONAME in that binary that matters, your dependency is still this libbz2.so.1
$ ldd a.out | grep bz2
libbz2.so.1 => /lib64/libbz2.so.1 (0x00002b3d1a000000)
Other than the -static trickery (which can break things in interesting ways), there is not easy way out of the mess (ideally the library would do nice symbol versioning like glibc and never or rarely change its SONAME).
Why don't you just link statically instead?
I have done that in the past for builds on Ubuntu and deployment on RHEL which works just fine using static builds.