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

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.

Related

How to statically link NetCDF in Fortran Executable

I'm trying to use NetCDF in a Fortran executable that then gets sent out to a lot of machines for parallel computation, so I need it to be statically linked. I'm doing the compiling on my own machine with mpif90, but I've also tried gfortran (Linux, though could also use Windows).
I'd love to build something entirely static, but packaging mpiexec in a static library seems difficult.
Here's a sketch of what I'm doing:
mpif90 -c -o somestuff.o somestuff.f90
mpif90 -c -o thing_that_uses_netCDF.o thing_that_uses_netCDF.f90 \
-I/usr/include -L/usr/lib/x86_64-linux-gnu -lnetcdff
ar cr libintermediate.a thing_that_uses_netCDF.o somestuff.o
mpif90 -c -o downstreamstuff.o downstreamstuff.f90 \
-I./path/to/intermediatelib -L./path/to/intermediatelib -lintermediate \
-I/usr/include -L/usr/lib/x86_64-linux-gnu -lnetcdff
mpif90 -o finalexecutable downstreamstuff.o \
-I./path/to/intermediatelib -L./path/to/intermediatelib -lintermediate \
-I/usr/include -L/usr/lib/x86_64-linux-gnu -lnetcdff
Could someone walk me through linking the netcdff library? When I try it with gfortran if I use the -static flag I get "undefined reference to `__netcdf_MOD..." errors, though it compiles fine without the -static flag.
Thanks.

GCC not finding LibSerial even with -lserial flag [Ubuntu] [duplicate]

I'm trying to compile my project and I use the lib ncurse. And I've got some errors when compiler links files.
Here is my flags line in Makefile:
-W -Wall -Werror -Wextra -lncurses
I've included ncurses.h
Some layouts :
prompt$> dpkg -S curses.h
libslang2-dev:amd64: /usr/include/slcurses.h
libncurses5-dev: /usr/include/ncurses.h
libncurses5-dev: /usr/include/curses.h
prompt$> dpkg -L libncurses5-dev | grep .so
/usr/lib/x86_64-linux-gnu/libncurses.so
/usr/lib/x86_64-linux-gnu/libcurses.so
/usr/lib/x86_64-linux-gnu/libmenu.so
/usr/lib/x86_64-linux-gnu/libform.so
/usr/lib/x86_64-linux-gnu/libpanel.s
And here are my erros :
gcc -W -Wall -Werror -Wextra -I./Includes/. -lncurses -o Sources/NCurses/ncurses_init.o -c Sources/NCurses/ncurses_init.c
./Sources/NCurses/ncurses_init.o: In function `ncruses_destroy':
ncurses_init.c:(.text+0x5): undefined reference to `endwin'
./Sources/NCurses/ncurses_init.o: In function `ncurses_write_line':
ncurses_init.c:(.text+0xc5): undefined reference to `mvwprintw'
./Sources/NCurses/ncurses_init.o: In function `ncurses_init':
ncurses_init.c:(.text+0xee): undefined reference to `initscr'
collect2: error: ld returned 1 exit status
Thanks a lot
You need to change your makefile so that the -lncurses directive comes after your object code on the gcc command line, i.e. it needs to generate the command:
gcc -W -Wall -Werror -Wextra -I./Includes/. -o Sources/NCurses/ncurses_init.o -c Sources/NCurses/ncurses_init.c -lncurses
This is because object files and libraries are linked in order in a single pass.
In C++ , I fixed it just by linking the ncurses library .
Here is the command :
g++ main.cpp -lncurses
I got flags to correct order by using LDLIBS variable:
ifndef PKG_CONFIG
PKG_CONFIG=pkg-config
endif
CFLAGS+=-std=c99 -pedantic -Wall
LDLIBS=$(shell $(PKG_CONFIG) --libs ncurses)
man gcc | grep -A10 "\-l library"
-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.)
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files
in the order they are specified. Thus, foo.o -lz bar.o searches
library z after file foo.o but
before bar.o. If bar.o refers to functions in z, those functions may not be loaded.

