Динамическая библиотека 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.
Длинная версия
Есть несколько вещей, которые варьируются между различными способами создания статических и динамических библиотек:
- Он построен как.a архив или как.so (или.dll/.dynlib) объект?
- Он построен с -fPIC, позиционно-независимым кодом или нет?
- Ожидаются ли внешние символы в том же 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 и связать все в одну огромную разделяемую библиотеку.