How to Link lapack and BLAS library to C++ code - c++

The above are linear algebra libraries. i am using armadillo which is like a c++ wrapper/framework for linking to more basic linear algebra libraries in fortran.
I can compile the example.cpp easily by having a #include "armadillo" using gcc -c option with the -I flag.
This generates example.o which is now supposed to be linked to liblapack_LINUX.a and libBLAS_linux.a Statically
Locations of the two:
liblapack_LINUX.a :-/home/nimish/HTMLProjects/WP2/lib/lapack/
libBLAS_linux.a :-/home/nimish/HTMLProjects/WP2/lib/blas
I issue the following command:
gcc -o example.o -L../lib/blas -lblas_LINUX -L../lib/lapack -llapack_LINUX
OR with absolute paths
nimish#ubuntu:~$ gcc -o example.o -L/home/nimish/HTMLProjects/WP2/lib/blas -lblas_LINUX -L/home/nimish/HTMLProjects/WP2/lib/lapack -llapack_LINUX
to get the error:
/usr/bin/ld: cannot find -lblas_LINUX
collect2: ld returned 1 exit status
However the libraries do exist --
nimish#ubuntu:~$ find /home/nimish/HTMLProjects/WP2 -name liblapack_LINUX.a
/home/nimish/HTMLProjects/WP2/lib/lapack/liblapack_LINUX.a
nimish#ubuntu:~$ find /home/nimish/HTMLProjects/WP2 -name libblas_LINUX.a
/home/nimish/HTMLProjects/WP2/lib/BLAS/libblas_LINUX.a
What am i doing wrong? I am somewhat new to this linking libraries business as well as gcc.

first you need to ensure you have BLAS installed using(+lapack)
sudo apt-get install libblas-dev liblapack-dev
then you can link using -lblas after your program files. or you can use a make file.
from my side I prefer to use OpenBlas instead, you can use the following in a makefile.
www.openblas.net, get the tar.gz
copy it in your directory
extract it : tar -zxvf OpenBLAS-0.2.20.tar.gz
compile it : cd OpenBLAS-0.2.20
make
When it is done you should have the file libopenblas.a, the openblas library
BLASLIB = OpenBLAS/libopenblas.a -lpthread

Related

How do I install and use PNGwriter to write PNG image files?

