Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler switch to turn debugging messages on/off?

Tags:

haskell

ghc

OK, so here's a simple question. I've written a function debug :: String -> IO (). I'd like to set things up so that when I compile my program one way, this function writes to standard error, and if I compile my program another way, this function becomes no-op. Is there some easy compile-time switch to do that? Or would I have to implement something myself?

like image 721
MathematicalOrchid Avatar asked May 19 '13 09:05

MathematicalOrchid


3 Answers

I don't think involving trace is the right approach to solve this problem.

Instead, you could use a preprocessor to disable/enable debug messages. Put the following in a separate file:

{-# LANGUAGE CPP #-}
import System.IO

debug :: String -> IO ()
debug message =
#ifdef DEBUG
  hPutStrLn stderr message
#else
  return ()
#endif

The {-# LANGUAGE CPP #-} line enables the C preprocessor for the current file. You can then compile the file with/without debugging by using ghc -DDEBUG or just ghc.

like image 63
dflemstr Avatar answered Oct 03 '22 23:10

dflemstr


You can do this using the CPP preprocessor and #ifdef.

  1. First, use #ifdef to choose between the two versions of the function.

    {-# LANGUAGE CPP #-}
    module Logging (debug) where
    
    debug :: String -> IO ()
    #ifdef DEBUG
    debug = putStrLn
    #else
    debug _ = return ()
    #endif
    
  2. Then, add a flag to your .cabal file to control it.

    ...
    
    flag debug
      description: Enable debug logging
      default:     False
    
    executable foo  -- or library
      if flag(debug)
        cpp-options:  -DDEBUG
    
      ...
    
  3. Finally, to enable debugging, enable the flag with -f when configuring:

    $ cabal configure -f debug
    
like image 32
hammar Avatar answered Oct 03 '22 22:10

hammar


To complement the excellent answers given here, I would like to mention this approach, in case people (like me) are using the latest version of stack together with hpack.

In the package.yaml file I added the following:

  flags:
    debug: # Or whatever name you want to give to the flag
      description: Enable debug
       manual: True
       default: False

   when:
     - condition: flag(debug)
       cpp-options:  -DDEBUG

Then I would recommend to use traceIO from Debug.Trace in combination with NoTrace, so that traceIO will have no effect when the code is compiled without the debug flag:

{-# LANGUAGE CPP #-}

-- ...

#ifdef DEBUG
import Debug.Trace
#else
import Debug.NoTrace
#endif              

-- ...
someFunc :: IO ()
someFunc = do
    -- ...
    traceIO "Whatever..."

When using stack, the debug flag can be enabled by using the --flag option:

stack build --flag "your-package:debug"

Or if you're testing your package:

stack build --flag "your-package:debug"

If hpack is not used, then you can configure your cabal file as explained by hammar.

like image 25
Damian Nadales Avatar answered Oct 03 '22 22:10

Damian Nadales