Data.Aeson с ForeignFunctionInterface в GHC

У меня есть следующий код haskell:

{-# LANGUAGE OverloadedStrings, DeriveGeneric, DeriveAnyClass  #-}

module BoardToJSON where

import GHC.Generics
import Data.Aeson
import Data.Aeson.Text (encodeToLazyText)
import Data.Text
import Control.Applicative
import Control.Monad
import qualified Data.ByteString.Lazy as B
import GHC.Generics
import Data.Text.Lazy.IO as I

import Foreign.C.Types
import Foreign.C.String
import Data.Maybe
import Data.List
import Data.Ix

import Data.List
import Data.Maybe
--foreign export ccall writef :: IO ()

data Piece = Piece {
_type :: !Text,
_color :: !Text,
_x :: Int,
_y :: Int
} deriving (Eq, Show, Generic, ToJSON, FromJSON)

piecesList::[Piece]
piecesList = [Piece "Rook" "White" 1 1, Piece "Knight" "White" 2 1, Piece "Bishop" "White" 3 1, Piece "Queen" "White" 4 1,
Piece "King" "White" 5 1, Piece "Bishop" "White" 6 1, Piece "Knight" "White" 7 1, Piece "Rook" "White" 8 1,
Piece "Pawn" "White" 1 2, Piece "Pawn" "White" 2 2, Piece "Pawn" "White" 3 2, Piece "Pawn" "White" 4 2,
Piece "Pawn" "White" 5 2, Piece "Pawn" "White" 6 2, Piece "Pawn" "White" 7 2, Piece "Pawn" "White" 8 2,
Piece "Rook" "Black" 1 8, Piece "Knight" "Black" 2 8, Piece "Bishop" "Black" 3 8, Piece "Queen" "Black" 4 8,
Piece "King" "Black" 5 8, Piece "Bishop" "Black" 6 8, Piece "Knight" "Black" 7 8, Piece "Rook" "Black" 8 8,
Piece "Pawn" "Black" 1 7, Piece "Pawn" "Black" 2 7, Piece "Pawn" "Black" 3 7, Piece "Pawn" "Black" 4 7,
Piece "Pawn" "Black" 5 7, Piece "Pawn" "Black" 6 7, Piece "Pawn" "Black" 7 7, Piece "Pawn" "Black" 8 7]

jsonFile :: FilePath
jsonFile = "pieces.json"
writef = I.writeFile jsonFile (encodeToLazyText piecesList)

getJSON :: IO B.ByteString
getJSON = B.readFile jsonFile

getPieces :: IO (Either String [Piece])
getPieces = (eitherDecode <$> getJSON) :: IO (Either String [Piece])

а также aeson установлен с кликой.

При выполнении:

$ ghci
Prelude> :load BoardToJSON
*BoardToJSON> writef

Я пишу файл Json с массивом частей в нем.

Однако при отмене комментариев foreign export ccall writef :: IO () и составление с:

CPP_SOURCES = main.cpp
HASKELL_SOURCES = haskell/BoardToJSON.hs
OBJECTS = haskell/*.o *.o

main: compileHaskell compileCPP link clean;

compileHaskell: $(HASKELL_SOURCES); ghc -c -XForeignFunctionInterface -fforce-recomp -O $(HASKELL_SOURCES)

compileCPP: $(CPP_SOURCES); g++ -c -I/usr/lib/ghc/include  -O $(CPP_SOURCES)

link: ; ghc -o Main -no-hs-main $(OBJECTS) -lstdc++

clean: ; rm -rf main && rm -rf haskell/*.o && rm *.o && rm -rf haskell/*.hi && rm -rf haskell/*_stub.h

compileHaskell а также compileCPP идет нормально, но я получаю кучу ошибок типа:

/tmp/ghca1ca_0/ghc_8.o:(.data.rel.ro+0x2a8): undefined reference to `bytestringzm0zi10zi8zi1_DataziByteStringziLazzy_getContents2_closure'
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)
makefile:12: recipe for target 'link' failed

Я думаю, что GHC не знает, где найти aeson так я и сделал:

$ sudo echo "/root/.cabal/lib/x86_64-linux-ghc-8.0.2" > /etc/ld.so.conf.d/x86_64-linux-gnu.conf
$ sudo ldconfig
$ sudo ldconfig -v | grep -i aeson
ldconfig: Path `/lib/x86_64-linux-gnu' given more than once
ldconfig: Path `/usr/lib/x86_64-linux-gnu' given more than once
ldconfig: /lib/x86_64-linux-gnu/ld-2.24.so is the dynamic linker, ignoring

libHSaeson-1.1.1.0-4sfmSwjYSZ4CJzSxs6L5hG-ghc8.0.1.so -> libHSaeson-1.1.1.0-4sfmSwjYSZ4CJzSxs6L5hG-ghc8.0.1.so

Без шансов.

Я пытался добавить -llibHSaeson, -lHSaeson или же -laeson чтобы связать цель. Но ничего не сработало.

Любая идея?


редактировать

После дальнейших исследований я попытался переустановить Aeson с --enable-shared

$ cabal install aeson --enable-shared --reinstall

Та же проблема.

3

Решение

Когда вы предоставляете .o файлы в качестве входных данных для GHC, он не знает, пришли они из модулей Haskell или нет. В результате он не может знать, какие зависимости Haskell должны быть связаны.

Вы можете указать зависимости вручную в командной строке ссылки (например, -package aeson), или предоставьте оригинальные модули Haskell в командной строке ссылки, и в этом случае GHC автоматически определит зависимости.

1

Другие решения

Других решений пока нет …