Is it possible to compile a standalone Fortran executable in Linux? - linux

For example, consider that I wrote a Fortran program in one computer and want to run it on another computer which may not have required libraries and/or has a different compiler (or even better, no Fortran compiler at all). Is it possible to create an executable with all its dependencies?
I am using gfortran (7.2.1) in Fedora 26 and sometimes use LAPACK routines in my code.
Using -static option with the program
program main
write (*,*) 'Hello'
end
I get the output
gfortran -static a.f90
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
There is no error with gfortran -static-libgfortran a.f90

In Fedora, gcc does not ship by default with static libraries.
You need to install the package glibc-static for the -static option to work, as hinted in this related question.
Note that -static-libgfortran will only do static linking of the libgfortran library and that you must have static versions of your dependencies as well.

The best option is to use Alpine Linux that uses musl libc. I highly recommend using the docker image (only 5 Mb).

Related

How do I link libraries from multiple locations (corresponding to multiple GCC versions)?

I am currently trying to use Oracle Linux 6 OS on a SPARC S7 server to run the NPB benchmarks (with OpenMP multithreading support). The OS comes preloaded with gcc 4.4.7, which is missing the Niagara 7 optimizations. I downloaded devtoolset-3 from the Oracle Yum Repository, which has gcc 4.9.2 installed in /opt/rh/devtoolset-3/root/usr/bin. However, when I compile the NPB benchmark using the newer gcc, it automatically links to libraries associated with the older gcc 4.4.7 (located in /usr/lib). This caused my program to segfault during execution. I believe that it is because libgomp 4.4.7 is incompatible with libgomp 4.9.2. I have tried several ways of linking to the libraries in the gcc 4.9.2 folder (which is /opt/rh/devtoolset-3/root/usr/lib/gcc); none of the methods work:
-Xlinker -rpath=lib_location
-Wl -Bstatic
-L lib_location
The closest I got was when using -Wl -Bstatic ~/libgomp.a or -static -L ~/libgomp.a. It fails to find libraries such as libm that reside in the default gcc lib folder (usr/lib).
The actual command used to link is:
/opt/rh/devtoolset-3/root/usr/bin/gcc -O3 -fopenmp -mcmodel=medmid -static -L/opt/rh/devtoolset-3/root/usr/lib/gcc/sparc64-redhat-linux/4.9.2 -o ../bin/bt.W.x bt.o initialize.o exact_solution.o exact_rhs.o set_constants.o adi.o rhs.o x_solve.o y_solve.o solve_subs.o z_solve.o add.o error.o verify.o ../common/print_results.o ../common/c_timers.o ../common/wtime.o -lm -L/opt/rh/devtoolset-3/root/usr/lib/gcc/sparc64-redhat-linux/4.9.2/lib/
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lm
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lrt
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lpthread
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lc
Is there a way I can link just the libgomp library from gcc 4.9.2 while linking the remaining libraries from gcc 4.4.7?
The devtoolset compilers are all using the system libgcc, libstdc++, version 4.4.7, and can therefore not compile e.g. c++11.
I guess the gcc53-c++-5.3.0-1.el6.x86_64.rpm will do. Comes with the internal */gcc53/lib64{libgcc_s.so**, libgomp.so**, libstdc++} (version 5.3.0) ... Provides /usr/bin/{ gcc53, g++53 }
The package was created a year ago ... well tested, as extra compiler. Download link : https://drive.google.com/file/d/0B7S255p3kFXNbTBneHgwSzBodFE/view?usp=sharing
If you're going to do the -Wl,-Bstatic thing, make sure to follow it immediately by -Wl,-Bdynamic to reset to normal after your added library argument. By default, not all system libraries have static versions installed, which is why you get e.g. cannot find -lc.
So you can try this as a modification of your workaround:
-Wl,-Bstatic ~/libgomp.a -Wl,-Bdynamic
Not pretty, and this question deserves a much better answer (this is still pretty much a hack), but it should get the job done for now.

DMD2 fails to compile shared library on Linux, amd64

