Statically link ruby libraries to c++ application - c++

I recently asked a question concerning embedding ruby in a c++ application
Embedding ruby in c++, problem with ruby libraries
Now I encountered another problem related to this. I managed to compile and run this application, but i can't link ruby statically. This is what my console says:
####:~/Desktop/rubyParser$ g++ -o ruby_test ruby_test.c -I/usr/lib/ruby/1.8/x86_64-linux/ -static -lruby1.8
/usr/bin/ld: cannot find -lruby1.8
But if I open /usr/bin, there is a "ruby1.8" file (no extension). Probably i need another file..
I'm using Ubuntu and I'm NOT a Linux expert of course, so please be patient with me :)
How can I fix it?
Thanks in advance
Bye

By specifying -lruby1.8 the linker will look for a file named libruby1.8.so in the standard library locations (probably /usr/lib/ or /usr/local/lib).
Take a look at those directories to see if you have something like that in there.
If not, have you installed the development package of ruby ? If only the linking process fails, I would assume you have (otherwise, it is likely that you wouldn't have the headers as well).
I never linked with ruby, but have you tried specifying -lruby instead of -lruby1.8 ?

Have you tried adding the binary to your PATH ?

You may need to, if you've recently installed the Ruby libraries in question, go to the command-line and type in sudo ldconfig to refresh ld's configuration files with the latest versions of your libraries and their locations.
Edit: From the comments below, you'll only need to-do this step if you run into a run-time linking problem, which you haven't at this point. But it's at least something to keep in-mind as it has solved run-time linking problems for me in the past (i.e., helped me with GMP).

Related

Cross Compiling from Linux-Windows, stdio has undefined references (to __imp___acrt_iob_func)

As the title says, I've been trying to cross compile a fairly large project with quite a few dependencies (both static and dynamic libraries). I've cross compiled every dependency successfully using MinGW-w64, set the include & library search paths to their MinGW counterparts (/usr/x86_64-w64-mingw32/lib & include), and yet on the linking step MinGW throws out an error for each call of printf (with stdio.h included, of course). The errors are as follows:
/usr/bin/x86_64-w64-mingw32-ld: ./obj/XXXX.o:/usr/share/mingw-w64/include/stdio.h:352: undefined reference to `__imp___acrt_iob_func'
(Where "XXXX" is a file name from my project)
This error is repeated the exact same (with the exception of the object file name). The command for linking looks like this:
/usr/bin/x86_64-w64-mingw32-g++ -o bin/ReleaseWin/Project #[file with object file names] -L. -L/usr/x86_64-w64-mingw32/lib/ [linking some dependencies (boost, openGL, SDL2, etc.)...] -m64 -flto
I've searched for a solution (or even someone with the same problem) to no avail. I've never been well-versed in linking any more than regular libraries, so if you need more information just ask.
Thanks in advance :)
Extra info:
This project has been cross compiled (from Linux to Windows) successfully before, and I haven't added/removed any dependencies since.
My MinGW-w64 version is 7.0.0
So, I apt-get purge'd mingw-w64 and mingw-w64-common, reinstalled just mingw-w64, and now it's working...
This might have something to do with the fact that I followed the issue that Richard Critten commented with (thanks!), which led me to try downloading and manually copy/pasting headers and CRT (mingw-w64-x86_64-headers-git-... & mingw-w64-x86_64-crt-git) from the MSYS2 repository. That didn't work right away (probably because I screwed up and used the 5.0.0 versions instead of my version), but it seems to have done something.
Therefore, for those who stumble upon this issue,
Try a re-install of MinGW (of course),
Try manually adding the CRT and headers from the link I supplied, and if that still doesn't work,
Try re-installing MinGW again. I'm not super familiar with apt, so I don't know if adding the CRT and headers actually changed how it installed MinGW, but it's worth a shot I guess.
Update: I had this exact same problem on another system. Simply reinstalling MinGW fixed it, so it seems like maybe there was some sort of issue with the files? It's possible that updating from an earlier version messed with things. Moral of the story: even if you think your files are good, a reinstall can't hurt.

Installing gfortran in Cygwin

I am trying to compile a modelling program in Cygwin using either a gfortran or g95 compiler. I have installed both compilers, but when I go to configure the program, it checks for the compilers and does not find then (error: Fortran compiler cannot create executables). I am new to Cygwin-- I suspect it is something with how/where I installed the compilers...Any ideas?
Thank you,
L.
For me, it's more helpful to have executable code to go through the process, so I'm going to put some in. This is addressing your concern,
I suspect it is something with how/where I installed the compilers...
because the installation from apt-cyg should be helpful in letting the system know where to look for the compilers. I'm also addressing a possible linkage issue.
bballdave025#MY-MACHINE /cygdrive/c/bballdave025
$ apt-cyg install gcc-fortran libgfortran5
If you don't have apt-cyg yet, follow these instructions from another answer.
# Get to where your setup executable lives.
# This is what you used to install Cygwin the first time.
# Note that mine is for the 64-bit version, and that
# I keep mine in C:\cygwin64. Your path might be
# different. You also might need to re-download
# The setup executable from Cygwin.
$ cd /path/to/setup_install/setup_x86-64.exe -q -P wget
$ wget https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg
$ chmod +x apt-cyg
$ mv apt-cyg /usr/local/bin
The libgfortran5 (or a more recent version, if available when you search) might be necessary. Here's why I think this might be the case.
bballdave025#MY-MACHINE /cygdrive/c/bballdave025
$ man gcc | grep -A 3 "[ ]*[-]l[ ]\{0,2\}library$"
-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.)
(Note that I haven't included some parts of the result that aren't useful and can be fixed by prefixing the command with MANWIDTH=160, cf here.)
There is a little more detail and a little different result from the answer to a question about the lib prefix on files:
You can name a library whatever you want, but if you want gcc's -l flag to find the right one, you need to name it the way that link describes. For example, gcc -o myapp myapp.c -lm, [w]ill compile myapp.c, link the resulting object with libm.a, and output an executable called myapp. These days, there might be a more complicated search path involving dynamic library names, etc., but you should get the basic idea from this example. [In addition, you can look at this section f]rom the gcc man page:
-l library ...
... surrounds library with lib and .a and searches several directories.
The basic reason for all of that info is this: it is very possible that, in order to link with the gfortran library, you need to have installed a package named something like libgfortran. I don't know for sure how this works, especially with the Cygwin man page being slightly different, but it's worth a try. The likely extra thing you would need in this case is something like
apt-cyg install libgfortran
or
apt-cyg install libgfortran5
Here's some helpful info on how I found what to install. When I had a similar problem, I went to the Cygwin package search, but I only got three entries with three versions of netcdf-fortran
(archived). I wanted gfortran, so I kept looking
I found a great gfortran answer in this SO answer. With that answer, I went back to the Complete Cygwin Package List, armed with my trusty Ctrl + F, since I knew there were packages different from what came back from the search. The complete list had
cygwin64-gcc-fortran GCC for Cygwin 64bit toolchain (Fortran)`
gcc-fortran GNU Compiler Collection (Fortran)
and entries for libgfortran.
Hopefully some of this information will be helpful, or at least educational.
This problem is common for beginners with autotools. It can be:
missing libraries; this can be missing libraries for your project or compiler/system libraries, like libgfortran or similar for g95.
autotools can not detect your compiler;
dynamic libraries problem; runtime path to the dynamic libraries not set. See LD_LIBRARY_PATH for linux environment.
cross-compiling problem, I do not know much about cygwin but that can be an issue. I am not expert of cross-compiling either. It can also be another situation that I am not aware of.
I ran into the 1st and 3rd situations.
Approaches of solutions.
make sure you can manually compile and run a simple hello world program. Install the missing libraries if necessary. Also make sure that you can link your hello world program against the same libraries used by your modelling program, this last statement could lead you to the 3rd situation.
add the path to your compiler to the PATH variable or similar variable in cygwin. Or explicitly give the full path to your compiler to configure.
add the path to your libraries to the runtime libraries path LD_LIBRARY_PATH for linux environment or similar variable in cygwin. In one of my cases, the problem was that the test program that autotools uses to test the compiler could not run. It was successfully compiled but could not run. I installed all the libraries that my project uses in a path that was not included in library path. What happened was that the path to those libraries were set in the configure.ac or makefile.am so that the compiling was OK. But the running of the test program included in configure could not find them. This is a problem mostly for dynamically linked libraries. Adding the path to my .so to the LD_LIBRARY_PATH solved the problem.
well, I can not really help. The only solution that I can suggest is to install a linux system (dual boot or virtual machine) if you know how to do it, because I will not be there to help.
The following link can also help.

How can I link to an older version of a shared library

I'm building my program on my computer, on which libtiff.so -> libtiff.so.5.
And then pushing the builds on another machine on which libtiff.so -> libtiff.so.4.
At runtime, my program exists : « error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory ».
I cannot upgrade the other machine, and I would like to avoid compiling on a virtual machine (with the same linux version than the executing machine). Therefore, I would like to force the compiler to use the libtiff.so.4 instead of libtiff.so.5.
I have libtiff.so.4 installed on my computer (as well as libtiff.so.5). How can I force the linkage with this version instead of the newer version. I thought about moving the libtiff.so -> libtiff.so.4, but I'm afraid of breaking my system if it needs the latest version (apt-get purge libtiff5 gives an error because some other package needs it).
Is it possible to link with an older (installed) version of a library? If yes, how?
And is it harmfull to change the symbolic link of libtiff.so to the older version? If not, will it solve my issue?
You can use this syntax to link to a specific version of a library:
gcc [other options] -l:libtiff.so.4
You do not need to specify a path; the usual directories are searched in order to find the library.
Note: as Michael Wild mentioned, you should have the header files for that version installed instead of the newest ones.
As others have mentioned, you can force the linker by specifying the full versioned name, or even the absolute path.
However, I would strongly advice against doing so. The problem is, that the installed headers correspond to the newer version of the library. If there have been API/ABI-breaking changes between these library versions, the program might work, crash intermittently, or if you're lucky, not work at all.
Instead you should temporarily install the development package that corresponds to the libtiff.so.4 library. If on Debian/Ubuntu or similar, this would be the libtiff4-dev package.
Specify the full path to the .so: instead of -ltiff pass /lib64/libtiff.so.4 to the linker.
You see that error when application is running. So you can either stop your application and then exrract your library tar file. Or, force to link the lib file to the newer version after you extract. In second case, you will use something like:
ln -fs libversionname libfile
Example:
ln -fs libomyapp.1.1.3 libomyapp.lib
This links your libomyapp.lib to the version specified. This can be your older vsersion or your newer version.
But as said, best way to work is to bring down your application to properly match to the expected lib functionality to work without errors or issues.

Issues with linking library C++

My problem is I am not able to include a library into my current project. [The way to include a library in netbeans into a project is to link it via linker to the project]. However, in my current project(which is written by another programmer who left the organization) the option of linker is not appearing. I have attached a screenshot. I am faced with the issue that the option of linking the library via linker to my current project is not appearing in IDE. Can someone please please help me out. I'll be highly thankful to you for the same.
Please guide me as to how should I link the library to my project. I have really spent a lot of days doing it but I did not succeed.
Assuming you are only interesting in libspatialindex:
Make sure you have the appropriate files installed: try a locate libspatialindex and see where it is installed. You could have a *.a, *.so or similar extension. Note the path.
Go into your project root directory, i.e: /home/keira/netbeans/projects/myproject
Try: gcc -i main.cpp -L/usr/lib/ -lspatialindex -o myfile
Replace the -L/usr/lib with the actual location where you know the library is at.
The cxx link flag is usually the name of the library with an -l prefix. If for example the name found in the system is libspatialindex.so then its a good bet to try with -lspatialindex.
There is a way to find the actual flags on Debian & Ubuntu systems but I cannot atm remember it. Alternatively you can always look on google or read the library documentation.
When you usually see linker errors with undefined functions, etc, it means you're not linking, provided you have included the headers and they are found.
Now for Netbeans, I assume there is the option of passing extra arguments to the compiler. In this case, all you need is the -lspatialindex flag, provided Netbeans knows where to find the library and the headers. That is how it works in KDevelop and other IDE's I have used.
Alternatively if you want more control and more automation, you may want use a tool like cmake.

Using 3rd Party Libraries in C++

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.