Linking to GNU scientific library on cluster? - c++

I am running a code (iHARM2D) which requires the GNU scientific library library (GSL) on a cluster. Since the GSL library is not installed on the cluster, I have to compile it there and properly link it during compilation of the actual code. In my shell script I write
cd whereGSLsource
./configure --prefix=/homefolder/iHARM/GSLcompiled
make && make install
This compiles the GSL and puts the results in /homefolder/iHARM/GSLcompiled/lib, /homefolder/iHARM/GSLcompiled/include etc.
According to this answer, I should be able to compile by writing the following lines into my shell script before compilation of my main code
export CPATH="/homefolder/iHARM/GSLcompiled/include":$CPATH
export LIBRARY_PATH="/homefolder/iHARM/GSLcompiled/lib":$LIBRARY_PATH
However, this does not seem to link GSL properly because the compilation returns errors of the type "undefined reference to `gsl_some_function'". (It works on my computer when default installation and linking of GSL is used.)
Another possibility suggested by the GSL output during compilation or this answer is to modify the LD_LIBRARY_PATH variable
LD_LIBRARY_PATH="/homefolder/iHARM/GSLcompiled/lib":$LD_LIBRARY_PATH
But this gives the same result. Similarly it does not when I try to link using the -L and -I option
cd iHARM
gcc -someoptions -I../GSLcompiled/include/ -L../GSLcompiled/lib ./some.o -o harm
Another option suggested by GSL was to use
gcc -someoptions -Wl,-rpath -Wl,"/homefolder/iHARM/GSLcompiled/lib" ./some.o -o harm
However, neither of these work.
How do I link the GSL properly then?
(I am not very experienced in this so this might also be some really basic mistake in the syntax or so.)

Run first configure --help; you'll find out that it accepts the --enable-static option which you do want to use.
BTW you could (and probably should) install Linux on your laptop and compile on it (then scp a mostly statically linked binary to your cluster).
You'll better share a common --prefix for all your autoconf-ed software. See this. Read the documentation of autoconf. Let's suppose you always use --prefix=$HOME/soft (which don't require any root permission).
You could compile with make then do a make install DESTDIR=/tmp/gslinst so that installed things go into /tmp/gslinst which you would inspect and latter copy appropriately to a directory related to your prefix.
You'll find both libgsl.a and libgslcblas.a. On my Debian system, the libgsl-dev package provides them (so I don't need to rebuild it).
Then you'll use these static libraries. You could provide a full path for them, that is use $HOME/soft/lib/libgsl.a explicitly in your linking gcc command for harm, e.g. link it with
gcc some.o $HOME/soft/lib/libgsl.a -o harm
but YMMV. Order of arguments to gcc matters a lot.
You don't need or want to mess with $LD_LIBRARY_PATH or -Wl,-rpath with static linking. Read about rpath when you want dynamic linking.
See also what pkg-config tells.

Related

Google ORTools C++ Makefile

I'm using ortools in c++ to model a vehicle routing problem. I was wondering whether there was a way to compile the code using my own Makefile by including the proper flags for the compiler, so that I don't have to use
make build SOURCE=/path/to/my/program
I have compiled ortools from source on Debian 10, making sure to follow the proper instructions on the guide (make third-party then make cc then make install_cc). make test_cc runs and finished without problems, so I don't think there is any issues with the installation.
The only clue that I found about this topic was someone writing they used
g++ -std=c++11 -o my_program my_program.cc -I/usr/local/include/or-tools -lortools
to compile their program, but upon trying that, I have a lot of undefined references. I have read somewhere that one should use -std=c++17 instead of -std=c++11 but either way it does not work.
Please let me know if you need more details.
All binary packages comes with a supplied makefile.
You can see the source here: https://github.com/google/or-tools/blob/stable/tools/Makefile.cc.java.dotnet
If you run make detect_cc. It will print out all compiling and linking options for your platform.
Since ortools is a shared library, you will have to specify its path using the environment variable LD_LIBRARY_PATH in addition to specifying the path using the -L flag.
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:<path-to-lib>.
You can put the export command above in the .bashrc file or run it every time your run the code. Also, you will have to used C++17.

How does the GNU linker decide what C/C++ library files are needed?

I'm building PHP7 on an OpenWRT machine (an ARM router). I wanted to include MySQL, so I had to build that as well. OpenWRT is 99.5% ordinary linux, but there are some weird building / shared library things that probably don't get exercised often, so I've run into some difficulties.
MySQL builds OK (after some screwing around) and I have a libmysqlclient.so that works. However, the configure process for PHP7 fails when trying to link the MySQL test program, because libmysqlclient.so must be linked with the C++ standard libraries, not the C standard libs. (MySQL is apparently at least partially C++, and it uses std::...stuff....) Configure tries to compile the test program with gcc, which doesn't include the C++ libraries in the link, so the test fails.
I bodged over this by making a simple C/C++ switching script: if the command line includes -lmysqlclient then I exec g++ $* else exec gcc $*. Then I told configure to use my script as the C compiler.
It occurs to me that there must be a better way to handle this, though. It seems like libmysqlclient.so should have some way to tell the linker that it also needs libstdc++.so, so that even if gcc is used to link, all the necessary libraries would get pulled in.
Is there some way to mark dependencies in libmysqlclient.so? Or to make configure smarter about running test programs?
You should virtually never try to link with the C++ standard library manually. Use g++ for linking C++ programs. gcc knows the minute details of what library to use and where it lives, so you don't have to.
Now the question is, when to use g++, and when not to. One possible answer to that question is "always use g++". There is no harm in it. g++ can link C programs just fine. There is no overhead in the produced program. There might be some performance loss in the link process itself, but it probably won't be noticeable for any but the most humongous of programs.

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.