I'd like to learn how to write PNG images pixel-by-pixel using both RGB and HSV color models with C++. I read that this should be fairly easy using PNGwriter (https://github.com/pngwriter/pngwriter), but I've spent many hours struggling with installing it (on Ubuntu) and compiling my code with it. Any help would be much appreciated.
Disclaimer: I have a weird background in the sense that I have many years of experience in using Unix-like operating systems, doing stuff in the terminal, and writing code, but I know little/nothing about installing software from the source code or compiling programs manually or with makefiles from multiple source code files.
The installation instructions on GitHub advise to do one of the following:
Spack:
spack install pngwriter
spack load pngwriter
From Source:
First install the dependencies zlib, libpng, and (optional for text support) freetype. PNGwriter >can then be installed using CMake:
git clone https://github.com/pngwriter/pngwriter.git
mkdir -p pngwriter-build
cd pngwriter-build
# for own install prefix append: -DCMAKE_INSTALL_PREFIX=$HOME/somepath
cmake ../pngwriter
make -j
# optional
make test
# sudo is only required for system paths
sudo make install
I managed to install Spack and then PNGwriter, but couldn't compile the simplest program with it and wasn't able to figure out why. I then installed PNGwriter manually, but still couldn't compile anything with it. This was many hours of struggling ago so I, unfortunately, don't remember what kind of errors or problems I was encountering at this point.
The instructions on GitHub say the following about linking:
First set the following environment hint if PNGwriter was not installed in a system path:
# optional: only needed if installed outside of system paths
export CMAKE_PREFIX_PATH=$HOME/somepath:$CMAKE_PREFIX_PATH
Use the following lines in your projects CMakeLists.txt:
find_package(PNGwriter 0.7.0)
if(PNGwriter_FOUND)
target_link_libraries(YourTarget PRIVATE PNGwriter::PNGwriter)
endif(PNGwriter_FOUND)
Questions: How do I know if PNGwriter was or wasn't installed in a system path? I have libPNGwriter.a in /usr/local/lib and pngwriter.h in /usr/local/include --- does this mean that it was installed in a system path? When installing I simply tried to follow the instructions above. Do I just type the environment hint to the terminal or add it to some file? If the former then does it need to be given every time I open a new terminal session? Is "somepath" /usr/local/lib, /usr/local/include or something else?
Questions: Does the second part regarding "CMakeLists.txt" depend on whether PNGwriter was installed in a system path? What is "CMakeLists.txt"? I assume it's some file one's IDE creates, but my NetBeans projects don't seem to contain such files. What if I have a single source file and compile it manually in the terminal?
Now, let's say I'd like to compile the PNGwriter quickstart example:
#include <pngwriter.h>
int main()
{
int i;
int y;
pngwriter png(300, 300, 0, "test.png");
for(i = 1; i ≤ 300; i++)
{
y = 150 + 100*sin((double)i*9/300.0);
png.plot(i, y, 0.0, 0.0, 1.0);
}
png.close();
return 0;
}
The PNGwriter manual instructs to compile as
g++ myprogram.cc -o my_program `freetype-config --cflags` -I/usr/local/include -L/usr/local/lib -lpng -lpngwriter -lz -lfreetype
but I get errors
$ g++ example.cpp -o example `freetype-config --cflags` -I/usr/local/include -L/usr/local/lib -lpng -lpngwriter -lz -lfreetype
Package freetype2 was not found in the pkg-config search path.
Perhaps you should add the directory containing `freetype2.pc'
to the PKG_CONFIG_PATH environment variable
Package 'freetype2', required by 'virtual:world', not found
Package freetype2 was not found in the pkg-config search path.
Perhaps you should add the directory containing `freetype2.pc'
to the PKG_CONFIG_PATH environment variable
Package 'freetype2', required by 'virtual:world', not found
Package freetype2 was not found in the pkg-config search path.
Perhaps you should add the directory containing `freetype2.pc'
to the PKG_CONFIG_PATH environment variable
Package 'freetype2', required by 'virtual:world', not found
Package freetype2 was not found in the pkg-config search path.
Perhaps you should add the directory containing `freetype2.pc'
to the PKG_CONFIG_PATH environment variable
Package 'freetype2', required by 'virtual:world', not found
sed: -e expression #1, char 0: no previous regular expression
sed: -e expression #1, char 0: no previous regular expression
In file included from example.cpp:1:0:
/usr/local/include/pngwriter.h:66:22: fatal error: ft2build.h: No such file or directory
compilation terminated.
The answer to this Stack Overflow question (Trying to install pygame on ubuntu which gives error) suggests to install libfreetype6-dev, but I apparently have the latest version already whereby the errors remain unchanged. If I instead actually add the directory containing freetype2.pc (I found it by going to / and using find -name "freetype2.pc") to the environment variable (added export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig/:$PKG_CONFIG_PATH to ~/.bashrc and did source ~/.bashrc) then I get new errors
$ g++ example.cpp -o example `freetype-config --cflags` -I/usr/local/include -L/usr/local/lib -lpng -lpngwriter -lz -lfreetype
/usr/bin/ld: cannot find -lpngwriter
collect2: error: ld returned 1 exit status
Here I figured out that I needed to replace -lpngwriter with -lPNGwriter (i.e., the manual is erroneous). Then I get:
$ g++ example.cpp -o example `freetype-config --cflags` -I/usr/local/include -L/usr/local/lib -lpng -lPNGwriter -lz -lfreetype
/usr/bin/ld: /usr/local/lib/libPNGwriter.a(pngwriter.cc.o): undefined reference to symbol 'png_set_sig_bytes##PNG12_0'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libpng.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
This is where I'm currently stuck. I can't seem to find a solution by googling (at least one that I'd understand).
Question: How do I get this working? How do I get it working in NetBeans? Do I get these problems because I effed up the linking step above?
Edit1: As per john's comment, I tried swapping -lpng and -lPNGwriter and I again get new errors:
$ g++ example.cpp -o example `freetype-config --cflags` -I/usr/local/include -L/usr/local/lib -lPNGwriter -lpng -lz -lfreetype
/usr/local/lib/libPNGwriter.a(pngwriter.cc.o): In function `pngwriter::close()':
pngwriter.cc:(.text+0x41c2): undefined reference to `png_convert_to_rfc1123_buffer'
/usr/local/lib/libPNGwriter.a(pngwriter.cc.o): In function `pngwriter::read_png_info(_IO_FILE*, png_struct_def**, png_info_def**)':
pngwriter.cc:(.text+0x4fdf): undefined reference to `png_set_longjmp_fn'
collect2: error: ld returned 1 exit status
I'm still left clueless.
Thanks to john, I think I got it figured out. My guess is that the installation from the source (after the Spack installation) messed things up somehow. I reinstalled PNGwriter using Spack and, now apparently having all the pieces for the compilation command, was finally able to compile the example code.
Summary:
Source Spack
# For bash/zsh/sh
$ . spack/share/spack/setup-env.sh
# For tcsh/csh
$ source spack/share/spack/setup-env.csh
# For fish
$ . spack/share/spack/setup-env.fish
Install using Spack (skip if already installed)
spack install pngwriter
Load PNGwriter (I guess one needs to do this in every new terminal session)
spack load pngwriter
Compile (note that this isn't quite what the PNGwriter manual suggests)
g++ example.cpp -o example `freetype-config --cflags` -I/usr/local/include -L/usr/local/lib -lPNGwriter -lpng -lz -lfreetype

Building GDAL with all libraries static

I want to develop a small program that checks which polygons from a shapefile intersect a given rectangle. This program is to be used in a website (with PHP's exec() command). The problem is, my webserver cannot install GDAL, for reasons unknown to me. So I can't link to the shared libraries. Instead, I must link to static libraries, but these aren't given.
I've downloaded the GDAL source code from here (2.3.2 Latest Stable Release - September 2018), and followed the build instructions from here. Since I already have GDAL working on my Debian, and don't want to mess with it, I followed the "Install in non-root directory" instructions, with some adjusts from the last item in the "Some caveats" section:
cd /home/rodrigo/Downloads/gdal232/gdal-2.3.2
mkdir build
./configure --prefix=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/ --without-ld-shared --disable-shared --enable-static
make
make install
export PATH=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/bin:$PATH
export LD_LIBRARY_PATH=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib:$LD_LIBRARY_PATH
export GDAL_DATA=/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/share/gdal
/usr/bin/gdalinfo --version
build/bin/gdalinfo --version
The first /usr/bin/gdalinfo --version gives 2.1.2 (the previous installed version). The second, build/bin/gdalinfo --version, gives 2.3.2 (the version just built).
By now, my program only uses the ogrsf_frmts.h header, which is in /usr/include/gdal/ or /home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/include/ directory, depending on the build. There's no ogrsf_frmts.a file, but only a libgdal.a. Is this the file I should be linking against? If so, how? I've tried so far:
gcc geofragc.cpp -l:libgdal.a
gcc geofragc.cpp -Wl,-Bstatic -l:libgdal.a
gcc geofragc.cpp -Wl,-Bstatic -l:/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp -Wl,-Bstatic -l/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp /home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp -l/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
gcc geofragc.cpp -l:/home/rodrigo/Downloads/gdal232/gdal-2.3.2/build/lib/libgdal.a
but nothing works. What am I missing?
EDIT
The second trial (gcc geofragc.cpp -Wl,-Bstatic -l:libgdal.a) is giving the following error:
/usr/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-linux-gnu/6/../../../../lib/libgdal.a(gdalclientserver.o): In function `GDALServerSpawnAsync()':
(.text+0x1f5e): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
You can use the gdal-config program to get correct options for compilation and linking. This program is a part of the GDAL library and it has its own options:
hekto#ubuntu:~$ gdal-config --help
Usage: gdal-config [OPTIONS]
Options:
[--prefix[=DIR]]
[--libs]
[--dep-libs]
[--cflags]
[--datadir]
[--version]
[--ogr-enabled]
[--gnm-enabled]
[--formats]
You have to make sure this program is on your search path, or you can create an alias - for example:
alias gdal-config='/home/rodrigo/Downloads/gdal232/gdal-2.3.2/bin/gdal-config'
Now your compilation and linking command becomes the following one:
g++ `gdal-config --cflags` geofragc.cpp `gdal-config --libs` `gdal-config --dep-libs`
You have to use the g++ compiler to link with C++-built libraries.
Another option is to create a Makefile with these lines:
CXXFLAGS += ${shell gdal-config --cflags}
LDLIBS += ${shell gdal-config --libs}
LDLIBS += ${shell gdal-config --dep-libs}
geofragc: geofragc.cpp
and just call make with this Makefile.
I hope, it'll help.

Speed up RcppArmadillo: How to link to OpenBlas in an R package

I am working on an R package which uses RcppArmadillo. I am trying to take advantage of faster matrix multiplication found in OpenBLAS. In the documentation of the C++ armadillo library, it says if we have OpenBLAS on our machine then Armadillo would use OpenBLAS instead of BLAS. However, when I compile my R package, I get something like this:
g++ -m64 -std=c++11 -shared -L/usr/lib64/R/lib -Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -o PackageTest.so class1.o class2.o class3.o class4.o class5.o class6.o class7.o RcppExports.o class8.o class9.o class10.o -L/usr/lib64/R/lib -lRlapack -L/usr/lib64/R/lib -lRblas -lgfortran -lm -lquadmath -L/usr/lib64/R/lib -lR
So it is compiling with the -lRlapack and -lRblas options. How can I properly modify the Makevars and Makevars.win files to have RcppArmadillo compile the package with the option -lopenblas? My attempt to solve this problem was to modify the Makevars file in the following way:
PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_CXXFLAGS =-fopenmp -std=c++11 -lopenblas
PKG_CXX1XFLAGS = $(PKG_CXXFLAGS)
The package did compile with -lopenblas, but is this the best way to do it?
That is a problem with your RedHat installation which chose to rely on the internal LAPACK sources for R when installing R --- plus the fact that RcppArmadillo uses whatever R uses.
On my Debian/Ubuntu based machine, it happens differently. Ie for
R> library(Rcpp)
R> cppFunction("arma::mat foo(arma::mat x) { return x + x;} ", depends="RcppArmadillo", verbose=TRUE)
I get (inter alia)
g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions \
-Wl,-z,relro -o sourceCpp_4.so file677111d81351.o \
-fopenmp -llapack -lblas -lgfortran -lm -lquadmath \
-L/usr/lib/R/lib -lR
and we see -llapack -lblas -lgfortran as expected.
Instructions for compiling R, OpenBLAS and linking R with OpenBLAS (GNU/Linux)
I believe your biggest problem is linking R to the OpenBLAS library. So the steps I write below can help you succeed in this link.
Compiling OpenBLAS
Initially download the R and OpenBLAS(Open Optimized BLAS Library) source codes in OpenBLAS. In the file directory, perform the following steps.
tar -zxvf OpenBLAS*
cd OpenBLAs*
make -j $nproc
sudo make install
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/
or
git clone https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS*
make -j $nproc
sudo make install
export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/
Note: This will make the compilation run faster using all the features of your CPU. To know the number of cores, do: nproc.
Compiling Armadillo C++ with OpenBLAS
For those who use C++ codes in R using the Rcpp library, setting up the Armadillo with the OpenBLAS library may be of some benefit.
tar -xvf armadillo*
cd armadillo*
./configure -DCMAKE_PREFIX_PATH=/opt/OpenBLAS/lib/
cmake . -DCMAKE_PREFIX_PATH=/opt/OpenBLAS/lib/
make -j $nproc
sudo make install
Note: Further details regarding the compilation of the Armadillo library can be found at https://gitlab.com/conradsnicta/armadillo-code.
Compiling R with OpenBLAS
After compiling OpenBLAS, download the R code. It is not necessary to compile R to make use of OpenBLAS, but compiling the language may bring some benefits that may be insignificant depending on what is being done in R. That way, download the source code of the language R.
Note: In my operating system, Arch Linux, OpenBLAS) was installed in the /opt directory. Search for the OpenBLASinstallation directory in your GNU/Linux distribution.
In the directory where the R was downloaded, do the following:
tar -zxvf R*
cd R-* && ./configure --enable-R-shlib --enable-threads=posix --with-blas="-lopenblas -L/opt/OpenBLAS/lib -I/opt/OpenBLAS/include -m64 -lpthread -lm"
make -j $nproc
sudo make install
Most likely the OpenBLAS library will be bound to R. To check, run in the R the sessionInfo() code. Something like the output below should appear:
Matrix products: default
BLAS/LAPACK: /opt/OpenBLAS/lib/libopenblas_haswellp-r0.3.6.dev.so
If linking does not occur, follow the steps outlined in the code below.
We need to link the R with the file libopenblas_*, created in the process of compiling the library OpenBLAS. In my case, the file is ibopenblas_haswellp-r0.2.20.so. Look for this in /opt/OpenBLAS/lib or in the directory where OpenBLAS was installed on your GNU/Linux system. Also look for the libRblas.so file directory found in the R language installation directory. In Arch, this directory is /usr/local/lib64/R/lib.
cd /usr/local/lib64/R/lib
mv libRblas.so libRblas.so.keep
ln -s /opt/OpenBLAS/lib/libopenblas_haswellp-r0.2.20.so libRblas.so
Start a section of language R and do sessionInfo(). You should note something like:
Matrix products: default
BLAS/LAPACK: /opt/OpenBLAS/lib/libopenblas_haswellp-r0.3.6.dev.so
To make use of multithreaded processing, do export OPENBLAS_NUM_THREADS=1 before starting a R section.
NOTE: For intel processors,sudo cpupower frequency-set -g performance, can boost performance. Read more at https://wiki.archlinux.org/index.php/CPU_frequency_scaling.

compiling boost.asio using g++ compiler

I'm new to g++ compiler and also trying to start coding with boost.asio libraries, but have some difficulties compiling the code using g++.
I have installed boost libraries usingsudo apt-get install libboost-all-dev and boost folder is located in /usr/include directory, and whole scenario:
geek#ubuntu:~/workspace/HelloBoost/src$ g++ -I /usr/include/ -l boost_asio HelloBoost.cpp
/usr/bin/ld: cannot find -lboost_asio
collect2: ld returned 1 exit status
Thanks for your answers.
Did you read about using boost.asio ? Apparently, it looks like a headers only library, and you only need to link -lboost_system -lboost_regex -lopenssl

libboost-system linker errors when cross-compiling to x86

I'm trying to build a 32-bit application on Ubuntu 11.04 x64. I'm having some issues with the build because of linker errors with libboost. The build statement has -lboost_system in it, but when I try to build I get a bunch of these:
CommunicationModule.cpp:(.text+0x68c1): undefined reference to boost::system::generic_category()
CommunicationModule.cpp:(.text+0x68d7): undefined reference to boost::system::system_category()
Everything I've found on google says I need to link to the boost_system library. One place I found says to try linking to it directly, but when i do locate boost_system the result is empty. When I try doing a sudo apt-get install libboost-system-dev it tells me that it's already installed. I'm kind of at a loss here. The library is installed, but it's not being found by locate?
Can anyone tell me what I need to do to properly link to boost::system? I'm fairly new to linux and the complexities of compilers so any help here would be appreciated.
Update:
Here is the output of dpkg -L libboost-system1.42-dev:
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libboost-system1.42-dev
/usr/share/doc/libboost-system1.42-dev/copyright
/usr/share/doc/libboost-system1.42-dev/NEWS.Debian.gz
/usr/share/doc/libboost-system1.42-dev/README.Debian.gz
/usr/lib
/usr/lib/libboost_system.a
/usr/lib/libboost_system-mt.so
/usr/lib/libboost_system-mt.a
/usr/lib/libboost_system.so
Is there a flag I can use to link to one of these directly? I tried using -L /usr/lib/libboost_system.so and -L /usr/lib/libboost_system-mt.so and neither of those fixed the issue. Same with just adding /usr/lib/libboost_system.a and /usr/lib/libboost_system-mt.a to the build statement.
Here is the compilation line:
g++ -m32 -Wl,-O1 -o UTNaoTool [.o files] -L/usr/lib32 -lqglviewer-qt4 -lqwt-qt4 -lboost_system -lboost_thread -lQtXml -lQtOpenGL -lQtGui -lQtNetwork -lQtCore -lGLU -lpthread
Update 2:
I downloaded boost 1.49 and built everything for 32-bit and that seemed to help. A lot of the errors went away, but now I still have these:
CommunicationModule.cpp:(.text+0x68c1): undefined reference to
boost::system::get_generic_category()
Note that the function is different. So all of my errors are regarding undefined references to get_system_category() and get_generic_category() now. I tried adding a -lboost_filesystem to the build command but that didn't fix this, and I made sure it was referencing the 32-bit library that I built when I built libboost_system.
Looking at my own installation, it seems libboost-system-dev does not install the libraries. Using dpkg to tell me what was installed bz libboost-system-dev I get:
$ dpkg -L libboost-system-dev
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libboost-system-dev
/usr/share/doc/libboost-system-dev/copyright
/usr/share/doc/libboost-system-dev/changelog.gz
Poking around, I think you need to install libboost-system1.48.1 (or some other version).
sudo apt-get install libboost-system1.XX.Y
You can also search fo rthe libraries using the find command, for example, search under /usr for all files starting with libboost_system:
find /usr -name "libboost_system*"
Edit: Since you are cross-compiling from a 64 bit OS to a 32 bit one, you need 32 bit versions of the boost libraries. I would be tempted to set up a small 32 bit virtual machine to do this, rather than cross-compiling all the dependencies.
I had the same problem with boost_serialization here is what i found out after couple of googling..
first this library need to be compiled separately :
so after downloading the boost library ,extract it and execute sudo ./bootstrap.sh' then
sudo ./b2 --with-system
after this step you should be find a result when executing locate boost_system
then to link it manually I did:
both should work
g++ boostexample.cpp -o run /PATH/libboost_serialization.a
g++ boostexample.cpp -o run -L/PATH/ -lboost_serialization
well this is a little work around and I'm still looking for how to link the library properly
I hope this helped :)