Отладка ввода-вывода в модуле пакета внутри GHCi
Я делаю IO низкого уровня (для связывания библиотек) в Haskell и испытываю segfault. Я хотел бы использовать GHCi :break, чтобы понять, что происходит, но вот что происходит:
> import SDL
> :break SDL.setPaletteColors
cannot set breakpoint on setPaletteColors: module SDL.Video.Renderer is not interpreted
Поскольку нарушающий код находится не внутри моих собственных модулей, а скорее внутри модуля во внешнем пакете, он загружается как скомпилированный код, и, очевидно, я не могу его использовать : сломать скомпилированные модули.
Руководство GHCi подтверждает это и дает подсказку:
Есть одно главное ограничение: точки останова и пошаговое выполнение доступны только в интерпретируемых модулях; скомпилированный код невидим для отладчика [5].
[5] Обратите внимание, что пакеты содержат только скомпилированный код, поэтому для отладки пакета необходимо найти его источник и загрузить его напрямую.
Давайте попробуем это напрямую:
> :load some_path/sdl2/src/SDL/Video/Renderer.hs
some_path/sdl2/src/SDL/Video/Renderer.hs:101:8:
Could not find module ‘Control.Monad.IO.Class’
It is a member of the hidden package ‘transformers-0.3.0.0’.
Perhaps you need to add ‘transformers’ to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
Я могу добавить зависимости в мой файл.cabal, но это уже кажется неправильным. Как только я это сделал:
> :load some_path/sdl2/src/SDL/Video/Renderer.hs
some_path/sdl2/src/SDL/Video/Renderer.hs:119:8:
Could not find module ‘SDL.Internal.Numbered’
it is a hidden module in the package ‘sdl2-2.0.0’
Use -v to see a list of the files searched for.
Я мог бы сделать эти модули общедоступными (возможно, "изменив пакет.cabal"), но на данный момент это кажется очень неловким способом сделать что-то, и я не стал его развивать.
РЕДАКТИРОВАТЬ:
Я действительно попробовал это и получил удивительный результат:
> :load some_path/sdl2/src/SDL/Video/Renderer.hs
[1 of 1] Compiling SDL.Video.Renderer ( some_path/sdl2/src/SDL/Video/Renderer.hs, interpreted )
Ok, modules loaded: SDL.Video.Renderer.
> :break SDL.setPaletteColors
cannot set breakpoint on SDL.setPaletteColors: module SDL.Video.Renderer is not interpreted
Мое (необразованное) предположение: это потому, что внешний модуль все еще связан с моим кодом в виде двоичного файла, и загрузка его динамически в интерпретируемом режиме не меняет этого.
Итак, подведем итог: что является хорошим способом отладки ввода-вывода во внешнем пакете?
Дополнительные примечания:
У меня есть исходный код пакета, который мне нужен для отладки; на самом деле, он был добавлен в проект с надстройкой-надписью "Кабал"
Альтернативным вариантом использования GHCi было бы добавление трассировок в исходный код пакета, но это неудачный вариант, поскольку он предполагает перекомпиляцию пакета при каждой модификации (всякий раз, когда мне требуется дополнительная информация о выполнении и изменении трассировок), и это занимает очень много времени Интерактивная отладка с помощью GHCi кажется лучшим инструментом для этой работы, если бы я только знал, как его использовать.
1 ответ
Стек имеет некоторую поддержку для этого. Бег stack ghci --load-local-deps $TARGET
загрузит ваш проект и любые зависимости, которые находятся в packages
поле stack.yaml
в том числе если они помечены как extra-dep
s. Точки останова будут работать тогда. Вы можете отладить зависимость в GHCi, запустив stack unpack $PACKAGE
и добавив его в packages
в stack.yaml
,
Однако это не панацея. Если пакеты имеют конфликтующие расширения глобального пакета (или другие динамические флаги) или конфликты имен модулей, это не сработает. Например, если ваш пакет верхнего уровня имеет default-extensions: NoImplicitPrelude
и ваши зависимости не будут, они не будут импортированы прелюдии и почти наверняка не будут загружены. Смотрите эту ошибку GHC.