Linux C++ linker /usr/bin/ld

I wrote a small application on Redhat Linux 6 using g++ 4.4.6. After compilation, I received an error
/usr/bin/ld: cannot find -lcrypto
I did a search for the crypto library and find them here,
[root#STL-DUNKEL01 bin]# find / -name libcrypto*
/usr/lib64/libcrypto.so.0.9.8e
/usr/lib64/libcrypto.so.10
/usr/lib64/libcrypto.so.6
/usr/lib64/libcrypto.so.1.0.0
My question is whether the compilation error is caused by /usr/bin/ld not having /usr/lib64/ in the search path? If yes, how can I add it?
Thanks.
No, you have likely incorrectly diagnosed the cause.
You need a libcrypto.so to link against. This is usually a symlink to one of the actual libraries, whose soname (libcrypto.so.??) will be embedded into the binary. Only that library is needed at runtime, but the symlink is necessary to compile.
See Diego E. Pettenò: Linkers and names for more details.
You have to add -L/usr/lib64 when calling gcc or ld.
Note, you can specify LD_LIBRARY_PATH as well/instead, but it is considered harmful to do so. (The link mentions Solaris specifically, but the issues apply to other OSs as well.)
Quote:
LD_LIBRARY_PATH is used in preference to any run time or default system linker path. If (God forbid) you had it set to something like /dcs/spod/baduser/lib, if there was a hacked version of libc in that directory (for example) your account could be compromised. It is for this reason that set-uid programs completely ignore LD_LIBRARY_PATH.
When code is compiled and depends on this to work, it can cause confusion where different versions of a library are installed in different directories, for example there is a libtiff in /usr/openwin/lib and /usr/local/lib. In this case, the former library is an older one used by some programs that come with Solaris.
Sometimes when using precompiled binaries they may have been built with 3rd party libraries in specific locations; ideally code should either ship with the libraries and install into a certain location or link the code as a pre-installation step. Solaris 7 introduces $ORIGIN which allows for a relative library location to be specified at run time (see the Solaris Linker and Libraries Guide). The alternative is to set LD_LIBRARY_PATH on a per-program basis, either as a wrapper program to the real program or a shell alias. Note however, that LD_LIBRARY_PATH may be inherited by programs called by the wrapped one ...
Add the directory to /etc/ld.so.conf
then run "sudo ldconfig" to make the changes take effect.
You can provide the directories to search for the libraries in as a parameter to gcc like so -L<directory_to_search_in>. And note that there can be multiple parameters to -L. Also, are you trying to build a 32-bit application or a 64-bit one?

How to make a library in c++ in linux

I am writing a small application in c++ and I have some questions regarding that. I am basically a Java developer now moving into c++.
If I use some library like boost, curl etc. can I make it run without installing that on the client machine (I mean something like including all library jar files inside the project in Java)
I have installed some library or software in linux. After that if I type in the terminal it pings the software. For example php, after you install it you can use php from terminal. How does this work? Can I use my simple c++ project to do so?
Yes. You use a process called static linking, which links all the libraries into one big executable. In ./configure scripts (from autotools), you use the --enable-static flag. When building your program, you use the -static flag. The static libraries are the ones with the .a suffixes; shared libraries use .so, sometimes with a version number suffix).
PHP is not a library, it is a language (i.e. executable) which provides its own command-line interface. Your C++ executable can work similarly, you just have to get the input from cin (in <iostream>) and write results to cout, using cerr for error messages.
Your title question, "How to make a library in c++ in linux" (as opposed to using a library): You use the ar program to link several .o files into a single .a library file. You can also use ranlib to clean up the .a file. Read the man pages for those commands to see how they are used.
1)Answer to your Q1 is compilation with libraries statically linked. For example with gcc Compiler:
# gcc -static myfile.c -o myfile
2)Answer to you Q2 is appending the absolute path of executable to $PATH Environment Variable. For example in Bash shell:
# export PATH=${PATH}:/home/user/pathofexecutable
The above setup will be temporary only for that terminal you do. To make it available to all terminal in you machine add the above export command to /home/user/.bashrc file.
For question 1, you want to compile the program as a static executable. (Just pass -static to g++.) It will make the program much larger since it needs to include a copy of stuff normally kept as libraries.
For question 2 I'm pretty sure what you mean is having a program in the PATH. Type echo $PATH to see the path on your current machine. If you install your program in one of those directories it will run from anywhere. (Most likely /usr/local/bin/)