Linking CUDA + plain C++ code: undefined reference to `__fatbinwrap_66_tmpxft_ etc

Somehow my CUDA binary build process has been messed up. All of the .cu files compile nicely to .o files, but when I try to link, I get:
CMakeFiles/tester.dir/tester_intermediate_link.o: In function `__cudaRegisterLinkedBinary_66_tmpxft_00007a5f_00000000_16_cuda_device_runtime_compute_52_cpp1_ii_8b1a5d37':
/tmp/tmpxft_00006b54_00000000-2_tester_intermediate_link.reg.c:7: undefined reference to `__fatbinwrap_66_tmpxft_00007a5f_00000000_16_cuda_device_runtime_compute_52_cpp1_ii_8b1a5d37'
Now, I have not used compute_52 anywhere. My nvcc command-line is:
/usr/local/cuda/bin/nvcc -M -D__CUDACC__ /home/joeuser/src/my_project/src/kernel_specific/elementwise/Add.cu -o /home/joeuser/src/my_project/CMakeFiles/tester.dir/src/kernel_specific/elementwise/tester_generated_Add.cu.o.NVCC-depend -ccbin /usr/bin/gcc-4.9.3 -m64 --std c++11 -D__STRICT_ANSI__ -Xcompiler ,\"-Wall\",\"-g\",\"-g\",\"-O0\" -gencode arch=compute_35,code=compute_35 -g -G --generate-line-info -DNVCC -I/usr/local/cuda/include -I/opt/cub -I/usr/local/cuda/include
and my link line is:
/usr/bin/g++-4.9.3 -Wall -std=c++11 -g some.o files.o here.o blah.o blahblah.o bar.cu.o baz.cu.o -o bin/myapp -rdynamic -Wl,-Bstatic -lcudart_static -Wl,-Bdynamic -lpthread -lrt -ldl /usr/lib/libboost_system.so /usr/lib/libboost_program_options.so -Wl,-Bstatic -lcudart_static -Wl,-Bdynamic -lpthread -lrt -ldl /usr/local/cuda/extras/CUPTI/lib64/libcupti.so -lnvToolsExt -lOpenCL /usr/lib/libboost_system.so /usr/lib/libboost_program_options.so /usr/local/cuda/extras/CUPTI/lib64/libcupti.so -lnvToolsExt -lOpenCL -Wl,-rpath,/usr/lib:/usr/local/cuda/extras/CUPTI/lib64
I'll note I have separate compilation enabled, and do not seem to have skipped my intermediate link phase.
Why is this happening?
CUDA has two compilation modes, relocatable and static.
The relocatable mode is required for some configurations-which we will not get into now.
If you want to compile in relocatable mode -rdc=true, you'll need the Cuda device runtime library.
Which is located in the file cudadevrt.lib.
On some instances, supplying -lcudadevrt as a command line switch to the CUDA linker does the job, but on e.g. MSVC, you'll also need to specify cudadebrt.lib as a link dependency.
Well, I'm not sure why I'm seeing missing references to Compute 5.2 calls, but adding -lcudadevrt to the end of the link command makes the error go away.

Undefined reference to symbol throw_out_of_range

I got following error while compiling library that computes some stuff with molecules. It is mostly academic project.
/usr/bin/ld: trajectory_manager.o: undefined reference to symbol '_ZSt24__throw_out_of_range_fmtPKcz##GLIBCXX_3.4.20'
//usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line
It occurs to me that linker is trying to use some specific version of GLIBC but fails to find it or something but I am unable to find any solution to this at all.
The code was compiled using g++ (gcc version 5.3). Linker I have in version ldd (Ubuntu EGLIBC 2.19-0ubuntu6.7) 2.19. If necessary please tell me in comment section and I will provide any further information.
Edit:
Each src is compiled using:
mpiCC -pthread -ansi -Wno-long-long -g -D_DEBUG -I /home/asd/tunnel_analyzer/boost_lib/include -I ../../../src/lib -o main.o -c ../../../src/main/main.cpp
mpiCC -pthread -ansi -Wno-long-long -g -D_DEBUG -I /home/asd/tunnel_analyzer/boost_lib/include -o cache.o -c ../../../src/lib/cache.cpp
etc. and linked
mpiCC -pthread -ansi -Wno-long-long -g -D_DEBUG -I /home/asd/tunnel_analyzer/boost_lib/include -L/home/asd/tunnel_analyzer/boost_lib/lib -L. -o caverdock main.o cache.o coords.o current_weights.o everything.o grid.o szv_grid.o manifold.o model.o monte_carlo.o mutate.o my_pid.o naive_non_cache.o non_cache.o parallel_mc.o parse_pdbqt.o pdb.o quasi_newton.o quaternion.o random.o ssd.o terms.o weighted_terms.o constraint.o scheduler.o trajectory_manager.o -l boost_system -l boost_thread -l boost_serialization -l boost_filesystem -l boost_program_options
Note that mpiCC is just alias for g++.
it seems to be a G++ bug; installing libstdc++6 (4.9) apparently helps solve this.

C++ Symbol lookup error in shared library when accessing boost bind

I am trying to add multithreading into my library, so I am working on creating a thread executor for my library. For this I am using boost threads.
This is the error I am getting when running a test case that links to the library:
symbol lookup error: libmylibexample.so.0: undefined symbol: _ZTVN5boost6detail16thread_data_baseE
This is the line of code in my shared library that is causing the error:
MyNameSpace::Producer producer = MyNameSpace::Producer();
threads.create_thread(boost::bind(&MyNameSpace::Producer::run, &producer));
I am compiling the library using autotools and libtool. The code compiles fine. I then create a test case that I am trying to reference the library. Here is the compilation order for compiling the test case:
g++ -I. -I../include -g -O2 -MT runTest-runTest.o -MD -MP -MF .deps/runTest-runTest.Tpo -c -o runTest-runTest.o `test -f 'runTest.cc' || echo './'`runTest.cc
and this is my linking stage:
mv -f .deps/runTest-runTest.Tpo .deps/runTest-runTest.Po
/bin/bash ../libtool --tag=CXX --mode=link g++ -g -O2 ../libmylibexample/libmylibexample.la -o runTest runTest-runTest.o -lboost_system -lboost_filesystem -lboost_regex -lboost_thread-mt -lfftw3 -ltiff
libtool: link: g++ -g -O2 -o .libs/runTest runTest-runTest.o ../libmylibexample/.libs/libmylibexample.so -lboost_system -lboost_filesystem -lboost_regex -lboost_thread-mt -lfftw3 /usr/lib/x86_64-linux-gnu/libtiff.so
One of my colleagues suggested initializing some boost templates relating to threading to help the shared library to load the symbol from the boost_thread library. I am not entirely certain the best method to do this and if this it the right way of making things get loaded.
So to wrap things up: The error appears to involve not being able to load a symbol defined in libboost_thread from my shared library.
As the error indicates, you need to link libmylibexample with libboost_thread.