Although there are a few tutorials on the web showing how to compile a C program utilizing Haskell functions, every tutorial compiles their C code with ghc. In the ``Real World'' C code files will be compiled using gcc.
My goal is to create .o files from Haskell code and then link them to the core C program. Below is a basic working example.
Fibonacci.hs:
{-# LANGUAGE ForeignFunctionInterface #-}
module Fibonacci where
import Foreign
import Foreign.C.Types
fibonacci :: Int -> Int
fibonacci n = fibs !! n
where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fibonacci_hs :: CInt -> CInt
fibonacci_hs = fromIntegral . fibonacci . fromIntegral
foreign export ccall fibonacci_hs :: CInt -> CInt
test.c:
#include "Fibonacci_stub.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
hs_init(&argc, &argv);
i = fibonacci_hs(42);
printf("Fibonacci: %d\n", i);
hs_exit();
return 0;
}
Makefile:
all: test
test: Fibonacci.o test.o
gcc -shared Fibonacci.o test.o -o test
test.o: test.c
gcc -c -I/usr/lib/ghc/include test.c
Fibonacci.o: Fibonacci.hs
ghc -c -O Fibonacci.hs
clean:
rm *.o *.hi test *_stub.h
https://dl.dropboxusercontent.com/u/14826353/fibonacci.tgz
When running make, first: the ghc compiler will generate a Fibonacci_stub.h and a Fibonacci.o file. Second: the gcc compiler will generate the test.o file from the test.c file. Lastly the gcc compiler should link the .o files and generate the executable.
Instead this error is provided:
/usr/bin/ld: Fibonacci.o: relocation R_X86_64_PC32 against undefined symbol `base_GHCziBase_plusInt_closure' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
The output says to use -fPIC, I've tried to place it in several places, but these attempts have not been fruitful in eliminating the error.
Where should I place -fPIC in the Makefile?
Is the -fPIC suggestion useful? Are there obvious deficits in the Makefile its self, which would prevent compilation?
I've been faced similar issue trying to put ghc's .o into shared library and realized that ghc just ignores -fPIC without immediate -shared flag (so your suggestion is correct). For detailed discussion see this link. The ticket by link marked as «solved», but nothing actually changed in ghc command lines since 2009. Briefly speaking, the reason of that behaviour lies in ghc implementation and only proposed solution is to build a separate shared library from Haskell code.
Related
At page 14 of the book "Introduction to GCC" by Brian Gough, the author wants to show a linker error due to not supplying gcc with the libm library, where the code for the function sqrt resides:
$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function ‘main’:
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference to ‘sqrt’
The file calc.c (where the functionsqrt is invoked) is this:
#include <math.h>
#include <stdio.h>
int main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
This book is from 2003.
On my current Ubuntu Linux 18, I can't reproduce the link error: it links and works, printing the correct result:
$ ./calc
1.414214
I found with ldd calc that the libm.so shared library is not invoked at runtime. Nor of course is the static library libm.a involved here.
So how does gcc deal with the function sqrt? I found that in this case it uses the sqrt GCC built-in function.
Its code gets inserted in the calc.o object file at compile time. So no "undefined reference" error.
First question: this the whole story or am I missing something?
Second question: why did this behavior regarding the built-in functions of GCC change so much between 2003 (when the book was written) and now? (Practically invalidating the whole example, it seems to me)
Third question: why does the author make his examples (e.g.$ gcc -Wall calc.c -lm -o cal) implying that the static library libc.a will be used, when in reality in Linux that syntax invokes the dynamic library libm.so? Is this specific to Linux and not to GNU GCC? What am I mising?
I think this is due to optimization of a constant value. Modern GCC can compute exact value of sqrt (2.0). If you force it not to use the built-ins with -fno-builtin, it will still fail to link. Also, if you change the code a little bit so that the argument to sqrt() is not literal, it will fail to link:
#include <math.h>
#include <stdio.h>
double t = 2.0;
int main (void)
{
double x = sqrt (t);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
This produces link error:
> gcc -o test test.c
/usr/bin/ld: /tmp/ccLjHnQx.o: in function `main':
test.c:(.text+0x11): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Regarding your 3rd question, -lm does not imply static library, AFAIK.
How do I compile a Haskell executable (not a library) using GHC >=8.2.1 (preferably on 8.6.*) on macOS 10.14.5 that successfully foreign exports a function (i.e. exposes it as a public symbol in the binary)? This works in GHC 8.0.2 but not in later versions.
I've tried this on ghc 8.0.2 (via stack), 8.2.2 (via both nix and stack), 8.4.4 (via both nix and stack), and 8.6.4 (via both nix and stack). Only 8.0.2 works. I know that 8.2 introduced this change: GHC will now use ld.gold or ld.lld instead of the system’s defaultld, if available. But I am unclear whether 8.0.2 would use a different 'system default' ld in the first place (darwin's ld as opposed to llvm's lld?). I know of ghc's -pgml [ld-program-here] option to set the linker but I haven't been able to manually set it to anything that has successfully compiled and linked anything to test further.
I have this file Main.hs:
module Main where
import Foreign.C
foreign export ccall "my_square" my_square :: CInt -> CInt
my_square :: CInt -> CInt
my_square x = x * x
main :: IO ()
main = putStrLn "FFI Test"
With ghc 8.0.2:
> rm Main.hi Main.o && ghc-8.0.2 Main.hs && nm -g Main | grep my_square
[1 of 1] Compiling Main ( Main.hs, Main.o )
[some apparently unrelated clang warnings]
Linking Main ...
[further clang warnings]
2544:0000000100001260 T _my_square
With ghc 8.6.4, the symbol doesn't seem to be exported, so future attempts to link another program with this symbol fail.
> rm Main.hi Main.o && ghc-8.6.4 Main.hs && nm -g Main | grep my_square
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking Main ...
Going off what I said in my comment, neither version of GHC you tested actually exports _my_square from Main. Instead, they export _my_square from Main.o (this is why you can use ghc to compile and link a .c file that uses my_square). When Main.o is linked into the final Main executable, neither GHC tells the linker to export _my_square. GHC 8.6.4 (and, I think, since 8.2) tells the linker to strip unused, unexported symbols, so _my_square evaporates. GHC 8.0.2 does not, leaving _my_sqaure in the Main executable purely by accident.
You can tell GHC to tell the linker to keep the symbol. The linker option for this is -exported_symbol <symbol>. My GHC actually invokes the linker through gcc, so I have to wrap those two arguments with -Wl. For whatever reason, passing that option to the GHC actually compiling Main.hs causes an error; you have to make Main.o with one bare GHC invocation and then call GHC again to link it into Main, this time with the linker options. Maybe this is peculiar to my system—you may experiment to find a better way.
$ ghc -c Main.hs
# Makes Main.hi Main.o Main_stub.h
$ ghc -optl-Wl,-exported_symbol -optl-Wl,_my_square Main.o -o Main
# Makes Main
$ objdump -t Main | grep _my_square
0000000100000dc0 g F __TEXT,__text _my_square
I would still recommend filing a GHC issue to make this easier.
I have compiled a c++ code using g++ -std=c++11 -o main main.cpp -pthread and it compiled fine however if I compile the same code using gcc -std=c++11 -o main main.cpp -pthread it does not compile and throws error. The program uses threading which properly taken care of using -pthread option while compiling. For the reference I am attaching the code below. Any help is highly appreciated.
#include <iostream>
#include <thread>
class foo
{
public:
void bar(int loop_num)
{
for (int i = 0; i < loop_num; ++i) {
std::cout << "Thread executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
std::thread t1(&foo::bar, &f, 5);
t1.join();
}
If you’ve written C++ code with GCC, you’ll know that you need to use the program g++, both for compilation and linking. For multi-module programs, this means every .cpp file gets compiled with g++, and then the entire program must be linked separately using g++. If you try to link the program using gcc, it will almost work, but you’ll get a lot of “undefined reference” errors, like this:
test.cpp:(.text+0x11): undefined reference to `std::cout'
The need to use g++ to link the entire program causes trouble when you have a very complicated build process you don’t have full control of. For instance, I’m trying to link C++ code with Mercury, and I have to use the Mercury linker, which in turn calls gcc.
So just a quick tip: If you are forced to use gcc to link the program, just add the library “stdc++”, as you would any other library, and it will work. That is, add the option “-lstdc++” to your GCC linker command line. For example:
g++ -c hello.cpp
gcc -lstdc++ -o hello hello.o
I assume the error you get looks something like this:
/tmp/ccUKAq0K.o: In function `main':
main.cpp:(.text+0x59): undefined reference to `std::thread::join()'
/tmp/ccUKAq0K.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0xb6): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0xcb): undefined reference to `std::ios_base::Init::~Init()'
/tmp/ccUKAq0K.o: In function `std::thread::~thread()':
main.cpp:(.text._ZNSt6threadD2Ev[_ZNSt6threadD5Ev]+0x1d): undefined reference to `std::terminate()'
(And so on.)
C++ programs which use the standard library (so most of them) need to be linked using g++, not gcc. Only the g++ compiler driver links in most of the standard library. The gcc compiler driver compiles C++ programs, just like g++, but when the linker is invoked, the program is treated as a C program, which usually leads to linker errors.
Try adding the -lrt flag after the pthread one.
This question already has answers here:
Why does the order in which libraries are linked sometimes cause errors in GCC?
(9 answers)
Compiling Fortran netCDF programs on Ubuntu
(2 answers)
Closed 4 years ago.
I want to compile some of my often-used Fortran code into a static library (assuming I would have access to both *.mod and *.a files).
This worked.
However, I have encountered the problem with linking.
Here is an example. Let's say I have mylib.f90 file:
MODULE MYLIB
IMPLICIT NONE
CONTAINS
INTEGER FUNCTION FOO(N)
INTEGER, INTENT(IN) :: N
FOO = N + 2
END FUNCTION FOO
END MODULE MYLIB
Which is compiled as
gfortran -c mylib.f90
ar rcs libmylib.a mylib.o
Now, I have a program that uses FOO function:
PROGRAM MYPROG
USE MYLIB
IMPLICIT NONE
INTEGER M
M = FOO(3)
WRITE (*,*) M
END PROGRAM MYPROG
For simplicity I put it in the same directory as mylib.mod and libmylib.a. Compilation:
gfortran -c myprog.f90
no issues. Linking, however results in error:
gfortran -L./ -lmylib myprog.o
myprog.o: In function `MAIN__': myprog.f90:(.text+0x11): undefined
reference to `__mylib_MOD_foo' collect2: error: ld returned 1 exit
status
However, symbol __mylib_MOD_foo is in libmylib.a:
nm libmylib.a
mylib.o:
0000000000000000 T __mylib_MOD_foo
and it compiles without a problem if I give it mylib.o. What am I doing wrong?
PS. I've seen somewhere, but can't find where now the way to link as follows:
gfortran -Wl,--whole-archive libmylib.a -Wl,--no-whole-archive myprog.o
It works. But it should solve the problem with weak symbols, whereas the output of nm didn't mark __mylib_MOD_foo as weak.
It seems to me that gcc can deal with both c and c++ projects,so why is g++/gcc-c++ needed?
What's the difference between g++ and gcc-c++?
gcc will compile C source files as C and C++ source files as C++ if the file has an appropriate extension; however it will not link in the C++ library automatically.
g++ will automatically include the C++ library; by default it will also compile files with extensions that indicate they are C source as C++, instead of as C.
From http://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html#Invoking-G_002b_002b:
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx; C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc; and preprocessed C++ files use the suffix .ii. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs (usually with the name gcc).
However, the use of gcc does not add the C++ library. g++ is a program that calls GCC and treats .c, .h and .i files as C++ source files instead of C source files unless -x is used, and automatically specifies linking against the C++ library. This program is also useful when precompiling a C header file with a .h extension for use in C++ compilations.
For example, to compile a simple C++ program that writes to the std::cout stream, I can use either (MinGW on Windows):
g++ -o test.exe test.cpp
gcc -o test.exe test.cpp -lstdc++
But if I try:
gcc -o test.exe test.cpp
I get undefined references at link time.
And for the other difference, the following C program:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int* new;
int* p = malloc(sizeof(int));
*p = 42;
new = p;
printf("The answer: %d\n", *new);
return 0;
}
compiles and runs fine using:
gcc -o test.exe test.c
But gives several errors when compiled using:
g++ -o test.exe test.c
Errors:
test.c: In function 'int main()':
test.c:6:10: error: expected unqualified-id before 'new'
test.c:6:10: error: expected initializer before 'new'
test.c:7:32: error: invalid conversion from 'void*' to 'int*'
test.c:10:9: error: expected type-specifier before '=' token
test.c:10:11: error: lvalue required as left operand of assignment
test.c:12:36: error: expected type-specifier before ')' token
As far as I know, g++ uses the correct C++ linker options whereas gcc uses the C linker options (so you may get undefined references, etc.).