Отладка ввода-вывода в модуле пакета внутри 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

Мое (необразованное) предположение: это потому, что внешний модуль все еще связан с моим кодом в виде двоичного файла, и загрузка его динамически в интерпретируемом режиме не меняет этого.


Итак, подведем итог: что является хорошим способом отладки ввода-вывода во внешнем пакете?

Дополнительные примечания:

  1. У меня есть исходный код пакета, который мне нужен для отладки; на самом деле, он был добавлен в проект с надстройкой-надписью "Кабал"

  2. Альтернативным вариантом использования GHCi было бы добавление трассировок в исходный код пакета, но это неудачный вариант, поскольку он предполагает перекомпиляцию пакета при каждой модификации (всякий раз, когда мне требуется дополнительная информация о выполнении и изменении трассировок), и это занимает очень много времени Интерактивная отладка с помощью GHCi кажется лучшим инструментом для этой работы, если бы я только знал, как его использовать.

1 ответ

Стек имеет некоторую поддержку для этого. Бег stack ghci --load-local-deps $TARGET загрузит ваш проект и любые зависимости, которые находятся в packages поле stack.yamlв том числе если они помечены как extra-deps. Точки останова будут работать тогда. Вы можете отладить зависимость в GHCi, запустив stack unpack $PACKAGE и добавив его в packages в stack.yaml,

Однако это не панацея. Если пакеты имеют конфликтующие расширения глобального пакета (или другие динамические флаги) или конфликты имен модулей, это не сработает. Например, если ваш пакет верхнего уровня имеет default-extensions: NoImplicitPrelude и ваши зависимости не будут, они не будут импортированы прелюдии и почти наверняка не будут загружены. Смотрите эту ошибку GHC.

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