Ld wrong symbol - c++

I'm buildnig application with boost.python library. I want to link it. Here is the code:
#include <boost/python.hpp>
using namespace boost::python;
// Boost.python definitions to expose classes to Python
BOOST_PYTHON_MODULE(arrayClasses) {
}
And makefile for it:
PYTHON = /usr/include/python2.7
BOOST_INC = /usr/include
BOOST_LIB = /usr/lib
TARGET = arrayClasses
$(TARGET).so: $(TARGET).o
g++ -shared -Wl,--export-dynamic \
$(TARGET).o -L$(BOOST_LIB) -lboost_python \
-L/usr/lib/python2.7/config -lpython2.7 \
-o $(TARGET).so
$(TARGET).o: $(TARGET).cpp
g++ -I$(PYTHON) -I$(BOOST_INC) -c -fPIC $(TARGET).cpp
When I compile it I get:
g++ -shared -Wl,--export-dynamic \
arrayClasses.o -L/usr/lib -lboost_python \
-L/usr/lib/python2.7/config -lpython2.7 \
-o arrayClasses.so
/usr/bin/ld: arrayClasses.o: relocation R_X86_64_32 against `init_module_arrayClasses()' can not be used when making a shared object; recompile with -fPIC
arrayClasses.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
What's wrong is there?

You have -fPIC for your .o target, but not
for the .so target. See if adding it helps.
Edit: Ignore that. This compiles for me on a 32-bit Ubuntu system using Python 2.6 and Boost 1.44. As Ignacio Vazquez-Abrams pointed out, you should probably check if your Python and Boost libraries were compiled for the same architecture.

Related

c++: making a shared object from a static library

we are trying to make a c++ shared object library to interface with a static fortran library (compiled with mpif90). There is one fortran wrapper file compiled with gfortran or mpif90 (both fail) and one c++ wrapper file compiled with g++
The compilation command is
g++ -std=c++11 -ftemplate-depth-256 -Wno-inline -fPIC -O3 -pthread -fopenmp -v -I /usr/lib/x86_64-linux-gnu/openmpi/include/ -I /opt/local/nextsim/modules/oasis/include -o /opt/local/nextsim/lib/liboasis.so.1.0 /opt/local/nextsim/objs/./oasis_cpp_interface.o /opt/local/nextsim/objs/./oasis_cpp_interface_ftn.o /docker_io/compile_oa3-mct/lib/libpsmile.MPI1.a /docker_io/compile_oa3-mct/lib/libmct.a /docker_io/compile_oa3-mct/lib/libmpeu.a /docker_io/compile_oa3-mct/lib/libscrip.a -fopenmp -Wl,-rpath,/usr/lib/x86_64-linux-gnu/openmpi/lib/ -L /usr/lib/x86_64-linux-gnu/openmpi/lib/ -lmpi_cxx -lmpi -ldl -lstdc++ -lpthread -L /docker_io/compile_oa3-mct/lib -Wl,-rpath,/usr/lib/x86_64-linux-gnu -L /usr/lib/x86_64-linux-gnu -lnetcdff -shared -Wl,-soname,liboasis.so.1
The error it gives is:
/usr/bin/x86_64-linux-gnu-ld: /docker_io/compile_oa3-mct/lib/libpsmile.MPI1.a(mod_oasis_auxiliary_routines.o): relocation R_X86_64_PC32 against symbol `__mod_oasis_data_MOD_mpi_comm_local' can not be used when making a shared object; recompile with -fPIC
/usr/bin/x86_64-linux-gnu-ld: final link failed: Bad value
As you can see we already compiled with -fPIC (as was the fortran library and the c++ objects). I also tried linking the fortran objects instead of the libraries, but they were also using some other static libraries which gave the same error.
Actually for some reason, our code compiles on one particular server, but not another, and not inside docker (ubuntu) so the problem is a little puzzling.
The -fPIC option is ineffective in your commandline:
g++ -std=c++11 -ftemplate-depth-256 -Wno-inline -fPIC -O3 -pthread -fopenmp -v \
-I /usr/lib/x86_64-linux-gnu/openmpi/include/ -I /opt/local/nextsim/modules/oasis/include \
-o /opt/local/nextsim/lib/liboasis.so.1.0 \
/opt/local/nextsim/objs/./oasis_cpp_interface.o \
/opt/local/nextsim/objs/./oasis_cpp_interface_ftn.o \
/docker_io/compile_oa3-mct/lib/libpsmile.MPI1.a \
/docker_io/compile_oa3-mct/lib/libmct.a \
/docker_io/compile_oa3-mct/lib/libmpeu.a \
/docker_io/compile_oa3-mct/lib/libscrip.a \
-fopenmp -Wl,-rpath,/usr/lib/x86_64-linux-gnu/openmpi/lib/ \
-L /usr/lib/x86_64-linux-gnu/openmpi/lib/ \
-lmpi_cxx -lmpi -ldl -lstdc++ -lpthread -L /docker_io/compile_oa3-mct/lib \
-Wl,-rpath,/usr/lib/x86_64-linux-gnu \
-L /usr/lib/x86_64-linux-gnu -lnetcdff \
-shared -Wl,-soname,liboasis.so.1
because -fPIC is a compilation option and this is a linkage command. No source files
are input. Compilation has already been done. The other compilation options in this commandline:
std=c++11 -ftemplate-depth-256 -Wno-inline -fopenmp
-I /usr/lib/x86_64-linux-gnu/openmpi/include/ -I /opt/local/nextsim/modules/oasis/include \
are also redundant.
The linker says that the object file libpsmile.MPI1.a(mod_oasis_auxiliary_routines.o),
i.e. member mod_oasis_auxiliary_routines.o of the archive libpsmile.MPI1.a, was not
compiled with -fPIC. You say that:
we already compiled with -fPIC (as was the fortran library and the c++ objects).
but it's more likely that -fPIC was not used in the compilation of
the object files in libpsmile.MPI1.a than that the linker is mistaken.
Recompile all the object files input to the linkage, including those within static libraries, ensuring that -fPIC is enabled. All object files that are linked into a shared library must be Position-Independent-Code.

