如何在macOS 10.14.5上使用GHC> = 8.2.1(最好在8.6。*上)编译Haskell可执行文件(不是库),该函数成功完成了foreign export
一个功能(即,将其公开为二进制中的公共符号) ?这在GHC 8.0.2中有效,但在更高版本中无效。
我已经在ghc 8.0.2(通过堆栈),8.2.2(通过nix和堆栈),8.4.4(通过nix和堆栈)和8.6.4(通过nix和堆栈)上进行了尝试。仅8.0.2有效。我知道8.2引入了此更改:GHC will now use ld.gold or ld.lld instead of the system’s default
ld , if available.
但是我不清楚8.0.2是否会首先使用其他“系统默认” ld(darwin的ld而不是llvm的lld?)。我知道ghc的-pgml [ld-program-here]
选项来设置链接器,但是我无法将其手动设置为已成功编译并链接任何东西以进行进一步测试的任何东西。
我有此文件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"
使用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
使用ghc 8.6.4时,似乎未导出该符号,因此将来尝试用该符号链接另一个程序都会失败。
> 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 ...
最佳答案
按照我在评论中所说的,您测试的GHC的两个版本均未从_my_square
导出Main
。相反,它们从_my_square
导出Main.o
(这就是为什么您可以使用ghc
编译和链接使用.c
的my_square
文件的原因)。当Main.o
链接到最终的Main
可执行文件时,GHC都不告诉链接器导出_my_square
。 GHC 8.6.4(我认为,从8.2开始)告诉链接器剥离未使用的,未导出的符号,因此_my_square
消失。 GHC 8.0.2不会,纯粹是偶然将_my_sqaure
保留在Main
可执行文件中。
您可以告诉GHC告诉链接器保留该符号。链接器选项为-exported_symbol <symbol>
。我的GHC实际上是通过gcc
调用链接器的,所以我必须用-Wl
包裹这两个参数。无论出于何种原因,将该选项传递给实际编译Main.hs
的GHC都会导致错误;您必须使用一个简单的GHC调用创建Main.o
,然后再次调用GHC将其链接到Main
,这一次是使用链接器选项。也许这是我的系统特有的-您可以尝试寻找更好的方法。
$ 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
我仍然建议您提交GHC问题,以简化此过程。
关于macos - 如何编译导出符号的Haskell Mach-O可执行文件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56305512/