I am building a C++ project on my Ubuntu 64bit system using a provided Makefile, and this project also provides an API library for developers.
The compilation was successful, no errors at all, but when I try to include in my files the API libraries provided in the "api" folder, then g++ complains about undefined references.
It is not a problem about dependencies (I already built the project succesfully), in fact the missing references are about classes and functions provided by the project, but they are in some specific (sub-)folders (I don't know which ones!), I guess in some .so files, and g++ is not finding them, probably because it does not know they are in those specific subfolders.
It is not the first time this happens when trying to use APIs from any project, then I think I am missing something or I am doing something wrong in general when trying to use the libraries provided in a project.
In particular, the main problem is that I don't know how to tell the compiler where some classes or data structures are declared, and moreover I don't know how to locate them in order to know where they are.
Usually, a workaround I use to avoid this problem is to run make install (as root or using sudo) so that libraries and APIs are installed in standard folders (like /usr/include or /usr/lib) and if I do this thend I can include the API libraries using #include <library>, but in this last case it didn't work either, because perhaps some required files containing the not found classes/structures are not properly installed in the right folders in the system.
Another workaround I used sometimes is to try to put all the project files in the same folder instead of using the project folder structure, but clearly this is not good! :-)
But I noticed that several other people managed to use the APIs, then apparently they know some way of finding the files containing the "undefined" references and including them in the compilation.
Then my general question is: given a "classic" C++ project based on "Makefile" files and with usual folder names like src, lib, build, bin, etc., if I want to write C++ files using the libraries provided by the project, but the compiler complains about undefined references, how can I find the files (.so or .o or .cpp) containing such references? Is there any tool to find them? And how can I tell the compiler where they are? Should I use some command-line option for g++ or should I use the #include macro in some smart way?
PS I also tried to use the pkc-config linux tool to get right options to use for compilation and they were available, but the compiler still complains about the undefined references.
Some more degails about the project i tried:
For interested people a link to the project is below:
https://github.com/dreal/dreal3
And instructions on how to build it:
http://dreal.github.io/download/
Look into the -rpath linker option - specifically with the "$ORIGIN" argument. That lets you find libraries relative to your executable location so you don't have to install them to the standard locations but just need to put them somewhere known, relative to the executable. That should help you with one piece of the puzzle.
Note: -Wl, can be used to pass arguments to the linker via g++.
As for pointing the compiler/linker at a library so it can resolve undefined references by using that library, use the -l (that's lowercase L) option to specify the library name and -L to specify directories to search for libraries.
As for looking into a library (.so) file to see what symbols are in there, you have a few tools at your disposal: objdump, nm, readelf and objcopy.
Related
I am learning C++ and, in order to do so, am writing a sample wxWidgets application.
However, none of the documentation I can find on the wxWidgets website tell me what library names to pass to the linker.
Now, apart from wxWidgets, is there a general rule of thumb or some other convention by which I should/would know, for any library, what the names of the object files are against which I am linking?
We have more of a "rule of ring finger", instead of a thumb
Generally, if you compile the library by hand, it will produce several library files (usually .a .lib or something similar, depending entirely on your compiler and your ./configure) these are produced (typically) because of a makefile's build script.
Now a makefile can be edited in any way the developer pleases, but there are some good conventions (there is, in fact, a standard) many follow- and there are tools to auto generate the make files for the library (see automake)
Makefiles are usually consistent
You can simply use the makefile to generate the files, and if it's compliant, the files will be placed in a particular folder (the lib folder I believe?) all queued up and ready to use!
Keep in mind, a library file is simply the implementation of your code in precompiled format, you could create a library yourself from your code quite easily using the ar tool. Because it is code, just like any other code, you don't necessarily want to include all of the library files for a given library. For instance with wxWidgets if you're not using rich text, you certainly don't want to waste the extra space in your end executable by including that library file. Later if you want to use it, you can add it to your project (just like adding a .cpp file)
Oh and also with wxWidgets, in their (fantastic) documentation, each module will say what header you need to include, and what library it is a part of.
Happiness
Libraries are amazing, magical, unicorns of happiness. Just try not to get too frustrated with them and they'll prance in the field of your imagination for the rest of your programming career!
After a bit more Googling, I found a page on the wxWidgets wiki which relates to the Code::Blocks IDE, but which also works for me. By adding the following to the linker options, it picks up all the necessary files to link:
`wx-config --libs`
(So that does not solve my "general rule" problem; for any library I am working with, I still have to find out what files to link against, but at least this solves the problem for wxWidgets).
The build instructions are different for each platform and so you need to refer to the platform-specific files such as docs/gtk/install.txt (which mentions wx-config) or docs/msw/install.txt to find them.
FWIW wxWidgets project would also definitely gratefully accept any patches to the main manual improving the organization of the docs.
In c/c++ we use -I for specifying header files location and -L path for specifying library path. I have an eigen and boost libraries, so what I did is that I copied these libraries to /usr/include directory in linux and in source file of my program I just used the header file of these libraries. My question is how does the source file of these libraries get linked with my program source file in which I am only using header files of these libraries?
It depends on the libraries you are using. Eigen3 is header-only: no need to link against it. With Boost, it depends. Most parts are header-only but some libraries might need to be linked.
On the copying to /usr/include. This sounds horribly wrong. Use the package manager of your distribution to get a package of the libraries you require. You should almost never put files yourself into /usr/{include|lib...} directly but prefer /usr/local/{include|lib...}.
You are also a little confused about source code and object code. Generally, a library will contain compiled, object, code, but C++ template expansion requires some kind of source code or source-like code in order to perform template instantiation.
However, the bottom line is that the syntax to include a library depends on the compiler/linker combination you are using. You need to state that before someone can answer the question fully.
The directory "/usr/include" is considered special, part of the operating system or platform you are using, so you should not copy files into it.
Note that the construction "c/c++" is not very meaningful - the two languages C and C++ have different syntax and different linkage models. Best to say which one you meant.
I'm totally spinning my wheels with getting a couple of 3rd party libraries to work with my c++ programs. I'm looking for some general advice (40,000 foot level) about the general steps that one needs to take when implementing libraries.
First, some specifics: I am using code::blocks in Windows as my IDE. I like this IDE and really don't want to switch to anything else if I don't have to (I've tried visual c++ and also some things in linux). The libraries that I am trying to use are GMP and crypto++.
OK. What I think I know is this: After downloading the library, I unzip the file to a folder. I've been unzipping directly to C:\ with each zip file extracted to its own folder (e.g. c:\cryptopp and c:\gmp). I think that the next step is to build the library, but this is where I get totally stuck. How is this done? There are no executable files among those extracted. From what I can tell, I believe that I do this in code::blocks, but I have no idea how?
Finally, assuming that I can get this done, which I believe creates the .lib files, the last step before actually using the library in my code, is to link into the library. This part, I believe that I understand.
So, my question is broad: do I understand this process overall? And if so, how do I go about building these libraries, if in fact that it the thing that I am missing.
Thanks very much for indulging my ignorance. I'm totally rudderless right now and despite hours and hours on google, I'm making no progress. Also, feel free to correct anything that I have stated as fact that is not correct. Thanks a lot!
Usually libraries have a special file called makefile in them, and are built with a utility called Make (or one of it's variations, whatever works uder windows).
Usually all you have to do is to run Make in the directory where you have unpacked the source files, and it will do the rest itself.
If those libraries you mention (GMP and crypto++; disclaimer: I'm not familiar with either of them) don't have project files for code::blocks then you may still be able to compile them under Windows with MinGW.
If you have installed MinGW you use the MinGW shell to navigate to the appropriate directories which would be /c/cryptopp/ and /c/gmp in your examples - The MinGW shell works like a Unix shell, and has different naming conventions.
Then you need to compile the libraries. Check whether there's a Makefile in those directories, if there isn't you can check whether there's a configure script, which will generate the Makefile. If you have the Makefile you can type make which will compile the libraries with MinGW's port of the GCC compiler.
When the compilation is complete you should have a library in the form of a .a file (say libcryptopp.a) that you can link to your project. In code::blocks you would set the linker path (the -L command line option in GCC) to C:\cryptopp\bin or wherever the library has been compiled, and then add libcryptopp.a to the list of libraries you want to link (this is associated with the -l option in GCC). The convention is to leave out the lib prefix and the .a extension, so you would just add cryptopp to your library list. In the end your linker options should look like -LC:\cryptopp\bin -lcryptopp along with the
Also, to be able to use the libraries you need to add the path to the headers directory to the include path of your project. This is associated to the -I command line option in GCC, so your compiler's command line options would have something like -IC:\cryptopp\include somewhere.
Of course, all of the above assumes that you use code::blocks with GCC. If you're using it with VisualC++ then the principles are the same, but the specific steps differ.
I used CMake and Visual C++ to build the HyDE library. Then, still in VC++, I was able to successfully create code and build an executable that links into HyDE.lib and the HyDE header files.
I then discovered that in order to work with others at my company, it would be preferable to develop in Eclipse CDT. Knowing very little about Eclipse CDT, I created a default hello world project, deleted the code and then dumped in all of my code into the src folder. Then I attempted to change the includes and lib path and libs to mirror what had worked in VC++. At this point everything seems to compile, but I get an error in linking:
/cygdrive/c/EclipseWorkspace/425HyDE/Debug/../src/FS5HyDE.cpp:16: undefined reference to `HyDEAPI::HyDE::HyDE(HyDESystemModel::SystemModel*, bool)'
(There are many more errors like this, all referring to HyDE methods.) Here is what is being run at the command line:
g++ -L"C:\Progra~1\boost\boost_1_42\lib" -L"C:\EclipseWorkspace\HyDE" -o"425HyDE.exe" ./src/Adapter_FS5HyDE.o ./src/EPSCommands.o ./src/EPSCurrentSensor.o ./src/EPSFault.o ./src/FS5HyDE.o ./src/HyDEObservation.o ./src/MCDH.o ./src/MCDH_Module.o ./src/PDBComponent.o ./src/PowerSystem.o ./src/Program.o ./src/SSPCComponent.o ./src/Telemetry.o ./src/TelemetryReport.o -l:libboost_thread-vc90-mt-gd-1_42.lib -lHyDE
This is definitely not a library ordering problem because I've the other ordering as well (there are only two). Is it possible that there is a problem with compiling HyDE.lib in VC++ (which uses a Windows compiler) and compiling my program with g++? Could there be a problem in the way that Eclipse CDT is autogen'ing the makefiles? Any other ideas?
(Note: there appear to be plenty of others questions on SO with similar problems, but after reading through them I have yet to find one that addresses my problem.)
Classic missing symbol error. Which source file defines:
HyDEAPI::HyDE::HyDE(HyDESystemModel::SystemModel*, bool)' ?
Was this file added to the compilation? Can you spot it on the command line you pasted?
If this symbol belongs to an external library, after adding the directory path with -L , you could add the name of the specific library you want to link with your program using -l.
I'm going to suggest that you try to add to the compilation command the directory path to HyDE.lib, followed immediately by the library name, like this:
-L"C:\path_to_hyde_library" -l:HyDE.lib
and then tell us what happened.
Solution: Since the HyDE library was compiled with the Visual Studios compiler and I'm attempting to build the code that links to it with the Cygwin toolchain the two compilers use different name mangling schemes so that the latter linker can not find the expected symbols in the HyDE library. The only solution that I've found is to recompile the HyDE library with the Cygwin toolchain or compile the new code with whatever compiler Visual Studios is using. (grumble grumble)
./src/FS5HyDE.o and ./src/HyDEObservation.o should be the latest parameter if other object files (*.o files) need them, it means that the most needed object files should be appeared as last as possible in the parameters list.
I'm wondering if there are any simple ways to link boost libraries (all or individual) via some entry like....
-lSDL_ttf
The above links SDL's True Type Font library. Can this be done with boost? If so, I'm not sure what file I'm linking for to link. I'm currently using boost_1_40_0.
If this isn't possible, or there are better ways to do this, I'd be happy to hear them.
P.S. I'm using the CodeBlocks IDE.
Most boost libraries don't need to be linked as they are header only.
For those that are not header only, see the instructions here on the naming conventions and make sure you put the folder containing the boost libraries in your library search path if you want to avoid specifying it explicitly.
For Xcode 7, A few updates to this post:
a. Following installation instructions the following link, I placed the zipped file in /usr/local, resulting in an installation directory of:
/usr/local/boost_1_60_0
http://www.boost.org/doc/libs/1_60_0/more/getting_started/unix-variants.html
b. As stated on the above page, many of the Boost libraries are "header only." In other words, there is no library, and you don't have to link the libraries; there is nothing to link! If you try and link them, you will get an error! You just have to specify the header location, like so:
Of course, if you're using a Boost library that must be compiled, you may have to link it differently, but it's important to keep this in mind.
c. Be sure to check the permissions on the installation directory. I installed as root, and had to do a chmod 755 on the install, as show below. If permission are not set, you will get the generic and utterly unhelpful "library not found" error.