How do I include a library in an .so file in C++

I am trying to compile a .so file the relies on the FTDI library. I'm not sure how to include the library so that it compiles correctly. (Below is my best guess). Is this possible or is there another way to go about it?
shared: pldevice pldeviceenttecpro pluniverse
$(CC) -shared -Wl,-soname,libplanklight.so -o libplanklight.so\
-L/usr/local/lib -lftd2xx \
pldevice.o pldeviceenttecpro.o pluniverse.o
Edit: This is what the output is:
g++ -fPIC -c pldevice.cpp
g++ -fPIC -c pldeviceenttecpro.cpp
g++ -fPIC -c pluniverse.cpp
g++ -shared -Wl,-soname,libplanklight.so -o libplanklight.so\
-L/usr/local/lib -lftd2xx \
pldevice.o pldeviceenttecpro.o pluniverse.o
/usr/bin/x86_64-linux-gnu-ld: cannot open output file libplanklight.so-L/usr/local/lib: No such file or directory
collect2: error: ld returned 1 exit status
Makefile:5: recipe for target 'shared' failed
make: *** [shared] Error 1
You're missing a space.
$(CC) -shared -Wl,-soname,libplanklight.so -o libplanklight.so \
^^
Add a space here
The \ just makes the command continue on the next line, so when you have
-o libplanklight.so\
-L/usr/local/lib
It will be the same as -o libplanklight.so-L/usr/local/lib
But you want -o libplanklight.so -L/usr/local/lib

cannot find -lMagick++-6.Q16

