fix: detect ghc-debug support more accurately, checking hledger-lib also

This commit is contained in:
Simon Michael 2024-05-01 15:27:42 -10:00
parent 6796decb72
commit 96caa8f352
4 changed files with 52 additions and 25 deletions

View File

@ -55,18 +55,25 @@ $ cabal install all:exes
### How do I build/run with ghc-debug support ?
```cli
$ stack build --flag hledger:ghcdebug --flag hledger-ui:ghcdebug --flag hledger-web:ghcdebug
$ stack build --flag hledger-lib:ghcdebug --flag hledger:ghcdebug --flag hledger-ui:ghcdebug --flag hledger-web:ghcdebug
```
You can check it in the --version output, which should mention "ghc-debug":
Use --flag to enable `ghcdebug` for hledger-lib and any of the executables you want to build, as above.
You might need to stop background builders like HLS while you do this, to avoid a fight over the build flag
(in VS Code, do Haskell: Stop Haskell LSP Server).
Your --version output should now say "supports ghc-debug":
```
$ stack exec -- hledger --version
```
With such a build, you can enable the ghc-debug listener by running hledger with a negative --debug level. Eg:
When a hledger executable supports ghc-debug, you can enable the ghc-debug listener by running with a negative --debug level. Eg:
```cli
$ hledger ... --debug=-1 # run normally, while also listening for ghc-debug commands
$ hledger ... --debug=-2 # pause for ghc-debug commands at program start
$ hledger ... --debug=-3 # pause for ghc-debug commands at program end
$ hledger CMD --debug=-1 # run normally, while also listening for ghc-debug commands
$ hledger CMD --debug=-2 # pause for ghc-debug commands at program start
$ hledger CMD --debug=-3 # pause for ghc-debug commands at program end
```
Then you can pause/resume hledger's execution and inspect memory and profile information
with the interactive `ghc-debug-brick` client,
or extract specific information with a custom ghc-debug script.
You should see "Starting ghc-debug on socket: ..." output.
Then in another window, run the interactive `ghc-debug-brick` client, select the running hledger process,
and explore memory/profile information, resume/pause execution, etc.
Or you can write a custom ghc-debug-client script to extract specific information.

View File

@ -163,6 +163,7 @@ module Hledger.Utils.Debug (
,dbg9With
-- * Utilities
,ghcDebugSupportedInLib
,GhcDebugMode(..)
,ghcDebugMode
,withGhcDebug'
@ -238,20 +239,28 @@ data GhcDebugMode =
| GDPauseAtStart
| GDPauseAtEnd
-- keep synced with ghcDebugMode
deriving (Eq,Ord)
deriving (Eq,Ord,Show)
-- | Is the hledger-lib package built with ghc-debug support ?
ghcDebugSupportedInLib :: Bool
ghcDebugSupportedInLib =
#ifdef GHCDEBUG
True
#else
False
#endif
-- | Should the program open a socket allowing control by ghc-debug-brick or similar ghc-debug client ?
-- See GhcDebugMode.
ghcDebugMode :: GhcDebugMode
ghcDebugMode =
case debugLevel of
-- keep synced with GhcDebugMode
#ifdef GHCDEBUG
_ | not ghcDebugSupportedInLib -> GDNotSupported
(-1) -> GDNoPause
(-2) -> GDPauseAtStart
(-3) -> GDPauseAtEnd
#endif
_ -> GDDisabled
-- keep synced with GhcDebugMode
-- | When ghc-debug support has been built into the program and enabled at runtime with --debug=-N,
-- this calls ghc-debug's withGhcDebug; otherwise it's a no-op.

View File

@ -85,11 +85,6 @@ dependencies:
- extra >=1.6.3
- Glob >= 0.9
when:
- condition: (!(os(windows)))
dependencies:
- pager >=0.1.1.0
ghc-options:
- -Wall
- -Wno-incomplete-uni-patterns
@ -98,6 +93,21 @@ ghc-options:
- -Wno-type-defaults
- -Wno-unused-do-bind
flags:
ghcdebug:
description: Build with support for attaching a ghc-debug client
default: false
manual: true
when:
- condition: (!(os(windows)))
dependencies:
- pager >=0.1.1.0
- condition: (flag(ghcdebug))
cpp-options: -DGHCDEBUG
dependencies:
- ghc-debug-stub >=0.6.0.0 && <0.7
source-dirs:
#- other/ledger-parse
- .

View File

@ -18,7 +18,7 @@ import System.Info (os, arch)
import Data.List (intercalate)
import Data.Maybe (fromMaybe)
import Hledger.Utils (splitAtElement)
import Hledger.Utils (ghcDebugSupportedInLib, splitAtElement)
type ProgramName = String
type PackageVersion = String
@ -38,9 +38,9 @@ packageversion =
packagemajorversion :: PackageVersion
packagemajorversion = intercalate "." $ take 2 $ splitAtElement '.' packageversion
-- | Given possible git state info from the build directory (or an error message, which is ignored),
-- the name of a program (executable) in the currently building package,
-- and the package's version, make a complete version string. Here is the logic:
-- | Given possible git state info from the build directory (or a git error, which is ignored),
-- and the ghcdebug build flag, executable name and package version for the package being built,
-- make the best version string we can. Here is the logic:
--
-- * Program name, OS and architecture are always shown.
-- * The package version is always shown.
@ -50,7 +50,8 @@ packagemajorversion = intercalate "." $ take 2 $ splitAtElement '.' packageversi
-- * (TODO, requires adding --match support to githash:
-- If there are tags matching THISPKG-[0-9]*, the latest one is used to calculate patch level
-- (number of commits since tag), and if non-zero, it and the branch name are shown.)
-- * If the ghcdebug build flag was enabled, "ghc-debug support" is shown.
-- * If the ghcdebug build flag was enabled for the package being built, and for hledger-lib (both are needed),
-- "ghc-debug support" is shown.
--
-- Some example outputs:
--
@ -70,10 +71,10 @@ packagemajorversion = intercalate "." $ take 2 $ splitAtElement '.' packageversi
-- so output should be suitable for all of those.
--
versionStringWith :: Either String GitInfo -> Bool -> ProgramName -> PackageVersion -> VersionString
versionStringWith egitinfo ghcdebug progname packagever =
versionStringWith egitinfo ghcDebugSupportedInThisPackage progname packagever =
concat $
[ progname , " " , version , ", " , os' , "-" , arch ]
++ [ " with ghc-debug support" | ghcdebug ]
++ [ " with ghc-debug support" | ghcDebugSupportedInThisPackage && ghcDebugSupportedInLib ]
where
os' | os == "darwin" = "mac"
| os == "mingw32" = "windows"