Fortran compile shared object which includes netcdf static library - makefile

I am trying to create a shared object in fortran, that uses the netcdf static library.
The ultimate aim is to use this shared object in R, but I think the problem starts with my makefile, so I am just focusing on this here:
In my makefile i use the following flags
'F90 = ifort
FFLAGS = -O3 -fPIC -r8 # double-precision now run in Fortran , -fpic
for creating shared object file
LDFLAGS = -lnetcdff -lnetcdf -shared #-shared, for creating a shared
object file'
I think I managed to link everything allright, (you see all my object files below in the error message), but in the next step, when creating the shared object, there is a netcdf-library specific error message:
'ifort -O3 -fPIC -r8 -o HX.so HX.o HANDLE_ERR.o GET_CLM.o INTEGRATE.o
CLIMATE.o STATE.o PARAMETERS.o CONTROL.o HYDRO.o DYNAMICS.o CARBON.o
RINGS.o INIT.o SET_PARAMS.o -lnetcdff -lnetcdf -shared
ld: /usr/local/Cluster-Apps/netcdf/4.1.3/lib/libnetcdff.a(netcdf4.o):
relocation R_X86_64_32 against `.bss' can not be used when making a
shared object; recompile with -fPIC
/usr/local/Cluster-Apps/netcdf/4.1.3/lib/libnetcdff.a: could not read
symbols: Bad value
make: *** [HX.so] Error 1'
I find 'similar' problems, but as I am not familiar with the terminology and this is my very first try in generating a shared object, I cannot follow their instructions for my problem.

You need to install the dynamic (.so) version of NetCDF, be it from your repository or by compiling it yourself. As tim18 say in the comments, it also needs to be compiled with -fPIC, and the .so version will be.

Related

Compiling OpenMP to WebAssembly

I am trying to compile a multi threaded application to WebAssembly. The application uses OpenMP for multithreading.
To compile I am using the Emscripten framework.
I have already downloaded the source files for OpenMP and compiled it for my host machine using make. With the following command I can get it to link with a simple demo application on my machine:
g++ -Wall -Werror -pedantic main.o -o main.x /$PATH_TO_OPENMP/build/runtime/src/libgomp.a -pthread -lstdc++ -Wl,--no-as-needed -ldl
I then tried to compile OpenMP to the llvm bytecode format used by Emscripten. To do so I tried to run 'emmake make', so that the emscripten framework executes the OpenMP makefiles with a suitable compiler. As emscripten does not like shared object files I compiled it to static library .a files.
This works and actually gives me object files to which I can link.
I then wanted to link my demo application with the following command
em++ -Wall -Werror -pedantic main.o -o main.html /home/main/data/Programming/openMP/openmp_web/build/runtime/src/libgomp.a -pthread -lstdc++ -Wl,--no-as-needed -ldl
But I get these warnings, that it couldn't link to OpenMP files:
shared:WARNING: object /tmp/emscripten_temp_ONa0eU_archive_contents/kmp_atomic.cpp.o is not a valid object file for emscripten, cannot link
.
.
shared:WARNING: object /tmp/emscripten_temp_ONa0eU_archive_contents/kmp_str.cpp.o is not a valid object file for emscripten, cannot link
shared:WARNING: object /tmp/emscripten_temp_ONa0eU_archive_contents
So I figured I must have compiled OpenMP with the wrong compiler. I then tried to change the compiler when building the library by using the following commands:
cmake -DCMAKE_C_COMPILER=emcc -DCMAKE_CXX_COMPILER=em++ -DLIBOMP_LIB_TYPE=normal -DLIBOMP_ENABLE_SHARED=OFF -DCMAKE_BUILD_TYPE=Release -DLIBOMP_ARCH=x86_64 OPENMP_STANDALONE_BUILD=1 ..
emmake make
But this just gives strange errors on some missing system variables
/home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_platform.h:82:2: error: Unknown OS
/home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_platform.h:203:2: error: Unknown or unsupported architecture
In file included from /home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_alloc.cpp:13:
In file included from /home/main/data/Programming/openMP/openmp_web/runtime/src/kmp.h:77:
/home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_os.h:171:2: error: "Can't determine size_t printf format specifier."
Does anyone have an idea on what I could do differently?

Building a shared library created a static library instead

I am trying to build libass into a shared library with static linking under MinGW-w64. When I configure with
./configure --disable-static --enable-shared
it generates the shared library (dynamically-linked) as expected. However, when I attempt to force static linking by setting
LDFLAGS=-static
instead of generating a statically-linked shared library (.dll with no dependency), it generates a static library (.a).
I am almost certain that I have all the dependent static libraries and no error or warning message is shown in the make process.
Can anyone please shed some light on what I'm doing wrong?
libtool says No.
The package's stock autotools ltmain.sh script parses the linkage flags and
if it finds -static it will not build a shared library, just a static
one.
Which is the most it could reasonably do, because you can't statically link a shared
library. A shared library must consist entirely of Position Independent (PIC)
code or the linkage will fail, whereas a static linkage will call for the linkage
of non-PIC object files, contributed by the non-PIC standard and runtime libraries,
if nothing else.
foo.c
#include <stdio.h>
void foo(void)
{
puts("foo");
}
Build a dynamically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -o libfoo.so foo.o
$ file libfoo.so
libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), \
dynamically linked, BuildID[sha1]=1adff7204d84d138a80bc4b6f3f38211e4b42812, \
not stripped
Attempt to build a statically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -static -o libfoo.so foo.o
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/6/crtbeginT.o: \
relocation R_X86_64_32 against hidden symbol `__TMC_END__' cannot be used \
when making a shared object
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
The static lib is just an ar package.
You can use command of ar to make the pack and unpack it.

