I am trying to make a program that, via some of the third party modules, is dependant upon icu library. I suspect that the dependency is via Network.HTTP.Conduit but maybe via something else. Dynamically linked binary is not portable even between adjacent versions of the same distribution because libicu* are of different versions that are not compatible.
So I am trying to build the program statically:
$ ghc --make -static -optc-static -optl-static my-prog.hs -optl-pthread
and I am getting a lot of errors of this kind:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libicuuc.a(dictionarydata.ao):(.data.rel.ro._ZTIN6icu_5222BytesDictionaryMatcherE[_ZTIN6icu_5222BytesDictionaryMatcherE]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libicuuc.a(dictionarydata.ao):(.data.rel.ro._ZTVN6icu_5217DictionaryMatcherE[_ZTVN6icu_5217DictionaryMatcherE]+0x28): undefined reference to `__cxa_pure_virtual'
collect2: error: ld returned 1 exit status
I believe that I have static versions of all involved libraries (libicu, libstdc++). It seems as if the linker has not been supplied with libstdc++ (or is it libitl? Apparently the offending functions are defined in the latter).
I tried adding the options -optl-static-libstdc++, -optl-lstdc++ and -optl-litm to the end of the command line to no avail.
What is the procedure to statically link a haskell program that is indirectly dependent on C++ support functions? I am running
The Glorious Glasgow Haskell Compilation System, version 7.6.3
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
or
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Edit:
I narrowed the problem to the package Data.Text.ICU, and here is a short program that cannot be built into a static executable:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Text.ICU
main = print $ toUpper Current "Hello!"
The problem boils down to the fact that gcc doesn't actually have libstdc++, or the other core c++ libraries available to it, but g++ does.
Asking ghc to use g++ instead of gcc for linking should do the trick. Add the following to your cabal file as a parameter under ghc-options: -pgml g++. It sets the linking program to g++ which should allow the system linker to find the libraries it needs.
Related
I'm working on a project that produces a shared object (.so) file. The source code is in both C and Haskell. It needs to be linked with libraries for the GHC Runtime System and for the Hint Haskell module.
Currently, the command to compile the file is:
ghc -Weverything -Werror -fforce-recomp $^ -o $# -dynamic -shared -lHSrts-ghc8.10.5 -lHShint-0.9.0.4-7GR8UnOuwIbHNCqCSHKCK0-ghc8.10.5
There must be a way to automate the finding of the libraries instead of hard-coding the names. I want the Makefile to continue to work with future releases of GHC and Hint. It seems to be that ghc-pkg
should be able to provide this, but I can't find how.
So I have the following makefile which I want to use to compile my haskell program. However, in my program.hs file I have imported a library that is not in the standard Haskell distribution (e.g. Data.List). As a result, when I try to compile I get the error below. How can I include the said library so that it compiles fine? P.S. I am NOT interested in other approaches which do not involve a makefile, thank you.
error:
Linking program...
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
makefile:
program: program.hs
ghc --make -static -optl-static program.hs
You went down the wrong path with static options. I assume you're on os-x. As explained at ld: library not found for -lcrt0.o on OSX 10.6 with gcc/clang -static flag that just makes things worse. In fact you got a different error, because you got an earlier error.
To write a good makefile, first ensure you can run ghc to compile the program without make, just by running the commands in the shell.
I.e. try to compile just ghc --make program.hs and see what happens. If you have the other libraries in your package environment already, it doesn't matter if they're in the standard distribution or not.
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).
I am having an issue that I believe is the result of compiler versions. I have three external libraries, we will call liba, libb, and libc. All of the libraries compiled without any issues using ifort 11.1 on Redhat Linux 5.3. This is the snippet of code from the makefile, which works just fine:
foo.exe: foo.o
ifort -m64 foo.o liba libb libc -o $#
I am trying to move the code to a new system, which is using ifort 16.0.2 on Redhat Linux 6.7. The makefiles for the external libraries work without any modification. However, when I go to compile the executable using the same code shown above, I get multiple undefined reference errors.
My guess is that there is an environmental variable I need to modify or a compiler/linker option that I need to add, but I am unsure where to go from here.
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...