Динамическая библиотека Haskell

http://www.vex.net/~trebla/haskell/so.xhtml описывает, как скомпилировать разделяемую библиотеку.

О компиляции команды:

ghc -O2 -dynamic -shared -fPIC -o libEval.so Eval.hs hsbracket.c -lHSrts-ghc7.6.3

это говорит:

(Не могли бы вы опустить -dynamic для запроса статических библиотек других пакетов? Не совсем, они не были сгенерированы с -fPIC. В частности, это недопустимо в x86_64.)

Почему это так? Что нужно сделать, чтобы скомпилировать разделяемую библиотеку без зависимостей libHS*?

2 ответа

Решение

Да, компиляция с -fPIC помогает. Вот как это сделать.

ghc-7.8.4/mk/build.mk:

 SRC_HC_OPTS     = -H64m -O 
 EXTRA_HC_OPTS   = -fPIC    
 SRC_CC_OPTS     = -fPIC -O 
 GhcStage1HcOpts = -fasm -O0
 GhcStage2HcOpts = -fasm -O0
 GhcLibHcOpts    = -fasm -O2
 GhcLibWays      = v dyn    
 DYNAMIC_GHC_PROGRAMS = YES 
 DYNAMIC_BY_DEFAULT   = NO  
 SplitObjs            = NO  
 HADDOCK_DOCS         = NO  
 BUILD_DOCBOOK_HTML   = NO  
 BUILD_DOCBOOK_PS     = NO  
 BUILD_DOCBOOK_PDF    = NO  

Пока вы компилируете ghc:

export EXTRA_CONFIGURE_OPTS="--disable-library-profiling --enable-shared"

Для создания пакетов cabal с -fPIC используйте:

cabal install --enable-shared --ghc-option=-fPIC text

Тестовый файл foo.hs (Data.Text используется для проверки работы пакетов Cabal):

import Foreign.C as C 
import Data.Text as T
import Data.Text.Foreign as T 
foreign export ccall   len :: CString -> IO CInt 
len t = C.peekCString t >>= return . CInt . fromIntegral . T.length . T.pack  
main = return ()

Динамическая сборка:

ghc -dynamic --make foo.hs

Динамическое смешивание со статической сборкой (не уверен, нужен ли pthread, но показывает, как добавить динамическое связывание):

ghc -fPIC -shared --make -o libfoo.so \
 -optl-Wl,-Bstatic -lHSrts -lCffi \
   -lHSbase-4.7.0.2 -lHSinteger-gmp-0.5.1.0 -lHSghc-prim-0.3.1.0 \
-optl-Wl,-Bdynamic -lpthread foo.hs

Так как Кайко связался со мной в частном порядке для ответа, с таким же успехом можно опубликовать его здесь...

Укороченная версия

Опуская -dynamic, вы пытаетесь взять все статические.a-библиотеки и связать их в один массивный.so-файл. Эти.a библиотеки были построены без -fPIC. Весь код, который заканчивается в файле.so, должен быть собран с -fPIC (по крайней мере, в ELF x86-64). Таким образом, в этом случае связывание не будет выполнено, поскольку требуется -fPIC, но библиотеки не были созданы с -fPIC.

Длинная версия

Есть несколько вещей, которые варьируются между различными способами создания статических и динамических библиотек:

  1. Он построен как.a архив или как.so (или.dll/.dynlib) объект?
  2. Он построен с -fPIC, позиционно-независимым кодом или нет?
  3. Ожидаются ли внешние символы в том же DSO или во внешнем DSO?

В принципе, множество различных комбинаций этих вещей имеет смысл, но на практике используются лишь немногие.

В Linux (ELF) существует два стандартных подхода к созданию библиотек: полностью статический и полностью динамический. В полностью статическом подходе ответ на вопрос 1,2,3 выше:.a архив, без -fPIC, тот же DSO. В полностью динамическом подходе ответы таковы: .so lib, -fPIC, внешний DSO.

Теперь то, что вы хотите сделать, это другое. Вы хотите, чтобы все библиотеки были собраны в виде файлов.a, но с -fPIC и внешними символами, которые должны находиться в одном DSO. Это позволит вам связать все эти библиотеки в одну огромную общую библиотеку. Поэтому принципиальным отличием является использование -fPIC, поскольку в ELF (в частности, в x86_64) код, который заканчивается в общей библиотеке, должен быть собран с -fPIC.

В отличие от этого, в Windows GHC может делать именно то, что вы хотите, чтобы связать все библиотеки Haskell (включая RTS и т. Д.) В одну массивную общую библиотеку (.dll). Это связано с тем, что в Windows (в отличие от ELF) независимый от позиции код не имеет значения. Поэтому в Windows можно взять статические библиотеки и связать их в большую общую библиотеку.

В принципе, это также возможно в Linux, если все библиотеки Haskell построены статически, но с параметром -fPIC. Это не значение по умолчанию, и это является непосредственной причиной, по которой вы не можете опустить -dynamic в этом случае в Linux.

Таким образом, в принципе, можно попытаться пересобрать ghc и основные библиотеки из исходного кода, используя флаг -fPIC, а затем посмотреть, работает ли он, чтобы опустить -dynamic и связать все в одну огромную разделяемую библиотеку.

Другие вопросы по тегам