I try to install magick R package but I get error:
g++ -std=gnu++11 -shared -L/path/apps/R/3.5.1-20180807-test/x86_64-linux-2.6-rhel6/lib64/R/lib -L/path/apps/R/static-zlib-gcc6.3/x86_64-linux-2.6-rhel6/lib -Wl,--exclude-libs,libz.a -Wl,--exclude-libs,libbz2.a -Wl,--exclude-libs,libcurl.a -Wl,--exclude-libs,libpcre.a -Wl,--as-needed -o magick.so RcppExports.o animation.o attributes.o base.o color.o composite.o config.o convolve.o device.o edit.o fonts.o options.o properties.o resize.o transformations.o -L/path/apps/R/static-zlib-gcc6.3/x86_64-linux-2.6-rhel6/lib/ /path/apps/R/static-zlib-gcc6.3/x86_64-linux-2.6-rhel6/lib/libcurl.a /path/apps/R/static-zlib-gcc6.3/x86_64-linux-2.6-rhel6/lib/libz.a -Wl,--exclude-libs,libz.a -Wl,--exclude-libs,libcurl.a -lidn -lssl -lcrypto -lldap -lrt -lcairo -L/path/apps/mysql/5.7.11/x86_64-linux-2.6-rhel6/lib -lmysqlclient -lpthread -lm -lrt -ldl -L/path/apps/R/static-zlib-gcc6.3/x86_64-linux-2.6-rhel6/lib -lxml2 -lz -lm -ldl -L/path/apps/V8/3.14/x86_64-linux-2.6-rhel6/lib64 -L/path/apps/openmpi/1.8.1/x86_64-linux-2.6-rhel6/gnu/lsf/lib -L/path/apps/imagemagick/7.0.7-8/x86_64-linux-2.6-rhel6/lib/pkgconfig -lMagick++-6.Q16 -L/path/apps/R/3.5.1-20180807-test/x86_64-linux-2.6-rhel6/lib64/R/lib -lR
/usr/bin/ld: cannot find -lMagick++-6.Q16
collect2: error: ld returned 1 exit status
make: *** [magick.so] Error 1
ERROR: compilation failed for package ‘magick’
My LIB_DIR and INCLUDE_DIR looks like that:
export LIB_DIR="$STATIC_LIB/lib/ $STATIC_LIB/lib/libcurl.a \
$STATIC_LIB/lib/libz.a -Wl,--exclude-libs,libz.a \
-Wl,--exclude-libs,libcurl.a -lidn -lssl -lcrypto -lldap -lrt \
-lcairo $MYSQL_LIBS $XML2_LIBS -L$V8_LIBS \
-L$MPI_HOME/lib \
-L/path/apps/imagemagick/7.0.7-8/x86_64-linux-2.6-rhel6/lib/pkgconfig"
export INCLUDE_DIR="$STATIC_LIB/include -I/usr/include/cairo \
-I/usr/include/pixman-1 -I/usr/include/freetype2 \
-I/usr/include/libpng12 \
-I$MPI_HOME/include \
-I/path/apps/imagemagick/7.0.7-8/x86_64-linux-2.6-rhel6/include/ImageMagick-7"
include contains:
ls /path/apps/imagemagick/7.0.7-8/x86_64-linux-2.6-rhel6/include/ImageMagick-7
Magick++ MagickCore Magick++.h MagickWand
I found this question but my lib directory contains similar set of files:
ls /path/apps/imagemagick/7.0.7-8/x86_64-linux-2.6-rhel6/lib/
ImageMagick-7.0.7 libMagickCore-7.Q16HDRI.so.4
libMagick++-7.Q16HDRI.a libMagickCore-7.Q16HDRI.so.4.0.0
libMagick++-7.Q16HDRI.la libMagickWand-7.Q16HDRI.a
libMagick++-7.Q16HDRI.so libMagickWand-7.Q16HDRI.la
libMagick++-7.Q16HDRI.so.3 libMagickWand-7.Q16HDRI.so
libMagick++-7.Q16HDRI.so.3.0.0 libMagickWand-7.Q16HDRI.so.4
libMagickCore-7.Q16HDRI.a libMagickWand-7.Q16HDRI.so.4.0.0
libMagickCore-7.Q16HDRI.la pkgconfig
libMagickCore-7.Q16HDRI.so
I'm using imagemagick 7 so why it still requires some flag/arg -lMagick++-6.Q16 from version 6?
If pkg-config and Magick++-config are not available, the magick package defaults to ImageMagick v6:
PKG_LIBS="-lMagick++-6.Q16"
So you will have to install version 6. In addition you might also report an issue asking to support version 7 in the case of a installation without pkg-config/Magick++-config.
Alternatively you can try to get pkg-config/Magick++-config working on your machine. If pkg-config/Magick++-config can be used, the flags provided from there are used directly.
I've finally managed to install magick. I compiled ImageMagick v6 from source and installed R package with following set of env variables:
STATIC_LIB="/path/static-zlib-gcc6.3"
IMAGEMAGICK_V6_HOME="/path/ImageMagick-6.9.10-10"
export LIB_DIR="$STATIC_LIB/lib/ \
-L$IMAGEMAGICK_V6_HOME/lib"
export INCLUDE_DIR="$STATIC_LIB/include \
-DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16 \
-I$IMAGEMAGICK_V6_HOME/include/ImageMagick-6"
export PKG_CONFIG_PATH="$IMAGEMAGICK_V6_HOME/lib/pkgconfig/:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$IMAGEMAGICK_V6_HOME/lib:$LD_LIBRARY_PATH"

Compiler and linker flags in Rcpp: Magick++