I've been programming on a 32 bit machine, until recently, I upgraded to a 64 bit one. I'm using the latest version of DMD (amd64), on xubuntu 16.04 (amd64).
Before the upgrade, I could easily compile shared libs using dmd -shared 'FILES', but now, it gives an error.
I have a file named q.d:
module q;
export extern(C) int abcd(){
return 4;
}
And now when I do dmd -shared 'q.d', I get this:
nafees#OptiPlex-755:~/Desktop/temp$ dmd -shared q.d
/usr/bin/ld: q.o: relocation R_X86_64_32 against `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC
q.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
--- errorlevel 1
and when I do dmd -shared -fPIC q.d:
nafees#OptiPlex-755:~/Desktop/temp$ dmd -shared -fPIC q.d
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libphobos2.a(exception_224_3b4.o): relocation R_X86_64_32 against `__dmd_personality_v0' can not be used when making a shared object; recompile with -fPIC
/usr/lib/x86_64-linux-gnu/libphobos2.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
--- errorlevel 1
How can I get it to compile?
EDIT: The library compiles fine if I use the -m32 flag.
Oh, I just realized I know this problem, sorry it took me so long to realize it though.
You just need to compile against the shared lib Phobos as well to make the shared lib on 64 bit.
dmd -shared q -m64 -fPIC -defaultlib=libphobos2.so
The -defaultlib switch tells it to use an alternate library. By specifying the .so (as opposed to the default static link with a .a file), it uses the shared lib - which happens to be compiled with -fPIC too, so it is all compatible.
Among other advantages here is that one runtime can be shared across all the shared objects and D executables, which means a lot of things just work when you distribute them all (though note you may also need to compile the program that loads this so with the -defaultlib switch too). On 32 bit, the library isn't built with these options regardless... but the result is you can see link errors for multiple definitions in some circumstances.
The one thing to be careful though is that libphobos2.so file is now a runtime dependency too, be sure to distribute it with your own library builds together. You might need to set the LD_LIBRARY_PATH or install it globally for the program to start up correctly, just like any other library (and you might want to version it too btw)

musl fails to link libc.a into shared library

