Подтвердить что ты не робот

Отладка ввода-вывода в модуле пакета внутри GHCi

Я делаю низкоуровневое IO (для привязки к библиотеке) в Haskell и испытываю segfault. Я хотел бы использовать GHCi : break, чтобы выяснить, что происходит, но вот что происходит:

> import SDL
> :break SDL.setPaletteColors
cannot set breakpoint on setPaletteColors: module SDL.Video.Renderer is not interpreted

Так как код нарушения не находится внутри моих собственных модулей, а скорее внутри модуля во внешнем пакете, он загружается как скомпилированный код и, по-видимому, я не могу использовать : break на скомпилированных модулях.

Руководство 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?), но на данный момент это кажется очень неудобным способом делать что-то, и я не преследовал его дальше.

EDIT:

Я действительно попробовал это и получил озадачивающий результат:

> :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

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


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

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

  • У меня есть источник для пакета, который мне нужно отлаживать; Фактически, он был добавлен в проект с дополнительным источником песочницы cabal

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

4b9b3361

Ответ 1

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

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