编译用 haskell 和模板 haskell 编写的共享对象并将其与 c 中的 main 链接

标签 c gcc makefile ghc template-haskell

我正在尝试将几个有文化的 haskell (.lhs) 文件编译为共享对象 (.so),然后将其与用 c 编写的主文件链接。不过,这里的问题是用于创建 .so 的文件中有 2 个是模板 haskell。我遵循使用模板 haskell 编译 .so 的规则,这意味着我执行了以下步骤:
1. 我编译了每个 .lhs 文件,静态
2. 然后我第二次动态编译它们。
3. 我从第 1 步和第 2 步获得的对象文件创建了共享对象。
4.我把main.c编译成了main.o
5. 我从第 3 步和第 4 步创建了一个可执行文件。

创建 .so 的文件有 3 个。 Dep1.lhs、Dep2.lhs & Dep3.lhs,还有一个用c写的main

当我编译 makefile 时,我收到这条消息:

my_directory >> make all
rm -f *.o *.hi *.so *.dyn_hi *.dyn_o main
ghc -c Dep3.lhs -XTemplateHaskell -XForeignFunctionInterface -o Dep3.o
ghc -c Dep3.lhs -dynamic -XTemplateHaskell -fPIC -no-hs-main -XForeignFunctionInterface -o Dep3.dyn_o -osuf dyn_o -hisuf dyn_hi ghc -c Dep2.lhs -XTemplateHaskell -XForeignFunctionInterface -o Dep2.o
ghc -c Dep2.lhs -dynamic -XTemplateHaskell -fPIC -no-hs-main -XForeignFunctionInterface -o Dep2.dyn_o -osuf dyn_o -hisuf dyn_hi
ghc -c Dep1.lhs -XTemplateHaskell -XForeignFunctionInterface -o Dep1.o

Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
ghc -c Dep1.lhs -dynamic -XTemplateHaskell -fPIC -no-hs-main -XForeignFunctionInterface -o Dep1.dyn_o -osuf dyn_o -hisuf dyn_hi
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
ghc -O2 -dynamic -shared -fPIC Dep1.dyn_o Dep2.dyn_o Dep3.dyn_o -o libShared.so -lHSrts-ghc7.6.3
gcc -O2 -I/usr/local/lib/ghc-7.6.3/include -L/usr/local/lib/ghc-7.6.3 -L/usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0/ -c Main.c -o main.o
gcc -o main main.o -L/usr/local/lib/ghc-7.6.3 -L/usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0/ -L. -lShared -Wl,-rpath,/usr/local/lib/ghc-7.6.3 -L/home/tal/a_prerequisites/new_haskell/ghc-7.6.3/libraries/base/dist-install/build/libHSbase-4.6.0.1-ghc7.6.3. -lHStemplate-haskell-2.8.0.0
/usr/bin/ld: dynamic variable `ghczmprim_GHCziTypes_True_closure' is zero size

/usr/bin/ld: dynamic variable `ghczmprim_GHCziTypes_ZMZN_closure' is zero size

/usr/bin/ld: /usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0//libHStemplate-haskell-2.8.0.0.a(Syntax__1744.o)(.text+0x77): unresolvable R_X86_64_32 relocation against symbol `ghczmprim_GHCziTypes_True_closure'

/usr/bin/ld: /usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0//libHStemplate-haskell-2.8.0.0.a(Lib__228.o)(.text+0x14): unresolvable R_X86_64_32S relocation against symbol `ghczmprim_GHCziTypes_ZMZN_closure'

/usr/bin/ld: /usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0//libHStemplate-haskell-2.8.0.0.a(Lib__137.o)(.text+0x14): unresolvable R_X86_64_32S relocation against symbol `ghczmprim_GHCziTypes_ZMZN_closure'

/usr/bin/ld: /usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0//libHStemplate-haskell-2.8.0.0.a(Lib__227.o)(.text+0x14): unresolvable R_X86_64_32S relocation against symbol `ghczmprim_GHCziTypes_ZMZN_closure'

/usr/bin/ld: /usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0//libHStemplate-haskell-2.8.0.0.a(Lib__124.o)(.text+0x14): unresolvable R_X86_64_32S relocation against symbol `ghczmprim_GHCziTypes_ZMZN_closure

并创建了一个可执行文件“main”,但是当我尝试运行它时,出现以下情况:

host113@/home/tal/Documents/mfbus >> main
main: error while loading shared libraries: libHSbase-4.6.0.1-ghc7.6.3.so: cannot open shared object file: No such file or directory

我试图在最后一条规则(主要)中包含“-l”选项中的“libHSbase-4.6.0.1-ghc7.6.3.so”目录,以便加载它。但它似乎不起作用.有人可以洞察错误吗?

Dep1.lhs 的代码:

