Как мне скомпилировать исполняемый файл Haskell Mach-O, который экспортирует символ? - PullRequest
4 голосов
/ 25 мая 2019

Как мне скомпилировать исполняемый файл Haskell (не библиотека), используя GHC> = 8.2.1 (предпочтительно на 8.6. *) В macOS 10.14.5, которая успешно выполняет foreign export sa функцию (т.е. предоставляет это как публичный символ в двоичном коде)? Это работает в 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, в первую очередь (ld Дарвина, в отличие от lvm lld?). Мне известна опция -pgml [ld-program-here] в ghc для установки компоновщика, но я не смог вручную установить для него что-либо, что было успешно скомпилировано и связало что-либо для дальнейшего тестирования.

У меня есть этот файл 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 ...

1 Ответ

1 голос
/ 27 мая 2019

Если не считать того, что я сказал в своем комментарии, ни одна из протестированных вами версий 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. По любой причине передача этой опции в GHC, фактически компилирующую Main.hs, вызывает ошибку; Вы должны сделать Main.o с помощью одного простого вызова GHC, а затем снова вызвать 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, чтобы сделать это проще.

...