I have a C99 shared library that I want to link in a few statically static libraries (via --whole-archive). Note: All the static libs are built with -fPIC
I also would like to build a universal linux binary and thus have decided to use musl. When I try to link in the static libc.a from musl I get the following error:
# Building shared library tgt/Linux-x86_64/mylib/lib/mylib.so
/root/mylib/./tgt/Linux-x86_64/libmusl/bin/musl-gcc -Wl,-whole-archive -L./tgt/Linux-x86_64/libmusl/lib -L./tgt/Linux-x86_64/libz/lib -L./tgt/Linux-x86_64/libssl/lib -L./tgt/Linux-x86_64/libsasl/lib -L./tgt/Linux-x86_64/librdkafka/lib -L./tgt/Linux-x86_64/libcurl/lib -L./tgt/Linux-x86_64/libgjalloc/lib -L./tgt/Linux-x86_64/libavro/lib -L./tgt/Linux-x86_64/libunwind/lib -l:libc.a -l:libpthread.a -l:libz.a -l:libssl.a -l:libcrypto.a -l:libsasl2.a -l:libm.a -l:librt.a -l:libcrypt.a -l:libunwind-x86_64.a -l:librdkafka.a -l:libcurl.a -l:libgjalloc.a -l:libavro.a -Wl,-no-whole-archive -shared -fPIC -o tgt/Linux-x86_64/mylib/lib/mylib.so ./tgt/Linux-x86_64/mylib/obj/myfile.o ./tgt/Linux-x86_64/mylib/obj/myotherfile.o ./tgt/Linux-x86_64/mylib/obj/cJSON.o
/usr/bin/ld: ./tgt/Linux-x86_64/libmusl/lib/libc.a(exit.lo): relocation R_X86_64_PC32 against undefined hidden symbol `__fini_array_start' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [tgt/Linux-x86_64/mylib/lib/mylib.so] Error 1
My musl build looks like:
cd mystatic_libs_build_dir/musl; \
./configure CFLAGS='-fPIC' \
--enable-shared \
--enable-static \
--prefix=/root/mylib/tgt/Linux-x86_64/libmusl; \
make; make install;
# libmusl is available
exit.lo will be written in assembler which is why your CFLAGS='-fPIC' is not having the effect you intend. This is either 1. a bug in 'musl' or 2. intentional and they do not support statically linking into .so's.
I would assume that it is unintentional and file a bug against 'musl'
You could also edit the asm yourself if you need a fix quickly.
Finally you might be able to configure musl to build with no asm?
Slightly off topic, but other options for a universal binary are:
Simply linking against glibc on the oldest version of Linux that you support.
Rather than struggling with a dependency on 'musl', simply use the Linux kernel api's directly.
Recompile musl as long as your own code with CFLAGS="-fPIC -Wa,-mrelax-relocations=no" (your binutils version must be >=2.27).

Haskell ghc compiling/linking error, not creating executable. (linux)

I wrote a basic hello world program in haskel and tried to compile it with:
ghc filename.hs. It produces .hi and .o files but no executable and displays
this error in the linker:
marox#IT-marox:~/Marox$ ghc tupel.hs
Linking tupel ...
/usr/bin/ld: --hash-size=31: unknown option
/usr/bin/ld: use the --help option for usage information
collect2: ld returned 1 exit status
Googling didn't return any useful information.
I am on ubuntu 12.04.
How can I fix this?
Have you binutils-gold installed? If yes, this is the problem (since the gold linker does not support --hash-size AFAIK).
Possible solutions:
remove gold
your ld probably links to ld.gold, so change the symlink to ld.ld
tell the haskell compiler explicitly which linker to use with the -pgml option: ghc -pgml ld.ld tupel.hs
install ghc from source, since the configure script of ghc will then build ghc so that it won't use --hash-size
Depending on your version of ghc, you can adjust the linker settings in ghc's setting file /usr/lib/ghc-your.ghc.version/settings
Update - gold on Ubuntu 12.10 appears to move GNU ld to ld.bfd. To fix this problem I deleted the ld link as recommended and remade the link with
ln -s ld.bfd ld
ghc compilations are now going through.
(Couldn't see how to subvert the settings file in usr/lib/ghc, as the entry is for gcc which passes through its commandline to ld, although this would have been my preferred option, in case something else needs ld to be the way it was.)
Thanks to Dominic for the pointer of where to look! It was driving me crazy...

Eclipse-CDT on x86_64 system cannot link to shared library [duplicate]

This question already has answers here:
How to link to a shared library without lib* prefix in a different directory? [duplicate]
(2 answers)
Closed 2 years ago.
I compiled a few libraries using Eclipse-CDT on windows. However, when I tried to compile them under linux gcc keeps giving me the error /usr/bin/ld: cannot find -lrequestedLib. I'm using the exact same build settings between the two environments (namely I made sure to add the directories that contain the libraries i need to link to). I'm sure the system has read access rights to the files as well. I'm not sure what to make of this. Please help.
Edit: These are the commands that ecplise runs to build the library:
gcc -I/home/me/lib/ -O3 -Wall -c -fmessage-length=0 -olibToMake.o ../libToMake.c
gcc -L/home/me/lib/ -shared -olibToMake.so libToMake.o -lrequestedLib
Edit 2: The command that renders the error is the second of the two, resulting in the /usr/bin/ld: cannot find -lrequestedLib being output.
Edit 3: I've confirmed that requestedLib.so is a x86_64 binary.
If you don't want to pass -L command line options to gcc(1), be sure to add the path containing the libraries to /etc/ld.so.conf or /etc/ld.so.cond.d/<something>.
Once you've installed your libraries you also need to run ldconfig(8) by hand. (Most new users forget this step because typical package managers take care of this for you when installing new libraries.)
gcc -I/home/me/lib/ -O3 -Wall -c -fmessage-length=0 -olibToMake.o ../libToMake.c
gcc -L/home/me/lib/ -shared -olibToMake.so libToMake.o -lrequestedLib
When building 64-bit shared libraries on x86_64, the -fPIC flag is usually required, or you get a recompile with -fPIC error at shared library link time.
Since you didn't use -fPIC, yet your link succeeded, you are likely using (non-default) gcc that targets i*86 (that is, produces 32-bit output). You can confirm that by running file libToMake.so.
You didn't show that command that actually fails (the one that produces cannot find -lrequestedLib error). I am guessing that that command is using a different gcc (default one?), that targets x86_64. If it looks something like
gcc main.c -L/home/me/lib -lrequestedLib
that command will ignore /home/me/lib/librequestedLib.so (because you can't link together 32-bit and 64-bit code), and will continue searching for librequestedLib elsewhere. When it can't find a 64-bit version of librequestedLib, it will produce the error message you are gettiing.

Resources