> {-# LANGUAGE TemplateHaskell #-} <br/>
> {-# LANGUAGE ForeignFunctionInterface #-} <br/>

> module Dep1 where

> import Foreign <br/>
> import Foreign.C.Types <br/>
> import Dep3 <br/>

> data MyData = MyData
>    { foo :: String
>    , bar :: Int
>    }

> emptyShow ''MyData

> foreign export ccall some_func :: IO () <br/>
> foreign export ccall factorial :: Int -> Int

> some_func :: IO () <br/>
> some_func = print $ MyData { foo = "bar", bar = 5 }

> factorial :: Int -> Int <br/>
> factorial 0 = 1  <br/>
> factorial n = n *(factorial $ n - 1)    

Dep3.lhs 的代码(出现在这里是因为 Dep1.lhs 导入了它):

> {-# LANGUAGE TemplateHaskell, FlexibleInstances #-}

> module Dep3 where

> import Language.Haskell.TH

> emptyShow :: Name -> Q [Dec] <br/>
> emptyShow name = [d|instance Show $(conT name) where show _ = "some meaningful sentence"|]

Dep2.lhs 的代码:

> {-# LANGUAGE ForeignFunctionInterface #-}

> module Dep2 where <br/>

> import Foreign    <br/>
> import Foreign.C.Types

> foreign export ccall power :: CInt -> CInt

> power :: CInt -> CInt
> power n = n*n

Main.c 的代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <HsFFI.h>

#ifdef __GLASGOW_HASKELL__
#include "Tal2_stub.h"
#endif

#ifdef __GLASGOW_HASKELL__
extern void __stginit_power ( void );
#endif

// int power(int i){ return i*i; }

int fact(int i){
  if (i == 0) return 1;
  else return i * fact(i-1);
}
nt main(int argc, char *argv[]){
  hs_init(&argc, &argv);

#ifdef __GLASGOW_HASKELL__
  hs_add_root(__stginit_power);
#endif

 printf("what is 5!?\n");
 char buf[2048];
 scanf("%s",buf);
 int x = atoi(buf);
 if(x == fact(5)){
   printf("You're right!\n");
 } else {
   printf("You're wrong!\n");
 }
 printf("what is the power of 2?\n");
 scanf("%s",buf);
 x = atoi(buf);
 if(x == power(2)){
   printf("You're right!\n");
 } else {
   printf("You're wrong!\n");
 }
 hs_exit();
 return 0;
}

我的生成文件代码:

all : clean main

main : shared main.o
        gcc -o main main.o -L/usr/local/lib/ghc-7.6.3 -L/usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0/ -L. -lShared -Wl,-rpath,/usr/local/lib/ghc-7.6.3 -L/home/tal/a_prerequisites/new_haskell/ghc-7.6.3/libraries/base/dist-install/build/libHSbase-4.6.0.1-ghc7.6.3. -lHStemplate-haskell-2.8.0.0 

main.o : 
    gcc -O2 -I/usr/local/lib/ghc-7.6.3/include -L/usr/local/lib/ghc-7.6.3 -L/usr/local/lib/ghc-7.6.3/template-haskell-2.8.0.0/ -c Main.c -o main.o 

shared : dep3second dep2second dep1second
        ghc -O2 -dynamic -shared -fPIC Dep1.dyn_o Dep2.dyn_o Dep3.dyn_o -o    libShared.so -lHSrts-ghc7.6.3

dep1second : dep1first
    ghc -c Dep1.lhs -dynamic -XTemplateHaskell -fPIC -no-hs-main -XForeignFunctionInterface -o Dep1.dyn_o -osuf dyn_o -hisuf dyn_hi   

dep2second : dep2first
    ghc -c Dep2.lhs -dynamic -XTemplateHaskell -fPIC -no-hs-main -XForeignFunctionInterface -o Dep2.dyn_o -osuf dyn_o -hisuf dyn_hi

dep3second: dep3first
    ghc -c Dep3.lhs -dynamic -XTemplateHaskell -fPIC -no-hs-main    -XForeignFunctionInterface -o Dep3.dyn_o -osuf dyn_o -hisuf dyn_hi

dep1first :
    ghc -c Dep1.lhs -XTemplateHaskell -XForeignFunctionInterface -o Dep1.o  

dep2first :
    ghc -c Dep2.lhs -XTemplateHaskell -XForeignFunctionInterface -o Dep2.o

dep3first :
    ghc -c Dep3.lhs -XTemplateHaskell -XForeignFunctionInterface -o Dep3.o

.PHONY : clean
clean :
    -rm -f *.o *.hi *.so *.dyn_hi *.dyn_o main

最佳答案

注意:我对 Haskell 的了解有限,这个答案根本没有假设任何关于 Haskell 的东西。

错误说:

<executable>: error while loading shared libraries: <shared lib>.so: cannot open shared object file: No such file or directory

这意味着在尝试执行您的程序时,未找到共享对象。请注意在链接期间和执行期间查找共享对象的区别。

粗略地说,当您使用 -L 时和 -l链接到一个共享对象,链接并没有完全完成,但记得要在运行时完成。当您执行依赖于该共享对象的可执行文件时,其他人(不是编译器)必须能够找到共享对象并进行链接:再次粗略地说,Linux .

因此您也需要让 Linux 找到您的共享对象。有几种方法可以做到这一点,其中一些已被弃用。我建议的方法是用共享对象的路径编写一个文件并将其放在 /etc/ld.so.conf.d/ 下。 .然后,执行ldconfig作为根(例如 sudo )和 Linux 应该能够找到共享对象。

我还没有测试过这个,但如果你只是编辑 /etc/ld.so.conf并添加包含 . 的行,如果共享对象位于执行可执行文件的同一目录中,Linux 应该能够找到共享对象。这对于开发来说可能没问题,但如果要安装共享对象,我不会推荐它。

关于编译用 haskell 和模板 haskell 编写的共享对象并将其与 c 中的 main 链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20729299/

相关文章:

c - 使用gdb调试时未找到调试符号

c - 我是否会面临缓冲区溢出的风险以及如何避免这种情况?

c++ - "multiple definition of ` 与 DLL 链接时 atexit '"

c++ - 调整可变跟踪分配长度

makefile - Gnu Make 自动依赖生成

C++/生成文件错误 : undefined reference to `main'

c - C 中的树结构,用于以预序深度优先方式导航

c - C在重新分配后是否重用内存?

c - 我构建的 glibc 中来自 ld-linux 的段错误

c - 除了原始机器指令外,可执行文件中还有什么?