Non-GOT style relocation for executable in GCC

In GCC, if I compile something into a shared library with GCC with g++ -shared func.cpp -o libfunc.so -fPIC, internal function calls to global symbols go through GOT in this generated shared library file. But if I compile with g++ func.cpp -o libfunc.so -mcmodel=large, it will not generate GOT but instead relocate by patching with R_X86_64_64 style relocation directly.
I want this behavior for executables as well. If I compile an executable with g++ main.cpp libfunc.so -o a.out, GCC will generate GOT for any function call from main.cpp to one defined in libfunc.so. I don't want this behavior. I want R_X86_64_64 style relocation. How can I achieve that?
Executables are compiled with -fPIE by default in modern distros for security reasons. To get old behavior add -no-pie to CFLAGS/CXXFLAGS.

How do I link libraries statically with gcc?

I am new to C++ compiling/linking.
I am trying to link all libraries statically with gcc, I tried using LDFLAGS=-static but did not work. Error message showed:
/bin/sh ./libtool --tag=CXX --mode=link /home/dizhang/lib/hdf5/bin/h5c++ -g -O2 -L/home/dizhang/lib/blitz/lib -L/home/dizhang/lib/libconfig/lib -o angora src/libangora.la -lblitz -lconfig++
libtool: link: /home/dizhang/lib/hdf5/bin/h5c++ -g -O2 -o angora -L/home/dizhang/lib/blitz/lib -L/home/dizhang/lib/libconfig/lib src/.libs/libangora.a -L/bgsys/drivers/V1R2M2/ppc64/comm/lib64 -L/bgsys/drivers/V1R2M2/ppc64/comm/lib -L/bgsys/drivers/V1R2M2/ppc64/spi/lib -lpthread -lm /home/dizhang/lib/blitz/lib/libblitz.a /bgsys/drivers/V1R2M2/ppc64/comm/lib/libmpichcxx-gcc.so /bgsys/drivers/toolchain/V1R2M2_base/gnu-linux/powerpc64-bgq-linux/lib/libstdc++.so /bgsys/drivers/V1R2M2/ppc64/comm/lib/libmpich-gcc.so /bgsys/drivers/V1R2M2/ppc64/comm/lib/libopa-gcc.so /bgsys/drivers/V1R2M2/ppc64/comm/lib/libmpl-gcc.so /home/dizhang/lib/libconfig/lib/libconfig++.a /bgsys/drivers/toolchain/V1R2M2_base-efix014/gnu-linux/powerpc64-bgq-linux/lib/libstdc++.so -Wl,-rpath -Wl,/bgsys/drivers/toolchain/V1R2M2_base-efix014/gnu-linux/powerpc64-bgq-linux/lib -Wl,-rpath -Wl,/bgsys/drivers/V1R2M2/ppc64/comm/lib -Wl,-rpath -Wl,/bgsys/drivers/toolchain/V1R2M2_base/gnu-linux/powerpc64-bgq-linux/lib -Wl,-rpath -Wl,/bgsys/drivers/toolchain/V1R2M2_base-efix014/gnu-linux/powerpc64-bgq-linux/lib -Wl,-rpath -Wl,/bgsys/drivers/V1R2M2/ppc64/comm/lib -Wl,-rpath -Wl,/bgsys/drivers/toolchain/V1R2M2_base/gnu-linux/powerpc64-bgq-linux/lib
/bgsys/drivers/toolchain/V1R2M2_base-efix014/gnu-linux/lib/gcc/powerpc64-bgq-linux/4.4.7/../../../../powerpc64-bgq-linux/bin/ld: attempted static link of dynamic object `/bgsys/drivers/V1R2M2/ppc64/comm/lib/libmpichcxx-gcc.so'
collect2: ld returned 1 exit status
I did some search and found that, telling Makefile -Wl -Bstatic may solve this problem, but how exactly I should change this in my Makefile?
I tried searching -Wl in Makefile but it was not in the text.
Thanks,
Di
Looks like you are trying to build HDF5 with MPI support on BGQ.
As long as you end up passing a ".so" version of a lib to gcc on BGQ -- you will see this error. You may need to check how you are passing MPI info to HDF5's configure script.
In my case (building another project that uses CMake) passing BGQ's MPI compiler wrappers to CMake always created a problem where it would try to link MPI using the shared libs instead of the static ones. To resolve this, I had to make sure to explicitly specify the ".a" variants of the MPI libs.

fail when creating shared library with libstdc++ statically linked

using gcc 4.5.1 in a 64bit x86 machine,I first create a.o as following:
g++ -fPIC -c a.cc -o a.o
then try to create liba.so as following:
g++ -static-libstdc++ -shared -W1,-soname,liba.so -o liba.so.1.0.0 a.o
but failed, with the following information:
relocation R_X86_64_32S against `vtable for __gnu_cxx::stdio_filebuf >' can not be used when making a shared object; recompile with -fPIC
I try to recompile libstdc++ library,with -fPIC added,but it failed anyway
I would expect that the static libstdc++ library was not build with -fPIC, and therefore can't be linked into a shared library.
Theoretically you could put non-PIC compiled code into a dynamic library, but it wouldn't be sharable (each program using it would have to have its own copy) so it's often not implemented.
You're going to need to link against the shared C++ library, make your own library a static library, or else rebuild libstdc++ yourself and grab the .o files from the build directory.
There is a similar question about this topic on stackoverflow, which refers to an external site about static linking of libstdc++.

Resources