I have an R script, which loads an Rcpp file. The Rcpp file needs the magick++ library, so I used:
#include <Rcpp.h>
#include <Magick++.h>
However when I run the script, I get:
fatal error: Magick++.h: No such file or directory
The library libmagick++-dev is installed.
How can I include Magick++ in an Rcpp file? How can I compile it with flags? For instance:
-DHAVE_CONFIG_H, -DMAGICKCORE_QUANTUM_DEPTH=16, -DMAGICKCORE_HDRI_ENABLE=0
A minimal working example:
mwe.r
library(Rcpp)
sourceCpp("./mwe.cpp")
mwe.cpp
#include <Rcpp.h>
#include <Magick++.h>
//[[Rcpp::plugins(cpp11)]]
As #hrbrmstr mentions, there is a CRAN package magick that provides ImageMagick functionality already; maybe that avoids the need to do anything yourself?
From these ImageMagick instructions you can see that a C++ program needs to know about compiler flags (the output of Magick++-config --cppflags --cxxflags) and linker flags (Magick++-config --ldflags --libs).
The best way to compile Rcpp code with complicated compilation and linkage steps is (I'm no expert here...) to create an Rcpp package
/tmp$ Rdev --vanilla -e "Rcpp::Rcpp.package.skeleton('Magick')"
/tmp$ cd Magick
I edited Magick/src/rcpp_hello_world.cpp to
#include <Rcpp.h>
#include <Magick++.h>
using namespace Rcpp;
// [[Rcpp::export]]
LogicalVector rcpp_hello_world()
{
Magick::InitializeMagick("RcppMagick");
return true;
}
And added package pre-processing, compilation, and linkage commands (following Writing R Extensions, available via RShowDoc("R-exts")) to a new file Magick/src/Makevars like
PKG_CPPFLAGS = `Magick++-config --cppflags`
PKG_CXXFLAGS = `Magick++-config --cxxflags`
PKG_LIBS = `Magick++-config --ldflags --libs`
I then updated the attributes of my package, installed it, and verified that it could be used
/tmp/Magick master$ Rdev --vanilla -e "Rcpp::compileAttributes()"
> Rcpp::compileAttributes()
>
>
/tmp/Magick master$ Rdev --vanilla CMD INSTALL .
* installing to library ...‘/home/mtmorgan/R/x86_64-pc-linux-gnu-library/3.5-Bioc-3.7’
* installing *source* package ‘Magick’ ...
** libs
g++ -I"/home/mtmorgan/bin/R-devel/include" -DNDEBUG `Magick++-config --cppflags` -I"/home/mtmorgan/R/x86_64-pc-linux-gnu-library/3.5-Bioc-3.7/Rcpp/include" -I/usr/local/include `Magick++-config --cxxflags` -fpic -g -O3 -Wall -pedantic -c RcppExports.cpp -o RcppExports.o
g++ -I"/home/mtmorgan/bin/R-devel/include" -DNDEBUG `Magick++-config --cppflags` -I"/home/mtmorgan/R/x86_64-pc-linux-gnu-library/3.5-Bioc-3.7/Rcpp/include" -I/usr/local/include `Magick++-config --cxxflags` -fpic -g -O3 -Wall -pedantic -c rcpp_hello_world.cpp -o rcpp_hello_world.o
g++ -shared -L/usr/local/lib -o Magick.so RcppExports.o rcpp_hello_world.o -L/usr/lib -L/usr/lib/X11 -lGraphicsMagick++ -lGraphicsMagick -ljbig -lwebp -llcms2 -ltiff -lfreetype -ljasper -ljpeg -lpng12 -lwmflite -lXext -lSM -lICE -lX11 -llzma -lbz2 -lxml2 -lz -lm -lgomp -lpthread
installing to /home/mtmorgan/R/x86_64-pc-linux-gnu-library/3.5-Bioc-3.7/Magick/libs
...
/tmp/Magick master$ Rdev --vanilla -e "Magick::rcpp_hello_world()"
> Magick::rcpp_hello_world()
[1] TRUE
I had to figure out what system package to install to get Magick++-config. When I first tried to install my package R complained that it didn't know about -lwebp, so I installed that system dependency too (libwebp-dev). The package would be good enough for personal use, but would need to be more robust for cross-platform or production use. There could be many problems encountered while trying to integrate this complicated library into R.

Linux g++ compiling error: /usr/bin/ld: cannot find -l/usr/local/include

I am working on a project in which protobuf and zmq are involved. I have finished it on VS2010 and now want to make it work under Linux. I just installed protobuf and zmq on our Linux server and the Makefile looks like this:
g++ -c -D_DEBUG TestTDFAPI_v2.cpp -I ../
g++ -c -D_DEBUG Platform.cpp
g++ -c -D_DEBUG PathHelper.cpp
g++ -c -D_DEBUG MyStruct.pb.cpp
g++ -c -D_DEBUG MyStruct.cpp
g++ -o Test_TDFAPI_v2 Platform.o PathHelper.o MyStruct.pb.o MyStruct.o TestTDFAPI_v2.o -l /usr/local/include -L /usr/local/lib -L../ -L../linux/ -lTDFAPI_v2 -lWHNetWork -lpthread -lprotobuf
After make, I got the following error:
/usr/bin/ld: cannot find -l/usr/local/include
collect2: ld returned 1 exit status
Anyone has any clue?
-l (minus ell) is for library files to search for resolving references, you want -I (minus eye) to specify include directories.