Ok, so I've built a C++ application that uses some external libraries.
I've built it with cmake and g++, both complete compilation without an error.
After compilation, I open my built application and out comes the error.
The procedure entry point _ZNKSt7_cxx1112basic_stringIcSt11char_traitsIcESaIcESaIcEE5c_strEv could not be located in the dynamic link library libstdc++-6.dll.
Now I'm wondering... Is there any way to compile it to be static? Do I need to get a newer version of libstdc++-6.dll?
my current code for compilation is
g++ main.cpp -o application.exe -L"C:/MinGW/lib/" -lopengl32 -lfreeglut -lDevIL -lILU -lILUT -I"C:/MinGW/include"
Related
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.
I am trying to link a compiled research experiment project, built in C/C++.
The project is dependant on HyperNEAT and robot simulation software WeBots.
I have cloned and built the HyperNEAT project successfully (in that project there are other dependancies such as Boost, TinyXML, JGTL (custom library) and other unrelated subprojects).
I have made a makefile including all neccesary header search paths and library paths, and compiling the two main .cpp files:
/ModHyperNEAT/mod_ctrler7.cpp
/ModSupervisor/mod_supervisor.cpp
works, giving me 2 .o files.
However, in the make link step, when I want to create (separate) executables of both files, I am getting the 'undefined symbols for architecture x86_64' error (see pastebin here: http://pastebin.com/kiwwCcUf). It seems that C++ standard datatypes and functions such as
std::string::end() const cannot be found.
I have googled and searched SO for answers regarding this, and it seems that either libraries are missing or binary incompatible if i understand correctly, but the libraries are there and both projects have been compiled with the -lstdc++ flag.
This is the make link step (and the used macro's from the makefile) :
CC = gcc
CFLAGS = -v -g -lstdc++ -Wall -Wno-error -ferror-limit=100 -fmessage-length=0
DEFINES = -DHCUBE_NOGUI -DTIXML_USE_STL
FLAGS = $(CFLAGS) $(DEFINES)
LIB_TINYXML = -L/Users/michahell/Documents/projects_c++/HyperNEAT/tinyxmldll/out
LIB_HYPERNEAT = -L/Users/michahell/Documents/projects_c++/HyperNEAT/NE/HyperNEAT/out
LIB_BOOST = -L/usr/local/Cellar/boost/1.57.0/lib
LIB_WEBOTS = -I/Applications/Webots/lib
LIBS = $(LIB_TINYXML) $(LIB_HYPERNEAT) $(LIB_BOOST) $(LIB_WEBOTS)
LIBFLAGS = -ltinyxmlpluslib -lboost_filesystem-mt -lboost_random-mt -lboost_system-mt -lNEATLib_d -lHypercube_NEAT_Base_d
WEBOTS_DYLIB = -dylib_file /Applications/Webots/lib/libController.dylib:/Applications/Webots/lib/libController.dylib
$(CC) $(FLAGS) $(LIBS) ./mod_ctrler7.o $(WEBOTS_DYLIB) $(LIBFLAGS)
I found out that to link to .dylib's I had to use a specific flag and specify the full path, hence the $(WEBOTS_DYLIB) macro.
I am using the -lstdc++ flag because in the HyperNEAT project that flag was also used for building that library. If i exclude this flag, i get a lot of errors during compilation (libc++ and libstdc++ incompatibility as I now understand). All of the library paths check out, and .a and/or .dylib files are present.
My knowledge of C/C++ and GCC tooling is very limited, as I have never had to use it before.
I think it might have to do with the fact that the HyperNEAT project contains a Boost 1.57.0 distribution which is used for their build, and that i have a separate (using homebrew) Boost version installed on my system, which is the same version:
$ brew info boost
boost: stable 1.57.0 (bottled), HEAD
http://www.boost.org
/usr/local/Cellar/boost/1.57.0 (10572 files, 439M) *
What could be the cause of this error failing my link step? Anyone should be able to reproduce my linker errors if both HyperNEAT and my project are cloned and put their root dirs in the same location. WeBots should be downloaded but only for the header includes and libraries. And of course my makefile paths should be modified.
If anyone can give me tips on how to solve this problem, i would GREATLY appreciate it!
It turns out that, for some reason, I had to include the lstdc++ flag to the library link flags and not as a compiler flag, AND the stdlib=libstdc++ as compiler flag.
I am trying to add a new library to the Qt plugins folder.
That plugin is located here:
http://qt.gitorious.org/qt-solutions/qt-solutions/trees/master/qtjp2imageformat
It says that it requires jasper to build, so I downloaded jasper, and built it, generating a libjasper.a in my jasper/lib folder (which is in my home dir, not in /usr or anything)
So i built out qtjp2imageformat using the jasper include files, and linking against that libjasper.a file
here are the relevant lines from the makefile:
INCPATH = -I/usr/lib64/qt4/mkspecs/linux-g++-64 -I. -I/usr/lib64/qt4/include/QtCore -I/usr/lib64/qt4/include/QtGui -I/usr/lib64/qt4/include -I../src -I. -I/home/dcole/software/jasper-1.900.1/include
LIBS = $(SUBLIBS) -L/usr/lib64/qt4/lib64 -L/home/dcole/software/jasper-1.900.1/lib -ljasper -lQtGui -L/usr/lib64/mysql -L/usr/lib64/qt4/lib64 -L/usr/X11R6/lib64 -lQtCore -lpthread
I then put the generated libqtjp2.so in the QT Plugins/imageformats folder, and now when my code runs, and gets to the part where it's going to read a jpeg2000, I get the following: symbol lookup error: /usr/lib64/qt4/plugins/imageformats/libqtjp2.so: undefined symbol: jas_init
So I think jas_init comes from jasper - how come my QT project can't see that? Do I need to also make MY project link against libjasper.a, or have I linked the library wrong when I built libqtjp2?
Thanks
You didn't say which distro you are using, but the simplest would be to install the jasper package and link your application to it's library.
by the way, did you build static library (.a) or dynamic (.so)? Try building a dynamic library
I would like to move the building of my C++ project completely to Eclipse CDT, however I am facing some configuration problems. Here is my old g++ compiler call:
g++ -I/home/lib/tinyxml
-I/usr/lib/jvm/java-6-openjdk/include
-L/usr/local/lib -L/home/konrad/tinyxml
-lboost_system
-lboost_thread
-lboost_regex
-fPIC
-shared
-o libagent.so
agent.cpp AgentSocket.cpp ThreadInfo.cpp
/home/lib/tinyxml/tinyxml.cpp
/home/lib/tinyxml/tinyxmlerror.cpp
/home/lib/tinyxml/tinyxmlparser.cpp
/home/lib/tinyxml/tinystr.cpp
When creating the project I choose Shared Library > Emtpy Project
Here are my problems:
The Eclipse CDT generates the makefile in a way, it first compiles every .cpp file and then recompile it to the shared library. This let's me face one or more issues. I would like to jump this step and run it in the same way I did in the console.
I cannot configure -L and -l options into the C++ building configuration, as Eclipse CDT offers these option only for the C++ linking part, but not for the C++ compiler part, but I need them already there, as the project doesn't compile without errors.
That's not a problem, but actually how makefiles usually are constructed. This way, if you change one source file, you don't have to recompile all other source files, but only the one that has changed. It minimizes recompilation time.
That shouldn't be a problem, because they are options that are only used during linking. Compilation of source files into object files shouldn't depend on external libraries.
I would like to utilize the UnitTest++ library in a testing file. However, I am having some difficulty getting the library to be included at compile time. So here is my current directory structure:
tests/
UnitTests++/
libUnitTest++.a
src/
UnitTests++.h
unit/
test.cpp
I have just used the UnitTest++ getting started guide to just get the library setup. Here is test.cpp:
// test.cpp
#include <UnitTest++.h>
TEST(FailSpectacularly)
{
CHECK(false);
}
int main()
{
return UnitTest::RunAllTests();
}
And I am currently trying to compile with:
gcc -lUnitTest++ -L../UnitTest++/ -I../UnitTest++/src/ test.cpp
I am currently getting a bunch output with ld: symbol(s) not found at the end. So how would I be able to get the UnitTest++ library properly included when this program is compiled? I am on a Mac and I'd also like for there to be an easy way for people on a Linux machine to run these same tests.
Whew, I hope this provides enough information, if not please let me know.
I was able to build it in the following manner
gcc -L../UnitTest++/ -I../UnitTest++/src/ test.cpp -lUnitTest++ -lstdc++
or
g++ -L../UnitTest++/ -I../UnitTest++/src/ test.cpp -lUnitTest++
that links to libstdc++ automatically.
GCC documentation says:
-llibrary
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified.
Thus, foo.o -lz bar.o' searches libraryz' after file foo.o but before bar.o. If bar.o refers to functions in `z', those functions may not be loaded.
I guess that's why the library symbols are not found when you first specify -lUnitTest++ and then test.cpp
Compile test.cpp to get test.o
and use
g++ test.o libUnitTest++.a -o ./exectest
to get the ./exectest executable
libUnitTest++.a is just an archive of all the object files of UnitTest++. You just need to link all the object files (your test object file + libUnitTest++.a)
Try editing the makefile that came with unittest++ and make it suitable for your case
The message ld: symbol(s) not found means you haven't compiled the library. So you need to go in the UnitTest++ folder, compile and install it.
I've never worked on a MAC, but in linux, libraries are usually compiled and installed with:
./configure
make
make install
In the UnitTest++ link you posted, you should simply:
make install
Then you will have the UnitTest++.so library in the libraries folder of your OS. Now the library can be linked with your program with the -lUnitTest++ command.
Usually you have to put -Lsomething before the -lsomething that requires it.